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!
Solved! Go to Solution.
Solved by _gile. Go to Solution.
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.
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!
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)
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!
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 }); }
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
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 }); }
Hi Gile.
My interpretation of the OP's post is that he can't have any dependenc on any AutoCAD APIs.
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.
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!