I am developing an application that uses a map. I want to show a polygon with a "hole", in Java Android. I searched, but unfortunately, I could not find a solution. I think my problem is that I can not set the correct fillColor. Can someone help me?
My result:
I want the hole's color to be transparent.
My code:
List<ArrayList<LatLng>> multiLatLon;
...
//draw polygon hole
for(int i=0; i<multiLatLon.size(); i++){
poly = new PolygonOptions();
for (int j=0; j<multiLatLon.get(i).size(); j++){
mop.position(multiLatLon.get(i).get(j));
poly.add(multiLatLon.get(i).get(j));
Marker m = mMap.addMarker(mop);
}
poly.fillColor(R.color.colorOcher);
Polygon polygon = mMap.addPolygon(poly);
}
Let me know if you need more info.
Solution:
...
poly = new PolygonOptions ();
poly.fillColor (ColorUtils.setAlphaComponent (Color.BLUE, 128));
for (int i = 0; i <multiLatLon.size (); i ++) {
if (i == 0) {
poly.addAll (multiLatLon.get (i));
} else {
poly.addHole (multiLatLon.get (i));
}
}
mMap.addPolygon(poly);
In my case, I know that the first point array (multiLatLon.get (i)) defines the polygon geometry; while the others are the polygon holes.
Note: I used addAll to delete one for loop
I think the solution you're looking for is the addHole function in the PolygonOptions class.
Give that function your points (as Iterable<LatLng>) you want to have a hole and you should be good to go.
I don't know exactly where the values of your hole are in your code, but basically, you just call that function like this :
poly = new PolygonOptions();
// set the polygon's attributes
//...
//Iterable<LatLng> hole = //whatever contains the hole
poly.addHole(hole);
Related
I'm using polygon on shape renderer and the problem is that the user should be able to add vertex whenever they want, basically the vertices are not set by me but by the user. What I did is whenever the user add a point, I add them to an arrayList.
ArrayList<Float> v = new ArrayList<Float>();
public void ontouch(screenX, screenY){
v.add(screenX);
v.add(screenY)
}
And then I have this problem when I try to render a polygon on a shapeRenderer
for(int i = 0; i < v.size; i++){
float[] vertices = new float[v.size()]
vertices[i - 1] = v.get(i - 1);
vertices[i] = v.get(i);
}
sr.polygon(v);
But I just get errors.
I am trying to achieve something like this, if you know a different way of doing this then that would be really helpful. By the way I'm also using box2d and this does not need to have collision it's just for the user visual.
The way I would personally do it is by having an LinkedList with Vector2 objects. Vector2 objects store two floats, so for every click, you get the x and y coordinates and make a new Vector2 object. By storing them in the LinkedList, you can retrieve the points at any time in the correct order so you can connect a line.
LinkedList<Vector2> v = new LinkedList<Vector2>();
public void ontouch(screenX, screenY){
v.add(new Vector2(screenX, screenY)); // add Vector2 into LinkedList
}
How you want to draw the lines or connect the points is up to you.
Another was is to just only keep the two most recent points that were clicked, and throw the others away. This would mean storing the lines instead of the points. If the lines are objects, then you can do this:
Vector2 previousPoint;
Vector2 currentPoint;
ArrayList<MyLineClass> lines = new ArrayList<MyLineClass>();
public void ontouch(screenX, screenY){
if(previousPoint == null){
previousPoint = new Vector2(screenX, screenY);
}else{
previousPoint = currentPoint;
currentPoint = new Vector2(screenX, screenY);
lines.add(new MyLineClass(currentPoint, previousPoint)
}
}
I wrote this off the cuff but I believe this example should work.
EDIT:
Good thing LibGDX is open source. If you want to use an array of float numbers, the method simply gets an x and y coordinate in alternating order. So for each index:
0 = x1
1 = y1
2 = x2
3 = y2
4 = x3
5 = y3
etc.
It's an odd method, but I suppose it works.
I work with the Google Tango right now and so far everything worked fine, but I stumbled upon a few strange things.
There is a class ScenePoseCalculator in the Tango Examples. And there is a method "toOpenGlCameraPose". When using this, the OpenGL camera however is not set up correctly. When I move forward, the camera moves backwards. Left and right are swapped as well.
But the most difficult thing is to transform the PointCloud correctly. I do the following:
Create an Vector3-Array:
Vector3f [] vertices = new Vector3f[mPointCloud.getGeometry().getVertices().capacity()];
for(int i=0; i<mPointCloud.getGeometry().getVertices().capacity(); i++) {
vertices[i] = new Vector3f(
mPointCloud.getGeometry().getVertices().get(i*3),
mPointCloud.getGeometry().getVertices().get(i*3+1),
mPointCloud.getGeometry().getVertices().get(i*3+2));
}
In the PointCloud Callback of the TangoListener I do:
private void updateXYZIJ() {
try {
if(pcm.getLatestXyzIj().xyzCount<10) return;
TangoCoordinateFramePair fp = new TangoCoordinateFramePair(
TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE,
TangoPoseData.COORDINATE_FRAME_DEVICE);
TangoXyzIjData xyzIj = pcm.getLatestXyzIj();
depthArray = new float[xyzIj.xyzCount * 3];
xyzIj.xyz.get(depthArray);
com.projecttango.rajawali.Pose p =
ScenePoseCalculator.toDepthCameraOpenGlPose(
tangoProvider.getTango().getPoseAtTime(
xyzIj.timestamp, fp), this.setupExtrinsics());
Pose cloudPose = this.rajawaliPoseToJMEPoseCLOUD(p);
currentPointCloudData = new PointCloudUpdate(
new Date(),
depthArray,
xyzIj.xyzCount,
xyzIj.ijRows,
xyzIj.ijCols,
0,
cloudPose,
null
);
// inform listeners
for (PointCloudListener listener : this.pointsListeners) {
listener.acceptMessage(tangoProvider, this.currentPointCloudData);
}
} catch (Exception e) {
e.printStackTrace();
}
}
To transform the PointCloud I do:
this.transformation = new Matrix4f();
this.transformation.setRotationQuaternion(
this.referencePose.orientation);
this.transformation.setTranslation(this.referencePose.place);
absVertices = new Vector3f[vertices.length];
for(int i=0; i<vertices.length; i++) {
// Create new Vertex
absVertices[i]=new Vector3f(
vertices[i].x,
vertices[i].y,
vertices[i].z
);
Vector3f v = absVertices[i];
transformation.rotateVect(absVertices[i]);
transformation.translateVect(absVertices[i]);
}
But whatever I do. I've tried everything. But it won't look right. The PointClouds get stapled over each other or look like they where placed without any sense.
Hope someone knows more...
For everyone still looking to find out how to do this, I just managed it in jMOnkeyEngine3. The secret is, one has to use the INVERSE of the rotation Quaternion which the Tango delivers.
Okay, here is how it works:
Getting depth data with the Callback:
public void onXyzIjAvailable(TangoXyzIjData xyzIj)
Create an Array of vertices from the xyz-Array:
// Create new array, big enough to hold all vertices
depthArray = new float[xyzIj.xyzCount * 3];
xyzIj.xyz.get(depthArray);
// Create Vertices
Vector3f[] vertices = new Vector3f[xyzIj.xyzCount];
for(int i=0; i<xyzIj.xyzCount; i++) {
vertices[i] = new Vector3f(
depthArray[i*3],
depthArray[i*3+1],
depthArray[i*3+2]);
}
Use the ScenePoseCalculator from Rajawali3d:
com.projecttango.rajawali.Pose p = ScenePoseCalculator
.toDepthCameraOpenGlPose(tangoProvider.getTango().getPoseAtTime(
xyzIj.timestamp, framePair_SS_D), this.setupExtrinsics());
Device intrinsics must be ordered before that, but remember to do it in an TRY/CATCH enclosure.
After that, get Rotation Quaternion and Pose Vector3 from the Tango Pose:
Pose cloudPose = this.rajawaliPoseToJMEPoseCLOUD(p);
That method is defined here:
private Pose rajawaliPoseToJMEPoseCLOUD(com.projecttango.rajawali.Pose p) {
Pose pose = new Pose(
new Vector3f(
(float)p.getPosition().x,
(float)p.getPosition().y,
(float)p.getPosition().z),
new Quaternion(
(float)p.getOrientation().x,
(float)p.getOrientation().y,
(float)p.getOrientation().z,
(float)p.getOrientation().w
));
return pose;
}
Then Put the vertices in a node and transform that node with the Pose Data of the according XYZIJ-Data:
meshNode.setLocalRotation(pcu.referencePose.orientation.inverse());
meshNode.setLocalTranslation(pcu.referencePose.place);
Hope it helps someone. Took me 4 days to figure it out x(
Cheers
never posted a question before though plenty of lurking, thanks for all the advice you've already unwittingly supplied! Couldn't seem to find any previous answers to help with this. I'm a scientist who's only picked up programming on the fly so tend to be a bodger, hopefully the question makes sense.
How do I set up an java.awt.geom.Area object for a set of triangles (for which I have the coordinates of the corners)?
The problem I’m trying to solve is that I have a mesh of triangles over which I'm drawing a mesh of rectangles and I’m trying to find for each rectangle which triangle or triangles it lies within. The java.awt.geom.Area class has an intersect method which given sufficient looping would seem to solve it - my problem is constructing the areas.
I can create the square mesh as areas in the following (possibly inefficient) manner
Rectangle2D.Double[] squareMesh = new Rectangle2D.Double[totalCells];
int k = 0;
for(int i=0; i < cellsY; i++) {
for(int j=0; j < cellsX; j++) {
squareMesh[k]= new Rectangle2D.Double(cellsXCoords[j],cellsYCoords[i],resolution,resolution);
k++;
}
}
Area[] squareMeshAreas = new Area[totalCells];
for(int i=0; i < totalCells; i++) {
squareMeshAreas[i] = new Area(squareMesh[i]);
}
For the triangles I have the coordinates of the corners for each. The java.awt.Polygon looked hopeful but won't work as it only takes integer coordinates. What is the best way to set up Areas for these triangles?
If there are better ways of solving the problem without using Area class then suggestions are also welcome.
In my game the character is constantly moving from left to right, so there will never be a situation where he hits the right side of a platform. I had a very brief talk with somebody and he suggested me to model my platform as 4 rectangles so that I would only need 3 cases in my algorithm (i.e. Player can only collide with the rectangles shaded green in the image below). Here's a visual description of what I mean:
I gave it a try but the collision detection is still messed up. It doesn't go through the side of the platform (this is good news since we want this to happen) but you can't glide on top of it or bounce under it. Can anyone see where I may have gone wrong?
public void checkCollisions(ArrayList<GameObject> list) {
for (int i = 0; i < list.size(); i++) {
for (int j = i + 1; j < list.size(); j++) {
GameObject go1 = list.get(i);
GameObject go2 = list.get(j);
boolean playerPlatformCollision = go1.getType()
.equalsIgnoreCase("player") && go2.getType().equalsIgnoreCase("platform");
if (playerPlatformCollision) {
Rectangle playerRect = go1.getRect();
Rectangle platformRect = go2.getRect();
if (playerRect.overlaps(platformRect)) {
float platformRectX, platformRectY, platformRectWidth, platformRectHeight;
platformRectX = go2.getRect().getX(); // x position of the platform
platformRectY = go2.getRect().getY(); // y position of the platform
platformRectWidth = go2.getRect().getWidth(); // width of platform
platformRectHeight = go2.getRect().getHeight(); // height of platform
Rectangle caseA = new Rectangle(platformRectX,
platformRectY, platformRectX + 1,
platformRectHeight);
Rectangle caseB = new Rectangle(platformRectX + 1,
(platformRectY + platformRectHeight) - 1,
platformRectWidth - 1, platformRectHeight);
Rectangle caseC = new Rectangle(platformRectX + 1,
platformRectY, platformRectWidth, 1);
if (playerRect.overlaps(caseA)) {
go1.setxSpeed(0);
} else if (playerRect.overlaps(caseB)) {
go1.setySpeed(0);
} else if (playerRect.overlaps(caseC)) {
go1.setySpeed(-3f);
}
}
}
}
}
}
Please let me know if you are not clear with any parts of the code.
I can't be sure that this is the issue, but it seems that this problem is not addressed in your code, and I have had similar problems myself when ignoring this. When your player collides with the platform, it means that its rectangle is already intersecting the platform, by anywhere between 1 and how fast you are going number of pixels. Just adjusting the x and y speed is not enough. You must also remove the player rectangle from the platform, or else the player will get stuck. This can be done by using a loop and checking if your player is still colliding. if so, move 1 pixel over in the direction you came from, until no longer colliding.
I currently have a program that draws overlapping rectangles and was wondering if there is an easy way to determine which shape is on the top (most visible). This has me stumped as there is no z axis to use like in when dealing in 3D.
I have tried looping through the rectangles and using the .contains method but it returns all rectangles under a specific point and not the highest level one.
I have also searched around but perhaps I'm using the wrong keywords?
Normally when people do painting code they do something like:
List rectangles = ....
for (int i = 0; i < rectangles.size(); i++)
//paint the rectangle
So if you want to search for a Point to determine what Rectanle it is in then you should use:
for (int i = rectangles.size() - 1; i >= 0; i--)
{
if (rectangles.get(i).contains(yourPoint))
{
// do something
break;
}
}
Starting from the end will give you the last rectangle painted which means it is on top of all aother rectangles.