I'm attempting to draw polygons on a map with location data as the user moves. I do not want any breaks between the polygons. I need one side of the next polygon to connect to the previous polygon's side. How would I go about this? I have what I've made so far, but I'm unsure how to gather the location data and use that from before to make the polygons connect.
I am using:
onLocationChanged(Location location) {
currentLocation = (new LatLng(location.getLatitude(), location.getLongitude()));
if(previousLocation != null) {
polygonCornerBackLeftCorner = SphericalUtil.computeOffset(currentLocation, widthInMeters / 2, location.getBearing() + 90);
polygonCornerBackRightCorner = SphericalUtil.computeOffset(currentLocation, widthInMeters / 2, location.getBearing() + 90);
}
previousLocation = currentLocation
}
polygonGenerator() {
PolygonOptions polygon = new PolygonOptions().add(polygonCornerBackLeftCorner, polygonCornerBackRightCorner, polygonCornerFrontRight, polyCornerFrontLeft).fillColor(Color.YELLOW);
getMap().addPolygon(whatsquare);
}
Whenever you get a new currentLocation, you'll want to compute the corner points that correspond to it, and you'll want to cache them for later. If this isn't the first location, then you'll have a pair of cached corner points, and you'll use them plus the new ones to make your polygon and add it to the map, and then cache the new corner points for the next iteration.
Related
Im working with OSMDroid to make map offline in Android Studio.
this is my code to create Polygon :
polygon = new Polygon();
polygon.setPoints(list_polygon);
polygon.setFillColor(Color.parseColor("#1D566E"));
polygon.setTitle(name_map);
polygon.getOutlinePaint().setColor(polygon.getFillPaint().getColor());
map.getOverlays().add(polygon);
this code is to create line :
line = new Polyline();
line.setPoints(list_line);
line.setGeodesic(true);
line.setColor(Color.parseColor("#E33E5A"));
line.getOutlinePaint().setStrokeWidth(30f);
line.setWidth(15f);
line.getPaint().setStrokeCap(Paint.Cap.ROUND);
map.getOverlays().add(line);
and this code is to get my location :
myLocation = new MyLocationNewOverlay(map);
myLocation.enableFollowLocation();
myLocation.setDirectionArrow(icTruk, icTruk);
myLocation.enableMyLocation();
myLocation.setDrawAccuracyEnabled(true);
map.getOverlays().add(myLocation);
I have done to create polygon and polyline in osmdroid.
But now i want read that polygon or polyline if mylocation inthere ?
How to make it posible ?
You could do the following to get the current location and then check if it is close to the Polyline.
MyLocationNewOverlay myLocation= new MyLocationNewOverlay(mapView) {
#Override
public void onLocationChanged(Location location, IMyLocationProvider source) {
super.onLocationChanger(location, source);
// Turn the current location into a GeoPoint
GeoPoint currentPoint = new GeoPoint(location.getLatitude(), location.getLongitude);
// Set tolerance for isCloseTo
// Might need to play around with this value
// and see which fits best for your needs
double tolerance = 5.0;
// Check if location is close to Polyline
if (line.isCloseTo(currentPoint, tolerance, map)) {
// Do here what you want to do,
// when location is close to Polyline
}
}
}
Checking, if the location/GeoPoint is within a given polygon is a bit more work, since the only integrated method for that is based on MotionEvent rather than GeoPoint and only returns a correct value in a very specific scenario, see this for reference. But there are some answers out there, which might be usable for your need, like this one.
References:
Get the current location
OSMDroid Geopoint class
Android Location class
OSMDroid Polyline.isCloseTo
OSMDroid Polygon.contains
One way to check if point is in a polygon
I have a number of TextButtons I can drag, checking if they overlap an Image when I let go. Currently what I'm experiencing is either a particular object will detect collision located anywhere on screen, or it will never collide. Note that I'm not using the native DragAndDrop class, but have adapted a parallel implementation from a book.
Given that my TextButtons move when I drag them, I think the following function is updating the (x,y) of the object:
public void touchDragged(InputEvent event, float eventOffsetX, float eventOffsetY, int pointer)
{
float deltaX = eventOffsetX - grabOffsetX;
float deltaY = eventOffsetY - grabOffsetY;
a.moveBy(deltaX, deltaY);
}
Is that correct that the Actor a's x, y change due to moveBy? Because my latter collision detection - where I examine the dragged objects coordinates - reports the same x,y coordinates for the dragged object no matter where I release it. Here's the log for releasing the object from two different locations on the screen:
Does (626.8995, 393.1301)(923.8995, 393.1301)(923.8995, 499.1301)(626.8995, 499.1301) fit into (610.0, 256.0)(990.0, 256.0)(990.0, 677.0)(610.0, 677.0)?
Does (626.8995, 393.1301)(923.8995, 393.1301)(923.8995, 499.1301)(626.8995, 499.1301) fit into (610.0, 256.0)(990.0, 256.0)(990.0, 677.0)(610.0, 677.0)?
and here's the collision detection and sys out generating those log messages:
//this is called by the dragged obj, a, on touchUp() against each of the targets
public boolean overlaps(Actor other)
{
//a is the first, dragged object, other is the target
if (poly1 == null)
poly1 = getPolygon(a);
Polygon poly2 = getPolygon(other);
float[] p1v = poly1.getVertices();
StringBuilder sb = new StringBuilder();
for (int i=0; i<p1v.length-1; i+=2)
sb.append("(").append(p1v[i]).append(", ").append(p1v[i+1]).append(")");
float[] p2v = poly2.getVertices();
StringBuilder sb2 = new StringBuilder();
for (int i=0; i<p2v.length-1; i+=2)
sb2.append("(").append(p2v[i]).append(", ").append(p2v[i+1]).append(")");
System.out.println("Does " + sb + " fit into " + sb2 + "?");
// initial test to improve performance
if ( !poly1.getBoundingRectangle().overlaps(poly2.getBoundingRectangle()) )
return false;
return Intersector.overlapConvexPolygons( poly1, poly2 );
}
public Polygon getPolygon(Actor a) {
Polygon p = new Polygon();
// float[] vertex = { a.getOriginX(), a.getOriginY(), a.getOriginX(), a.getY(), a.getX(), a.getY(), a.getX(), a.getOriginY() };//new float[8];
// float[] vertex = { 0, 0, a.getWidth(), 0, a.getWidth(), a.getHeight(), 0, a.getHeight()};
float[] vertex = { a.getX(), a.getY(), (a.getX() + a.getWidth()), a.getY(), (a.getX() + a.getWidth()), (a.getY() + a.getHeight()), a.getX(), (a.getY() + a.getHeight())};
p.setVertices(vertex);
// p.setPosition(a.getX(), a.getY());
//p.setOrigin(a.getOriginX(), a.getOriginY());
return p;
}
There are a HORDE of collision detection posts already on StackOverflow, and they helped some in showing me how to form valid polygons. Perhaps the 3rd party drag and drop is why I'm not finding my answer in the wealth of knowledge out there, but I'm leaning towards some annoying mistake I'm overlooking.
Score another one for logic failure. Originally I thought I'd just be saving the dimensions of the dragged polygon when I decided to cache it, thinking it would save a few polygon creation steps as it was checked against a number of potential targets. Later, as I kept reworking what values to feed the polygon vertices, I tied in the location of the polygon as well. So it was just caching the first place I dragged it to, and using that every time I dragged it somewhere.
Thanks for the comment, it helped me move past thinking I wasn't understanding the classes. I'm doubtful this particular mistake/resolution will ever be of use to someone else, and would be very understanding if this post is removed.
I want to do some geometric calculations in Java and found that Spatial4j should suit my needs.
I want to be able to compute stuff like whether two polygons overlap or what their bounding box is.
My thinking is that I need to create a polygon from a series of points.
To that end I have tested with this code:
Point point1 = shapeFactory.pointXY(0, 0);
Point point2 = shapeFactory.pointXY(5, 1);
Point point3 = shapeFactory.pointXY(3, 3);
Point point4 = shapeFactory.pointXY(0, 1);
List<Point> points = new ArrayList<>();
points.addAll(Arrays.asList(point1, point2, point3, point4));
So, I have my points now. How do I go about making a polygon (or for that matter any shape) from these points ?
I would think that shapeFactory.polygon() would create me a polygon but that throws me an UnsupportedOperationException. Any help ?
Alright, it seems that Spatial4j does not connect the points, so it is not a filled shape. Instead I relied on the Spatial4j implementation of JTS and that did the trick. (Spatial4j's polygon is not implemented).
JtsSpatialContextFactory jtsSpatialContextFactory = new JtsSpatialContextFactory();
JtsSpatialContext jtsSpatialContext = jtsSpatialContextFactory.newSpatialContext();
JtsShapeFactory jtsShapeFactory = jtsSpatialContext.getShapeFactory();
ShapeFactory.PolygonBuilder polygonBuilder = jtsShapeFactory.polygon();
// note due to it being a builder one needs to chain the points.
Shape shape1 = polygonBuilder.pointXY(4, 0).pointXY(3, 3).pointXY(1, 4).pointXY(0, 0).pointXY(4, 0).build();
Now doing for example shape.getArea() returns the surface area.
One can also create a Geometry from a Shape by doing jtsShapeFactory.getGeometryFrom(shape), which then returns a Geometry.
Note: Watch out with doing polygonBuilder.pointXY() even after calling build(). It will still append these points to whatever was chained to the builder before the build.
I am currently using OpenCV to create a system which detects whether vehicles are in certain zones. So far, I've got to the point where a Rect is drawn around each vehicle. My next step is to find the central points of these rectangles and see whether that falls within a particular zone.
I realise that the best way of doing this is probably to find the coordinates of the Rect's four corners and then take an average x and average y-coordinate to find the coordinates for the central point. However, I'm not sure how to do this. Is there some function which lets me access OpenCV's Rect coordinates directly?
Edit to original: As was pointed out, we cannot use '+' operator directly on tl() and br().
Use this instead to get the center of a rectangle:
Point p1 = new Point(100, 100);
Point p2 = new Point(600, 800);
Rect myrect = new Rect(p1, p2);
System.out.println(String.format("Rectangle: %s", myrect));
Point centroid = new Point(myrect.x + 0.5*(myrect.width), myrect.y + 0.5*(myrect.height));
System.out.println(String.format("centroid: %s", centroid));
This prints:
Rectangle: {100, 100, 500x700}
centroid: {350.0, 450.0}
Old answer:
[Use rect's methods:
tl ()
br ()
to get the top left and bottom right points, respectively.]
If you did want to use tl, br methods you can do:
Point anotherCentroid = new Point(0.5 * (myrect.br().x + myrect.tl().x), 0.5 * (myrect.br().y + myrect.tl().y));
I am using the following code to find a point of coordinates exists in the code or not:
mMap.setOnMapClickListener(new OnMapClickListener()
{
public void onMapClick(LatLng point)
{
boolean checkPoly = true;
Point2D[] points = new Point2D[ myPoints.size()];
for ( int i = 0; i < myPoints.size(); i ++)
{
LatLng pt = myPoints.get(i);
points[i] = new Point2D(pt.latitude, pt.longitude);
}
Polygon2D polygon2d = new SimplePolygon2D(points);
double a = point.latitude;
double b = point.longitude;
Point2D myPt = new Point2D(a,b);
checkPoly = polygon2d.contains(myPt);
Log.i("CHECK", String.valueOf(checkPoly));
if (checkPoly)
{
setMarker(point);
}
else
Toast.makeText(NewSearch.this,"The Location is outside of the Area", Toast.LENGTH_LONG).show();
}
I am using the JavaGeom 0.11.1 library for finding polygon point. However this code was working exactly fine. Note that myPoints array is an ArrayList<LatLng> of all vertices of the polygons drawn on map. However something happened and now it's working for opposite that is outside of map; if i change !checkPoly then it works fine.
Does anyone know what is wrong?
I looked at the source for the polygon boundary definition. It's using the usual convention for "inside," which requires the vertices to be given in CCW order around the "inside" space. It's likely your boundary is given in CW order, which makes the "inside" what most people would call the outside.
In other words, what you think is a polygon is really a hole in the infinite polygon that covers the whole x-y universe.
So reverse the order of boundary vertices and things should start working as you intend.
ADDITION
If you can't reverse the order of vertices, there is a different polygon membership test that doesn't rely on point order. If you are testing membership of the point (x,y), this algorithm assumes that the point (infinity, y) is outside the polygon and then decides whether (x,y) is on the opposide side. The implementation here in C is due to WR Franklin. It would be easy to port this to Java. I've used it several times with excellent results.
I have been using Google android-maps-utils library and you can make use of the PolyUtil class, particularly at this method:
public static boolean containsLocation(LatLng point, List<LatLng> polygon, boolean geodesic)