How to extend the polygon to a certain distance? - sql

How to extend the polygon to a certain distance?
I create a convex hull around the multipoint. But I need to extend the range to several kilometers. At least in theory.
http://img.radiokot.ru/files/21274/1oykzc5pez.png

Assuming that you're able to get a convex hull (which maybe you're using ConvexHullAggregate!), STBuffer() should do what you want.
declare #hull geography = «your value here»;
select #hull.STBuffer(10000); -- 10 km buffer
NB: the 10000 may need to change based on the SRID that you're using since SRIDs have units of distance baked into them inherently. But SRID 4326 is what's used in the docs most often and the native unit for that SRID is meters. So 10 km → 10000 m.

Build outer bisector vector in every vertex (as sum of normalized normals na and nb of two neighbor edges) and normalize it
bis = na + nb
bis = bis / Length(bis)
Make length of bisector to provide needed distance as
l = d / Cos(fi/2)
where d is offset, and fi is angle between vectors na and nb.
fi = atan2(crossproduct(na,nb), dotproduct(na,nb))
or without trigonometric functions:
l = d / Sqrt((1 + dotproduct(na,nb))/2)
And find offset polygon vertex:
P' = P + l * bis

Related

Vulkan calculation of Barycentric coordinates? Is area function 2D or 3D?

In section 25.8.1 Basic Polygon Rasterization of the Vulkan spec it says:
Barycentric coordinates are a set of three numbers, a, b, and c, each in the range [0,1], with a + b + c
= 1. These coordinates uniquely specify any point p within the triangle or on the triangle’s
boundary as
p = a * p_a + b * p_b + c * p_c
where p_a , p_b , and p_c are the vertices of the triangle. a, b, and c are determined by:
a = A(p, p_b, p_c) / A(p_a, p_b, p_c)
b = A(p, p_a, p_c) / A(p_a, p_b, p_c)
c = A(p, p_a, p_b) / A(p_a, p_b, p_c)
where A(l,m,n) denotes the area in framebuffer coordinates of the triangle with vertices l, m, and n.
Framebuffer coordinates technically have three components. This is specified in 24.5 Controlling the Viewport as:
The vertex’s framebuffer coordinates (x_f , y_f , z_f ) are given by [snip]
What precisely is the formula of the A function?
Is it either:
(a) the same as the formula given to calculate whether the triangle is back-facing or front-facing in 25.8.1, namely:
a = -0.5 * sum_i(x_f[i] * y_f[i+1] - x_f[i+1] * y_f[i])
That is, is it taken as read that the forumla of A does not use the z_f components of its arguments, and is purely a function of the (x_f, y_f) components? (ie It is calculating the area of the two dimensional projection of the triangle onto the x-y plane in framebuffer-space)
or (b), does A use all three framebuffer components? ie Does A return the area of the triangle in the full three-dimensional framebuffer-space (like shown here for example)
or (c) something else?
It actually doesn't matter, mathematically speaking. Whichever function you pick, you'll find that the particulars of the math divide out when computing the barycentric coordinate.
A barycentric coordinate is computed by taking the ratio of two areas. If you linearly project two co-planar triangles from 3D space to 2D space with the same projection, the ratio of their areas is unchanged (assuming that they have an area post-projection).

The mass of components in a binary system for given largest and smallest distance

