Polygon created using centroid in postgis has incorrect length - postgis

I am trying to create a polygon around a centroid by projecting the 4 points 2 meter each. But the polygon sides are not 4 meter. I am seeing only 3.7 meter and 2.8 meter.
SELECT ST_AsText(ST_MakeValid(ST_MakeEnvelope(
ST_X(ST_Project(ST_SetSRID(ST_MakePoint(-94.308946032318019, 41.189416186516212), 4326), 2, radians(225))::geometry),
ST_Y(ST_Project(ST_SetSRID(ST_MakePoint(-94.308946032318019, 41.189416186516212), 4326), 2, radians(225))::geometry),
ST_X(ST_Project(ST_SetSRID(ST_MakePoint(-94.308946032318019, 41.189416186516212), 4326), 2, radians(135))::geometry),
ST_Y(ST_Project(ST_SetSRID(ST_MakePoint(-94.308946032318019, 41.189416186516212), 4326), 2, radians(315))::geometry),
4326
)));
The diagonal is also not coming as 4m. It is 4.7m.
QGIS

The distance of 4m is not the side of the box but its diagonal.
If you want the box side to be 4m, you would have to project the point centroid with angles of 0, 90, 180 or 270 degrees.
edit following measurement comment : The diagonal is indeed 4m long. You can measure it in Postgis (using 45degrees for the project leads to the same point that you create using 2 different angles)
SELECT st_distance(
ST_Project(ST_SetSRID(ST_MakePoint(-94.308946032318019, 41.189416186516212), 4326), 2, radians(225))::geography,
ST_Project(ST_SetSRID(ST_MakePoint(-94.308946032318019, 41.189416186516212), 4326), 2, radians(45))::geography);
st_distance
-------------
4
In QGIS, you need to define and use the ellipsoidal distance, else a degree of longitude is consider to be of the same length as a degree of latitude, which is wrong.

Related

Calculating Displacement based on the compass direction

I need some help with programming the calculation of displacement. Given the distance the object has moved in the XY plane, and the yaw (heading) of the object, I'd like to calculate the displacement of the object. For example, the object moved 5m North and 2m East.
The data I have is the distance it travels in the XY plane (X distance and Y distance) and the heading of the device which is determined by the direction of X. I know how to calculate it on paper but I am having trouble to program it.
I've attached two examples that shows how I obtained the calculations. The black dot is the displacement of the object. In the 1st example, the X-distance travelled is 3 meters while the Y-distance is 4 meters and the heading of the X-axis is 70°. After calculating, I managed to get that it has travelled 2.733m South and 4.187m East. In example 2, it travel, the X-distance is -5m and the Y-distance is -12m, the heading is 160°. I calculated that the object travels 8.80m North and 9.566m East.
Example 1
Example 2
Assume you have your XY pane rotated by some angle Zp and have a 2D movement vector within that pane, let's say its direction rotated by Zv – what is total rotation of the vector, relative to the global orientation? Zp + Zv...
So all you need to do is applying the rotation Zp to the movement vector within XY-pane, i. e. apply a rotation matrix to the vector. This matrix for a rotation by z looks like:
cos(z) -sin(z)
sin(z) cos(z)
With our data above:
north = cos(Zp) * x - sin(Zp) * y
east = sin(Zp) * x + cos(Zp) * y
which gives, with your first sample data applied:
north = cos(70°) * 3 - sin(70°) * 4 ~ -2.7327
east = sin(70°) * 3 + cos(70°) * 4 ~ 4.1872
north = cos(160°) * -5 - sin(160°) * -12 ~ 8.8027
east = sin(160°) * -5 + cos(160°) * -12 ~ 9.5662
Corresponding pretty much to the values you calculated (note: negative movement to north is positive movement towards south...).
What you are doing is a conversion from polar to Cartesian coordinates. https://en.wikipedia.org/wiki/Polar_coordinate_system#Converting_between_polar_and_Cartesian_coordinates
If your Cartesian coordinates are not aligned to the polar axis, just compensate by adding the rotation angle to the polar argument.

Plotting logistic regression line

