Is there a possibility to connect two marker locations with a line? I have two location marker:
LocationMarker point1 = new LocationMarker(
20.501925,
44.792181,
new AnnotationRenderer("point1 ")
);
LocationMarker point2 = new LocationMarker(
20.502972,
44.790873,
new AnnotationRenderer("point2 ")
);
Any example? I use ArCore Location
The code below will draw a line between two points - the points are associated with anchors in Sceneform - this is adapted from the answer here https://stackoverflow.com/a/52816504/334402:
private void drawLine(AnchorNode node1, AnchorNode node2) {
//Draw a line between two AnchorNodes
Log.d(TAG,"drawLine");
Vector3 point1, point2;
point1 = node1.getWorldPosition();
point2 = node2.getWorldPosition();
//First, find the vector extending between the two points and define a look rotation
//in terms of this Vector.
final Vector3 difference = Vector3.subtract(point1, point2);
final Vector3 directionFromTopToBottom = difference.normalized();
final Quaternion rotationFromAToB =
Quaternion.lookRotation(directionFromTopToBottom, Vector3.up());
MaterialFactory.makeOpaqueWithColor(getApplicationContext(), new Color(0, 255, 244))
.thenAccept(
material -> {
/* Then, create a rectangular prism, using ShapeFactory.makeCube() and use the difference vector
to extend to the necessary length. */
Log.d(TAG,"drawLine insie .thenAccept");
ModelRenderable model = ShapeFactory.makeCube(
new Vector3(.01f, .01f, difference.length()),
Vector3.zero(), material);
/* Last, set the world rotation of the node to the rotation calculated earlier and set the world position to
the midpoint between the given points . */
Anchor lineAnchor = node2.getAnchor();
nodeForLine = new Node();
nodeForLine.setParent(node1);
nodeForLine.setRenderable(model);
nodeForLine.setWorldPosition(Vector3.add(point1, point2).scaled(.5f));
nodeForLine.setWorldRotation(rotationFromAToB);
}
);
}
Update: Full working example available here:
https://github.com/mickod/LineView
Related
I'm using onLocationChanged to:
//set the location of a point
point1 = (new LatLng(location.getLatitude() , location.getLongitude()));
I'm trying to construct a polyline that points in the direction of the heading as I'm moving. Ive used the computeHeading method to calculate the heading and then I put that in computeOffset to generate another point x feet away as the far point to generate a polyline. This is done like this:
#Override
public void onLocationChanged(Location location) {
point1 = (new LatLng(location.getLatitude() , location.getLongitude()));
point2 = (new LatLng(location.getLatitude() , location.getLongitude()));
heading = SphericalUtil.computeHeading(point1, point2);
navOrigin = (new LatLng(location.getLatitude() , location.getLongitude()));
navSecPoint = SphericalUtil.computeOffset(point2, 500, heading);
PolylineOptions navigation = new PolylineOptions()
.add(navOrigin)
.add(navSecPoint)
.color(Color.MAGENTA);
if(navigationalLine !=null) { navigationalLine.remove(); }
else { navigationalLine = getMap().addPolyline(navigation); }
navigationalLine = getMap().addPolyline(navigation);
Only problem is to determine an instantaneous heading I need a distinct location for point1 and for point2. Currently as they are both in my onLocationChanged they both fill with the same location data. You can't compute a heading if both points are in the same spot.
How do I create some sort of timer or location based firing mechanism that gives some millisecond time delay between when point1 is filled with location data and a couple feet later to fill point2 with location data.
You can see the problem illustrated here
Using a timer to offset the location of two points is not necessary. Although a heading could be calculated with the spherical util tools the android.location series has a getBearing() method that continually updates with the heading of the device.
The
navSecPoint = SphericalUtil.computeOffset(point2, 500, heading);
could be substituted with:
navSecPoint = SphericalUtil.computeOffset(point2, 500, bearing);
the getBearing() method is a float and the computeOffset requires a double. This can be done:
float floatbearing = location.getBearing();
double bearing = floatbearing;
If you did decide to use a timer. Use the java.util.TimerTask.
Follow this tutorial:
run() with Timer
im trying to build a 3D Model, by building dynamically 3D models and translate them to where i need them.
Im starting with a basic model, trying to to achieve what is on the picture bellow. I want to dynamically build two cylinders, and the X,Y,Z of the TOP of my cylinder will be the same X,Y,Z of the BOTTOM of the second Cylinder, like the picture bellow:
For now i have this code:
public static void main(String[] args) throws FileNotFoundException, IOException {
int height = 10;
int radius = 1;
int angle = 0;
BranchGroup objRoot = new BranchGroup();
Cylinder cylinder;
Vector3f last_coordinates = new Vector3f(0f,0f,0f);
TransformGroup transf_group_cylinder = null;
//---- Working ok -----/
//build cylinder
cylinder = new Cylinder(radius, height);
transf_group_cylinder = createTransformGroup_Cylinder(new Vector3f(0f,0f,0f),angle);
transf_group_cylinder.addChild(cylinder);
objRoot.addChild(transf_group_cylinder);
last_coordinates = calculateLastPoint(height/2, angle);
System.out.println(last_coordinates);
//----------------------------//
//build 2nd cylinder
cylinder = new Cylinder(radius, height);
transf_group_cylinder = createTransformGroup_Cylinder(last_coordinates, Math.PI/2);
transf_group_cylinder.addChild(cylinder);
objRoot.addChild(transf_group_cylinder);
OBJWriter objWriter = new OBJWriter("myObj.obj");
objWriter.writeNode(objRoot);
objWriter.close();
}
private static Vector3f calculateLastPoint(int height, int angle) {
float x = (float) (height * Math.sin(angle));
float y = (float) (height * Math.cos(angle));
return new Vector3f(0, x, y);
}
private static TransformGroup createTransformGroup_Cylinder(
Vector3f last_coordinates, double angle) {
TransformGroup transf_group = new TransformGroup();
//position the model
Transform3D transform_origin = new Transform3D();
transform_origin.setTranslation(new Vector3f(0, 0, 0));
// set model in horizontal position
Transform3D transf_horizontal = new Transform3D();
transf_horizontal.rotZ(Math.PI / 2);
transform_origin.mul(transf_horizontal);
// rotate object
Transform3D angleRotation = new Transform3D();
angleRotation.rotX(angle);
transform_origin.mul(angleRotation);
Transform3D transform_xyz = new Transform3D();
transform_xyz.setTranslation(last_coordinates);
transform_origin.mul(transform_xyz); // set Transform for
transf_group.setTransform(transform_origin);
return transf_group;
}
With this code im achieving this:
My first cylinder is ok, but my 2nd cylinder is not placed in a proper place.
I can add any value for the size and angle values, so i need to calculate this two values in a dynamically way.
Can someone help solving this translation problem?
Thank you in advance.
The first step here is to give each cylinder a different color to allow you to see which one is which.
Next: When you create a cylinder, then it's centered at the origin. Since you want to chain them at the end point, you need to move them accordingly: First, you need to move the cylinder (or its transformation matrix) by -half its height to virtually move the "cylinder origin" to it's end.
The next step is that you need to apply the same transformation matrix to the end point (this time plus a full cylinder height), so it lines up with the actual end point.
That said, I would suggest you create a helper function that can create a cylinder between two points. This would allow you to say:
Point endPoint = cylinder(new Point(-1,.5,0), new Point(0,.5,0))
cylinder(endPoint, new Point(0,-.5,0))
...
or even create a helper function which accepts a list of points and creates all the cylinders between them.
I've been looking into getting an object on a two dimensional plane to follow a smooth curve defined by several control points.From what I've found, I'm looking for a Catmull-Rom-Spline.
I've been using LibGDX for my project, and it has its own Catmull-Rom-Spline implementation but I'm having trouble wrapping my head around how it works, as I've had trouble finding documentation or other source code implementing Catmull-Rom-Splines using LibGDX.
I'm looking for either an explanation of the LibGDX Catmull-Rom-Spline implementation or another way to implement a smooth path that implements control points using Catmull-Rom-Splines or another method. All I'm looking for is the ability to generate a path and pass back the x and y coordinates of a point on that path. If anyone has any suggestions or pointers, it would be appreciated. Thanks.
The libgdx Path classes (including CatmullRomSpline) are suitable for both 2D and 3D. So when creating a CatmullRomSpline, you must specify which Vector (Vector2 or Vector3) to use:
CatmullRomSpline<Vector2> path = new CatmulRomSpline<Vector2> ( controlpoints, continuous );
For example:
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
Vector2 cp[] = new Vector2[]{
new Vector2(0, 0), new Vector2(w * 0.25f, h * 0.5f), new Vector2(0, h), new Vector2(w*0.5f, h*0.75f),
new Vector2(w, h), new Vector2(w * 0.75f, h * 0.5f), new Vector2(w, 0), new Vector2(w*0.5f, h*0.25f)
};
CatmullRomSpline<Vector2> path = new CatmullRomSpline<Vector2>(cp, true);
Now you can get the location on the path (ranging from 0 to 1) using the valueAt method:
Vector2 position = new Vector2();
float t = a_vulue_between_0_and_1;
path.valueAt(position, t);
For example:
Vector2 position = new Vector2();
float t = 0;
public void render() {
t = (t + Gdx.graphics.getDeltaTime()) % 1f;
path.valueAt(position, t);
// Now you can use the position vector
}
Here's an example: https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/PathTest.java
I'm testing something with jMonkeyEngine and I'm attempting to have the camera follow a box spatial. I followed official instructions here:
http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:making_the_camera_follow_a_character
When applying, what I learnt there I produced the following code:
#Override
public void simpleInitApp() {
flyCam.setEnabled(false);
//world objects
Box b = new Box(Vector3f.ZERO, 1, 1, 1);
Geometry geom = new Geometry("Box", b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);
geom.setMaterial(mat);
rootNode.attachChild(geom);
//Ship node
shipNode = new Node();
rootNode.attachChild(shipNode);
//Ship
Box shipBase = new Box(new Vector3f(0, -1f, 10f), 5, 0.2f, 5);
Geometry shipGeom = new Geometry("Ship Base", shipBase);
Material shipMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
shipMat.setColor("Color", ColorRGBA.Green);
shipGeom.setMaterial(shipMat);
shipNode.attachChild(shipGeom);
//Camera node
cameraNode = new CameraNode("Camera Node", cam);
cameraNode.setControlDir(ControlDirection.CameraToSpatial);
shipNode.attachChild(cameraNode);
initPhysics();
initKeys();
}
When the following code is called:
#Override
public void simpleUpdate(float tpf) {
//Update ship heading
shipHeading = shipHeading.mult(shipRotationMoment);
shipNode.setLocalRotation(shipHeading);
shipPos = shipPos.add(shipVelocity);
shipNode.setLocalTranslation(shipPos);
}
The box moves as is predicted but the camera stays where it is. The graph should be something like this:
rootNode
b (Box)
shipNode
shipBase
cameraNode
Therefore the camera should be already bound to shipNode. What am I missing?
Reading through the tutorial you provided, it seems you might have a typo. You have:
cameraNode.setControlDir(ControlDirection.CameraToSpatial);
However, the tutorial has:
//This mode means that camera copies the movements of the target:
camNode.setControlDir(ControlDirection.SpatialToCamera);
Lower down in the tutorial it defines the difference between these 2 ControlDirections. The one the tutorial provides has the camera follow the movement of the object, whereas what you have the object follows the movement of the camera.
Hope this helps.
I've been searching for a way to send a list of coord(x,y,z) to jzy3d. But without success.
The only way I found is to use a "builder" with a list of "coord3d" and a "tesselator", but it actually doesn't work.
I don't realy get the meaning of the Tesselator in fact ?
Here is the code I tried :
public Chart getChart(){
List<Coord3d> coordinates = new ArrayList<Coord3d>();
for(int i=0; i<200; i++)
coordinates.add( new Coord3d(5, 10, 15) );
Tesselator tesselator = new Tesselator() {
#Override
public AbstractComposite build(float[] x, float[] y, float[] z) {
return null;
}
};
tesselator.build(coordinates);
org.jzy3d.plot3d.primitives.Shape surface = (Shape)Builder.build(coordinates, tesselator);
/*/ Define a function to plot
Mapper mapper = new Mapper(){
public double f(double x, double y) {
return 10*Math.sin(x/10)*Math.cos(y/20)*x;
}
};*/
// Define range and precision for the function to plot
// Range range = new Range(-150,150);
// int steps = 50;
// Create the object to represent the function over the given range.
// org.jzy3d.plot3d.primitives.Shape surface = (Shape)Builder.buildOrthonormal(new OrthonormalGrid(range, steps, range, steps), mapper);
//surface.setColorMapper(new ColorMapper(new ColorMapRainbow(), surface.getBounds().getZmin(), surface.getBounds().getZmax(), new Color(1,1,1,.5f)));
// surface.setWireframeDisplayed(true);
// surface.setWireframeColor(Color.BLACK);
//surface.setFace(new ColorbarFace(surface));
//surface.setFaceDisplayed(true);
//surface.setFace2dDisplayed(true); // opens a colorbar on the right part of the display
// Create a chart
Chart chart = new Chart("swing");
chart.getScene().getGraph().add(surface);
return chart;
}
Could someone please tell me how to feed my graph with many XYZ coordonates so that I may get a 3d surface plot like this one :
(source: free.fr)
A tesselator allows creating polygons out of a list of points. Jzy3d provides two base tesselators: one that supports points standing on a regular grid (called OrthonormalTesselator), one that supports unstructured points as input (DelaunayTesselator). The second one is not always "working good": not a problem concerning its implementation but mainly the fact that it's difficult to decide how points should work together to form a polygon in 3d. You may find some discussions about it on Jzy3d wiki and discussion groups.
To manually build polygons, here's what you should do:
// Build a polygon list
double [][]distDataProp = new double[][] {{.25,.45, .20},{.56, .89, .45}, {.6, .3,.7}};
List<Polygon> polygons = new ArrayList<Polygon>();
for(int i = 0; i < distDataProp.length -1; i++){
for(int j = 0; j < distDataProp[i].length -1; j++){
Polygon polygon = new Polygon();
polygon.add(new Point( new Coord3d(i, j, distDataProp[i][j]) ));
polygon.add(new Point( new Coord3d(i, j+1, distDataProp[i][j+1]) ));
polygon.add(new Point( new Coord3d(i+1, j+1, distDataProp[i+1][j+1]) ));
polygon.add(new Point( new Coord3d(i+1, j, distDataProp[i+1][j]) ));
polygons.add(polygon);
}
}
// Creates the 3d object
Shape surface = new Shape(polygons);
surface.setColorMapper(new ColorMapper(new ColorMapRainbow(), surface.getBounds().getZmin(), surface.getBounds().getZmax(), new org.jzy3d.colors.Color(1,1,1,1f)));
surface.setWireframeDisplayed(true);
surface.setWireframeColor(org.jzy3d.colors.Color.BLACK);
chart = new Chart();
chart.getScene().getGraph().add(surface);