I try to calculate the mass of the component stars in a binary system.
I only have the period and the largest and smallest distance between them and know how to use them to get the total mass.
To my knowledge, I think I need the distance from one of the stars to the barycenter.
Is that possible to calculate each mass of the component members with this information?
Thank you for your help!
I think, if you only have the period T and the largest a_max and smallest a_min distance between the two stars, as you pointed out, you can calculate the total mass, using the formula
mass_1 + mass_2 = (2*pi / T)^2 * ((a_min + a_max)^3 / G)
However, you cannot calculate the individual masses solely from this information, because the prescribed data, the period T and the largest a_max and smallest a_min distance, are for the relative postion of the stars, not the individual.
What do I mean. Assume you have two stars whose motion has the parameters given above. Then, by Newtonian mechanics, let us assume your coordinate system is placed at the barycenter and if you denote the position vectors r1 and r2 pointing from the barycenter to the respective stars, then, the equations of motion are
(d/dt)^2 r1 = - ( mass_2*G / |r2 - r1|^3 )*(r1 - r2)
(d/dt)^2 r2 = - ( mass_1*G / |r2 - r1|^3 )*(r2 - r1)
If you subtract the first vector differential equation from the second, and you set r = r2 - r1, you obtain the vector differential equation (3 scalar differential equations and 3 scalar variables, the 3D coordinates of the relative position vector r)
(d/dt)^2 r = - ( (mass_1 + mass_2)*G / |r|^3 ) * r
This is the classical vector differential equation that describes the time-evolution of the relative position vector r between the two stars. The information you have, the period T and the largest a_max and smallest a_min, can be used to find a specific solution to the last equation above, the one for r, which gives you the relative motion r = r(t) between the two stars with the prescribed properties. However, the motion of any pair of stars with arbitrary masses mass_1 and mass_2, that sum up to the same value mass_1 + mass_2, will provide a solution to the vector differential equation
(d/dt)^2 r = - ( (mass_1 + mass_2)*G / |r|^3 ) * r
and among all such solution there will be some that posses the desired properties: period T and the largest a_max and smallest a_min. Observe that T, a_min and a_max are properties of the vector r and not so much properties of the individual r1 and r2, which tells you that you cannot find the individual masses.

orientation of normal surface/vertex vectors

Given a convex 3d polygon (convex hull) How can I determine the correct direction for normal surface/vertex vectors? As the polygon is convex, by correct I mean outward facing (away from the centroid).
def surface_normal(centroid, p1, p2, p3):
a = p2-p1
b = p3-p1
n = np.cross(a,b)
if **test including centroid?** :
return n
else:
return -n # change direction
I actually need the normal vertex vectors as I am exporting as a .obj file, but I am assuming that I would need to calculate the surface vectors before hand and combine them.
This solution should work under the assumption of a convex hull in 3d. You calculate the normal as shown in the question. You can normalize the normal vector with
n /= np.linalg.norm(n) # which should be sqrt(n[0]**2 + n[1]**2 + n[2]**2)
You can then calculate the center point of your input triangle:
pmid = (p1 + p2 + p3) / 3
After that you calculate the distance of the triangle-center to your surface centroid. This is
dist_centroid = np.linalg.norm(pmid - centroid)
The you can calculate the distance of your triangle_center + your normal with the length of the distance to the centroid.
dist_with_normal = np.linalg.norm(pmid + n * dist_centroid - centroid)
If this distance is larger than dist_centroid, then your normal is facing outwards. If it is smaller, it is pointing inwards. If you have a perfect sphere and point towards the centroid, it should almost be zero. This may not be the case for your general surface, but the convexity of the surface should make sure, that this is enough to check for its direction.
if(dist_centroid < dist_with_normal):
n *= -1
Another, nicer option is to use a scalar product.
pmid = (p1 + p2 + p3) / 3
if(np.dot(pmid - centroid, n) < 0):
n *= -1
This checks if your normal and the vector from the mid of your triangle to the centroid have the same direction. If that is not so, change the direction.

Finding out Force from Torque and Distance

