Move polygon points based on center location? - turfjs

Would someone have an example using Turf moving all polygon points from one location to another based on a new center point?
For example, let’s say I have calculated a center based on where the points were originally created.
Then I need to move those points to a new location based on that calculated center.
As always any help would be great!

You need to use transformTranslate
var poly = turf.polygon([[[0,29], [3.5,29], [2.5,32], [0,29]]]);
//calculates the centroid of the polygon
var center = turf.centroid(poly);
var from = turf.point([center.geometry.coordinates[0], center.geometry.coordinates[1]]);
var to = turf.point([4, 35]);
//finds the bearing angle between the points
var bearing = turf.rhumbBearing(from, to);
//calculates the distance between the points
var distance = turf.rhumbDistance(from, to);
//moves the polygon to the distance on the direction angle.
var translatedPoly = turf.transformTranslate(poly, distance, bearing)

Related

Generating country-shaped geometry on the surface of a sphere in Godot

I am currently working on a game in Godot which involves rendering countries on a globe. I have very little prior experience with Godot, but have experimented with it in the past.
I am using this data from Natural Earth for country borders, and have successfully gotten it to display on the globe using a line mesh. The data was originally in shapefile format, but I converted it to GeoJSON using mapshaper.org.
Picture
The data basically boils down to a list of points given in latitude and longitude, which I then converted into 3d points and created a mesh using SurfaceTool.
I am having trouble generating an actual surface for the mesh, however. Firstly, I am unable to find a built-in function to generate a triangle mesh from this data. I have looked into numerous solutions, including using the built-in Mesh.PRIMITIVE_TRIANGLE_FAN format, which doesn't work on concave shapes.
I have looked into triangulation algorithms such as delaunay triangulation, but have had little success implementing them.
My current plan is to generate a triangle mesh using the 2d data (x,y = longitude,latitude), and project it onto the surface of the sphere. In order to produce a curved surface, I will include the vertices of the sphere itself in the mesh (example).
I would like to know how to go about constructing a triangle mesh from this data. In essence, I need an algorithm that can do the following things:
Create a triangle mesh from a concave polygon (country border)
Connect the mesh to a series of points within this polygon
Allow for holes within the polygon (for lakes, etc.)
Here is an example of the result I am looking for.
Again, I am quite new to Godot and I am probably over-complicating things. If there is an easier way to go about rendering countries on a globe, please let me know.
This is my current code:
extends Node
export var radius = 1
export var path = "res://data/countries.json"
func coords(uv):
return (uv - Vector2(0.5, 0.5)) * 360
func uv(coords):
return (coords / 360) + Vector2(0.5, 0.5)
func sphere(coords, r):
var angles = coords / 180 * 3.14159
return Vector3(
r * cos(angles.y) * sin(angles.x),
r * sin(angles.y),
r * cos(angles.y) * cos(angles.x)
)
func generate_mesh(c):
var mesh = MeshInstance.new()
var material = SpatialMaterial.new()
material.albedo_color = Color(randf(), randf(), randf(), 1.0)
var st = SurfaceTool.new()
st.begin(Mesh.PRIMITIVE_LINE_STRIP)
for h in c:
var k = sphere(h, radius)
st.add_normal(k / radius)
st.add_uv(uv(h))
st.add_vertex(k)
st.index()
mesh.mesh = st.commit()
mesh.set_material_override(material)
return mesh
func load_data():
var file = File.new()
file.open(path, file.READ)
var data = JSON.parse(file.get_as_text()).result
file.close()
for feature in data.features:
var geometry = feature.geometry
var properties = feature.properties
if geometry.type == "Polygon":
for body in geometry.coordinates:
var coordinates = []
for coordinate in body:
coordinates.append(Vector2(coordinate[0], coordinate[1]))
add_child(generate_mesh(coordinates))
if geometry.type == "MultiPolygon":
for polygon in geometry.coordinates:
for body in polygon:
var coordinates = []
for coordinate in body:
coordinates.append(Vector2(coordinate[0], coordinate[1]))
add_child(generate_mesh(coordinates))
func _ready():
load_data()
What about using Geometry.triangulate_polygon() method to triangulate a polygon:

How to move camera around object to look at object from all sides?

How can a cesium camera be moved around an object in circular path?
Assuming you want something similar to helicopter circles... It can be done by 'lookAt' at every clock tick.
let heading = 0; //or any starting angle in radians
let rotation = -1; //counter-clockwise; +1 would be clockwise
let centre = new Cesium.Cartesian3.fromDegrees(longitude, latitude);
let elevation = 100; // 100 meters
let pitch = -0.7854; //looking down at 45 degrees
const SMOOTHNESS = 600; //it would make one full circle in roughly 600 frames
viewer.clock.onTick.addEventListener(() => {
heading += rotation * Math.PI / SMOOTHNESS;
viewer.camera.lookAt(centre, new Cesium.HeadingPitchRange(heading, pitch, elevation));
});

Explain code in Kinect SDK

I am working with Kinect and reading example from DepthWithColor-D3D, has some code but i don't understand yet.
// loop over each row and column of the color
for (LONG y = 0; y < m_colorHeight; ++y)
{
LONG* pDest = (LONG*)((BYTE*)msT.pData + msT.RowPitch * y);
for (LONG x = 0; x < m_colorWidth; ++x)
{
// calculate index into depth array
int depthIndex = x/m_colorToDepthDivisor + y/m_colorToDepthDivisor * m_depthWidth;
// retrieve the depth to color mapping for the current depth pixel
LONG colorInDepthX = m_colorCoordinates[depthIndex * 2];
LONG colorInDepthY = m_colorCoordinates[depthIndex * 2 + 1];
How to calculate the value of colorInDepthX and colorInDepthY as above code?
colorInDepthX and colorInDepthY is a mapping between the depth and color images so that they will align. Because the Kinect's cameras are slightly offset from each other their field of views are not lined up perfectly.
m_colorCoordinates is defined at the top of the file as such:
m_colorCoordinates = new LONG[m_depthWidth*m_depthHeight*2];
This is a single dimension array representing a 2-dimensional image, it is populated just above the code block you post in your question:
// Get of x, y coordinates for color in depth space
// This will allow us to later compensate for the differences in location, angle, etc between the depth and color cameras
m_pNuiSensor->NuiImageGetColorPixelCoordinateFrameFromDepthPixelFrameAtResolution(
cColorResolution,
cDepthResolution,
m_depthWidth*m_depthHeight,
m_depthD16,
m_depthWidth*m_depthHeight*2,
m_colorCoordinates
);
As described in the comment, this is running an calculation provided by the SDK to map the color and depth coordinates onto each other. The result is placed inside of m_colorCoordinates.
colorInDepthX and colorInDepthY are simply values within the m_colorCoordinates array that are being acted upon in the current cycle of the loop. They are not "calculated", per se, but just point to what already exists in m_colorCoordinates.
The function that handles the mapping between color and depth images is explained in the Kinect SDK at MSDN. Here is a direct link:
http://msdn.microsoft.com/en-us/library/jj663856.aspx

Android Location.distanceTo

I wrote a function to determine the distance between two GPS locations.
public float latDistance(Location newLocal){
// get distance
Location tempLocal1 = new Location("ref1");
Location tempLocal2 = new Location("ref2");
// get lon difference
tempLocal1.setLatitude(local.getLatitude());
tempLocal1.setLongitude(0);
tempLocal1.setAltitude(0);
tempLocal2.setLatitude(newLocal.getLatitude());
tempLocal2.setLongitude(0);
tempLocal2.setAltitude(0);
return tempLocal2.distanceTo(tempLocal1);
}
My question is, will this ever return a negative value? my goal is to get a distance that reflects whether they moved north or south.. so if they move south from the starting location i want a negative value, and if north a positive?
It seems that i am always getting a positive number, but i can't tell if that is just my innaccurate gps readings
EDIT:
my code now looks like this.. and i know it irregular to ask people to comment on the logic, but its a difficult thing to test as it relies on a gps signal and to test i have to basically go out side and get a good signal, which pulls me away from my IDE and LogCat..
public float getLattitudeDistance(Location newLocal){
// get distance
Location tempLocal1 = new Location("ref1");
Location tempLocal2 = new Location("ref2");
// get lon difference
tempLocal1.setLatitude(local.getLatitude());
tempLocal1.setLongitude(0);
tempLocal1.setAltitude(0);
tempLocal2.setLatitude(newLocal.getLatitude());
tempLocal2.setLongitude(0);
tempLocal2.setAltitude(0);
if(local.getLatitude()>newLocal.getLatitude()){
return -tempLocal2.distanceTo(tempLocal1);
}else{
return tempLocal2.distanceTo(tempLocal1);
}
}
public float getLongitudeDistance(Location newLocal){
// get distance
Location tempLocal1 = new Location("ref1");
Location tempLocal2 = new Location("ref2");
// get lon difference
tempLocal1.setLatitude(0);
tempLocal1.setLongitude(local.getLongitude());
tempLocal1.setAltitude(0);
tempLocal2.setLatitude(0);
tempLocal2.setLongitude(newLocal.getLongitude());
tempLocal2.setAltitude(0);
if(local.getLongitude()>newLocal.getLongitude()){
return -tempLocal2.distanceTo(tempLocal1);
}else{
return tempLocal2.distanceTo(tempLocal1);
}
}
does that seem right?
No, distances are never negative!
For south movement you may extend your code :
float distance = tempLocal2.distanceTo(tempLocal1);
// lat1: previous latitude
// lat2: current latitude
if (lat2 < lat1) {
// movement = south
distance = -distance:
} else {
// movement = north or parallel aeqator or not moving
}
return distance
Although i reccomend to separate distance and South Movement (in future maybe you would like to detect an East-West movement, too)

Polygon from collection of Latitudes & Longitudes

I have a collection of latitudes and longitudes and I'll be grabbing sets of these and want to draw a polygon based on them.
The datasets won't be the outline so will need an algorithm to establish which ones make up the outline of a polygon containing all the latitudes and longitudes supplied. This polygon needs to be flexible so the polygon can be concave if the points dictate that.
Any help would be appreciated.
** UPDATE **
Sorry, should have put more detail.
My code below produces a horrible looking polygon. As explain in my first post I want to create a nice concave or convex polygon based on the latlng's provided.
Just need a way of plotting the outer latlngs.
Apologies if this is still asking too much but thought it was worth one last try.
function initialize() {
var myLatLng = new google.maps.LatLng(51.407431, -0.727142);
var myOptions = {
zoom: 12,
center: myLatLng,
mapTypeId: google.maps.MapTypeId.TERRAIN
};
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var bermudaTriangle;
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var triangleCoords = [
new google.maps.LatLng(51.392692, -0.740358),
new google.maps.LatLng(51.400618, -0.742469),
new google.maps.LatLng(51.40072, -0.72418),
new google.maps.LatLng(51.400732, -0.743817),
new google.maps.LatLng(51.401258, -0.743386),
new google.maps.LatLng(51.401264, -0.741445),
new google.maps.LatLng(51.401443, -0.725555),
new google.maps.LatLng(51.401463, -0.744042),
new google.maps.LatLng(51.402281, -0.739059)
];
var minX = triangleCoords[0].lat();
var maxX = triangleCoords[0].lat();
var minY = triangleCoords[0].lng();
var maxY = triangleCoords[0].lng();
for (var i = 1; i < triangleCoords.length; i++) {
if (triangleCoords[i].lat() < minX) minX = triangleCoords[i].lat();
if (triangleCoords[i].lat() > maxX) maxX = triangleCoords[i].lat();
if (triangleCoords[i].lng() < minY) minY = triangleCoords[i].lng();
if (triangleCoords[i].lng() > maxY) maxY = triangleCoords[i].lng();
}
// Construct the polygon
bermudaTriangle = new google.maps.Polygon({
paths: triangleCoords,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35
});
bermudaTriangle.setMap(map);
}
Your problem is not enough defined : with a given set of points, you may end up with many different polygons if you do not add a constraint other than 'create a nice concave or convex polygon'.
And even a simple example shows that :
imagine a triangle ABC, and let D be the center of this triangle, what output will you expect for {A,B,C,D} set of points ?
ABC, since D is inside ?
or ADBCA polygon ?
or ABDCA polygon ?
or ABCDA polygon ?
now if you say 'well D is in the center, it's obvious we should discard D', let D be closer and closer from, say, the AB segment. When do you decide the best output is ABC or ADBCA ?
So you have to add constraints to be able to build an algorithm, since if you cannot not decide by yourself for the above {A,B,C,D} example, how could a computer do ? :-) For example if you call AvgD the average distance beetween points, you could add the constraint that no segment of your outer polygon should be longer than 1.2*AvgD (or, better, Alpha*AvgD, and you try your algorithm with different alpha).
To solve your issue, i would use first a classical hull algorithm to get the outer convex polygon (which is deterministic), then break down the segments that are 'too' long (with the constraint(s) you want) putting more and more inner points into the outlining until all constraints are ok. Something like 'digging holes' into the convex polygon.
'Breaking down' a too long segment is also a thing you can do in quite different maners. One may be to search for the nearest not-in-the-outline point from the middle point of the segment. Another would be to choose the point having lowest radius with current segment... Now that you have your new point, break the segment in two, update your list of too-loong segment, and do it again until you're done (or until you reach a 'satisfactory' average length for too long segments, or ...)
Good luck !