TheSwamp

Code Red => .NET => Topic started by: huiz on May 26, 2011, 03:19:19 PM

Title: Who is good in math...
Post by: huiz on May 26, 2011, 03:19:19 PM
I've not seen a school from inside the last 20 years (besides kindergarten where my kids are playing around) and I did not pay much attention when I had math lessons... So who can help me with a formula?

I have 3 points (Point2D objects), let's say A, B and C. I have an imaginary line between A and B. I want to project C on the line A-B (C can be before A or after B on that line) and I would like to know the coordinates of the projected point C. And all that in plain VB or C#.

I know I could draw two rays, get the intersection and remove the rays but there is some formula for. Anyone with a quick help?  :-)
Title: Re: Who is good in math...
Post by: Lee Mac on May 26, 2011, 03:30:44 PM
I would use the vector dot product of the vector AC and the unit vector AB, this will give you the distance of the projection of C along AB as measured from A
Title: Re: Who is good in math...
Post by: Jeff H on May 26, 2011, 03:38:08 PM
Here is a great resources for catching back up on math http://www.theswamp.org/index.php?topic=37552.0


*********Edit*******
Link to the videos http://www.khanacademy.org/#browse
Title: Re: Who is good in math...
Post by: sinc on May 26, 2011, 06:22:52 PM
Have you looked at Curve.GetClosestPointTo()...?
Title: Re: Who is good in math...
Post by: Lee Mac on May 26, 2011, 07:10:53 PM
Another, using a crafty coordinate transformation:

Code: [Select]
(defun LM:ClosestPointToLine ( pt p1 p2 / n )
  (setq n  (mapcar '- p2 p1)
        p1 (trans p1 0 n) pt (trans pt 0 n)
  )
  (trans (list (car p1) (cadr p1) (caddr pt)) n 0)
)

Code: [Select]
pt  -  given point
p1  -  first point of line
p2  -  second point of line

 :wink:
Title: Re: Who is good in math...
Post by: jgr on May 26, 2011, 08:01:01 PM
Code: [Select]
Public Shared Sub ClosestPointOnSegmentFromPoint(ByVal x1 As Double, _
                                                  ByVal y1 As Double, _
                                                  ByVal x2 As Double, _
                                                  ByVal y2 As Double, _
                                                  ByVal px As Double, _
                                                  ByVal py As Double, _
                                                  ByRef nx As Double, _
                                                  ByRef ny As Double)

     Dim vx As Double = x2 - x1
     Dim vy As Double = y2 - y1
     Dim wx As Double = px - x1
     Dim wy As Double = py - y1
     Dim c1 As Double = vx * wx + vy * wy

     If c1 <= 0# Then
         nx = x1
         ny = y1
         Return
     End If

     Dim c2 As Double = vx * vx + vy * vy
     If c2 <= c1 Then
         nx = x2
         ny = y2
         Return
     End If

     Dim Ratio As Double = c1 / c2

     nx = x1 + ratio * vx
     ny = y1 + ratio * vy

 End Sub

 Public Shared Sub ClosestPointOnSegmentFromPoint(ByVal x1 As Double, _
                                                  ByVal y1 As Double, _
                                                  ByVal z1 As Double, _
                                                  ByVal x2 As Double, _
                                                  ByVal y2 As Double, _
                                                  ByVal z2 As Double, _
                                                  ByVal px As Double, _
                                                  ByVal py As Double, _
                                                  ByVal pz As Double, _
                                                  ByRef nx As Double, _
                                                  ByRef ny As Double, _
                                                  ByRef nz As Double)

     Dim vx As Double = x2 - x1
     Dim vy As Double = y2 - y1
     Dim vz As Double = z2 - z1
     Dim wx As Double = px - x1
     Dim wy As Double = py - y1
     Dim wz As Double = pz - z1
     Dim c1 As Double = vx * wx + vy * wy + vz * wz

     If c1 <= 0# Then
         nx = x1
         ny = y1
         nz = z1
         Return
     End If

     Dim c2 As Double = vx * vx + vy * vy + vz * vz

     If c2 <= c1 Then
         nx = x2
         ny = y2
         nz = z2
         Return
     End If

     Dim ratio As Double = c1 / c2

     nx = x1 + ratio * vx
     ny = y1 + ratio * vy
     nz = z1 + ratio * vz
 End Sub
Title: Re: Who is good in math...
Post by: gile on May 27, 2011, 01:27:05 AM
Hi,

Using the dot product, returns the 'pt' point projection on 'p1 p2' unbounded line.

Code: [Select]
        private Point3d ProjectPointOnLine(Point3d pt, Point3d p1, Point3d p2)
        {
            Vector3d v1 = p1.GetVectorTo(p2);
            Vector3d v2 = p1.GetVectorTo(pt);
            double scale = v1.DotProduct(v2) / p1.DistanceTo(p2);
            return p1 + v1.GetNormal().MultiplyBy(scale);
        }
Title: Re: Who is good in math...
Post by: huiz on May 27, 2011, 04:01:20 AM
Wow, all different solutions :-) Thanks all! I will play with all this to find out which is the best for me.