I have solid object that is spinning with a torque W, and I want to calculate the force F applied on a certain point that's D units away from the center of the object. All these values are represented in Vector3 format (x, y, z)
I know until now that W = D x F, where x is the cross product, so by expanding this I get:
Wx = Dy*Fz - Dz*Fy
Wy = Dz*Fx - Dx*Fz
Wz = Dx*Fy - Dy*Fx
So I have this equation, and I need to find (Fx, Fy, Fz), and I'm thinking of using the Simplex method to solve it.
Since the F vector can also have negative values, I split each F variable into 2 (F = G-H), so the new equation looks like this:
Wx = Dy*Gz - Dy*Hz - Dz*Gy + Dz*Hy
Wy = Dz*Gx - Dz*Hx - Dx*Gz + Dx*Hz
Wz = Dx*Gy - Dx*Hy - Dy*Gx + Dy*Hx
Next, I define the simplex table (we need <= inequalities, so I duplicate each equation and multiply it by -1.
Also, I define the objective function as: minimize (Gx - Hx + Gy - Hy + Gz - Hz).
The table looks like this:
Gx Hx Gy Hy Gz Hz <= RHS
============================================================
0 0 -Dz Dz Dy -Dy <= Wx = Gx
0 0 Dz -Dz -Dy Dy <= -Wx = Hx
Dz -Dz 0 0 Dx -Dx <= Wy = Gy
-Dz Dz 0 0 -Dx Dx <= -Wy = Hy
-Dy Dy Dx -Dx 0 0 <= Wz = Gz
Dy -Dy -Dx Dx 0 0 <= -Wz = Hz
============================================================
1 -1 1 -1 1 -1 0 = Z
The problem is that when I run it through an online solver I get Unbounded solution.
Can anyone please point me to what I'm doing wrong ?
Thanks in advance.
edit: I'm sure I messed up some signs somewhere (for example the Z should be defined as a max), but I'm sure I'm wrong when defining something more important.
There exists no unique solution to the problem as posed. You can only solve for the tangential projection of the force. This comes from the properties of the vector (cross) product - it is zero for collinear vectors and in particular for the vector product of a vector by itself. Therefore, if F is a solution of W = r x F, then F' = F + kr is also a solution for any k:
r x F' = r x (F + kr) = r x F + k (r x r) = r x F
since the r x r term is zero by the definition of vector product. Therefore, there is not a single solution but rather a whole linear space of vectors that are solutions.
If you restrict the solution to forces that have zero projection in the direction of r, then you could simply take the vector product of W and r:
W x r = (r x F) x r = -[r x (r x F)] = -[(r . F)r - (r . r)F] = |r|2F
with the first term of the expansion being zero because the projection of F onto r is zero (the dot denotes scalar (inner) product). Therefore:
F = (W x r) / |r|2
If you are also given the magnitude of F, i.e. |F|, then you can compute the radial component (if any) but there are still two possible solutions with radial components in opposing directions.
Quick dirty derivation...
Given D and F, you get W perpendicular to them. That's what a cross product does.
But you have W and D and need to find F. This is a bad assumption, but let's assume F was perpendicular to D. Call it Fp, since it's not necessarily the same as F. Ignoring magnitudes, WxD should give you the direction of Fp.
This ignoring magnitudes, so fix that with a little arithmetic. Starting with W=DxF applied to Fp:
mag(W) = mag(D)*mag(Fp) (ignoring geometry; using Fp perp to D)
mag(Fp) = mag(W)/mag(D)
Combining the cross product bit for direction with this stuff for magnitude,
Fp = WxD / mag(WxD) * mag(Fp)
Fp = WxD /mag(W) /mag(D) *mag(W) /mag(D)
= WxD / mag(D)^2.
Note that given any solution Fp to W=DxF, you can add any vector proportional to D to Fp to obtain another solution F. That is a totally free parameter to choose as you like.
Note also that if the torque applies to some sort of axle or object constrained to rotate about some axis, and F is applied to some oddball lever sticking out at a funny angle, then vector D points in some funny direction. You want to replace D with just the part perpendicular to the axle/axis, otherwise the "/mag(D)" part will be wrong.
So from your comment is clear that all rotations are spinning around center of gravity
in that case
F=M/r
F force [N]
M torque [N/m]
r scalar distance between center of rotation [m]
this way you know the scalar size of your Force
now you need the direction
it is perpendicular to rotation axis
and it is the tangent of the rotation in that point
dir=r x axis
F = F * dir / |dir|
bolds are vectors rest is scalar
x is cross product
dir is force direction
axis is rotation axis direction
now just change the direction according to rotation direction (signum of actual omega)
also depending on your coordinate system setup
so ether negate F or not
but this is in 3D free rotation very unprobable scenario
the object had to by symmetrical from mass point of view
or initial driving forces was applied in manner to achieve this
also beware that after first hit with any interaction Force this will not be true !!!
so if you want just to compute Force it generate on certain point if collision occurs is this fine
but immediately after this your spinning will change
and for non symmetric objects the spinning will be most likely off the center of gravity !!!
if your object will be disintegrated then you do not need to worry
if not then you have to apply rotation and movement dynamics
Rotation Dynamics
M=alpha*I
M torque [N/m]
alpha angular acceleration
I quadratic mass inertia for actual rotation axis [kg.m^2]
epislon''=omega'=alpha
' means derivation by time
omega angular speed
epsilon angle

Equation to find average of multiple velocities?

I need to find the average Edit: total 2D velocity given multiple 2D velocities (speed and direction). A few examples:
Example 1
Velocity 1 is 90° at a speed of 10 pixels or units per second.
Velocity 2 is 270° at a speed of 5 pixels or units per second.
The average velocity is 90° at 5 pixels or units per second.
Example 2
Velocity 1 is 0° at a speed of 10 pixels or units per second
Velocity 2 is 180° at a speed of 10 pixels or units per second
Velocity 3 is 90° at a speed of 8 pixels or units per second
The average velocity is 90° at 8 pixels or units per second
Example 3
Velocity 1 is 0° at 10 pixels or units per second
Velocity 2 is 90° at 10 pixels or units per second
The average velocity is 45° at 14.142 pixels or units per second
I am using JavaScript but it's mostly a language-independent question and I can convert it to JavaScript if necessary.
If you're going to be using a bunch of angles, I would just calculate each speed,
vx = v * cos(theta),
vy = v * sin(theta)
then sum the x velocities and the y velocities separately as vector components and divide by the total number of velocities,
sum(vx) / total v, sum(vy) / total v
and then finally calculate the final speed and direction with your final vx and vy. The magnitude of the speed can be found by a simple application of pythagorean theorem, and then final angle should just be tan-1(y/x).
Per example #3
vx = 10 * cos(90) + 10 * cos(0) = 10,
vy = 10 * sin(90) + 10 * sin(0) = 10
so, tan-1(10/10) = tan-1(1) = 45
then a final magnitude of sqrt(10^2 + 10^2) = 14.142
These are vectors, and you should use vector addition to add them. So right and up are positive, while left and down are negative.
Add your left-to-right vectors (x axis).
Example 1 = -10+5 = -5
Example 2 = -8 = -8
Example 3 = 10 = 10. (90 degrees is generally 90 degrees to the right)
Add you ups and downs similarly and you get these velocities, your left-to-right on the left in the brackets, and your up-to-down on the right.
(-5, 0)
(-8,0)
(10, 10)
These vectors contain all the information you need to plot the motion of an object, you do not need to calculate angles to plot the motion of the object. If for some reason you would rather use speeds (similar to velocity, but different) and angles, then you must first calculate the vectors as above and then use the Pythagorean theorem to find the speed and simple trigonometry to get the angle. Something like this:
var speed = Math.sqrt(x * x + y * y);
var tangeant = y / x;
var angleRadians = Math.atan(tangeant);
var angleDegrees = angleRadians * (180 / Math.PI);
I'll warn you that you should probably talk to someone who know trigonometry and test this well. There is potential for misleading bugs in work like this.
From your examples it sounds like you want addition of 2-dimensional vectors, not averages.
E.g. example 2 can be represented as
(0,10) + (0,-10) + (-8, 0) = (-8,0)
The speed is then equal to the length of the vector:
sqrt(x^2+y^2)
To get average:
add each speed, and then divide by the number of speeds.
10mph + 20mph / 2 = 15
12mph + 14mph + 13mph + 16mph / 4 = 14 (13,75)
This is not so much average as it is just basic vector addition. You're finding multiple "pixel vectors" and adding them together. If you have a velocity vector of 2 pixels to the right, and 1 up, and you add it to a velocity vector of 3 pixels to the left and 2 down, you will get a velocity vector of 1 pixel left, and 1 down.
So the speed is defined by
pij = pixels going up or (-)down
pii = pixels going right or (-)left
speedi = pii1 + pii2 = 2-3 = -1 (1 pixel left)
speedj = pij1 + pij2 = 1-2 = -1 (1 pixel down)
From there, you need to decide which directions are positive, and which are negative. I recommend that left is negative, and down is negative (like a mathematical graph).
The angle of the vector, would be the arctan(speedj/speedi)
arctan(-1/-1) = 45 degrees