this is my first post ever here so I'm not quit sure what is the proper form to ask the question. I'm trying to put picture of the results but since its my first post, the website telling me that I need 10 positive post for some credibility so I think that my charts doesn't appear. Also, I'm french, not perfectly bilingual. Please, be indulgent, I'm open for all comments and suggestions. I really need this for my master's projet. Thank you very much!
I have two sets of arrays which contains thousands of values In one (x_1_3) is all the value of temperature and y_0_100 contain only 0's and 100's which are associated to every temperature in x_1_3 sorted.
x_1_3 = array([[ 2.02],
[ 2.01],
[ 3.08],
...,
[ 0.16],
[ 0.17],
[-2.12]])
y_0_100 = array([ 0., 0., 0., ..., 100., 100., 100.])
The 0 in y_0_100 represent solid precipitation and 100 represent liquid precipitation I just want to plot a logistic regression line across my values
(I also tried to put the values in a dataframe, but it didnt work)
dfsnow_rain
AirTemp liquid%
0 2.02 0.0
1 2.01 0.0
2 3.08 0.0
3 3.05 0.0
4 4.89 0.0
... ... ...
7526 0.78 100.0
7527 0.40 100.0
7528 0.16 100.0
7529 0.17 100.0
7530 -2.12 100.0
7531 rows × 2 columns
X = x_1_3
y = y_0_100
# Fit the classifier
clf = linear_model.LogisticRegression(C=1e5)
clf.fit(X, y)
# and plot the result
plt.figure(1, figsize=(10, 5))
plt.clf()
plt.scatter(X.ravel(), y, color='black', zorder=20)
X_test = np.linspace(-15, 15, 300)
loss = expit(X_test * clf.coef_ + clf.intercept_).ravel()
plt.plot(X_test, loss, color='red', linewidth=3)
ols = linear_model.LinearRegression()
ols.fit(X, y)
plt.plot(X_test, ols.coef_ * X_test + ols.intercept_, linewidth=1)
#plt.axhline(1, color='.5')
plt.ylabel('y')
plt.xlabel('X')
plt.xticks(range(-10, 10))
plt.yticks([0, 100, 10])
plt.ylim(0, 100)
plt.xlim(-10, 10)
plt.legend(('Logistic Regression Model', 'Linear Regression Model'),
loc="lower right", fontsize='small')
plt.tight_layout()
plt.show()
Chart results
When I zoom in I realise that my logistic regression line is not flat, its the line that curves in a very small range (see picture below)
Chart when it's zoomed
I would like something more like this :
Logistic regression chart i would like
What am i doing wrong here? I just want to plot a regression line across my values from y0 to y100

How do I plot these values against each other?

So I have a .csv file which has 3 value-types: Time, Torque and Angle.
The values are saved in seperate columns like that:
Row 1: Time1, Torque1, Angle1, ..., TimeX,TorqueX,AngleX.
The rest of the rows are the Values (745 Values each Instance and Variable)
So first I transposed the DataFrame and seperated it into the different variables.
time=df_trans.iloc[::3, :]
torque=df_trans.iloc[1: : 3, :]
angle=df_trans.iloc[2 : :3,:]
So now I have DataFrames with the Times, Torques and Angles of the X instances. (In this example 5 instances) Each Instance having a row and the columns being the values of the Instance.
For example print(angle):
0 ... 745
01.01.1990 01:33:51 Angle 0 ... 5225,68408203125
01.01.1990 01:35:09 Angle 0 ... 5186,560546875
01.01.1990 01:35:58 Angle 0 ... 3794,25634765625
01.01.1990 01:37:11 Angle 0 ... 3230,36791992188
01.01.1990 01:37:57 Angle 0 ... 3794,13012695313
[5 rows x 746 columns]
Now I want to plot the angles against the torque of the Instance for all instances in one plot, but I can't seem to get it working.
The code:
df = pd.read_csv("Kurven.csv", sep=';', header=[0])
df_trans=df.transpose()
time=df_trans.iloc[::3, :]
time
torque=df_trans.iloc[1: : 3, :]
torque
angle=df_trans.iloc[2::3,:]
angle
Then I tried plotting:
import matplotlib.pyplot as plt
plt.plot(angle,torque)
got this Error:
TypeError: unhashable type: 'numpy.ndarray'
Then I tried:
import matplotlib.pyplot as plt
for i, j in angle,torque:
plt.plot(i,j)
Got this Error:
ValueError: too many values to unpack (expected 2)

generating/creating hexagon grid in C

