.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Projection by a vector to a plane

10 REPLIES 10
SOLVED
Reply
Message 1 of 11
huaxiamengqing
3888 Views, 10 Replies

Projection by a vector to a plane

Hi guys! This days I was troubled by a problem.

First of all, I find a function in the netapi:

Public Shared Function Projection(projectionPlane As Autodesk.AutoCAD.Geometry.Plane, projectDir As Autodesk.AutoCAD.Geometry.Vector3d) As Autodesk.AutoCAD.Geometry.Matrix3d
    Autodesk.AutoCAD.Geometry.Matrix3d 的成员

Now ,I just want to figure out this Matrix3d by the vector and plane known! Because I can't use this function In other software like Rhino. Can you help me to get this transform?Thank you very much!

 

10 REPLIES 10
Message 2 of 11

Hi

 

That's a pure algorithmic question, nothing here related to Autodesk APIs. The source code of this method is not public, you should be able to find detailed elements of answer from mathematical resources on the web looking for projection matrices, unless somebody on this forum has custom code to share with you:

 

http://en.wikipedia.org/wiki/Projection_%28linear_algebra%29

 

I hope it helps.

 

Regards,

Philippe.



Philippe Leefsma
Developer Technical Services
Autodesk Developer Network

Message 3 of 11

Yes, you are right. But the url is useless,I have read it before.I have read many math resource.But I can get the right Matrix.

In rhino Grassshoper forum they can not solve this problem, They say this forum May have some upperhand can make it. I think they are wrong.

So few people Know this.

Tell me does code need math??

Yes, absolutly yes. if you didn't do best in math, You will always need to find apis,If there is not a api you need,You are OVER!

Message 4 of 11

I am not sure if you need this but below I quickly put alogorithm for finding perpendicular projection from point on plane.
But if you need projection by any vector it is just finding intersection between line and plane ( that is not so hard to calculate)

To find perp. projection on plane can be calculated like this (it is not code just algorithm)

1) calculate normal of plane by 3 points A B C
for(i=0;i<3;i++)
{
v1[i] = c[i]-b[i];
v2[i] = a[i]-b[i];
}
vnorm[0]=v1[1]*v2[2]-v1[2]*v2[1];
vnorm[1]=v1[2]*v2[0]-v1[0]*v2[2];
vnorm[2]=v1[0]*v2[1]-v1[1]*v2[0];
 
it must have size 1 therefore
rdist=vnorm[1-1]*vnorm[1-1]+vnorm[2-1]*vnorm[2-1]+vnorm[3-1]*vnorm[3-1];
rdist=sqrt(rdist);
 
vnorm[0]=vnorm[0]/rdist;
vnorm[1]=vnorm[1]/rdist;
vnorm[2]=vnorm[2]/rdist;
 
2) perpendicular projection of point on plane
double product=0;
for (i=0;i<3;i++)
    product+=(a[i]-d[i])*vorm[i];
 
    for (i=0;i<3;i++)
          pktproj[i]=d[i]+product*vnorm[i]
 
Richard
   
Message 5 of 11

Thank you.But you code is to simple. That matrix is easy for me.All the projection of point or projection by plane.x,y,z has figured.

but  Projection by a vector to a plane  ,if the vector is Arbitrary is hard to figure out!

Whatever,Thank you for your answer!

Message 6 of 11
_gile
in reply to: huaxiamengqing

Hi,
 
Inspired by this (old) LISP routine from my library (AutoLISP does not provide functions to deal with vectors and matrices),

 

