The task itself:
Triangle set. Implement its motion on the basis of mirror reflection with respect to an arbitrary straight line ax + by + c = 0 , whose coefficients are entered by the user.

What has already been done:
I read from the fields on the form the coordinates of three points of the triangle.
Placing them in objects of class Point ( left(x, y) , top(x, y) , right(x, y) ).
I make an array of points from the points of a triangle:

 Point[] points = new Point[3] { left, top, right }; 
I draw the Cartesian coordinate system:
 DrawField(); 
DrawCoordinateSystem();
I draw a triangle:
 graph.FillPolygon(Brushes.ForestGreen, points); 
I make a mirror reflection of a triangle:
(as I understand it, you just need to change the sign of all points of Y )
 Point[] pointsCopy = (Point[]) points.Clone();

for (int i = 0; i pointsCopy.Length; i++)
    pointsCopy[i].Y = -pointsCopy[i].Y;

graph.FillPolygon(Brushes.RoyalBlue, pointsCopy); 
I read the coefficients ( a , b , c ) for the equation ax + by + c = 0 from the fields in the form.

Here's what happened:
Affine transformation of triangle

Question:
Tell me how can I move it further with respect to the straight ax + by + c = 0 ?

  • one
    sernam.ru/book_mm3d.php?id=46 - Alexander Muksimov
  • 3
    “As far as I understand, you just need to change the sign of all points of Y” - misunderstood. This mirrors the Ox axis, and you need a relatively straight line ax + by + c = 0 . - VladD

4 answers 4

The point of the reflected triangle (polygon) can be calculated as follows:

 x = Ax + (Ax - P0.x) y = Ay + (Ay - P0.y) 

Where,

  |B*P0.x + C*P0.y, C| |C*P1.x - B*P1.y, -B| Ax = --------------------- , -B*B - C*C |B, B*P0.x + C*P0.y| |C, C*P1.y - B*P1.y| Ay = --------------------- -B*B - C*C B = P2.x - P1.x C = P2.y - P1.y 

P0 - polygon point,

P1, P2 - points forming a line (ax + by + c = 0)

For detailed explanations about where these formulas came from, look at my answer to a similar question.

visualization

  • I have already decided my question, but thanks anyway. Described as an answer. - Taras Koval
  • This solution is engaged in the search for projection points on a straight line. If these points are really needed, then this is useful. But if only reflection is of interest, then the effort expended in searching for points of projections is in fact redundant. - AnT
  • @AnT agrees, but there wasn’t any outrageous effort at all - the system of 2 equations with 2 unknowns was solved only - ampawd

In such tasks, the easiest way to work with the vector representation is that it is very visual and accessible for the head to understand. No complex formulas for calculations, turns, matrices do not need to know.

enter image description here

A is a point, B is a vector, together they define a line from which to mirror.

The formula for this line is: A + B * t

Point C and vector D define a perpendicular line. Point C known from the condition that it is one of the points of the triangle. Vector D is also known. This vector is perpendicular to vector B , that is, it has coordinates By,-Bx , or -By,Bx , any one will suit us.

We make the equation of the intersection point

 Ax + Bx * t = Cx + Dx * f Ay + By * t = Cy + Dy * f 

t and f are coefficients by which we multiply the B and D vectors to get to the intersection point, they are our variables that we need to find.

we substitute for Dx,Dy components calculated on the basis of B , that is, the vector perpendicular to it.

 Ax + Bx * t = Cx - By * f Ay + By * t = Cy + Bx * f 

solve the equation and find the coefficient f . He then we need.

Mirror point to point C , this is C + 2 * f * D

Coordinate

 x = Cx + 2 * f * Dx y = Cy + 2 * f * Dy; 
  • Can I have more details? I don’t really understand - Taras Koval
  • @TarasKoval then I will clarify the task, do I need to display a relatively straight line and then animate the movement parallel to the straight line? - Dmitry Polyanin
  • @TarasKova or just mirror? - Dmitry Polyanin
  • You just need to mirror - Taras Koval
  • @TarasKoval well, now I will explain - Dmitry Polyanin

From the "mathematical" point of view to reflect the point (Px, Py) with respect to the straight line A * x + B * y + C = 0 you can do this:

  1. Normalize the equation of a straight line, i.e. we divide all the coefficients of the equation by the length of the normal vector (A, B) . We obtain the normalized equation

     A' * x + B' * y + C' = 0 
  2. We calculate the sign distance from the point (Px, Py) to the straight line

     D = A' * Px + B' * Py + C' 
  3. Move the point (Px, Py) at a distance of 2D against the direction of the normal vector (A', B')

     Px' = Px - 2 * A' * D Py' = Py - 2 * B' * D 

