Rectangle in a triangle - c++

I am trying to build a program in C++ that will procedurally generate cities.
For the moment, the city is represented by an array of blocks either Quad blocks or Triangle blocks.
I can't find an effective way to subdivide a triangle (TBlock) into a rectangle (QBlock) and three triangles.
So picture a triangle ABC. We have two point T and T' which are the first and second tier of line segment BC.
Now I need to find P and P' which are respectively on AB and AC line segments.
P is the intersection of AB and the normal of BC passing through T.
P' is the intersection of AB and the normal of BC passing through T'.
I know how to find T and T' and the inward normal of vector BC but I can't find a way to compute the normal passing through T or T'.
Thanks !

Given your (BC) vector is (x, y), a normal vector of BC is (-y, x). Now offset the normal vector by coordinates of T', and you will get the normal of BC passing through T'.

the normal to a line y = m*x + c is the line y = (-1/m)*x + d, where c and d are constants.
You have two lines with a common point (T or T'), you can solve simultaneously to find m and d for both T and T'.

You know that the angle formed by CBA is the same angle formed by TBP. Let's call that O. You also know the distance between B and T. Call it D. Using this we can find P using trigonometry.
Tan(O) = X / D
Where X is the y_axis distance between T and P. Just solve for X since you know O and D.
Once you know X you can just add X to the y value of T to find P.

Related

Finding point perpendicular to two intersecting lines in 3D

I have two lines (L1, L2) in 3D.
L has the following starting and ending coordinates : P1(x1, y1, z1) and P2(x2, y2, z2).
L2 has P3(x3, y3, z3) and P2(x2, y2, z2). Notice how both L1's and L2's P2 are same: meaning they intersect at this specific point.
Now I want to find a point P(x,y,z) at any distance from P2 that line (P,P2) is perpendicular to plane on which points (P1,P2,P3) are placed.
The cross product is the way of calculating perpendicularity relative to your two lines. You need to make vectors of your line parameters, simples way would be this:
vecL1 = (x1-x2, y1-y2, z1-z2) and
vecL2 = (x3-x2, y3-y2, z3-z2)
Cross product you can google how to calculate, but in this scenario:
//Replacing the new x,y,z's with i, j, k to avoid naming confusion.
vecL3 = vecL1 x vecL2 = (j1*k2 - j2*k1, k1*i2 - k2*i1, i1*j2 - j1*i2)
Now the cross product per definition is a new vector (line) that is strictly perpendicular to the two lines/vectors you used to calculate this with. But vectors lack position, so you need to add the intersection point to this vector in order to find some point.
//i3, j3, k3 being the third vector's parameters
P3(i3+x2, j3+y2, k3+z2)
PS: The distance from your P2 to P3 is per definition (how cross products work) to the area of a parallelogram that the two lines are sides of, I found a link to illustrate:
Normalizing the 3rd vector will make the distance equal to 1 from P2.
The cross product will give you a perpendicular vector to the plane described by two other vectors, in pseudo-code:
normal = cross(normalize(P1-P2), normalize(P3-P2))
Since you've defined P2 as the point of intersection, you can simply add this normal vector to P2 to get your perpendicular point.
If you have any line AB then an arbitrary point C will always be perpendicular to AB IFF triangle ABC has no angle larger than π/2
That means there will always be a point D on line AB such that CD is perpendicular to AB

How to find correct rotation from one vector to another?

I have two objects, and each object has two vectors:
normal vector
up vector
Like on this image:
Up vector is perpendicular to normal vector. Now I want to find unique rotation from one object to another, how to do that?
I have one method to find rotation between one vector to another, and it works. The problem is that I need to take care the two vectors: normal vector and up vector. If I use this method to rotate normal vector from object one to normal from object two, the up vector could be pointing wrong way, and they needs to be parallel.
Here is the code for finding the shortest rotation:
GE::Quat GE::Quat::fromTo(const Vector3 &v1, const Vector3 &v2)
{
Vector3 a = Vector3::cross(v1, v2);
Quat q;
float dot = Vector3::dot(v1, v2);
if ( dot >= 1 )
{
q = Quat(0,0,0,1);
}
else if ( dot < -0.999999 )
{
Vector3 axis = Vector3::cross(Vector3(1,0,0),v2);
if (axis.length() == 0) // pick another if colinear
axis = Vector3::cross(Vector3(0,1,0),v2);
axis.normalize();
q = Quat::axisToQuat(axis,180);
}
else
{
float s = sqrt( (1+dot)*2 );
float invs = 1 / s;
Vector3 c = Vector3::cross(v1, v2);
q.x = c.x * invs;
q.y = c.y * invs;
q.z = c.z * invs;
q.w = s * 0.5f;
}
q.normalize();
return q;
}
What should I change/add to this code, to find the correct rotation?
Before we begin, I will assume that both UP vector and normal vector are normalized and orthogonal (dot product is zero) between them.
Let's say that you want to rotate your yellow plate to be aligned with the rose (red?) plate. So, our reference will be the vectors from yellow plate and we will call our coordinate system as XYZ, where Z -> normal yellow vector, Y -> Up yellow vector and X -> YxZ (cross product).
In the same way, for rose plate, the rotated coordinate system will be called X'Y'Z' where Z' -> normal rose vector, Y' -> up rose vector and X' -> Y'xZ' (cross product).
Ok to find the rotation matrix, we only need to make sure that our normal yellow vector will become normal rose vector; that our up yellow vector will be transfomed in the up rose vector, and so on, i.e.:
RyellowTOrose = |X'x Y'x Z'x|
|X'y Y'y Z'y|
|X'z Y'z Z'z|
in other words, after you have any primitives transformed to be in coordinates of yellow system, applying this transformation, will rotate it to be aligned with rose coordinates system
If your up and normal vector aren't orthogonal, you can correct one of them easily. Just make the cross product between normal and up (results in a vector called C, for convenience) and do again the cross product between with C and normal, to correct the up vector.
First of all, I make the claim that there is only one such transformation that will align the orientation of the two objects. So we needn't worry about finding the shortest one.
Let the object that will be rotated be called a, and call the object that stay stationary b. Let x and y be the normal and up vectors respectively for a, and similarly let u and v be these vectors for b. I will assume x, y, u, and v are unit length, and that is x is orthogonal to y, and u is orthogonal to v. If any of this is not the case code can be written to correct this (via planar projection and normalization).
Now let’s construct matrices defining the “world space” the orientation of a and b. (let ^ denote the cross product) construct z as x ^ y, and construct c as a ^ b. Writing x, y, z and a, b, c to columns of each matrix gives us the two matrices, call them A and B respectively. (the cross product here gives us a unit length and mutually orthogonal vector since the same is true of the operands)
The change of coordinate system transformation to obtain B in terms of A is A^-1 (the inverse of matrix A, where ^ denotes a generalization of an exponent), in this case A^-1 can be computed as A^T, the transpose, since A is an orthogonal matrix by construction. Then the physical transformation to B is just matrix B itself. So, transforming an object by A^-1, and then by B will give the desired result. However these transformations can be concatenated into one transformation by multiplying B on the right into A^-1 on the left.
You end up with this matrix (assuming no arithmetic errors):
_ _
| x0*u0+x1*u1+x2*u2 x0*v0+x1*v1+x2*v2 x0*(u1*v2-u2*v1)+x1*(u2*v0-u0*v2)+x2*(u0*v1-u1*v0) |
| |
| y0*u0+y1*u1+y2*u2 y0*v0+y1*v1+y2*v2 y0*(u1*v2-u2*v1)+y1*(u2*v0-u0*v2)+y2*(u0*v1-u1*v0) |
| |
| (x0*y2-x2*y1)*u0+(x2*y0-x0*y2)*u1+(x0*y1-x1*y0)*u2 (x0*y2-x2*y1)*v0+(x2*y0-x0*y2)*v1+(x0*y1-x1*y0)*v2 (x0*y2-x2*y1)*(u1*v2-u2*v1)+(x2*y0-x0*y2)*(u2*v0-u0*v2)+(x0*y1-x1*y0)*(u0*v1-u1*v0) |
|_ _|
The quaternion code rotates just one vector to another without "Up" vector.
In your case simply build rotation matrix from 3 orthogonal vectors
normalized (unit) direction vector
normalized (unit) up vector
cross product of direction and up vectors.
Than you will have R1 and R2 matrix (3x3) representing rotation of object in two cases.
To find rotation from R1 to R2 just do
R1_to_R2 = R2 * R1.inversed()
And matrix R1_to_R2 is the transformation matrix from one orientation to other. NOTE: R1.inversed() here can be replaced with R1.transposed()

How to project a point onto a plane in 3D?

I have a 3D point (point_x,point_y,point_z) and I want to project it onto a 2D plane in 3D space which (the plane) is defined by a point coordinates (orig_x,orig_y,orig_z) and a unary perpendicular vector (normal_dx,normal_dy,normal_dz).
How should I handle this?
Make a vector from your orig point to the point of interest:
v = point-orig (in each dimension);
Take the dot product of that vector with the unit normal vector n:
dist = vx*nx + vy*ny + vz*nz; dist = scalar distance from point to plane along the normal
Multiply the unit normal vector by the distance, and subtract that vector from your point.
projected_point = point - dist*normal;
Edit with picture:
I've modified your picture a bit. Red is v. dist is the length of blue and green, equal to v dot normal. Blue is normal*dist. Green is the same vector as blue, they're just plotted in different places. To find planar_xyz, start from point and subtract the green vector.
This is really easy, all you have to do is find the perpendicular (abbr here |_) distance from the point P to the plane, then translate P back by the perpendicular distance in the direction of the plane normal. The result is the translated P sits in the plane.
Taking an easy example (that we can verify by inspection) :
Set n=(0,1,0), and P=(10,20,-5).
The projected point should be (10,10,-5). You can see by inspection that Pproj is 10 units perpendicular from the plane, and if it were in the plane, it would have y=10.
So how do we find this analytically?
The plane equation is Ax+By+Cz+d=0. What this equation means is "in order for a point (x,y,z) to be in the plane, it must satisfy Ax+By+Cz+d=0".
What is the Ax+By+Cz+d=0 equation for the plane drawn above?
The plane has normal n=(0,1,0). The d is found simply by using a test point already in the plane:
(0)x + (1)y + (0)z + d = 0
The point (0,10,0) is in the plane. Plugging in above, we find, d=-10. The plane equation is then 0x + 1y + 0z - 10 = 0 (if you simplify, you get y=10).
A nice interpretation of d is it speaks of the perpendicular distance you would need to translate the plane along its normal to have the plane pass through the origin.
Anyway, once we have d, we can find the |_ distance of any point to the plane by the following equation:
There are 3 possible classes of results for |_ distance to plane:
0: ON PLANE EXACTLY (almost never happens with floating point inaccuracy issues)
+1: >0: IN FRONT of plane (on normal side)
-1: <0: BEHIND plane (ON OPPOSITE SIDE OF NORMAL)
Anyway,
Which you can verify as correct by inspection in the diagram above
This answer is an addition to two existing answers.
I aim to show how the explanations by #tmpearce and #bobobobo boil down to the same thing, while at the same time providing quick answers to those who are merely interested in copying the equation best suited for their situation.
Method for planes defined by normal n and point o
This method was explained in the answer by #tmpearce.
Given a point-normal definition of a plane with normal n and point o on the plane, a point p', being the point on the plane closest to the given point p, can be found by:
p' = p - (n ⋅ (p - o)) × n
Method for planes defined by normal n and scalar d
This method was explained in the answer by #bobobobo.
Given a plane defined by normal n and scalar d, a point p', being the point on the plane closest to the given point p, can be found by:
p' = p - (n ⋅ p + d) × n
If instead you've got a point-normal definition of a plane (the plane is defined by normal n and point o on the plane) #bobobobo suggests to find d:
d = -n ⋅ o
and insert this into equation 2. This yields:
p' = p - (n ⋅ p - n ⋅ o) × n
A note about the difference
Take a closer look at equations 1 and 4. By comparing them you'll see that equation 1 uses n ⋅ (p - o) where equation 2 uses n ⋅ p - n ⋅ o. That's actually two ways of writing down the same thing:
n ⋅ (p - o) = n ⋅ p - n ⋅ o = n ⋅ p + d
One may thus choose to interpret the scalar d as if it were a 'pre-calculation'. I'll explain: if a plane's n and o are known, but o is only used to calculate n ⋅ (p - o),
we may as well define the plane by n and d and calculate n ⋅ p + d instead, because we've just seen that that's the same thing.
Additionally for programming using d has two advantages:
Finding p' now is a simpler calculation, especially for computers. Compare:
using n and o: 3 subtractions + 3 multiplications + 2 additions
using n and d: 0 subtractions + 3 multiplications + 3 additions.
Using d limits the definition of a plane to only 4 real numbers (3 for n + 1 for d), instead of 6 (3 for n + 3 for o). This saves ⅓ memory.
It's not sufficient to provide only the plane origin and the normal vector. This does define the 3d plane, however this does not define the coordinate system on the plane.
Think that you may rotate your plane around the normal vector with regard to its origin (i.e. put the normal vector at the origin and "rotate").
You may however find the distance of the projected point to the origin (which is obviously invariant to rotation).
Subtract the origin from the 3d point. Then do a cross product with the normal direction. If your normal vector is normalized - the resulting vector's length equals to the needed value.
EDIT
A complete answer would need an extra parameter. Say, you supply also the vector that denotes the x-axis on your plane.
So we have vectors n and x. Assume they're normalized.
The origin is denoted by O, your 3D point is p.
Then your point is projected by the following:
x = (p - O) dot x
y = (p - O) dot (n cross x)
Let V = (orig_x,orig_y,orig_z) - (point_x,point_y,point_z)
N = (normal_dx,normal_dy,normal_dz)
Let d = V.dotproduct(N);
Projected point P = V + d.N
I think you should slightly change the way you describe the plane. Indeed, the best way to describe the plane is via a vector n and a scalar c
(x, n) = c
The (absolute value of the) constant c is the distance of the plane from the origin, and is equal to (P, n), where P is any point on the plane.
So, let P be your orig point and A' be the projection of a new point A onto the plane. What you need to do is find a such that A' = A - a*n satisfies the equation of the plane, that is
(A - a*n, n) = (P, n)
Solving for a, you find that
a = (A, n) - (P, n) = (A, n) - c
which gives
A' = A - [(A, n) - c]n
Using your names, this reads
c = orig_x*normal_dx + orig_y*normal_dy+orig_z*normal_dz;
a = point_x*normal_dx + point_y*normal_dy + point_z*normal_dz - c;
planar_x = point_x - a*normal_dx;
planar_y = point_y - a*normal_dy;
planar_z = point_z - a*normal_dz;
Note: your code would save one scalar product if instead of the orig point P you store c=(P, n), which means basically 25% less flops for each projection (in case this routine is used many times in your code).
Let r be the point to project and p be the result of the projection. Let c be any point on the plane and let n be a normal to the plane (not necessarily normalised). Write p = r + m d for some scalar m which will be seen to be indeterminate if their is no solution.
Since (p - c).n = 0 because all points on the plane satisfy this restriction one has (r - c).n + m(d . n) = 0 and so m = [(c - r).n]/[d.n] where the dot product (.) is used. But if d.n = 0 there is no solution. For example if d and n are perpendicular to one another no solution is available.

Enlarge and restrict a quadrilateral polygon in opencv 2.3 with C++

I can't find this answer anywhere, I hope somebody could help me.
I have an image (all black) with a white generic quadrilateral polygon inside it, and the correspondent 4 corners coordinates of such polygon.
I need to find the corners of a slightly enlarged quadrilateral and the same for a slightly reduced one (the shape must be the same, just a resize of the quadrilateral inside the image).
Is there a function which allows me to do that, or should I compute manually some geometry?
Thank you for your help.
Consider a vertex p of the polygon, with its predecessor p1 and successor p2.
The vectors between these points are
v1 = p1 - p
v2 = p2 - p
(The computation is componentwise for the x and y coordinates respectively).
In the shrunk polygon the vertex p is moved to p' along the line
which halves the angle a between the vectors v1 and v2.
The vector w in this direction is
w = v1 + v2
and the unit vector v in this direction is
v = w / |w| = (w_x, w_y) / sqrt(w_x*w_x + w_y*w_y)
The new point p' is
p' = p + k * v , i.e. :
p_x' = p_x + k * v_x
p_y' = p_y + k * v_y
where k is the shifting distance (a scalar).
If the vertex p is convex (as in the figure), then k >= 0 means
shrinking and k <= 0 means expanding.
If the vertex p is concave, then k >= 0 means
expanding and k <= 0 means shrinking.
What you want is polygon offset. If you want to use an existing library. Consider using Clipper
void OffsetPolygons(const Polygons &in_polys,
Polygons &out_polys,
double delta,
JoinType jointype = jtSquare, double MiterLimit = 2.0);
This function offsets the 'polys' polygons parameter by the 'delta' amount. Positive delta values expand outer polygons and contract inner 'hole' polygons. Negative deltas do the reverse.
Although I must add for a simple geometry like a Quadrilateral it is easy to do it from scratch.
Identity all four infinite lines that form the Quadrilateral
Offset the lines parallel to themselves
Compute intersection of these new lines
Just be careful of corner cases. When you offset a quadrilateral which has one very small edge. It will become a triangle on offset.
I agree with the answer of parapura rajkumar. I wanted to add that the solution of Jiri is not 100% correct because the vertex centroid of a quadrilateral is different to the area centroid of a quadrilateral, as it is written here. For the enlargement one would have to use the area centroid - or the much more elegant solution with the parallel lines mentioned by parapura rajkumar. I just want to add the following to this answer:
You can simply determine the outer points of the enlarged quadrilateral by computing the normal vectors of the vectors between the points of the original quadrilateral. Afterwards, normalize the normal vectors, multiply them with the offset and add them to the points of the original quadrilateral. Given these outer points you can now compute the intersection of the parallel lines with this formula.

given a triangle and a segment, find third point which would create a similar triangle [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 11 years ago.
Improve this question
I've seen similar questions asked, but I find the explanations still somewhat difficult.
I have a triangle with its 3 vertices given in (x,y). I am also given a segment of two points. I want to place a third point around the segment so that it completes a triangle with similar shape to the original triangle. This new triangle might not be the same size, but all the angles would be the same. How would I find this third point?
I have gotten as far as finding the length of each segment and the angles of the triangle, but I'm kind of stuck.
I saw the following post and tried to implement the code discussed with no luck on getting the correct coordinates..
Calculating the coordinates of the third point of a triangle
Edit: Sorry about that, I forgot to specify that I know that I want to place my third point close to one of the ends of the segment. Example: I have triangle with verticies A, B, and C. I have a segment DE (created by points D and E), where DE is similar to AB. I want to place point F at a position so that AD is similar to EF and AC is similar to DF.
For the sake of being specific, suppose your original triangle has vertices A, B, and C. The line segment has end points D and E. Furthermore, you want DE to correspond to AB. The problem is then to find a point F such that triangle DEF is similar to triangle ABC. I hope that's what you're trying to solve, because that's what I'm going to give you as a solution. Explaining the solution is going to be a lot longer than coding it. :)
I think you can do all this with vector arithmetic, without using angles and trig functions. Let all points be represented by their x and y coordinates in some shared coordinate system. (If you don't know vector arithmetic, see the appendix below.)
First, we'll imagine a local coordinate system u-v with A as the origin and AB parallel to the u axis; the v axis is perpendicular to u; we'll nail down which direction is positive in a second. Now, even though AB is the side of the triangle, from now on we'll think of it as a vector from A to B. It can be computed in the x-y system as AB = (B[x] - A[x], B[y] - A[y]). The same goes for all other point pairs. Individual points will also be vectors in the x-y system. A unit vector in the x-y system along the u axis is given by:
u = (u_x, u_y) = AB / ‖AB‖
A unit vector along the v axis is just:
v = (-u_y, u_x)
(We could also have used (u_y, -u_x).) We will now compute the vector components of AC in the u-v system:
AC_u = (AC_x * u_x, AC_y * u_y) // = (AC ∙ u)
AC_v = ‖AC - AC_u * u‖
Now we imagine another local coordinate system, r-s, with origin at D and r axis along DE. The unit vectors along r and s in the x-y system are:
r = (r_x, r_y) = DE / ‖DE‖
s = (-r_y, r_x)
We can scale the u-v components of AC by the ratio ‖DE‖ / ‖AB‖ to get r-s components of DF:
DF_r = AC_u * ‖DE‖ / ‖AB‖
DF_s = AC_v * ‖DE‖ / ‖AB‖
Finally, we just need to add everything together:
F = D + DF_r * r + DF_s * s
(Recall that D, r, and s are vectors.) That's it. Although the post is long, there are only a dozen or so lines of code (each vector calculation step takes one lines for each component) plus another handful for a function to compute the norm of a vector.
APPENDIX: Vector arithmetic
Vectors in an x-y coordinate system are ordered pairs of numbers: (x, y). Two vectors A and B can be added or subtracted by adding or subtracting their components: A ± B = (A_x ± B_x, A_y ± B_y). A vector can be multiplied by a number (also called a scalar) by multiplying each vector component by the scalar: q*A = (q*A_x, q*A_y). Division by a scalar is just multiplication by the inverse of the scalar. The norm of a vector A (also called its length) is written ‖A‖; it can be computed using the Pythagorean theorem: ‖A‖ = sqrt(A_x * A_x + A_y * A_y). A unit vector is a vector with norm = 1. The dot product of two vectors is the sum (a simple number) of the products of corresponding components: A ∙ B = A_x*B_x + A_y*B_y. Note that the dot product of a vector with itself is the square of its norm. An important identity about the dot product is: A ∙ B = ‖A‖ * ‖B‖ * cos(α) where α is the angle between A and B. A corollary is that the dot product of two non-zero vectors is zero exactly when the vectors are perpendicular to one another.