.NET

.NET

Active Contributor
Posts: 35
Registered: ‎05-23-2012
Message 1 of 11 (659 Views)

Projection by a vector to a plane

659 Views, 10 Replies
05-06-2013 03:37 AM

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

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

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!

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
});
}```

Posts: 662
Registered: ‎06-02-2009
Message 2 of 11 (609 Views)

Re: Projection by a vector to a plane

05-09-2013 07:59 AM in reply to: huaxiamengqing

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

Active Contributor
Posts: 35
Registered: ‎05-23-2012
Message 3 of 11 (606 Views)

Re: Projection by a vector to a plane

05-09-2013 08:15 AM in reply to: philippe.leefsma

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!

Valued Contributor
Posts: 58
Registered: ‎12-08-2010
Message 4 of 11 (569 Views)

Re: Projection by a vector to a plane

05-10-2013 06:03 AM in reply to: huaxiamengqing

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

Active Contributor
Posts: 35
Registered: ‎05-23-2012
Message 5 of 11 (564 Views)

Re: Projection by a vector to a plane

05-10-2013 06:14 AM in reply to: huaxiamengqing

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!

*Expert Elite*
Posts: 2,125
Registered: ‎04-29-2006
Message 6 of 11 (541 Views)

Re: Projection by a vector to a plane

05-10-2013 01:59 PM 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
Valued Mentor
Posts: 370
Registered: ‎05-06-2012
Message 7 of 11 (521 Views)

Re: Projection by a vector to a plane

05-10-2013 11:53 PM in reply to: huaxiamengqing

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

*Expert Elite*
Posts: 2,125
Registered: ‎04-29-2006
Message 8 of 11 (511 Views)

Re: Projection by a vector to a plane

05-11-2013 01:06 AM 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
Valued Mentor
Posts: 370
Registered: ‎05-06-2012
Message 9 of 11 (501 Views)

Re: Projection by a vector to a plane

05-12-2013 12:15 AM 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.

*Expert Elite*
Posts: 2,125
Registered: ‎04-29-2006
Message 10 of 11 (496 Views)

Re: Projection by a vector to a plane

05-12-2013 01:01 AM 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
Post to the Community