I have drawn a polygon on google map(with certain lats and lngs) now I would like to grow the outer of this polygon by 40 meters(input from users). How can I achieve this? Thank you
Thank you #geocodezip, I tried buffering polygon data(without using center point of polygon) and got this
distance between black and red lines seems not same.
Thanks for all replies && answers! I found a way to do that without buffering polygon/polylines data. Should have a better way to do this. But I would like to share what I have done in here:
I know two gps points: A and B so I could get bearing between those two points.
Based on this bearing I could get the bearing between A and the point(C) 40 meters away from A because line between A and C is 90 degrees against the line between A and B
With the new bearing and distance(40m) I could get the gps point of C (How to calculate the latlng of a point a certain distance away from another?)
finally do step from 1~3 again with point from B to A
Here is a screenshot of what I have done (I have not finish yet, will upload a final screenshot later.)
Draw lines parallel to the existing ones 40 meters (or whatever the desired buffer is) to either side.
Remove the ones that have either endpoint inside the polygon
Extend the new lines and find their intersections
The intersections define the new "bigger" polygon.
Finally got this problem solved, not perfect I know.XD
Implement lines intersection: from here ( [http://jsfiddle.net/justin_c_rounds/Gd2S2/])
Related
I have a scenario in my JavaScript application where I have the coordinates of a starting point which consist of Latitude and Longitude, similarly an ending point with it's respective coordinates.
Now I need to search for a location which basically provides with a set of coordinates and find if the recently entered location lies in between the previously mentioned starting point or ending point. However, the location does not need to match exactly within the points of the path of the start and end point. That is even if the location lies around the distance of say 2-3 km from the derived path, it should give a match.
I believe that we can create a triangle by providing three coordinates i.e start-point, end-point and a third point. So once the triangle is formed we can use google.maps.geometry.poly.containsLocation method to find if our searched location is present inside this triangle.
So my question is how can we get a third point to create a triangle which will provide locations that are nearby within 2-3 km from start to end point.
Else is there any alternate approach to deal with my use case?
Use googlemap's geometry library
This function specifically
isLocationOnEdge
Here's an example
0.001 tolerance value would be 100m
var isLocationNear = google.maps.geometry.poly.isLocationOnEdge(
yourLatLng,
new google.maps.Polyline({
path: [
new google.maps.LatLng(point1Lat, point1Long),
new google.maps.LatLng(point2Lat, point2Long),
]
}),
.00001);
Please note that the following answer assumes Plane Geometry where you should be using Spherical Geometry instead. Although this will be fine for less accurate purposes (like approximate distance, etc..)
It seems more of a geometry question than a programming question. A triangle like you mentioned won't be able to cover a straight line path in a uniform way. The situation can be thought of more like a distance between point and a line problem (Refer the given diagram
Here you can just find the distance between point C and line AB which you can check whether it's below 2.5 KMs (I've omitted all the units and conversions for simplicity)
Please note that you will also need to convert the distances from radian to appropriate units that you require using haversine formula, etc. which is not a trivial task (https://www.movable-type.co.uk/scripts/latlong.html).
I am trying to find the closest distance from a point to large, complex Mesh along a plane in a direction range:
for (var zDown in verticalDistances) {
var myIntersect = {};
for (var theta = Math.PI / 2 - 0.5; theta < Math.PI / 2 + 0.5; theta += 0.3) {
var rayDirection = new THREE.Vector3(
Math.cos(theta),
Math.sin(theta),
0
).transformDirection(object.matrixWorld);
// console.log(rayDirection);
_raycaster.set(verticalDistances[zDown].minFacePoint, rayDirection, 0, 50);
// console.time('raycast: ');
var intersect = _raycaster.intersectObject(planeBufferMesh);
// console.timeEnd('raycast: '); // this is huge!!! ~ 2,300 ms
// console.log(_raycaster);
// console.log(intersect);
if (intersect.length == 0) continue;
if ((!('distance' in myIntersect)) || myIntersect.distance > intersect[0].distance) {
myIntersect.distance = intersect[0].distance;
myIntersect.point = intersect[0].point.clone();
}
}
// do stuff
}
I get great results with mouse hover on the same surface but when performing this loop the raycasting is taking over 2 seconds per cast. The only thing i can think of is that the BackSide of the DoubleSide Material is a ton slower?
Also i notice as I space out my verticalDistances[zDown].minFacePoint to be farther apart raycast starts to speed up up (500ms /cast). So as the distance between verticalDistances[i].minFacePoint and verticalDistances[i+1].minFacePoint increases, the raycaster performs faster.
I would go the route of using octree but the mouse hover event works extremely well on the exact same planeBuffer. Is this a side of Material issue,. that could be solved by loading 2 FrontSide meshes pointing in opposite directions?
Thank You!!!!
EDIT: it is not a front back issue. I ran my raycast down the front and back side of the plane buffer geometry with the same spot result. Live example coming.
EDIT 2: working example here. Performance is little better than Original case but still too slow. I need to move the cylinder in real time. I can optimize a bit by finding certain things, but mouse hover is instant. When you look at the console time the first two(500ms) are the results i am getting for all results.
EDIT 3: added a mouse hover event, that performs the same as the other raycasters. I am not getting results in my working code that i get in this sample though. The results I get for all raycast are the same as i get for the first 1 or 2 in the sample around 500ms. If i could get it down to 200ms i can target the items i am looking for and do way less raycasting. I am completely open to suggestions on better methods. Is octree the way to go?
raycast: : 467.27001953125ms
raycast: : 443.830810546875ms
EDIT 4: #pailhead Here is my plan.
1. find closest grid vertex to point on the plane. I can do a scan of vertex in x/y direction then calculate the min distance.
2. once i have that closest vertex i know that my closest point has to be on a face containing that vertex. So i will find all faces with that vertex using the object.mesh.index.array and calculate the plane to point of each face. Seems like a ray cast should be a little bit smarter than a full scan when intersecting a mesh and at least cull points based on max distance? #WestLangley any suggestions?
EDIT 5:
#pailhead thank you for the help. Its appreciated. I have really simplified my example(<200 lines with tons more comments); Is raycaster checking every face? Much quicker to pick out the faces within the set raycasting range specified in the constructor and do a face to point calc. There is no way this should be looping over every face to raycast. I'm going to write my own PlaneBufferGeometry raycast function tonight, after taking a peak at the source code and checking octree. I would think if we have a range in the raycaster constructor, pull out plane buffer vertices within that range ignoring z. Then just raycast those or do a point to plane calculation. I guess i could just create a "mini" surface from that bounding circle and then raycast against it. But the fact that the max distance(manual uses "far") doesn't effect the speed of the raycaster makes me wonder how much it is optimized for planeBuffer geometries. FYI your 300k loop is ~3ms on jsfiddle.
EDIT 6: Looks like all meshes are treated the same in the raycast function. That means it wont smart hunt out the area for a plane Buffer Geometry. Looking at mesh.js lines 266 we loop over the entire index array. I guess for a regular mesh you dont know what faces are where because its a TIN, but a planeBuffer could really use a bounding box/sphere rule, because your x/y are known order positions and only the Z are unknown. Last edit, Answer will be next
FYI: for max speed, you could use math. There is no need to use ray casting. https://brilliant.org/wiki/3d-coordinate-geometry-equation-of-a-plane/
The biggest issue resolved is filtering out faces of planeBufferGeometry based on vertex index. With a planeBufferGeometry you can find a bounding sphere or rectangle that will give you the faces you need to check. they are ordered in x/y in the index array so that filters out many of the faces. I did an indexOf the bottom left position and lastIndexOf the top right corner position in the index array. RAYCASTING CHECKS EVERY FACE
I also gave up on finding the distance from each face of the object and instead used vertical path down the center of the object. This decreased the ray castings needed.
Lastly I did my own face walk through and used the traingle.closestPointToPoint() function on each face.
Ended up getting around 10ms per point to surface calculation(single raycast) and around 100 ms per object (10 vertical slices) to surface. I was seeing 2.5 seconds per raycast and 25+ seconds per object prior to optimization.
My goal is to calculate the distance between two Cesium entities in kilometers. As a bonus, I eventually want to be able to measure their distance in pixels.
I have a bunch of placemarks in KML format like this:
<Placemark>
<name>Place</name>
<Point><coordinates>48.655,-31.175</coordinates></Point>
<styleUrl>#style</styleUrl>
<ExtendedData>
...
</ExtendedData>
</Placemark>
I am importing them into Cesium like so:
viewer.dataSources.add(Cesium.KmlDataSource.load('./data.kml', options)).then(function(dataSource) {
var entities = dataSource.entities._entities._array;
I have attempted to create new Cartesian3 objects of entities I care about, but the x, y, and z values I get from the entity object are in the hundreds of thousands. The latitude and longitude from my KML are nowhere to be found in the entity objects.
If I do create Cartesian3 objects and compute the distance like so:
var distance = Cesium.Cartesian3.distance(firstPoint, secondPoint);
it returns numbers in the millions. I have evaluated the distance between multiple points this way and when I compare those values returned to the result of an online calculator which returns the actual value in kilometers, the differences in the distances are not linear (some of the distances returned by Cesium are 900 times the actual distance and some are 700 times the actual distance).
I hope that is enough to receive help. I am not sure where to start fixing this. Any help would be appreciated. Thank you.
A couple of things are going on here. The Cesium.Cartesian3 class holds meters, so it is correct to divide by 1000 to get km, but that's not the full story. Cartesian3s are positions on a 3D globe, and if you compute a simple Cartesian.distance between two of them on opposite sides of that globe, you'll get the Cartesian linear distance, as in the length of a line that cuts through the middle of the globe to get from one to the other, rather than traveling around the surface of the globe to get to the far side.
To get the distance you actually want -- the distance of a line that follows the curvature of the surface of the Earth -- check out the answer to Cesium JS Line Length on GIS SE.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Trilateration using 3 latitude and longitude points, and 3 distances
This is more of a math question than programming question. Basically, I have P1:(lat1, lon1), P2:(lat2, lon2), P3:(lat3, lon3) and D1, D2, D3, and a 4th unknown point Px:(latx, lonx); also P1, P2, P3 do not lie in the same path of Great Circle, and D1 is the distance between P1 and Px, and D2 is the distance betwwen P2 and Px, etc.
How do I figure out the coordinates of Px?
=edited based on reply=
Thanks a lot!
PS. If you are going to point to any API, I would like it to be in JavaScript.
You have to understand that there will be multiple points that satisfy the mathematical constraint here. Think clearly, if you have two points on a sphere (ignore the geodesic form for now), P1 and P2, and you have another point T1, at distance x from P1 and distance y from P2, then you will have another symmetric (mirrored) point T1' which will satisfy the same distance conditions, on the other side, so to speak.
Even worse: Consider the case of a sphere with a diameter D. Your P1 is at the North Pole, and your P2 is at the South pole. Do you see that the all points on the equator will satisfy your condition?
Apply this to your example: Consider P1 at the North Pole. Consider P2 at the South Pole. Consider distance to Px, i.e. D1 = D2 = (2.pie.r)/4. See the problem? All points on the equator satisfy this, not a single unique point. In fact, for this case, even if D1 != D2, then you have smaller concentric lines (concentric to the equator) whose points satisfy these constraints.
Too many Px's in your case, not one. To come to a singularity point on a spherical surface, the description constraints would be more specific.
Lastly, establishing correctness of the context is important. Should your algorithm support all points that meet the criteria? Or should your criteria be altered such that the algorithm evaluates to a singular point, always. Be careful.
Some links to help you:
Wikipedia: http://en.wikipedia.org/wiki/Spherical_coordinates
SO: Plotting a point on the edge of a sphere
Updates, based on your three point example:
Again, there can be multiple points satisfying your criteria. What if P1, P2, P3 lie on the same arc? See the diagram below. Even with three points, there is no guarantee that there will be a single fourth point satisfying the distance criteria. Even with n points, there is no such guarantee.
In mathematical language, for a set of n random points, and a set of distances from these individual points, the set of resulting points that satisfy the distance criteria MAY have more than one elements.
You may be fooled into thinking: Oh, this guy is always assuming points lying on the same arc. Well, you are not making a special algorithm, are you? Your algo will be a generalized solution, won't it?
You need to guarantee that the points are not on the same arc (in a set of n points, I think at least 1 point cannot be on the same arc).
For keeping source points to a bare minimum : You need to establish traingular relations between points, because then, using ONLY two points, the triangle relation will yield exactly one point.
What triangle? Visualize this: You have two points, and a third unknown point. All distance you mention are SPHERICAL, i.e. curved surface distances. Do you see that there are also flat distances between these points? Can you visualize, that there will be a plane passing through these points, slicing the sphere, right? I say this to emphasize that you do not need to worry about surface curvature (hence 3d steradian angles). You can see the underlying 2d triangle, whose unknown vertex will also be the third point on the sphere surface.
I know this maybe very hard for you to visualize, I'll try making a diagram for this. (Can't find any good online tools!).
Lastly, this will be of significant help: Please read carefully.
Taken from Wikipedia: http://en.wikipedia.org/wiki/Great-circle_distance
The great-circle or orthodromic distance is the shortest distance between any two points on the surface of a sphere measured along a path on the surface of the sphere (as opposed to going through the sphere's interior). Because spherical geometry is different from ordinary Euclidean geometry, the equations for distance take on a different form. The distance between two points in Euclidean space is the length of a straight line from one point to the other. On the sphere, however, there are no straight lines. In non-Euclidean geometry, straight lines are replaced with geodesics. Geodesics on the sphere are the great circles (circles on the sphere whose centers are coincident with the center of the sphere).
Some more updates:
Conversion between long, lats to Cartesian coordinates can be done by the Haversine formula. Google it. See here: Converting from longitude\latitude to Cartesian coordinates
and here: http://en.wikipedia.org/wiki/World_Geodetic_System
I'm trying to do a Tiny Wings like in javascript.
I first saw a technique using Box2D, I'm using the closure-web version (because of the memory leaks fix).
In short, I explode the curve into polygons so it looks like that:
I also tried with Chipmunk-js and I use the segment shape to simulate my ground like that:
In both cases, I'm experiencing some "crashes" or "bumps" at the common points between polygons or segments when a circle is rolling.
I asked about it for Chipmunk and the author said he implemented a radius property for the segment to reduce this behavior. I tried and it indeed did the trick but it's not perfect. I still have some bumps(I had to set to 30px of radius to get a positive effect).
The "bumps" append at the shared points between two polygons :
Using, as illandril suggested to me, the edging technique (he only tested with polygon-polygon contact) to avoid the circle to crash on an edge:
Also tried to add the bullet option as Luc suggested and nothing seems to change.
Here the demo of the issue.
You can try to change the value to check :
bullet option
edge size
iterations count
the physics
(only tested on latest dev Chrome)
Be patient (or change the horizontal gravity) and you'll see what I mean.
Here the repo for the interested.
The best solution is edge shapes with ghost vertices, but if that's not available in the version/port you're using, the next best thing is like the diagram in your question called 'edging', but extend the polygons further underground with a very shallow slope, like in this thread: http://www.box2d.org/forum/viewtopic.php?f=8&t=7917
I first thought the problem could come from the change of slope between two adjacent segments, but since on a flat surface of polygons you still have bumps I think the problem is rather hitting the corner of a polygon.
I don't know if you can set two sets of polygons, overlapping each other ? Just use the same interpolation calculations and generate a second set of polygons just like in the diagram hereafter : you have the red set of polygons built and add the green set by setting the left vertices of a green polygon in the middle of a red polygon, and its right vertices in the middle of the next red polygon.
![diagram][1]
This should work on concave curves and... well you should be flying over the convex ones anyway.
If this doesn't work try setting a big number of polygons to build the slope. Use a tenth of the circle's radius for the polygon's width, maybe even less. That should reduce your slope discontinuities.
-- Edit
In Box2D.js line 5082 (in this repo at least) you have the PreSolve(contact, manifold) function that you can override to check if the manifolds (directions in which the snowball are impulsed when colliding the polygons) are correct.
To do so, you would need to recover the manifold vector and compare it to the normal of the curve. It should look like that (maybe not exactly) :
Box2D.Dynamics.b2ContactListener.prototype.PreSolve = function (contact, oldManifold) {
// contact instanceof Box2D.Dynamics.Contacts.b2Contact == true
var localManifold, worldManifold, xA, xB, man_vect, curve_vect, normal_vect, angle;
localManifold = contact.GetManifold();
if(localManifold.m_pointCount == 0)
return; // or raise an exception
worldManifold = new Box2D.Collision.b2WorldManifold();
contact.GetWorldManifold( worldManifold );
// deduce the impulse direction from the manifold points
man_vect = worldManifold.m_normal.Copy();
// we need two points close to & surrounding the collision to compute the normal vector
// not sure this is the right order of magnitude
xA = worldManifold.m_points[0].x - 0.1;
xB = worldManifold.m_points[0].x + 0.1;
man_vect.Normalize();
// now we have the abscissas let's get the ordinate of these points on the curve
// the subtraction of these two points will give us a vector parallel to the curve
var SmoothConfig;
SmoothConfig = {
params: {
method: 'cubic',
clip: 'mirror',
cubicTension: 0,
deepValidation: false
},
options: {
averageLineLength: .5
}
}
// get the points, smooth and smooth config stuff here
smooth = Smooth(global_points,SmoothConfig);
curve_vect = new Box2D.Common.Math.b2Vec2(xB, smooth(xB)[1]);
curve_vect.Subtract(new Box2D.Common.Math.b2Vec2(xA, smooth(xA)[1]));
// now turn it to have a normal vector, turned upwards
normal_vect = new Box2D.Common.Math.b2Vec2(-curve_vect.y, curve_vect.x);
if(normal_vect.y > 0)
normal_vect.NegativeSelf();
normal_vect.Normalize();
worldManifold.m_normal = normal_vect.Copy();
// and finally compute the angle between the two vectors
angle = Box2D.Common.Math.b2Math.Dot(man_vect, normal_vect);
$('#angle').text("" + Math.round(Math.acos(angle)*36000/Math.PI)/100 + "°");
// here try to raise an exception if the angle is too big (maybe after a few ms)
// with different thresholds on the angle value to see if the bumps correspond
// to a manifold that's not normal enough to your curve
};
I'd say the problem has been tackled in Box2D 2.2.0 , see its manual, section 4.5 "Edge Shapes"
The thing is it's a feature of the 2.2.0 version, along with the chainshape thing, and the box2dweb is actually ported from 2.2.1a - don't know about box2dweb-closure.
Anything I've tried by modifying Box2D.Collision.b2Collision.CollidePolygonAndCircle has resulted in erratic behaviour. At least a part of the time (e.g. ball bumping in random directions, but only when it rolls slowly).