Done - we got the mirror image of the point (Px', Py') .

From a practical point of view, instead of pre-normalizing the equation in step 1, it is better to use unnormalized coefficients A , B and C and then just take into account the length of the vector in step 3 - this eliminates the need to calculate the square root to calculate the length and allows you to solve the problem in integers

 D = A * Px + B * Py + C L = A * A + B * B; Px' = Px - 2 * A * D / L Py' = Py - 2 * B * D / L 

    Here's how I figured out my task, can someone come in handy.


    To perform a reflection of a triangle with respect to an arbitrary line, you must perform specific actions:

    • moving the line and triangle so that the line passes through the origin;
    • rotation of the line and triangle around the point of origin of coordinates to coincide with the coordinate axis X;
    • reflection relative to the coordinate axis;
    • reverse rotation around the origin;
    • move to the starting position.

    In the matrix form, this transformation has the idea
    [T] = [T'] [R] [R'] [R^(-1)] [T'^(-1)] , where T' is the displacement matrix, R is the rotation matrix around the origin, R ' - reflection matrix.


    The equation ax + by + c = 0 can be reduced to the form:

      by = -ax - c
     y = -a / bx - c / b 

    From it we find two points of the line A , B :

     Point A = new Point( -width, -(a / b) * -width - c / b ); Point B = new Point( width, -(a / b) * width - c / b ); 

    Where a , b , c are coefficients read from fields on the form, width is the distance from the beginning of the canvas to the middle ( width = Canvas.Width / 2 ), where x = 0.

    As a result, there is a line L passing through the entire coordinate system.
    We write it in matrix form:

     float[,] L = new float[2, 3] { { AX, AY, 1 }, { BX, BY, 1 } }; 

    We also write the matrix X from the array of points of the triangle points :

     float[,] X = new float[3, 3] { { points[0].X, points[0].Y, 1 }, { points[1].X, points[1].Y, 1 }, { points[2].X, points[2].Y, 1 } }; 

    Now we make affine transformations by multiplying matrices.
    For multiplication we will use the MultiplyMatrix method.

     private static float[,] MultiplyMatrix(float[,] a, float[,] b) { float[,] product = new float[a.GetLength(0), b.GetLength(1)]; for (int row = 0; row product.GetLength(0); row++) for (int col = 0; col product.GetLength(1); col++) // Multiply the row of A by the column of B for (int inner = 0; inner a.GetLength(1); inner++) product[row, col] += a[row, inner] * b[inner, col]; return product; } 

    1) To move a line and a triangle so that the line passes through the origin, we find the position of y at x = 0 :

     float ys = -(a / b) * 0 - c / b; 

    Move the line and triangle to the origin using the displacement matrix:

     float[,] T = new float[3, 3] { { 1, 0, 0 }, { 0, 1, 0 }, { 0, -ys, 1 } }; L = MultiplyMatrix(L, T); X = MultiplyMatrix(X, T); 

    2) Rotate the line and triangle around the origin point until it coincides with the coordinate axis X To do this, we find at what angle is the line relative to the X axis:

     double radians = Math.Atan(-(a / b)); 

    And rotate using the rotation matrix around the origin:

     float[,] R = new float[3, 3] { { Math.Cos(radians), -Math.Sin(radians), 0 }, { Math.Sin(radians), Math.Cos(radians), 0 }, { 0, 0, 1 } }; L = MultiplyMatrix(L, R); X = MultiplyMatrix(X, R); 

    3) Reflect the triangle relative to the coordinate axis using the reflection matrix:

     float[,] Rr = new float[3, 3] { { 1, 0, 0 }, { 0, -1, 0 }, { 0, 0, 1 } }; X = MultiplyMatrix(X, Rr); 

    4) Make a reverse rotation around the origin:

     float[,] Rh = new float[3, 3] { { Math.Cos(radians), Math.Sin(radians), 0 }, { -Math.Sin(radians), Math.Cos(radians), 0 }, { 0, 0, 1 } }; L = MultiplyMatrix(L, Rh); X = MultiplyMatrix(X, Rh); 

    5) Making the move to the starting position:

     float[,] Th = new float[3, 3] { { 1, 0, 0 }, { 0, 1, 0 }, { 0, ys, 1 } }; L = MultiplyMatrix(L, Th); X = MultiplyMatrix(X, Th); 

    Assign new values ​​to the points array:

     for (int i = 0; i p.Length; i++) { points[i].X = X[i, 0]; points[i].Y = X[i, 1]; } 

    We draw a triangle with new coordinates:

     graph.FillPolygon(Brushes.RoyalBlue, points); 

    Affine transformation

    • "you need to perform specific actions ..." This is called "scratching your left ear with your right foot." Nothing like this is necessary. - AnT