Jump to content

Recommended Posts

The Matrix node just flatten the input vector tuples. 
(1,0,0),(0,1,0), (0,0,1), (0,0,0) ase example results in (1,0,0,0,0,1,0,0,1,0,0,0). 
I bet, this comment do not help you really 😀

I think it could be used to serve one of the other matrix nodes. to rotate as example a matrix. 

I am not an expert but try to explain:
In computer-graphic, the "Eulerschen Winkel" (Formulas on the left) can be used to descripe the orientation of an object (A rotated coord system). Vectorworks uses this as example for planes, Entity Matrix etc. The Interesting point for me would be, how to get efficient such a matrix (which is just X rotation Angle, Y rotation Angle, Z rotation Angle and offset vector) as example from 3 points in space without using additional libraries (scypi, numpy etc.). I never tried this very intense but also would be interested in some explanations in this area. Something by script what we have with set working plane or automatic working plane. No function is provided for that as far as I can see. 


Link to comment


   What do your 3 points represent?

P1 = Plane's center point?

P2-P1 = Plane's Normal vector?

P3-P1 = Plane's X` axis (or U vector)?

Or something else? 


I believe what you want is doable, but would require going back to college texts, or the internet, a bunch. Do you have a specific problem you are trying to solve?



Link to comment

@DomC die angehängte Datei enthält einige meiner Gedanken. Momentan bin ich jedoch noch nicht soweit alles zu verstehen, was die jeweiligen Knoten anstellen. Bitte die Ebenen durchschauen, vielleicht ist etwas mit dabei. Ich denke, dass durch den Erhalt eines Vektors zweier Punkte der nächste Punkt mit einer Rotation errechnet werden könnte. Schlussendlich wäre eine lange Aneinanderreihung von Vorgängen notwendig.

Daher möchte ich die Matrix richtig anwenden um direkt an den resultierenden Punkt zu gelangen. Dazu müsste allerdings ein definierter Abstand zwischen den Punkten in die Matrix mit einfliessen. Ich gehe davon aus, dass nebst der Matrix auch einige Trigonometrie Kenntnisse erforderlich sein werden.

Vielleicht gibt es auch eine rein Vector basierte Lösung.

Sicher ist nur, dass ich die Matrixknoten besser verstehen muss um damit arbeiten zu können.


Daher die Frage nach Beispielen.






the attached file contains some of my thoughts. At the moment, however, I'm not ready to understand everything that the respective nodes do. Please look through the levels, maybe something is included. I think that by getting a vector of two points, the closest point could be computed with a rotation. Ultimately, a long sequence of processes would be necessary.
So I want to use the matrix correctly to go directly to the resulting point. To do this, however, a defined distance between the points would have to be included in the matrix. I assume that in addition to the matrix, some knowledge of trigonometry will also be required.
Perhaps there is also a purely Vector-based solution.
The only thing that is certain is that I need to understand the matrix nodes better in order to be able to work with them.

Hence the question of examples.




Den Punkt einer Drehung um die Achsen zy kann ich mit Trigonometrie errechnen. Eine Rotation um xyz Achse habe ich noch nicht geschaft. 
Ich denke, dass die Lösung bei den Matrixknoten ist.

Schlussendlich geht es darum, einen Punkt im Raum mit bestimmten Neigungswinkel und Abständen zu finden.

Stellen sie sicht ein sich drehendes Flugzeug im Sturtzflug vor.
Sie sehen aus dem Kockpit und möchten wissen, wo sich die Flügelspitze befindet? --> Bild


I can calculate the point of a rotation around the zy axis with trigonometry. I haven't done a rotation around the xyz axis yet.
I think the solution is at the matrix nodes.

Ultimately, it's about finding a point in space with a certain angle of inclination and distance.

Imagine a spinning airplane in a nosedive.
Looking out of the cockpit and want to know where the wing tip is? --> picture






Gedanken zu Matrix.vwx

Link to comment

Hello @MullingRJ

I have several specific projects but this one would be on ice right now (As a saw the matrixes I had to joine the duscussion :-) and I think it is solvable but need some investigations to have a proper and elegant solution.  
I already have some code, which calculates points from edge of a 3D Path which a specific distance from the corners. What is needed not is a rotation vector which contains the rotation matrix related to the layer coordinate system. Thats how we insert symbols. I am pretty close to that by calculationg the x y z angle but i have not yet defined an algorithm to define if it is minus or plus angle. The code does not yet consoder, if i go up down left or right. 

But I am pretty sure, on our old math books there is a very compact and itelligent solution.
So it would be great if you can join the project! Thanks

@Simon. It is just "simple trigometric" but we have to check direction to if rotation is minus or plus or 180 - rotation. Without that, we have the direction of the plane but do not know from which side we look at the plane. 

What you see in the movie is, that I set the working plane which is defined with x, y, z, rotation. Then I place a symbol on that. That's what I want to do with the script. The plane of the corner is defined with the 3 points on the corner (i draw 3D locus to make it visible)

"Just" left to solve to calculate the entity matrix from those 3 points on every corner. I alread have X Vector (p2, vorner_p) and Y Vector (corner_p - p3). z_vector also is defined through this two vectors I think. Now we need the rotation from that u' v' w' planen to the Layer coord plane. 