;; Multiply a vector by a scalar
(defun vxs (v s)
  (mapcar (function (lambda (x) (* x s))) v)
)
;; Return the dot product of two vectors
(defun vxv (v1 v2)
  (apply '+ (mapcar '* v1 v2))
)
;; Apply a transformation matrix to a vector -Vladimir Nesterovsky-
(defun mxv (m v)
  (mapcar (function (lambda (r) (vxv r v))) m)
)
;; Return the transformation matrix (4x4) describing the projection
;; to the plane defined by its origin and normal along the direction vector
(defun projMat (org norm dir / mat)
  (append
    (mapcar
      (function (lambda (v x) (append v (list x))))
	(setq mat
	       (mapcar
		 (function (lambda (v1 v2) (mapcar '- v1 v2)))
		 '((1. 0. 0.) (0. 1. 0.) (0. 0. 1.))
		 (mapcar
		   (function (lambda (x) (vxs norm x)))
		   (vxs dir (/ 1. (vxv norm dir)))
		 )
	       )
	)
	(mapcar '- org (mxv mat org))
      )
    '((0. 0. 0. 1.))
  )
)

 here's a C# adaptation. It returns the same matrix as the built-in Matrix3d.Projection() method.
I overloaded the method so that it's possible to pass a Plane instance or a Point3d (origin) and a Vector3d (normal) as arguments.

 

        public Matrix3d ProjectionMatrix(Plane projectionPlane, Vector3d projectDir)
        {
            return ProjectionMatrix(projectionPlane.PointOnPlane, projectionPlane.Normal, projectDir);
        }
public Matrix3d ProjectionMatrix(Point3d origin, Vector3d normal, Vector3d projectDir) { double scale = normal.DotProduct(projectDir); Vector3d dir = projectDir / scale; Vector3d xVec = Vector3d.XAxis - normal * dir.X; Vector3d yVec = Vector3d.YAxis - normal * dir.Y; Vector3d zVec = Vector3d.ZAxis - normal * dir.Z; Vector3d orgVec = origin.GetAsVector(); return new Matrix3d(new double[16] { xVec.X, xVec.Y, xVec.Z, origin.X - xVec.DotProduct(orgVec), yVec.X, yVec.Y, yVec.Z, origin.Y - yVec.DotProduct(orgVec), zVec.X, zVec.Y, zVec.Z, origin.Z - zVec.DotProduct(orgVec), 0.0, 0.0, 0.0, 1.0 }); }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 7 of 11

Perhaps this will help (no dependence on any commercial software and completely open source without restriction):

 

The OpenNurbs Initiative:  http://www.opennurbs.org/

.NET managed wrappers for OpenNurbs:  https://github.com/mcneel/rhinocommon

Message 8 of 11
_gile
in reply to: _gile

Here's a (may be) more explainatory version (decomposed and commented).

 

        public Matrix3d ProjectionMatrix(Point3d origin, Vector3d normal, Vector3d projectDir)
        {
            // Calculate a scale factor
            // If scale = 0 (normal is perpendicular to projectDir) this won't throw
            // an exception but return an unusable matrix :
            // ((NaN,NaN,-Infinity,NaN),(NaN,NaN,NaN,NaN),(NaN,NaN,NaN,NaN),(0,0,0,1))
            double scale = normal.DotProduct(projectDir);

            // apply the scale factor to projectDir 
            Vector3d dir = projectDir / scale;

            // Build the row vectors of the 'linear part' of the matrix (3x3 matrix)
            Vector3d xVec = Vector3d.XAxis - normal * dir.X;
            Vector3d yVec = Vector3d.YAxis - normal * dir.Y;
            Vector3d zVec = Vector3d.ZAxis - normal * dir.Z;

            // Build the 'translational part' of the matrix (column vector)
            Vector3d orgVec = origin.GetAsVector();
            // Apply the 'linear part' matrix to the origin
            Point3d transformedOrigin = new Point3d(
                xVec.DotProduct(orgVec), yVec.DotProduct(orgVec), zVec.DotProduct(orgVec));
            // The displacement vector is the vector from tranformedOrigin to origin
            Vector3d disp = origin - transformedOrigin;

            // Assemble the 4x4 transformation matrix
            return new Matrix3d(new double[16]
            {
                xVec.X, xVec.Y, xVec.Z, disp.X,
                yVec.X, yVec.Y, yVec.Z, disp.Y,
                zVec.X, zVec.Y, zVec.Z, disp.Z,
                0.0,    0.0,    0.0,    1.0 
            });
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 9 of 11
DiningPhilosopher
in reply to: _gile

Hi Gile.

 

My interpretation of the OP's post is that he can't have any dependenc on any AutoCAD APIs.

Message 10 of 11
_gile
in reply to: DiningPhilosopher

Hi Tony,

 

This is what I understood too.

The reasons why I posted some code are the ability to test in AutoCAD if the returned matrix is the same as the one returned by Matrix3d.Projection(), and the fact it's easier for me to post some commented code than to try an explanation in English.

 

I hope the OP would be able to adapt it with the corresponding types to Point3d, Vector3d and the DotProduct() method.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 11 of 11
huaxiamengqing
in reply to: _gile

Geat,That's What I want! I have converted it to the VB.net code under Rhino apis below!

Private Sub RunScript(ByVal P As Plane, ByVal V As Vector3d, ByRef M As Object) 
    M = ProjectionMatrix(P, V)
  End Sub 

  '<Custom additional code> 
  Public Function ProjectionMatrix(projectionPlane As Plane, projectDir As Vector3d) As Matrix
    Return ProjectionMatrix(projectionPlane.Origin, projectionPlane.Normal, projectDir)
  End Function
  Public Function ProjectionMatrix(origin As Point3d, normal As Vector3d, projectDir As Vector3d) As Matrix
    Dim scale As Double = normal.X * projectdir.X + normal.Y * projectdir.Y + normal.Z * projectdir.Z
    Dim dir As Vector3d = projectDir / scale
    Dim xVec As Vector3d = Vector3d.XAxis - normal * dir.X
    Dim yVec As Vector3d = Vector3d.YAxis - normal * dir.Y
    Dim zVec As Vector3d = Vector3d.ZAxis - normal * dir.Z
    Dim orgVec As Vector3d = New Vector3d(origin)
    Dim aa As New Matrix(4, 4)
    aa.item(0, 0) = xvec.X:  aa.item(0, 1) = xVec.Y:  aa.item(0, 2) = xVec.Z:  aa.item(0, 3) = origin.X - _
      (xVec.x * orgVec.x + xVec.y * orgVec.y + xVec.z * orgVec.z)
    aa.item(1, 0) = yvec.X:  aa.item(1, 1) = yVec.Y:  aa.item(1, 2) = yVec.Z:  aa.item(1, 3) = origin.y - _
      (yVec.x * orgVec.x + yVec.y * orgVec.y + yVec.z * orgVec.z)
    aa.item(2, 0) = zvec.X:  aa.item(2, 1) = zVec.Y:  aa.item(2, 2) = zVec.Z:  aa.item(2, 3) = origin.z - _
      (zVec.x * orgVec.x + zVec.y * orgVec.y + zVec.z * orgVec.z)
    aa.item(3, 0) = 0:  aa.item(3, 1) = 0:  aa.item(3, 2) = 0:  aa.item(3, 3) = 1
    Return aa
  End Function

 Thank you all Guys. CAD forum is Good, There are so many classical orgorithm here!

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost