I set the coordinates of some entities to fixed positions, of course, according to the values I specified, but the displayed positions are chaotic and deformed. It seems that the entities will be automatically offset by some pixels. If the entities are manually placed in the canvas, they will not be offset. Move, why?
double startX = point.getX();
double startY = point.getY();
double x = startX;
double y = startY;
if(shipid%10==1 || shipid%10==6)
x = startX;
if(shipid%10==2 || shipid%10==7)
x = startX+120;
if(shipid%10==3 || shipid%10==8)
x = startX+210;
if(shipid%10==4 || shipid%10==9)
x = startX+300;
if(shipid%10==5 || shipid%10==0)
x = startX+390;
if(shipid%10>=6 || shipid%10 ==0)
y = startY+65;
Xy xy = new Xy();
xy.x = x;
xy.y = y;
traceln(shipid+"..."+x+"..."+y);
return xy;
Related
I am creating a simple navigation application using GoogleMap.
When the user set the start location and destination location I am drawing the path using polylines.
If the user deviate from the path, I want to redraw the path based on current user location.
Problem I have is how to detect user is not in the current route?
I am using
https://maps.googleapis.com/maps/api/directions/json?
to get the directions.
Is there a function in that to detect whether user is outside the route?
I also have the list of coordinates used to draw the poly lines.
Can they be used to detect user moved outside the current route ?
Based on an example I found in web, I created this method. The example is not designed to for the map coordinates.
Function for finding the distance between a point and an edge in java
Is there a better way of doing this?
static double perpendicularDistance(LatLng point, LatLng start, LatLng end) {
double x = point.longitude;
double y = point.latitude;
double x1 = start.longitude;
double y1 = start.latitude;
double x2 = end.longitude;
double y2 = end.latitude;
double A = x - x1;
double B = y - y1;
double C = x2 - x1;
double D = y2 - y1;
double dot = A * C + B * D;
double len_sq = C * C + D * D;
double param = -1;
if (len_sq != 0) //in case of 0 length line
param = dot / len_sq;
double xx, yy;
if (param < 0) {
xx = x1;
yy = y1;
} else if (param > 1) {
xx = x2;
yy = y2;
} else {
xx = x1 + param * C;
yy = y1 + param * D;
}
var dx = x - xx;
var dy = y - yy;
// one degree is equivalent to 111km approximately
return (sqrt(dx * dx + dy * dy)).abs() * 111000;
}
May be you need to get coordinates of user everytime he/she walks, and check if that coordinates lies in the list of coordinates which you have.
You can get location using https://pub.dev/packages/location.
These is just a thought, I can be wrong.
You can use this package
https://pub.dev/packages/google_maps_utils
with this method to check if you are not near of your route:
/// Computes whether the given point lies on or near a polyline, within a specified
/// tolerance in meters. The polyline is composed of great circle segments if geodesic
/// is true, and of Rhumb segments otherwise. The polyline is not closed -- the closing
/// segment between the first point and the last point is not included.
static bool isLocationOnPathTolerance(Point point, List<Point> polyline,
bool geodesic, double tolerance
)
Where point is, a class to represent two dimensional positions, for example;
var rightBottom = const Point(200, 400);
As you can see, you can send the tolerance for the distance in meters.
I am making an application in which the user can draw a polygon on a map by points.
I need to somehow make sure that the polygon does not have self-intersections.
I know it is possible to manually check each line.
There are various methods for this.
But I noticed that Google Maps
automatically fills polygons that do not have self-intersections.
Is it possible to get this value from the plugin somehow?
i am using google_maps_flutter
without self-intersection
with self-intersection
Perhaps this will be useful to someone.
I did not find a built-in function in the plugins listed in the question.
So I wrote my own function:
true - there are self-intersections
bool isNotSimplePolygon(List<LatLng> polygon){
if(polygon.length <= 3)
return false;
for(int i = 0; i < polygon.length - 2; i++){
double x1 = polygon[i].latitude;
double y1 = polygon[i].longitude;
double x2 = polygon[i + 1].latitude;
double y2 = polygon[i + 1].longitude;
double maxx1 = max(x1, x2), maxy1 = max(y1, y2);
double minx1 = min(x1, x2), miny1 = min(y1, y2);
for (int j = i + 2; j < polygon.length; j++) {
double x21 = polygon[j].latitude;
double y21 = polygon[j].longitude;
double x22 = polygon[(j + 1) == polygon.length ? 0 : (j + 1)].latitude;
double y22 = polygon[(j + 1) == polygon.length ? 0 : (j + 1)].longitude;
double maxx2 = max(x21, x22), maxy2 = max(y21, y22);
double minx2 = min(x21, x22), miny2 = min(y21, y22);
if ((x1 == x21 && y1 == y21) || (x2 == x22 && y2 == y22) || (x1 == x22 && y1 == y22) || (x2 == x21 && y2 == y21))
continue;
if (minx1 > maxx2 || maxx1 < minx2 || miny1 > maxy2 || maxy1 < miny2)
continue; // The moment when the lines have one common vertex...
double dx1 = x2-x1, dy1 = y2-y1; // The length of the projections of the first line on the x and y axes
double dx2 = x22-x21, dy2 = y22-y21; // The length of the projections of the second line on the x and y axes
double dxx = x1-x21, dyy = y1-y21;
double div = dy2 * dx1 - dx2 * dy1;
double mul1 = dx1 * dyy - dy1 * dxx;
double mul2 = dx2 * dyy - dy2 * dxx;
if (div == 0)
continue; // Lines are parallel...
if (div > 0) {
if (mul1 < 0 || mul1 > div)
continue; // The first segment intersects beyond its boundaries...
if (mul2 < 0 || mul2 > div)
continue; // // The second segment intersects beyond its borders...
}
else{
if (-mul1 < 0 || -mul1 > -div)
continue; // The first segment intersects beyond its boundaries...
if (-mul2 < 0 || -mul2 > -div)
continue; // The second segment intersects beyond its borders...
}
return true;
}
}
return false;
}
When I plot point1(p1) and point2(p2), the line between p1 and p2 is drawn. I wanna know a set of the points making the line.
For example, I wanna get x, y coordinates (as array type: x[], y[]). Is there any algorithms or code?
Here's what I have come up with:
It is fair to say that we need to use the slope formula, y = m*x + b to find the slope so we can plot our points along that line. We need the following:
(x1, y1)
(x2, y2)
to find the following:
m = (y2 - y1) / (x2 - x1)
b = y1 - (m * x1)
minX = min(x1, x2) used for limiting our lower bound
maxX = max(x1, x2) used for limiting our upper bound
Now that everything is set, we can plot our line pixel by pixel and obtain all (x,y) coordinates we need. The logic is simple:
let x loop from minX to maxX and plug it in y = m*x + b (we already have all the variables except y). Then, store the (x,y) pair.
I have used Java for coding this logically and visually. Also, I used LinkedList instead of arrays (because I we can't know the number of points we will obtain).
I have also drawn what Java would draw (in blue) and my approach (in red). They are almost perfectly the exact output and coordinates. The image below is zoomed 5x the original size.
Note! The above explanation is what you would use if the line is not vertical (because the slope would be undefined, division by zero). If it is, then you will plug y (instead of x) values and find the x (instead of y) value from the following formula x = (y - b) / m (instead of y = m*x + b). Though, the code takes care of vertical lines.
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.LinkedList;
import javax.swing.JFrame;
public class LineDrawing extends Canvas {
int x1 = 5;
int y1 = 10;
int x2 = 105;
int y2 = 100;
double m = ((double) (y2 - y1)) / ((double) (x2 - x1));//slope
double b = y1 - (m * ((double) x1));//vertical shift
//Takes care of the domain we will loop between.
//min and max will be assigned minX and maxX if the line is not vertical.
//minY and maxY are assigned to min and max otherwise.
int minX = Math.min(x1, x2);//minimum x value we should consider
int maxX = Math.max(x1, x2);//maximum x value we should consider
int minY = Math.min(y1, y2);//minimum y value we should consider
int maxY = Math.max(y1, y2);//maximum y value we should consider
int min = 0;
int max = 0;
boolean plugX = true;//if true, the line is not vertical.
LinkedList<Point> points = new LinkedList<>();//Store all points here
public LineDrawing() {
if (x1 == x2) {//plug the y value instead the x, this is a vertical line.
plugX = false;
min = minY;
max = maxY;
} else {//dont change and plug x values.
min = minX;
max = maxX;
}
}
#Override
public void paint(Graphics g) {
super.paint(g);
//Draw the line, using default java drawLine in blue.
g.setColor(Color.BLUE);
g.drawLine(x1, y1, x2, y2);
//change the color to red, it will draw our verison.
g.setColor(Color.RED);
//Draw the points, point by point on screen.
//Plug m, x, and b in the formula y = m*x + b
//to obtain the y value.
//OR
//Plug m, y, and b in the formula x = (y - b) / m
//to obtain the x value if vertical line.
//Then plot (x,y) coordinate on screen and add the point to our linkedList.
for (int i = min; i <= max; i++) {
int obtained = 0;
if (plugX) {//not a vertical line
obtained = (int) Math.round((m * i + b));
System.out.println("x = " + i + " , y = " + obtained);
points.add(new Point(i, obtained));
//Uncomment to see the full blue line.
g.drawLine(i, obtained, i, obtained);
} else {//vertical line
obtained = (int) Math.round((double) (i - b) / (double) m);
System.out.println("x = " + x1 + " , y = " + i);
g.drawLine(x1, i, x1, i);//Uncomment to see the full blue line.
points.add(new Point(x1, i));
}
}
//Print out the number of points as well as the coordinates themselves.
System.out.println("Total points: " + points.size());
for (int i = 0; i < points.size(); i++) {
System.out.println(i + " ( " + points.get(i).x
+ ", " + points.get(i).y + " )");
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(120, 150);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new LineDrawing());
frame.setVisible(true);
}
}
I need to get the four edges of the bounding rectangle of a set of 3D points stored as a 3xN matrix (tt). N >=4. The points lies on a plane.
Code sample:
% Simulate some points
deltaXY = 20;
[xx,yy] = meshgrid(-100:deltaXY:100,-100:deltaXY:100);
XYZ = [xx(:)'; yy(:)'; zeros(1,numel(xx))];
% Add some imperfection to data removing the top rigth point
maxXids = find(XYZ(1,:) == max(XYZ(1,:)));
maxYids = find(XYZ(2,:) == max(XYZ(2,:)));
id = intersect(maxXids,maxYids);
XYZ = removerows(XYZ',id)';
% Lets rotate a bit
XYZ = roty(5)*rotx(7)*rotz(0)*XYZ;
% Plot points
figure;
grid on;
rotate3d on;
axis vis3d;
hold on;
plot3(XYZ(1,:),XYZ(2,:),XYZ(3,:),'.r');
% Find bounding rectangle
% ??? :(
%Currently I'm using this code:
tt = XYZ;
%Get the max and min indexes
minX = find(tt(1,:) == min(tt(1,:)));
minY = find(tt(2,:) == min(tt(2,:)));
maxX = find(tt(1,:) == max(tt(1,:)));
maxY = find(tt(2,:) == max(tt(2,:)));
%Intersect to find the common index
id1 = intersect(minX,minY);
id2 = intersect(maxX,minY);
id3 = intersect(maxX,maxY);
id4 = intersect(minX,maxY);
%Get the points
p1 = tt(:,id1(1));
p2 = tt(:,id2(1));
p3 = tt(:,id3(1));
p4 = tt(:,id4(1));
Sample points plot:
The problem is that intersect some times can be null, eg: if the points does not form a rectangle. Resulting this error:
Index exceeds matrix dimensions.
First solution : Use logical indexing to get rid of the find calls
p1=tt(:,tt(1,:)==min(tt(1,:))&tt(2,:)==min(tt(2,:)));
p2=tt(:,tt(1,:)==max(tt(1,:))&tt(2,:)==min(tt(2,:)));
p3=tt(:,tt(1,:)==max(tt(1,:))&tt(2,:)==max(tt(2,:)));
p4=tt(:,tt(1,:)==min(tt(1,:))&tt(2,:)==max(tt(2,:)));
Second solution : Use convhull to get the corners :
k=convhull(tt(1,:),tt(2,:));
Corners=[tt(:,k(1:end-1))];
Ok found a solution:
% Find bounding rectangle
tt = XYZ;
%Get the max and min indexes
minXids = find(tt(1,:) == min(tt(1,:)));
minYids = find(tt(2,:) == min(tt(2,:)));
maxXids = find(tt(1,:) == max(tt(1,:)));
maxYids = find(tt(2,:) == max(tt(2,:)));
%Intersect to find the common index
id1 = intersect(minXids,minYids);
id2 = intersect(maxXids,minYids);
id3 = intersect(maxXids,maxYids);
id4 = intersect(minXids,maxYids);
%Get the points
% Find affine plane on points
[np,~,pp] = affine_fit(tt');
% Converts to cart. eq.
% ax + yb + cz + d = 0
% Find d
a = np(1); b = np(2); c = np(3);
x = pp(1); y = pp(2); z = pp(3);
d = - (a*x + y*b + c*z);
% Get only one value
minX = min(tt(1,minXids)); maxX = max(tt(1,maxXids));
minY = min(tt(2,minYids)); maxY = max(tt(2,maxYids));
if numel(id1) == 0
x = minX; y = minY;
% Calculate z at xy.
z = - (d + a*x + y*b)/c;
p1 = [x y z]';
else
p1 = tt(:,id1(1));
end
if numel(id2) == 0
x = maxX; y = minY;
z = - (d + a*x + y*b)/c;
p2 = [x y z]';
else
p2 = tt(:,id1(1));
end
if numel(id3) == 0
x = maxX; y = maxY;
z = - (d + a*x + y*b)/c;
p3 = [x y z]';
else
p3 = tt(:,id1(1));
end
if numel(id4) == 0
x = minX; y = maxY;
z = - (d + a*x + y*b)/c;
p4 = [x y z]';
else
p4 = tt(:,id1(1));
end
ps = [p1 p2 p3 p4];
plot3(ps(1,:),ps(2,:),ps(3,:),'ob');
I have to draw a hipsometric map on a 3D plot. I have two vectors 1x401 (named xLabels and yLabels) which are the geo coordinates, and401x401(namedA`) matrix with the altitude data. To plot the data I use:
surf(xLabels, yLabels,A,'EdgeColor','None','Marker','.');
which leads to something like that:
But i would like to have something like that:
On the second image, only the surface is plotted, while my image looks like pillars.
I tried even make my vectors to 401x401 using meshgrid but it did not have any effect.
Do you have any idea what I should change?
#EDIT
I checked for X and Y data. I quess is too small interval (0.0083), but when i try plot good second of upper plots with same interval it draws correctly.
#EDIT2:
sizeX = 4800;
sizeY = 6000;
pixdegree = 0.0083; % 1 pixel is 0.0083 degree on map
intSize = 2;
lon = 37 + (35/60);
lat = 55+ (45/60);
fDEM = 'E020N90';
fHDR = 'E020N90.HDR';
[startXY, endXY] = calcFirstPixel(lon, lat); %calc borders for my area
f = fopen('E020N90.DEM');
offset = (startXY(1,2)*sizeX*intSize)+(startXY(1,1)*intSize);
fseek(f, offset,0); %seek from curr file pos
x = 0;
A = [];
BB = [];
jump = (intSize*sizeX)-(401*2);
while x<401
row = fread(f, 802);
fseek(f, jump, 0); %jump 2 next row
A = [A row];
x = x+1;
end
fclose(f);
A = A';
A = A(:,2:2:802);
m1 = min(A(:)); %wartość minimalna dla naszej podziałki
m2 = max(A(:)); %wartość maksymalna dla naszej podziałki
step = m2/8; % będzie 8 kolorów
highScale = m1:step:m2-step; %wartości graniczne dla każdego z nich
%handles.axes1 = A;
colormap(hObject, jet(8));
startXtick = 20 + pixdegree*startXY(1,1);
endXtick = 20 + pixdegree*endXY(1,1);
startYtick = 90 - pixdegree*endXY(1,2);
endYtick = 90 - pixdegree*startXY(1,2);
[XX,YY] = ndgrid(startXtick:pixdegree:endXtick,startYtick:pixdegree:endYtick);
xLabels = startXtick:pixdegree:endXtick;
yLabels = startYtick:pixdegree:endYtick;
surf(xLabels, yLabels,A,'EdgeColor','None','Marker','.');
set(gca,'YDir','normal');
grid on;
view([45 45])
And .DEM files
function [startXY, endXY] = calcFirstPixel(lon,lat)
global fHDR;
format = '%s %s';
f = fopen(fHDR);
cont = textscan(f, format);
LonStart = str2double(cont{1,2}{11,1});
LatStart = str2double(cont{1,2}{12,1});
diffPerPix = str2double(cont{1,2}{13,1});
fclose(f);
x = LonStart;
countX = 0
y = LatStart;
countY= 0;
while x<lon
x=x+diffPerPix
countX = countX +1;
end
while y>lat
y=y-diffPerPix
countY = countY+1;
end
startXY= [countX-200 countY-200];
endXY = [countX+200 countY+200];
end