Small shift when transforming from GIS to netlogo coordinates - gis

When storing turtle coordinates as GIS coordinates, and then loading them into NetLogo by converting them back to NetLogo coordinates, there is a slight shift in position.
This is the code I use to store NetLogo to GIS coordinates:
let env gis:envelope-of agentToStore
file-open "agentLocations.csv"
file-print (word first env "," last env)
file-close
And this is the code I use to convert GIS coordinates back to NetLogo coordinates (here x and y are coordinates read from the file):
let envelope gis:world-envelope
let xscale (max-pxcor - min-pxcor) / (item 1 envelope - item 0 envelope)
let yscale (max-pycor - min-pycor) / (item 3 envelope - item 2 envelope)
if x >= item 0 envelope and x <= item 1 envelope
and y >= item 2 envelope and y <= item 3 envelope[
let netlogo-x (x - item 0 envelope) * xscale + min-pxcor
let netlogo-y (y - item 2 envelope) * yscale + min-pycor
ask patch (ceiling netlogo-x) (floor netlogo-y) [sprout 1]
]
Without 'ceiling' and 'floor', the loaded agent is always shifted by a cell in NetLogo. However even with ceiling and floor, there is still a small shift by in GIS space for some agents, which affects my output. Is there a better way of doing this?

Related

Convert Yolo output to a real-world coordinate system

We have detected objects on UAV data using Yolo v5 and obtained bounding box coordinates (x1,y1,x2,y2) in the format relative to the origin of the satellite data. The data looks like this and is returned as a tab-delimited text file.
[ 7953 11025 7978 11052]
[16777 10928 16817 10970]
[15670 10591 15685 10607]
The results are accompanied by a PNG and the PGW (world file) reads like this:
0.1617903116883119
0
0
-0.1617903116883119
655854.20159515587147325
2716038.70000312989577651
How can the bounding boxes be converted into real-world global projection EPSG:4328 usable in GIS? Any hints towards a python script are much appreciated.
go in Detect.py and set gn = 1 and it'll get you the un-normalized coordinates. Attaching the screenshot below for you reference
I wrote this short function to convert the yolo detections to real-world polygons. The yolo detections.txt needs to be read without the [].
# function to return polygon
def bbox(x1, y1, x2, y2):
# world file content
# Line 1: A: x-component of the pixel width (x-scale)
xscale = 0.1617903116883119
# Line 2: D: y-component of the pixel width (y-skew)
yskew = 0
# Line 3: B: x-component of the pixel height (x-skew)
xskew = 0
# Line 4: E: y-component of the pixel height (y-scale), typically negative
yscale = -0.1617903116883119
# Line 5: C: x-coordinate of the center of the original image's upper left pixel transformed to the map
xpos = 655854.20159515587147325
# Line 6: F: y-coordinate of the center of the original image's upper left pixel transformed to the map
ypos = 2716038.70000312989577651
X_proj = xpos + (xscale * x1) + (xskew * y1)
Y_proj = ypos + (yscale * y1) + (yskew * x1)
X1_proj = xpos + (xscale * x2) + (xskew * y2)
Y1_proj = ypos + (yscale * y2) + (yskew * x2)
return Polygon([[X_proj, Y_proj],
[X1_proj, Y_proj],
[X1_proj, Y1_proj],
[X_proj, Y1_proj]])
outGDF = gpd.GeoDataFrame(geometry = dataset.apply(lambda g: bbox(int(g[0]),int(g[1]),int(g[2]),int(g[3])),axis=1),crs = {'init':'epsg:32638'})

Misaligned between imported GIS files and network (nodes have X and Y coordinates) - NetLogo