At the end we also could place objects on 3D planes very simple with a node, that creates a plane matrix (which can be used to SetEntityMatrix) from 3D points. That is something I think would help many users. We also maybe could draw a NURBS Surfaces and evaluate points on that with the vs-Commands. But always better to do that directly with math.


Fillet v2022.vwx

  • Like 1
Link to comment

Hi @DomC,

   From the picture and movie you posted, you have everything you need to define a working plane (WP) at each vertex, with no additional math required.

1) Your WP Origin is the vertex p_corner.

2) The local WP Xaxis, or Uvec, is p1-p_corner (vector subtraction). You'll need to spin your own function for this if you don't want to import any modules. Easy.

3) Your WP Normal vector is p1xp2, or vs.CrossProduct(p1, p2), or vs.CrossProduct(p2, p1)*.

4) And your WP Yaxis, or Vvec, (which is not needed to define the plane, but may be nice to have) is CrossProduct(Normal, Uvec).


To define a WP at point p_corner use:

    vs.SetWorkingPlaneN(p_corner, Normal, Uvec)


Easy Peasy. You don't need to convert your 3DPoly points to rotation angles, but you can use vs.GetWorkingPlane() after you set the WP with vs.SetWorkingPlaneN() and VW will give you a set of rotation angles that will be equivalent.


* The only finesse point concerns which side of the corner vertex is the UP side of the WP. Since the Poly is in 3D space, there really is no Up side and your Normal could point in in either direction. vs.CrossProduct(p1, p2), or vs.CrossProduct(p2, p1) point in opposite directions. If it's not important, use either one. If you are familiar with the Right Hand Rule, you can visualize which way the Normal vector points relative to the 3 points you're using to define the plane. If not, google Right Hand Rule and you will find tons of websites showing how to use it. There are lots of videos are out there.


If I left anything out, let me know.




  • Like 1
Link to comment

I think you are right. Even we do not ned to create a working plane to set the entity matrix which already can handle vectors instead angles. My bad is to look into the marionette SetEntityNode, which do not use vs.SetEntityMatrixN()
There is no up and down. In my first example the edge symbol is inserted from bottom. 


Edited by DomC
Link to comment

Good morning, @DomC.

   One thing about the Entity Matrix (EM) that is NOT in the documentation – The EM for symbols and images is encoded differently from all other 2D planar objects on the same plane. The EM for symbols and images contain information about their rotations on the plane, combined with the location and rotation of the plane where they reside. This means the EM for a symbol on a WP is NOT the same as that of a rectangle, line, locus, or circle on the same WP. The latter four will all have the same EM if they exist on the same WP, as the EM is supposed to define the WP, and not the object on the plane.


   I spent almost an entire summer figuring exactly how symbols and image EMs are put together and how to take them apart, only to realize that all I needed was a Working Plane's Reference ID to manipulate objects freely on Working Planes or move objects between them. Does Marionette have access to RefIDs? If not, you should request that it does. EMs are way too clunky to deal with, and they are not consistent between object types on the same plane. 


My 2¢,


Link to comment

Hallo Zusammen



Nun zu der Matrix kann ich nicht mehr viel beitragen, das Thema scheint über meine Gehaltsstufe gewachsen zu sein.

Anwendungsbeispiele nehme ich weiterhin gerne entgegen.


Mit der Datei im Anhang finde ich meine Punkte im freien Raum. 

Dabei verwende ich jeweils einen fixen Startpunkt und einen veränderten Endpunkt. 


Betreffend Trigonometrie verwende ich meistens diese Seite



Zwei der drei Rotationen bekomme ich so hin. Wenn nun jemand die passende Mathematische Vorgehensweise liefert, dann benötige ich die Matrix nicht mehr.






Now I can't contribute much more to the matrix, the topic seems to have grown beyond my salary level.
I am always happy to receive application examples.


With the file attached I find my points in free space.
I use a fixed starting point and a modified end point.


Concerning trigonometry I mostly use this site


I can do two of the three rotations that way. If someone now provides the appropriate mathematical procedure, then I no longer need the matrix.






Nurbs und Trigonometrie.vwx

Link to comment

Haha - I think the highest level somebody reach if he can trigger others to do the work 🙂

OK, I did it with the crowbar. The script now works so:
1. Always move the points virtually on center before calculations
2. getting zangle from p1-p2 > Easy Peasy
3. for vertical segments taking p1-p3
3. I take the 3 points and turn them mathematically aligned with first segment on x-axis of the standard-coord-system.
4. then i look from coord center (from left) and geht the rotation angle by using z-difference as y coord to get xangle
5. y angle is build from turned p1-2 segment and the xdiff of that segment and the height of that segment.

Try to provide a node create EM form 3d points node anytime. I imagine we can create wonderful stuff with that. placing object on faces of objects! 
For the moment my own need is nursed to hav a corner vertex matrix plane for the pipe-project.


#just crude test-coding
import math 