So i m trying to make hexagonal grid in C for a game. I am really dumb founded on where to start on it. ANyone have any ideas.
EDIT: I need about 15-20 hexagons in a grip shape all joined,something like a game board. for a game i m working on. Sorry for not being clear
Absolutely. Despite their odd shape, hexagons can still be contained in your usual multidimensional array, for future use (I assume you'll want to put things in your hexagons). As for drawing them, it's simple. Sum of angles = (6 - 2) * 180 = 4 * 180 = 720. One angle is 720 / 6 = 120 degrees. Calculate first the leftmost angle's Y position, which is equal to √(hexagonSide - hexagonWidth * hexagonWidth). I'm sure you can figure out hexagonWidth, right? Okay, now the X position relative to the last one will be 0. You'll need to offset the Y position by half the height of the hexagon before it, up or down depending on whether row * col is even or odd. Since you know the hexagon's width you have the coordinates of the opposite angle. Rotate by 120° and repeat.
Before I continue, is this supposed to be in the console? Or is it real graphics?
So let's get this straight, the game will be played on the console? Right, well now you will need to set up your data structures, the most obvious is with nodes.
The nodes
Each hexagon is a node with six edges.
typedef struct Node {
void *object; /* Pointer to object */
Node *node_array; /* Pointer to node_array with 'node_count' nodes */
int node_count; /* size of node_array */
} Node;
How to initialize and connect the node structure
Imagine the following hexagon:
/\
| |
\/
It has the following edges, NORTHEAST, EAST, SOUTHEAST, SOUTHWEST, WEST and NORTHWEST. Next observe how they will be arranged (10, 11 and 12 were represented in Hex so that they can fit in one space):
// 0 1 2 3
// 4 5 6 7 8
// 9 A B C
So 0 will link to 5 through it's SOUTHEAST link, and 4 through it's SOUTHWEST link. Also notice how the rows alternate between odd and even numbers of elements. Let's call {0, 1, 2, 3} row[0], and {4, 5, 6, 7, 8} row[1]. And let's call this a 5x3 hexmap. The easiest way to create this array is with malloc(sizeof(Node) * width * height).
Connecting the nodes
First of all let me point out that every even row (0, 2, 4, ...) will have width-1 elements. But there's more, each element (x, y) on this row will link to the following element in your array:
(x+1, y-1) - NORTHEAST
(x+1, y) - EAST
(x+1, y+1) - SOUTHEAST
(x, y+1) - SOUTHWEST
(x-1, y) - WEST
(x, y-1) - NORTHWEST
Elements on the other rows, such as {4, 5, 6, 7, 8} will have width elements, where element (x, y) links to the following:
(x, y-1) - NORTHEAST
(x+1, y) - EAST
(x, y+1) - SOUTHEAST
(x-1, y+1) - SOUTHWEST
(x-1, y) - WEST
(x-1, y-1) - NORTHWEST
When trying to link (x1,y1) with (x2, y2), ensure that 0 <= x < width and 0 <= y < height.
Remember ...
Your array contains one unused element at the end of every two rows (row[0], row[2], etc.). Also you might want to provide them all with some sort of label or index so that you can refer the player to them. You could label them as (x,y) pairs, or numerically by their index, it's all up to you. The (x, y) pair is very easy for you since that will map directly to the array they are stored in.

How to get an evenly distributed sample from Perl array values?

I have an array containing many values between 0 and 360 (like degrees in a circle), but unevenly distributed:
1,45,46,47,48,49,50,51,52,53,54,55,100,120,140,188, 210, 280, 355
Now I need to reduce those values to e.g. 4 only, but as evenly as possible distributed values.
How to do that?
Thanks,
Jan
Put the numbers on a circle, like a clock. Now construct a logical cross, say at 12, 3, 6, and 9 o’clock. Put the 12 at the first number. Now find what numbers would be nearest to 3, 6, and 9 o’clock, and record the sum of those three numbers’ distances next to the first number.
Iterate by rotating the top of your cross — the 12 o’clock point — clockwise until it exactly lines up with the next number. Again measure how far the nearest numbers are to each of your three other crosspoints, and record that score next to this current 12 o’clock number.
Repeat until you reach your 12 o’clock has rotated all the way to the original 3 o’clock, at which point you’re done. Whichever number has the lowest sum assigned to it determines the winning configuration.
This solution generalizes to any range of values R and any number N of final points you wish to reduce the set to. Each point on the “cross” is R/N away from each other, and you need only rotate until the top of your cross reaches where the next arm was in the original position. So if you wanted 6 points, you would have a 6-pointed cross, each 60 degrees apart instead of a 4-pointed cross each 90 degrees apart. If your range is different, you still do the same sort of operation. That way you don’t need a physical clock and cross to implement this algorithm: it works for any R and N.
I feel bad about this answer from a Perl perspective, as I’ve not managed to include any dollar signs in the solution. :)
Use a clustering algorithm to divide your data into evenly distributed partitions. Then grab a random value from each cluster. The following $datafile looks like this:
1 1
45 45
46 46
...
210 210
280 280
355 355
First column is a tag, second column is data. Running the following with $K = 4:
use strict; use warnings;
use Algorithm::KMeans;
my $datafile = $ARGV[0] or die;
my $K = $ARGV[1] or 0;
my $mask = 'N1';
my $clusterer = Algorithm::KMeans->new(
datafile => $datafile,
mask => $mask,
K => $K,
terminal_output => 0,
);
$clusterer->read_data_from_file();
my ($clusters, $cluster_centers) = $clusterer->kmeans();
my %clusters;
while (#$clusters) {
my $cluster = shift #$clusters;
my $center = shift #$cluster_centers;
$clusters{"#$center"} = $cluster->[int rand( #$cluster - 1)];
}
use YAML; print Dump \%clusters;
returns this:
120: 120
199: 188
317.5: 355
45.9166666666667: 46
First column is the center of the cluster, second is the selected value from that cluster. The centers' distance to one another should be maximized according to the Expectation Maximization algorithm.

Resources