Jump to content

DomC

Member
  • Posts

    529
  • Joined

  • Last visited

Everything posted by DomC

  1. @Marissa Farrell Ist the behavior of the concat node WAD or should report a bug? I think it is a bug because it converts the list (List absorb) in a string. And then re-adds every character of that string together so the result is again str(self.Params.stringIn.value)
  2. 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)
  3. With the SetRecordField, you can change parameters from PIOs. Like Diameter, Depth which would be the most common I think.
  4. 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)
  5. 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.
  6. I must correct my statement It seems, that the drillings drill the part directly with the Marionette. O. M. G. Drilling with a Marionette.mp4 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
  7. 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. Test Drilling Stamp.mp4 ic marionette.vwx
  8. 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.
  9. 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. At the end, those objects would not be able to "marry" with the interior custom parts if they are inside a Marionette PIO.
  10. Best Option is to sort data before creating the Objects. There is also a send backward Node here available.
  11. 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.
  12. I guess no magic you do not already know.😉 And this inside the python code: 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".
  13. 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.
  14. 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.
  15. DomC

    use matrix

    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. planes.mp4 #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()
  16. DomC

    use matrix

    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.
  17. DomC

    use matrix

    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. Rotation matrix corner points.mp4 Fillet v2022.vwx
  18. DomC

    use matrix

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

    3D Fillet??

    Thanks for input Larry and Pat. ConvertToNURBS can't put several segments together. If that is possible it would also not be needed to draw planar polylines and rotate them into the 3D Plane. I have corner points and control points already calculated and can directly draw a NURBS in 3D. It seems, that the hurdle is, that one segment of NURBS can only handle one type of vertex. Rounded vertex or edge vertex. every time we have an unrounded edge we have to create a new segment which we can't combine together. Minimum not in an easy way. What I also thought about is, that maybe the NURBS Curve with several NURBS internally is a different object as a single segment. What i maybe will try later: 1. Creating the object with different segments seems to be an attractive and proper solution. Also additionally the Level of detail for a fitting can be implemented here. 2. Menu Command compose making to work inside a Marionette PIO. But for that think I have to parent the Object on a layer then compose it and parent it back into the PIO. Which could work but is somehow ass-backward (Translation from "von hinten durch die Brust ins Auge" ?).
  20. DomC

    3D Fillet??

    Hello There are some old threads for this theme but it seems, there is no proper solution. I also searching for an elegant solution to make fillet on NURBS Curves. As the Tool works fantastic, by script it seems to be not so trivial. Maybe because we need to combine somehow several segment of NURBS and not all parameters can be edited by script. So far I tinkered an approximated solution, which seems to work for my usecase it is exact enough and works but somehow not pleased yet for nitpicker like me and many of us 🙂 Target is to model filled NURBS for modeling pipes without using compose as menu command. The Script: The calculation of the control points is exact. Also think about to stop pipe, insert a corner segment with right rotation (because calculation of the plane and points already done in this script) Also this could improve dramatically level of detail instead of a path extrude, which anyway have some issues when profile is bigger than radius. It normalize the segment line and generates offset points from the vertex points. One control point with offset from the corner point with diameter and another control point diameter * (2**0.5 -1). The same as we got with the filled tool. The issue seems to be creating a "double" point with ends line segment to a radius NURBS. We get that with the tool but by script it is still a secret. I "solved" by giving a big weight (10) at the end of the line segment and weight 1 at the control points. It draws nearly an exact radius. I hope maybe join again the thema and help improving the solution or can use the existing approximative method. import math sqr2 = 0.41421356237 #faster to have constante value instead of calculation 2**0.5 several times I guess def point_on_line_3D(p1, p2, d): #3d Points d = distance from p1 to p2 x1, y1, z1 = p1 x2, y2, z2 = p2 # a little long but it just substract p1 from p2, then normalize and then multiply with new lengt and add to old point 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 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 = [] vtxCnt = vs.NurbsGetNumPts(nurbsObj, segm) num_knot = vs.NurbsNumKnots(nurbsObj, segm) for vtx in range(0, vtxCnt): # python range is always one less than pascal v = vs.NurbsGetPt3D(nurbsObj, segm, vtx) pts.append(v) if vtx < vtxCnt - 1: #some code of the developper wiki p1 = v p2 = vs.NurbsGetPt3D(nurbsObj, segm, vtx+1) #vs.Locus3D(p1); points.append(p1) #corner point p = point_on_line_3D(p1, p2, radius*sqr2) points.append([p,1]); #points.append(p) p = point_on_line_3D(p1, p2, radius) #start radius point points.append([p,10]); p = point_on_line_3D(p2, p1, radius) #start radius point points.append([p,10]) p = point_on_line_3D(p2, p1, radius*sqr2) points.append([p,1]); #points.append(p) segments.append([vtxCnt, num_knot, pts]) new_curve = vs.CreateNurbsCurve(points[0][0][0],points[0][0][1],points[0][0][2],True,3); for i in range(1, len(points)): p, weight = points[i] vs.AddVertex3D(new_curve, p) vs.NurbsSetWeight(new_curve, 0, i, weight) #vs.Locus3D(p) vs.DrawNurbsObject(new_curve) vs.ReDraw() num_knots = vs.NurbsNumKnots(new_curve, 0) for i in range(num_knots-3): pass fillet.mp4 Fillet v2022.vwx
  21. DomC

    Data Tags

    Oh, direct before my very eyes. Thank you so much, that works perfectly!
  22. DomC

    Data Tags

    Hello Someone knows the secret of tagging an object with the DataTag by script? Seems to be not so easy. So far my researches: 1. Read the ASSKINDs of Object and DataTag. It shows me: 37 for the Data-Tag 36 for the Tagged Object obj1 = vs.FSActLayer() num = vs.GetNumAssociations(obj1) out_str = 'Associations\r' for i in range(num): v = str(vs.GetAssociation(obj1, i)) out_str += str(v)+'\r' vs.Message(out_str) 2. Further Assiciations obj1 = vs.FSActLayer() obj2 = vs.NextSObj(obj1) result = vs.AddAssociation(obj1, 17, obj2) #4(deleted if delete), 5(reset if deleted) 17(?) vs.HMove(obj1, 1,0) 3. Remove Associations obj1 = vs.FSActLayer() #stempel = vs.GetObject('stempel') num = vs.GetNumAssociations(obj1) out_str = 'Associations\r' for i in range(num): ioTargetObj, inKind, value = vs.GetAssociation(obj1, i) vs.RemoveAssociation(obj1, inKind, ioTargetObj) 4. Maybe with a constraint? h1 = vs.Handle(0) h2 = vs.GetObject('line1') h3 = vs.GetObject('symbol1') if h2 != vs.Handle(0): p2 = vs.Get2DPt(h2, 0) x1, y1 = vs.HCenter(h3) obj, index, containedObj = vs.GetClosestPt( h3, x1, y1) vs.AlrtDialog(str([obj, index, containedObj, h1, h2, h3])) #obj1 and h1 are the same contObj1 is None bool = vs.SetBinaryConstraint(1, h3, h2, index, -1, 1, -1, containedObj, 0) if h2 != vs.Handle(0) and h3 != vs.Handle(0): bool = vs.HasConstraint(h2) vs.AlrtDialog(str(bool)) This works for a line and a symbol. Maybe this works with data-tags and object also if we could find the right arguments.
  23. The Rendering in VW Design Layer: Rendering in Viewport: (Rendering is a little brighter because of image effect) All is set to Renderstile "Moebel freistehend" Panorama Export Setting: Here the panorama export with the same renderstile: The Link to the panorama https://cloud.vectorworks.net/links/11ece6958ee3d58291a90e8843f6c72d/ How it would be used: This panorama is exported Renderworks but with a renderstile with a darker hdri. https://cloud.vectorworks.net/presentations/11ecc73b611af0e39a191233fa6cc30d/ File: https://cloud.vectorworks.net/links/11ece69bcd28bbdaaf4c0e8843f6c72d/
  24. Hello Also very interested in making visible the work of an algorithm. I think it is possible by script to show the Objects created or manipulated by script. But a Marionette saves the view before the script runs and recovers it. Somehow this results in a different behavior from Marionette compared to a python script. I played around with this some time ago. The Attached Document shows a script that contains the same code as a Marionette. By executing the script the movement of rectangle is plotted on the screen. Animation Test.mp4 For another example I putted every of the steps of the script on different layers. Then after the execution I batch-export the layers as pictures then combined into a movie with an external tool. Like this: I can't find that example anymore but I think i just hardcoded an Object creation and a vs.SetParent to put it on a new Layer Animation.vwx
×
×
  • Create New...