sqr2 = 0.41421356237
PI								= 3.141592653589793239
kRadiansPerDegree				= PI / 180.0
kDegreesPerRadian				= 180.0 / PI
kNearlyEqualEpsilonForDoubles 	= 1e-13

def point_on_line_3D(p1, p2, d): #3d Points d = distance from p1 to p2
	x1, y1, z1 = p1
	x2, y2, z2 = p2
	c = vs.Distance3D(x1, y1, z1, x2, y2, z2)
	new_pt = ((x2 - x1) / c * d + x1,  (y2- y1) / c * d + y1 , (z2 - z1) / c * d + z1)
	return new_pt

def DoublesAreNearlyEqual(n1, n2):
		epsilon = kNearlyEqualEpsilonForDoubles
		abs_n1 = abs(n1)
		abs_n2 = abs(n2)
		abs_n1n2 = abs(n1 - n2)
		if ((abs_n1 <= epsilon) or (abs_n2 <= epsilon)):   # if either is very nearly zero, don't take the magnitude into account
			return (abs_n1n2 <= epsilon)
			temp = abs_n1 if (abs_n1 > abs_n2) else abs_n2
			return (abs_n1n2 <= temp * epsilon)

def DoubleIsNearlyZero(n):
	return DoublesAreNearlyEqual(n, 0)

def DotProduct(p1, p2):
	return (p2[0] * p1[0]) + (p2[1] * p1[1]) + (p2[2] * p1[2])

def Magnitude(vec):
		return math.sqrt( vec[0]*vec[0] + vec[1]*vec[1] )

nurbsObj = vs.FSActLayer() # take care to select a NURBS curve

radius = 100
segments = []

points = []
segmentCnt = vs.NurbsCurveGetNumPieces(nurbsObj)

for segm in range(0, segmentCnt): # python range is always one less than pascal
	pts_infos = []
	vtxCnt = vs.NurbsGetNumPts(nurbsObj, segm)
	num_knot = vs.NurbsNumKnots(nurbsObj, segm)
	vertex_plane = []
	for vtx in range(0, vtxCnt): # python range is always one less than pascal
		v = vs.NurbsGetPt3D(nurbsObj, segm, vtx)
		if vtx < vtxCnt - 1:
			p1 = v
			p2 = vs.NurbsGetPt3D(nurbsObj, segm, vtx+1)
			p = point_on_line_3D(p1, p2, radius*sqr2)
			points.append([p,1]); pts_infos.append([p, 'control_end'])
			p = point_on_line_3D(p1, p2, radius) #start radius point
			points.append([p,10]); pts_infos.append([p, 'segment_start'])
			p = point_on_line_3D(p2, p1, radius) #start radius point
			points.append([p,10]); pts_infos.append([p, 'segment_end'])
			p = point_on_line_3D(p2, p1, radius*sqr2)
			points.append([p,1]); pts_infos.append([p, 'control_start'])
			pts_infos.append([p2, 'vertex'])			

	segments.append([segm, vtxCnt, pts_infos])	

def rotate2d(degrees,point,origin):
	x = point[0] - origin[0]
	yorz = point[1] - origin[1]
	newx = (x*math.cos(math.radians(degrees))) - (yorz*math.sin(math.radians(degrees)))
	newyorz = (x*math.sin(math.radians(degrees))) + (yorz*math.cos(math.radians(degrees)))
	newx += origin[0]
	newyorz += origin[1] 

	return newx,newyorz

def get_angle(p1, p2):
	diffx = p1[0]
	diffy = p1[1]
	p2 = p2[0]-diffx, p2[1]-diffy
	x2, y2 = p2
	a = vs.Vec2Ang(x2,y2,0)

	return a

for i in range(len(segments)):
	segm, vtxCnt, pts_infos = segments[i]
	p1 = pts_infos[2][0] #start
	p2 = pts_infos[4][0] #corner

	if i < len(segments) - 1:
		segm2, vtxCnt2, pts_infos2 = segments[i+1]
		p3 = pts_infos2[1][0] #start next segment
		x3, y3, z3 = p3
		x2, y2, z2 = p2
		x1, y1, z1 = p1
		zangle = get_angle(p1, p2)
		if (x1,y1) == (x2,y2): #vertical > no zangle from p1 - p2
			zangle = get_angle(p1, p3)

		p3_1 = rotate2d(360-zangle, p3, p1)
		p2_1 = rotate2d(360-zangle, p2, p1)
		p3_1_angle = get_angle(p2_1, p3_1)
		if p3_1_angle >= 0:
			cw_seg_2 = False #counter clockwise
			cw_seg_2 = True #clockwise

		diff_y = p3_1[1] - p2_1[1]
		diff_z = p3[2] - p2[2]
		xangle = vs.Vec2Ang(diff_y, diff_z,0)
		diff_x = p2_1[0] - p1[0]
		diff_z = p2[2] - p1[2]
		#vs.AlrtDialog(str([diff_x, diff_z]))	
		yangle = vs.Vec2Ang(diff_x, -diff_z, 0)
		vs.Symbol('Symbol-1', p1, 0)
		sym_h = vs.LNewObj()
		vs.SetEntityMatrix(sym_h, p1, xangle, yangle, zangle)




Edited by DomC
Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...