I, once again have a question. My previous solution to my problem didn't work as I expected. To remind you, I imported some polygons and had a problem setting some turtles (cities) in the NetLogo world appropriately (to read GIS coordinates from non-gis file and set their position in the world, more on Netlogo doesen't recognize the GIS coordinates in the defined envelope of the world, it treats them as netologo world coordinates). So, in the end, I came up with a solution to transform the GIS coordinates in NetLogo coordinates (nl-x and nl-y procedures). The cities are actually in graphml format with x and y attributes. So, my code is this:
extensions [nw gis]
directed-link-breed [highways highway]
breed [cities city]
highways-own [ name ]
cities-own [ x y ]
globals [ paldrino ]
to setup
ca
;; set the world envelope
gis:load-coordinate-system "wgs84.prj"
set paldrino gis:load-dataset "paldrino.shp"
let world ( gis:envelope-of paldrino )
gis:set-world-envelope (world)
;; Make them visible
foreach gis:feature-list-of paldrino [ ;for each polygon
polygon ->
let temp-color one-of base-colors
ask patches gis:intersecting polygon [
set pcolor temp-color
]]
;; load network
nw:set-context cities highways
nw:load-graphml "highway-network.graphml"
ask cities[
set xcor nl-x(read-from-string x) ;; if I put set xcor read-from-string x, then it will put all the nodes in one point in Netlogo world, same for setxy fix-x(read-from-string x) fix-y (read-from-string y)
set ycor nl-y (read-from-string y)
]
end
to-report nl-x [#x]
let world gis:envelope-of paldrino
let minx item 0 world
let maxx item 1 world
report ((#x - minx) / (maxx - minx)) * (max-pxcor - min-pxcor) + min-pxcor
end
to-report nl-y [#y]
let world gis:envelope-of paldrino
let miny item 2 world
let maxy item 3 world
report ((#y - miny) / (maxy - miny)) * (max-pycor - min-pycor) + min-pycor
end
In the end, the problem is that NetLogo doesn't perfectly align those two files: polygons (paldrino) and network (cities). Approximately it put them ok, but I need them to be perfectly set in the world. For example, some cities should have been in one polygon, but they are in the adjacent polygon.
So, for example, this is how NetLogo puts them:
And this is how they should be (read in QGIS):
If anyone please can help me or point me in another direction. I start losing my mind.
Thank you!

find point of intersection between two arc

I'm creating a game for kids. It's creating a triangle using 3 lines. How I approached this is I create two arcs(semi circle) from two end points of a base line. But I couldn't figure how to find the point of intersection of those two arc. I've search about it but only found point of intersection between two straight lines. Is there any method to find this point of intersection? Below is the figure of two arcs drawn from each end of the baseline.
Assume centers of the circle are (x1, y1) and (x2, y2), radii are R1 and R2. Let the ends of the base be A and B and the target point be T. We know that AT = R1 and BT = R2. IMHO the simplest trick to find T is to notice that difference of the squares of the distances is a known constant (R1^2 - R2^2). And it is easy to see that the line the contains points meeting this condition is actually a straight line perpendicular to the base. Circles equations:
(x - x1)^2 + (y-y1)^2 = R1^2
(x - x2)^2 + (y-y2)^2 = R2^2
If we subtract one from another we'll get:
(x2 - x1)(2*x - x1 - x2) + (y2 - y1)(2*y - y1 - y2) = R1^2 - R2^2
Let's x0 = (x1 + x2)/2 and y0 = (y1 + y2)/2 - the coordinates of the center. Let also the length of the base be L and its projections dx = x2 - x1 and dy = y2 - y1 (i.e. L^2 = dx^2 + dy^2). And let's Q = R1^2 - R2^2 So we can see that
2 * (dx * (x-x0) + dy*(y-y0)) = Q
So the line for all (x,y) pairs with R1^2 - R2^2 = Q = const is a straight line orthogonal to the base (because coefficients are exactly dx and dy).
Let's find the point C on the base that is the intersection with that line. It is easy - it splits the base so that difference of the squares of the lengths is Q. It is easy to find out that it is the point on a distance L/2 + Q/(2*L) from A and L/2 - Q/(2*L) from B. So now we can find that
TC^2 = R1^2 - (L/2 + Q/(2*L))^2
Substituting back Q and simplifying a bit we can find that
TC^2 = (2*L^2*R1^2 + 2*L^2*R2^2 + 2*R1^2*R2^2 - L^4 - R1^4 - R2^4) / (4*L^2)
So let's
a = (R1^2 - R2^2)/(2*L)
b = sqrt(2*L^2*R1^2 + 2*L^2*R2^2 + 2*R1^2*R2^2 - L^4 - R1^4 - R2^4) / (2*L)
Note that formula for b can also be written in a different form:
b = sqrt[(R1+R2+L)*(-R1+R2+L)*(R1-R2+L)*(R1+R2-L)] / (2*L)
which looks quite similar to the Heron's formula. And this is not a surprise because b is effectively the length of the height to the base AB from T in the triangle ABT so its length is 2*S/L where S is the area of the triangle. And the triangle ABT obviously has sides of lengths L, R1 and R2 respectively.
To find the target T we need to move a along the base and b in a perpendicular direction. So coordinates of T calculated from the middle of the segment are:
Xt = x0 + a * dx/L ± b * dy / L
Yt = y0 + a * dy/L ± b * dx / L
Here ± means that there are two solutions: one on either side of the base line.
Partial case: if R1 = R2 = R, then a = 0 and b = sqrt(R^2 - (L/2)^2) which makes obvious sense: T lies on the segment bisector on a length of sqrt(R^2 - (L/2)^2) from the middle of the segment.
Hope this helps.
While you have not stated clearly, I assume that you have points with coordinates (A.X, A.Y) and (B.X, B.Y) and lengths of two sides LenA and LenB and need to find coordinates of point C.
So you can make equation system exploiting circle equation:
(C.X - A.X)^2 + (C.Y - A.Y)^2 = LenA^2
(C.X - B.X)^2 + (C.Y - B.Y)^2 = LenB^2
and solve it for unknowns C.X, C.Y.
Not that it is worth to subtract A coordinates from all others, make and solve simpler system (the first equation becomes C'.X^2 + C'.Y^2 = LenA^2), then add A coordinates again
So I actually needed this to design a hopper to lift grapes during the wine harvest. Tried to work it out myself but the algebra is horrible, so I had a look on the web -in the end I did it myself but introduced some intermediate variables (that I calculate in Excel - this should also work for the OP since the goal was a calculated solution). In fairness this is really much the same as previous solutions but hopefully a little clearer.
Problem:
What are the coordinates of a point P(Xp,Yp) distance Lq from point Q(Xq,Yq) and distance Lr from point R(Xr,Yr)?
Let us first map the problem onto to new coordinate system where Lq is the origin, thus Q’ = (0,0), let (x,y) = P’(Xp-Xq,Yp-Yq) and let (a,b) = R’(Xr-Xq,Yr-Yq).
We may now write:
x^2 + y^2 = Lq^2 -(1)
(x-a)^2 + (y-b)^2 = Lr^2 -(2)
Expanding 2:
x^2 – 2ax + a^2 + y^2 -2ay + b^2 =Lr^2
Subtracting 1 and rearranging
2by = -2ax + a2 + b2 - Lr^2+ Lq^2
For convenience, let c = a^2 + b^2 + Lq^2 + Lr^2 (these are all known constants so c may be easily computed), thus we obtain:
y = -ax/b + c/2b
Substituting into 1 we obtain:
x^2 + (-a/b x + c/2b)^2 = Lq^2
Multiply the entire equation by b^2 and gather terms:
(a^2 + b^2) x2 -ac x + c/4 + Lq^2 b^2 = 0
Let A = (a2 + b2), B= -ac ,and C= c/4 + Lq^2 b^2
Use the general solution for a quadratic
x = (-B +-SQRT(B^2-4AC))/2A
Substitute back into 1 to get:
y= SQRT(Lq^2 - x^2 )
(This avoids computational difficulties where b = 0)
Map back to original coordinate system
P = (x+Xq, y + Yq)
Hope this helps, sorry about the formatting, I had this all pretty in Word, but lost it

Matlab plotting the shifted logistic function

I would like to plot the shifted logistic function as shown from Wolfram Alpha.
In particular, I would like the function to be of the form
y = exp(x - t) / (1 + exp(x - t))
where t > 0. In the link, for example, t is 6. I had originally tried the following:
x = 0:.1:12;
y = exp(x - 6) ./ (1 + exp(x - 6));
plot(x, y);
axis([0 6 0 1])
However, this is not the same as the result from Wolfram Alpha. Here is an export of my plot.
I do not understand what the difference is between what I am trying to do here vs. plotting shifted sin and cosine functions (which works using the same technique).
I am not completely new to Matlab but I do not usually use it in this way.
Edit: My values for x in the code should have been from 0 to 12.
fplot takes as inputs a function handle and a range to plot for:
>> fplot(#(x) exp(x-6) / (1 + exp(x-6)), [0 12])
The beauty of fplot in this case is you don't need to spend time calculating y-values beforehand; you could also extract values from the graph after the fact if you want (by getting the line handle's XData and YData properties).
Your input to Wolfram Alpha is incorrect. It is interpreted as e*(x-6)/(1-e*(x-6)). Use plot y = exp(x - 6) / (1 + exp(x - 6)) for x from 0 to 12 in Wolfram Alpha (see here) for the same results as in MATLAB. Also use axis([0 12 0 1]) (or no axis statement at all on a new plot) to see the full results in MATLAB.
In reply to your comment: use y = exp(1)*(x - 6) ./ (1 + exp(1)*(x - 6)); to do in MATLAB what you were doing in Wolfram Alpha.

How can I find the smallest difference between two angles around a point?

Given a 2D circle with 2 angles in the range -PI -> PI around a coordinate, what is the value of the smallest angle between them?
Taking into account that the difference between PI and -PI is not 2 PI but zero.
An Example:
Imagine a circle, with 2 lines coming out from the center, there are 2 angles between those lines, the angle they make on the inside aka the smaller angle, and the angle they make on the outside, aka the bigger angle.
Both angles when added up make a full circle. Given that each angle can fit within a certain range, what is the smaller angles value, taking into account the rollover
This gives a signed angle for any angles:
a = targetA - sourceA
a = (a + 180) % 360 - 180
Beware in many languages the modulo operation returns a value with the same sign as the dividend (like C, C++, C#, JavaScript, full list here). This requires a custom mod function like so:
mod = (a, n) -> a - floor(a/n) * n
Or so:
mod = (a, n) -> (a % n + n) % n
If angles are within [-180, 180] this also works:
a = targetA - sourceA
a += (a>180) ? -360 : (a<-180) ? 360 : 0
In a more verbose way:
a = targetA - sourceA
a -= 360 if a > 180
a += 360 if a < -180
x is the target angle. y is the source or starting angle:
atan2(sin(x-y), cos(x-y))
It returns the signed delta angle. Note that depending on your API the order of the parameters for the atan2() function might be different.
If your two angles are x and y, then one of the angles between them is abs(x - y). The other angle is (2 * PI) - abs(x - y). So the value of the smallest of the 2 angles is:
min((2 * PI) - abs(x - y), abs(x - y))
This gives you the absolute value of the angle, and it assumes the inputs are normalized (ie: within the range [0, 2π)).
If you want to preserve the sign (ie: direction) of the angle and also accept angles outside the range [0, 2π) you can generalize the above. Here's Python code for the generalized version:
PI = math.pi
TAU = 2*PI
def smallestSignedAngleBetween(x, y):
a = (x - y) % TAU
b = (y - x) % TAU
return -a if a < b else b
Note that the % operator does not behave the same in all languages, particularly when negative values are involved, so if porting some sign adjustments may be necessary.
An efficient code in C++ that works for any angle and in both: radians and degrees is:
inline double getAbsoluteDiff2Angles(const double x, const double y, const double c)
{
// c can be PI (for radians) or 180.0 (for degrees);
return c - fabs(fmod(fabs(x - y), 2*c) - c);
}
See it working here:
https://www.desmos.com/calculator/sbgxyfchjr
For signed angle:
return fmod(fabs(x - y) + c, 2*c) - c;
In some other programming languages where mod of negative numbers are positive, the inner abs can be eliminated.
I rise to the challenge of providing the signed answer:
def f(x,y):
import math
return min(y-x, y-x+2*math.pi, y-x-2*math.pi, key=abs)
For UnityEngine users, the easy way is just to use Mathf.DeltaAngle.
Arithmetical (as opposed to algorithmic) solution:
angle = Pi - abs(abs(a1 - a2) - Pi);
I absolutely love Peter B's answer above, but if you need a dead simple approach that produces the same results, here it is:
function absAngle(a) {
// this yields correct counter-clock-wise numbers, like 350deg for -370
return (360 + (a % 360)) % 360;
}
function angleDelta(a, b) {
// https://gamedev.stackexchange.com/a/4472
let delta = Math.abs(absAngle(a) - absAngle(b));
let sign = absAngle(a) > absAngle(b) || delta >= 180 ? -1 : 1;
return (180 - Math.abs(delta - 180)) * sign;
}
// sample output
for (let angle = -370; angle <= 370; angle+=20) {
let testAngle = 10;
console.log(testAngle, "->", angle, "=", angleDelta(testAngle, angle));
}
One thing to note is that I deliberately flipped the sign: counter-clockwise deltas are negative, and clockwise ones are positive
There is no need to compute trigonometric functions. The simple code in C language is:
#include <math.h>
#define PIV2 M_PI+M_PI
#define C360 360.0000000000000000000
double difangrad(double x, double y)
{
double arg;
arg = fmod(y-x, PIV2);
if (arg < 0 ) arg = arg + PIV2;
if (arg > M_PI) arg = arg - PIV2;
return (-arg);
}
double difangdeg(double x, double y)
{
double arg;
arg = fmod(y-x, C360);
if (arg < 0 ) arg = arg + C360;
if (arg > 180) arg = arg - C360;
return (-arg);
}
let dif = a - b , in radians
dif = difangrad(a,b);
let dif = a - b , in degrees
dif = difangdeg(a,b);
difangdeg(180.000000 , -180.000000) = 0.000000
difangdeg(-180.000000 , 180.000000) = -0.000000
difangdeg(359.000000 , 1.000000) = -2.000000
difangdeg(1.000000 , 359.000000) = 2.000000
No sin, no cos, no tan,.... only geometry!!!!
A simple method, which I use in C++ is:
double deltaOrientation = angle1 - angle2;
double delta = remainder(deltaOrientation, 2*M_PI);