I had searched Google first but after 3 hours of examing complicated formulas I quit.
Title: Re: Who is good in math...
Post by: bieres on May 27, 2011, 04:06:03 AM
Hi,
Returns the point or distance perpendicular to the direction formed by two points.

Code: [Select]
       /// <summary>
        /// Devuelve el punto o distancia perpendicular a la direccion formada por dos puntos.
        /// </summary>
        /// <param name="pto">Punto a calcular.</param>
        /// <param name="p1">Primer punto alineación.</param>
        /// <param name="p2">Segundo punto alineación.</param>
        /// <param name="modo">[True] punto, [False] distancia.</param>
        /// <returns></returns>
        static internal object PntPrpndclr(Point3d pto, Point3d p1, Point3d p2, bool modo)
        {
            Vector3d vect1 = pto.GetVectorTo(p1);
            Vector3d vect2 = vect1.GetPerpendicularVector();
            Plane plano = new Plane(pto, vect1, vect2);
            Point3d pt = p2.OrthoProject(plano);
            if (modo == true){return pt;}else{return pt.DistanceTo(pto);}
        }
Title: Re: Who is good in math...
Post by: gile on May 27, 2011, 04:28:29 PM
The same as in reply #6 in a more concise way.

Code: [Select]
        private Point3d ProjectPointOnLine(Point3d pt, Point3d p1, Point3d p2)
        {
            Vector3d vect = (p2 - p1).GetNormal();
            return p1 + vect * vect.DotProduct(pt - p1);
        }
Title: Re: Who is good in math...
Post by: gile on May 27, 2011, 04:47:39 PM
But IMO the simplest way is to use a Geometry.Line3d instance and the Curve3d.GetClosestPont method.

Code: [Select]
        private Point3d ProjectPointOnLine(Point3d pt, Point3d p1, Point3d p2)
        {
            return new Line3d(p1, p2).GetClosestPointTo(pt).Point;
        }
Title: Re: Who is good in math...
Post by: huiz on May 29, 2011, 04:06:40 PM
But IMO the simplest way is to use a Geometry.Line3d instance and the Curve3d.GetClosestPont method.

Code: [Select]
        private Point3d ProjectPointOnLine(Point3d pt, Point3d p1, Point3d p2)
        {
            return new Line3d(p1, p2).GetClosestPointTo(pt).Point;
        }


Simplicity has power!!! :)

Gile, you are brilliant! This function works great and it is really simple. Thanks for your advice! :-)
Title: Re: Who is good in math...
Post by: sinc on May 30, 2011, 11:07:47 AM
Guess I was a little too vague, eh?   ;-)
Title: Re: Who is good in math...
Post by: huiz on May 30, 2011, 01:59:48 PM
Guess I was a little too vague, eh?   ;-)

Hehe :) Not really, I had in mind to examine this one too but at first sight I thought this routine would give back the closest node of a line. I still had in mind that a mathematical formula was the best way till I saw the routine of Gile. Then I tried that and found out that this returned a perpendicular point instead of the nearest point. You also thanks, if Gile didn't post his solution I would find out your solution after I got stuck with complicated formulas :)

Title: Re: Who is good in math...
Post by: Lee Mac on May 30, 2011, 02:02:10 PM
Then I tried that and found out that this returned a perpendicular point instead of the nearest point.

Replace 'instead of' with 'which is, of course,'  ;-)
Title: Re: Who is good in math...
Post by: gile on May 30, 2011, 03:09:00 PM
I'am sorry. It's easier for me to give some lines of code rather than a good explaination in English even i know it's not 'educational'.
Sinc gave the way for the GetClosestPointTo() route, I only wanted to show there was no need to  draw two rays.
And Lee talk about the dot product way before I posted the codes.
Title: Re: Who is good in math...
Post by: huiz on May 31, 2011, 08:09:24 AM
Yes, but with a full function in front of me I got the message.

Because I assumed the nearest point would return the nearest vertex of a line.
Title: Re: Who is good in math...
Post by: gile on May 31, 2011, 08:26:48 AM
Yes, but with a full function in front of me I got the message.

Because I assumed the nearest point would return the nearest vertex of a line.

Look at the code, it uses a Geometry.Line3d instance which has none vertex: it is unbounded.
The Geometry namespace contains plenty of classes (such as points, lines, segments, circular arcs, vectors, matrices, and so on) which aren't DBObject and are provided to solve geometry issues.