Jump to content

DomC

Member
  • Posts

    604
  • Joined

  • Last visited

Posts posted by DomC

  1. The Text Node converts the input in a string. That should not be the issue. Try the following:

    1. The Text is place by coord (0,0) you should found your text oject there. Get 2D Center or BBox Center to place your text in the middle of the poly and intert the resulting point into the text Node
    2. Try to connect a prefix. Even if you do not have an area it should return the prefix

    There is a great DataTag Tool, that would tag your polys automatically with an area. Maybe there is no script necessary.

    • Like 2
  2. Hi 
    You can repeat the Wires by the value of Multiplier. The Best point is to multiply at the beginning, where are not so many wires yet. So just repeating the lines by Multiplier. Also Create some new Numbers for the space.
    image.thumb.png.fcd866f965c6e08c2de027f348e46783.png


    I will upload the example to the other File in the gallery

    Attention:
    1. In the Configuration Window, the first column A is ignored (original Space Numbers, which will not work for the space anymore very good)
    2. Second Column B of my file is "11_Space Name Cust". Do not choose anything else there
    3. Column C is connected to column out1 which is the space are.

     

    • Like 1
  3. Got it for an example, in which the Cabinet is not rotated. At the Moment I am overhelmed by calculating the rotation angle through both PlugIns. offset it easy. It is offset vector Cabinet (related to World coords) + offset Vector Custom Part (Related to Cabinet PIO). 
    The Rotation Matrix is cabinet angle + custom part angle or cabinet angle - custom part angle. But the rotation could be on 3 axis and it debends on the order how those angles are calculated. I think the "Matrix" Nodes would do the job but nobody seems to know, how they can be used. Because the "Set Entity Matrix" needs x y z angles and the Transform Matrix delivers u v w and x y z values. I once short got busy with it but still hoping that someone else can solve it with the Marionette Node🙂 
    image.thumb.png.011dac62f1d04636d00a1766a93bfaf4.png

    The other thread about the Transform MAtrix:

     

    Custom Part Entity.vwx

  4. Hello
    every container has its own coordinate system and rotation plane. If you pull out something inside a PIO, you have to attach the PIOs Plane (Entity Matrix) on it, to convert it to the World Plane. It works, if you get the plane of the parent Object (custom part) and attach it to the Covering.

    O .... K, While I am writing I see, that this is not the end-solution. Because the Covering is nested in a Custom Part which is part of the Cabinet. So we have to combine the entity matrixe's of the cabinet AND the Custom Part. 

    Another approach would be, to "convert to group" the whole cabinets and then grabbing the coverings out of the  result.

    image.thumb.png.a8ad37c2a5ea6fae8fd3abc55feeb185.png

  5. Hi
    Also Failing here. Seems the python script is waiting for the python execution and not for Vectorworks. If I as example importing 10 Symbols from a source it takes about 10 seconds. The progress bar (and Message Window) ends in 1 Second. If i build in 10 seconds of wait or sleep function it is visible 10 seconds but the execution takes then 20 seconds.

    Next try would be to run the function inside a dialog loop

     

    def place_symbols():
    	vs.ClrMessage()
    	vs.ProgressDlgOpen("Ersetze Objekte", False)
    	if globals.settings['Ebene'] == 1: #new Layer
    		vs.HideLayer()
    		l_handle = vs.CreateLayer(globals.settings['Ebene Name'], 1)
    		vs.HideLayer()
    
    	vs.ProgressDlgStart(100, len(globals.pairs))
    	counter = 1
    	for target, source in globals.pairs:
    		#vs.ProgressDlgStart(counter, counter)
    		sym_name, [ListID, index] = source
    
    		vs.ProgressDlgSetMeter('Ersetze' + sym_name)
    		vs.Message('Ersetze' + sym_name)
    		vs.ProgressDlgYield(1)
    		#time.sleep(1)
    		if vs.GetObject(sym_name):
    			vs.DelObject(vs.GetObject(sym_name))
    
    		vs.ImportResourceToCurrentFile(ListID, index)
    		vs.Layer(vs.GetLName(l_handle))
    		vs.Symbol(sym_name, (0,0), 0)
    		h_new = vs.LNewObj()
    		counter += 1
    		off_x, off_y, off_z = target['PositionXYZ']
    		rot_x, rot_y, rot_z = target['RotationXYZ']
    		vs.SetEntityMatrix(h_new, (off_x, off_y, off_z), rot_x, rot_y, rot_z )
    
    	if 	globals.settings['Ebene'] == 0: #replace on active layer
    		for target, source in globals.pairs:
    			handle = target['handle']
    			if handle != vs.Handle(0):
    				vs.DelObject(handle)
    
    	vs.ClrMessage()
    	vs.ProgressDlgEnd()
    	vs.ProgressDlgClose()

     

  6. Hello
    Try to insert that lines. Looks somehow rude, but it seems to "burn" the image into the texture:
    Also it fixes the width of the image to (document unit?) 10.
     

    			vs.SetObjectVariableHandle(hTextureBitMap, 528, hImage) #Were the magic happens!
    			vs.ResetObject(hTexture)
    			vs.SetObjectVariableHandle(hTextureBitMap, 528, hImage) 
    			
    			resolutionx = vs.GetObjectVariableLongInt(hPaint,530)
    			resolutiony = vs.GetObjectVariableLongInt(hPaint,531)
    			vs.SetTexBFeatureStart(hTextureBitMap, 0, 0) #pixel start
    			vs.SetTexBFeatureEnd(hTextureBitMap, resolutionx, 0) #pixel End
    			vs.SetTexBitFeatureSize(hTextureBitMap, 10) #size units

     

  7. On 8/27/2021 at 3:47 AM, rbryanharrison said:

    I'd bake cookies for a version that recalculates only the active worksheet.


    I think right-click method is nearly as fast as shortcut but if theoretically someone is interested in the update-selected-script-variante.

    #DomC 2022-09-17 Use at your own risk
    #Recalculates selectes worksheets on the active layer.
    #Worksheets with the same names were also recalculated, even if 
    #they are not on the same layer and/or are not selected
    
    selected_worsheets = []
    def add_handle(h): 
    	selected_worsheets.append(h)
    
    vs.ForEachObjectInLayer(add_handle, 2, 1, 0)
    
    for worksheet_insctance_handle in selected_worsheets:
    	sheet_resource_handle = vs.GetWSFromImage(worksheet_insctance_handle)
    	vs.RecalculateWS(sheet_resource_handle)
    	vs.ResetObject(worksheet_insctance_handle)
  8. Hi

    I would not say i am a python expert and i also was fighting a lot with path-strings (strings and text encoding generally) in the past. Let python os-module do the job. Allow me to suggest this as following:
     

    import os
    full_absolut_path = os.path.join('c:', 'DOCs', 'SCRIPT', 'NNR.dxf')
    LNR = vs.ImportDXFDWGFile(full_path, isBatch)
    
    #or in one line
    LNR = vs.ImportDXFDWGFile(os.path.join('c:', 'DOCs', 'SCRIPT', 'NNR.dxf'), isBatch)


    This would work on both platforms. Also i saw if we are reading path from os and use it as a string, it can be necessary to normalize the path string because of some special characters to make it look good in Vectorworks on both platforms:
     

    import unicodedata
    path_string = unicodedata.normalize('NFC', full_absolut_path)


    Edit:
    In my opinion it is just "luck", that \D and \S are no special controls in python. \n creates a new line \N --> No idea, what creates that. Something that is not compatible for unicode decoding. The String is forwarded from python to VW and VW can "parse" the path with some rules but here python itself just can't interpret the code of the programmer. string 'C:\DOCs\SCRIPT\NNR.dxf' is as unallowed as a division by 0 which also put an error on the screen without any further arguments.
    We could try to push a raw string to the VW function and see what happens. 
    like that:
     

    NNR = vs.ImportDXFDWGFile(r'C:\DOCs\SCRIPT\NNR.dxf', isBatch)

     

  9. Hi
    The "Universal" (english) Names of the PIOs you can get by creating a Worksheet as example. The Formula in the worksheet will show you the Name. 

    As far as I can see, you can start your drilling script with locus to test and debug. If it works replace the locus through the drilling. The Drilling you can insert. The Options in the Object Info Palette for PIOs you change with "Set Record Field". There is no need of creating special Nodes for that. 

    As a Box Object your Marionette would work. Directly putting it on a part will be not a good idea as far as I can see it is getting instable. Because the part pulls out the drillings out of the marionette somehow and after moving marionette the move event does not trigger the right action to the part to release. 

    Try it as a marionette box object. 

     

    • Like 1
  10. I must correct my statement
    It seems, that the drillings drill the part directly with the Marionette.   O.    M.    G.  
     


    I could imagine to make a Frame on the Part or get automatically the part dimension and attach an own intelligent drilling pattern to the object. for me this looks like a litte revolution.

    Just that I said that. I do not know if this is a good Idea or if this is stable. No guarantee for that.
     

    ic marionette 2.vwx

    • Love 2
  11. Short Test
    Works more like a "Drilling Stamp". Just a short raw test. There would be two bigger issues left:
    1. How to get Position of Marionette Object before Objects are putted out. Because first the objects are created and after that the PIO gets his new position.
    2. How to delete the existing drillings before put in some new drillings on the layer.

    I think theoretically solvable but I think i am notching out at this point 🤔
    By the way, Box Objects would support Marionette PIOs in a Cabinet. Also the Cabinet could be reduced to a single part and then it could work together.
     

     

     


    image.thumb.png.0d237e206ec8e52193a349294fabb362.png

    ic marionette.vwx

    • Love 1
  12. Yes exactly. As long as the PIOs are inside the Marionette, they would not react with the interiorcad parts. 
    Well there is always a way to get something to work. As example:

    - If we would create objects and then set parent Object on the layer instead of the pio
    - and recalculate positon and rotation outside the PIO plane to the world-plane   
    - And regenerate/reposition the objects while executing the marionette. By linking the Objects to the script by uuid as example

    There seems to be some options but there is need for additional coding the script and making special nodes which do not exists.

    • Like 1
  13. You could control those objects by insert an object as a symbol then manipulate the path. Point objects like macro or drilling you could control with "Create Custom object" also there is a "create custom object path" which would create parts or contours.


     

    image.png

    At the end, those objects would not be able to "marry" with the interior custom parts if they are inside a Marionette PIO.

  14. 2 hours ago, twk said:

    Would this mean that we would have to run separate scripts languages for either operation? ie (pascal for interaction, python for everything else).

    I wish not that we need to do this but it seemed to be necessary if i have python scripts and wants to interact with Vectorworks while script is running. Theoretically is should work with a python script,  if we use the python script as a callback of the temp tool and additionally tweaks.


    But that seems to be even more unstylish, then embed everything into pascal scripts which handle user interactions.
    Can't estimate if this disadvantage of python code inside VW technically and reasonable at all can be eliminated.

  15. I guess no magic you do not already know.😉


    image.thumb.png.8d4924f2c872daa6082fa1b79ba5f6bc.png


    And this inside the python code:
    image.png.55e34c5279dae7c6b2f963e1dd4bca18.png
    Newly I found the method here in the forum to write the values directly to value repository. Which is more clean than values2python function.


    What I did not used yet is go back to pascal and do further interactions and then start next python script. But I think this should work. While pascal seems to be nativ-integrated in VW, python have much more comfort to create code or access to OS.  So combining pascal and python seems to be very attractive for scripts.

    Next step would be C++. But I am scared from having so much more "magic".
     

    • Like 2
  16. Hi
    I am using PyCharm CE and never tried remote debugging but it sounds interesting. I think there is improvement potential here, because honestly I do not know what a remote debugger would really improve and if it would be worth the effort 🙂

    My (ammateur) Workflow:

    1.  import the vs.py methods in PyCharm to have intellisense and error-redlining
    2. I have a string list which I append frequently with line-Numbers, comments from the code which i can write to a log file. So I can later find where my script stucked and maybe add further comments for more detailed debugging.
    3. Or I just make some vs.Message() or vs.AlrtDialog() inside the script for quick and dirty checks.
    4. For Script with user interaction (RunTempTool etc. ) I embed the python code into a pascal Script. Because there seems no Events that can make a python script is waiting for VW or VW wait for debugger?. Don't know how that would work with remote-debugging.

    Because I do not think a remote debugger can prevent from crashes (as example modification of a not anymore existing object-handle or similar.). Never tried myself to setup a remote debugger.
     

  17. Hi @fernicus01

    Seems like holding the ctrl key blocks keyboard-input from other keys like tab or enter.
    So in Fact on windows the workflow on my computer is:

    1. drag object in desired direction
    2. pressing and releasing tab (both Hands free now)
    3. Enter the value
    4. Pressing Enter once
    5. Holding Ctrl. Key
    6. clicking with mouse button


    On Mac

    1. drag object in desired direction
    2. pressing and releasing tab (both Hands free now)
    3. Enter the value
    4. holding alt-key
    5. pressing enter twice


    So windows is one step more and my vegetative brain can't handle that in a smooth way anymore like on my mac.
    (Too many steps and between the action using mouse button again is very un-elegant)

    I would sware, this once also was working similar on Windows. But it seems also be OS-related because also my
    VW 2016 (Oldest Version i can find on my Windows Computer) works this way.


    I will do a report. I hope, that engineers can adjust the bahaviour.

    • Like 4
  18. 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)
    		else:
    			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)
     #[(xoff,yoff,zoff),(xrot,yrot,zrot)],[...]]
    
    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'])
    			#vertex_planes.append(False)
    			
    			p = point_on_line_3D(p1, p2, radius) #start radius point
    			points.append([p,10]); pts_infos.append([p, 'segment_start'])
    			#vertex_planes.append(False)
    			
    			
    			p = point_on_line_3D(p2, p1, radius) #start radius point
    			points.append([p,10]); pts_infos.append([p, 'segment_end'])
    			#vertex_planes.append(True)
    			
    			p = point_on_line_3D(p2, p1, radius*sqr2)
    			points.append([p,1]); pts_infos.append([p, 'control_start'])
    			#vertex_planes.append(False)
    			
    			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
    		else:
    			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)
    
    
    	vs.Locus3D(p1)
    	vs.Locus3D(p2)
    	vs.Locus3D(p3)
    
    vs.ReDrawAll()
    
    





     

  19. 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. 


     

  20. 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.

     image.thumb.png.53fdc74d0a548fb3b0d3dc327215f033.png 

    Fillet v2022.vwx

    • Like 1
  21. 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. 

     

×
×
  • Create New...