Jump to content

DomC

Member
  • Posts

    604
  • Joined

  • Last visited

Everything posted by DomC

  1. The Marionette Result of scanning the OV of a Viewport from 0 - 5000. I think it would need a function like calling an array but the only array what is callable for object-variables is a point tuple.
  2. Thanks for your worthwhile feedbacks. So far my strategy (But I do not know if it will work reliable enough) 1. Inside the Section there is a Section Line Type 86 that contains the position of the section and a direction matrix 2. There are Informations on the Section VP directly that tells, if section is horizontal or vertical 3. The VP cache Group contains the projected geometry of the elements In combination of this 3 information it is possible to compare the Design-Layer coords and the section coords. I build some functions to test what works. So far i see the following stumbling stocks: - There are differences if the horizontal section was created from clip cube or from sectioning a VP - VP cache has not the same informations if the objects behind section plane are disabled - So far my function are not secure to return always the right informations Prototype Method to get Section Line: Gets Section Informations = vs.FSActLayer() rname = 'Section Line2' def create_field_value_dict(obj, rname): rhandle = vs.GetObject(rname) num_fields = vs.NumFields(vs.GetObject(rname)) fdict = {'found' : True} for i in range(1, num_fields+1): fname = vs.GetFldName(rhandle, i) value = vs.GetRField(obj, rname, fname) fdict[fname] = value return fdict def get_sl_in_vp(vp): obj = vs.GetVPGroup(vp, 2) #vs.Message(str(obj)) groups = [] while obj != vs.Handle(0): t = vs.GetTypeN(obj) if t == 11: groups.append(obj) obj = vs.NextObj(obj) section_line = vs.Handle(0) #vs.Message(str(groups)) for group in groups: obj = vs.FInGroup(group) while obj != vs.Handle(0): t = vs.GetTypeN(obj) n = rname if t == 86 and n == 'Section Line2': section_line = obj break obj = vs.NextObj(obj) return section_line section_line = get_sl_in_vp(h) m = vs.GetEntityMatrix(section_line) fdict = create_field_value_dict(section_line, rname) fdict['entity_matrix'] = m fdict['is_horizontal'] = vs.GetObjectVariableBoolean(h, 1048) vs.Message(str(fdict)) Prototype Method to get VP cache infos: This Function puts a 3D Locus on the Design-Layer in Projection to the Objects vertical to Section Plane. h = vs.FSActLayer() rname = 'Section Line2' lh = vs.GetLayerByName('Konstruktionsebene-1') fdict = {} def create_field_value_dict(obj, rname): rhandle = vs.GetObject(rname) num_fields = vs.NumFields(vs.GetObject(rname)) fdict = {'found' : True} for i in range(1, num_fields+1): fname = vs.GetFldName(rhandle, i) value = vs.GetRField(obj, rname, fname) fdict[fname] = value return fdict def get_poly_in_vp(vp): obj = vs.GetVPGroup(vp, 3) groups = [] while obj != vs.Handle(0): t = vs.GetTypeN(obj) if t == 11: groups.append(obj) obj = vs.NextObj(obj) #vs.AlrtDialog(str(groups)) objs = [] for group in groups: obj = vs.FInGroup(group) while obj != vs.Handle(0): t = vs.GetTypeN(obj) #vs.AlrtDialog(str(t)) if t in [5, 21]: if vs.GetFPat(obj) != 0: objs.append(obj) obj = vs.NextObj(obj) return objs objs = get_poly_in_vp(h) fdict['polys'] = objs fdict['is_horizontal'] = vs.GetObjectVariableBoolean(h, 1048) vs.AlrtDialog(str(fdict['is_horizontal'])) #vs.AlrtDialog(str(objs)) def get_center_points(objs): center_points_3D = [] for obj in objs: p = vs.HCenter(obj) if fdict['is_horizontal']: m_pt = p[0], p[1], 0 vs.AlrtDialog(str(m_pt)) else: #vertical section y = z m_pt = p[0], 0, p[1] center_points_3D.append(m_pt) return center_points_3D center_points_3D = get_center_points(objs) for p in center_points_3D: vs.Locus3D(p) locus = vs.LNewObj() #vs.SetParent(obj, lh) vs.SetParent(locus, lh) And next prototype Method can check if the center point of the section cache-geometry is inside the parent object on the design-layer. lh = vs.ActLayer() ln = vs.GetLName(lh) espsilon = 1 c = "(INOBJECT & NOTINDLVP & NOTINREFDLVP & ((L='l-dummy') & (PON='XG Custom Part')))" c = c.replace('l-dummy', ln) custom_parts = [] def add_handle(h): custom_parts.append(h) vs.ForEachObject(add_handle, c) def is_pt3_in_cube(pt, cube, epsilon): x, y, z = pt xmin2, xmax2, ymin2, ymax2, zmin2, zmax2 = cube # vs.Message(str(cube)) overlapx = overlapy = overlapz = False if xmin2 - epsilon < x < xmax2 + epsilon: overlapx = True if ymin2 - epsilon < y < ymax2 + epsilon: overlapy = True if zmin2 - epsilon < z < zmax2 + epsilon: overlapz = True return min(overlapx, overlapy, overlapz) def bbox3D(p, zValue, height, width, depth): centerPt = (p[0], p[1], zValue) botZ = zValue - depth / 2 topZ = zValue + depth / 2 w2 = width / 2 h2 = height / 2 bbox_bl = p[0] - w2, p[1] - h2 bbox_tr = p[0] + w2, p[1] + h2 bbox_tl = p[0] - w2, p[1] + h2 bbox_br = p[0] + w2, p[1] - h2 xmin = bbox_tl[0] xmax = bbox_br[0] ymin = bbox_br[1] ymax = bbox_tl[1] zmin = botZ zmax = topZ return [xmin, xmax, ymin, ymax, zmin, zmax], ((xmin, ymin, zmin), (xmin, ymax, zmin), (xmax, ymax, zmin), (xmax, ymin, zmin), (xmin, ymin, zmax), (xmin, ymax, zmax), (xmax, ymax, zmax), (xmax, ymin, zmax)) #h = vs.FSActLayer() h = custom_parts[0] parent = vs.GetParent(vs.GetParent(h)) BOOLEAN, offset, rotationXAngle, rotationYAngle, rotationZAngle = vs.GetEntityMatrix(parent) (p, zValue) = vs.Get3DCntr(h) (height, width, depth) = vs.Get3DInfo(h) cube, pts = bbox3D(p, zValue, height, width, depth) is_in_cube = is_pt3_in_cube(pt, cube) for pt in pts: x, y, z = pt x = x + offset[0] y = y + offset[1] z = z + offset[2] pt = x,y,z vs.Locus3D(pt) Additional it would help to check classes and attributes to be sure not targeting an invisible object etc. With this 3d Methods it is possible to manually make a relation between a coord point inside the section annotations and the object on the design-layer. The shakiness of this strategy here is, that the Method of traversing the VP to collect Section-Line and Section Geometry is maybe not reliable enough or can wreck after an VW Update. Further it can be tricky to get positions of rotated and nested object rotations. That would be the the hardest part. Even the Data-Tag hat some (fixed) issues to find the Objects in every situation so I do expect that would be really expensive to solve that. Also I saw, that I corrupted some VP after working on them with this scripts. But I think this was because of creating Test-Marker-Objects inside the VP. At the end, this would be a "read-only" access to the VP which should not corrupt anything -SHOULD. I will pause working on that specific feature ☺️
  3. Hi Does anybody know, how to get a handle related to the geometry of the vp cache "vs.GetVPGroup(h, 3) or the VP coordinates to the Object on the Design Layer? Target would be tagging or annotate Elements in a Section viewport by script. Somehow it would work because the data-tag can also can access to this elements. I can imagine that it is necessary to evaluate the original object of a location from the vp coordinates and the section plane. Or is there an other solution for that? DomC
  4. Hi Hm, I was quite sure "SetTexBitFeatureSize" changed once the texture size. However I would confirm, the size is always 10mm, 1cm or 0.01m. So far what seems to change the size (but not as we needed) 1. Changing the Document units to the imperial unit-system inch. Texture size is now 1 inch instead of 10mm but somehow other units do not change the size. 2. If I change the line vs.SetTexBFeatureEnd(hTextureBitMap, int(resolutionx*100), 0) The Size is 100 times bigger but this value is not update till i go into the dialog box of the texture. Also Tried: Layer Scale, Different units, scaling the image, scaling the paint. Reload Document. So it seems, we have not a solution for the default texture size yet.
  5. Like with many scripts, you would need a "ResetObject" at the end to redraw the drilling.
  6. OK I can reproduce two issues. Wich looks not like a messed up script it looks like an issue with the style duplication and replacement on a new document. 1. Importing Style to new Document and edit the object or insert a second one 2. import and Edit the style and import and replace new from source The Styles Marionette PIOs are a new System since VW 2023. Before that we got the workaround with Script-Symbols inside of the PIOs which worked quite good at the end. It is very hard do foresee all workflow and issues in development and so I think the styles need a little time to loose the growing pains. I will bug-submit those two issues.
  7. The File was saved with SP2, maybe first try Updating on SP3. Also I can't see the issue in SP2 and SP3. But I saw this kind of errors in early SPS of VW 2023. I reported a lot of them they are all fixed. Please try to exactly find out, what steps are necessary to got the broken result.
  8. I think I found it vs.GetPolylineArcMaxRadius(hPoly, vertexNum) Just to close question .Correction in the loop by return 0 if Vertex Type is not Radius or Arc. Also harmonized units, this function returns mm (which is in my opinion very progressive if everything would returns mm and not document units > just a thought but how many code would fail after such an update :-). So good just new things returns mm. However here my little fiddle obj = vs.FSActLayer() num = vs.GetVertNum(obj) units = vs.GetPrefReal(150) output = [] for i in range(1, num + 1 ): p, vertexType, arcRadius = vs.GetPolylineVertex(obj, i) if vertexType in [3,4]: arcRadius = vs.GetPolylineArcMaxRadius(obj, i) / units else: arcRadius = 0 res = p, vertexType, arcRadius output.append(res) vs.CreateText('\r'.join(map(str, output)))
  9. Hi Did not find some hints in the forum, so a deside to make a new post. I think I am doing something the wrong way. But What I want to do is, to grab directly data of a polyline with arcs and radius without converting them or decomposing them. So the GetPolylineVertex command looks like the right workflow for this. But what I can see (depended how the polyline is created or which tools are used to modify it) it returns the radius not directly on the returned point index. The only pattern I can see is, that the last radius which was returned before the vertex point is the right radius. I can imagine, that this workes as designed to bequest the value to the next value which is 0. But somehow not logical is, that other points which are type 0 (edge) contains the radius value. Someone see behind the scene here? polylinie.vwx
  10. Maybe you also could recycle this marionette script. It will create a record from an external list of record fields. creating records from txt or xls. Also in the Marionette you could find the script commands you need for creating fields and record formats.
  11. DomC

    Translator

    Hi Maybe just the Variable Name "Zubehör" is the issue or return list. Try Changing the names of those two variable Names. list() is a python function and should not be used as a variable Name. Also special Character in function or variable names could maybe creates an issue somewhere. The rest I can't say much. You could test by renaming or deleting objects (take care about crashes) to see, where your handle is pointing to. Also caution with the nodes. If it returns None/Null maybe the print node attach the type to the prior object or something like this. I would first take the code out of the marionette nodes to search the bug.
    Just used it and it worked like a charm even without viewing the instructions 🙂 Have Potential for improvement, but since there is by far not a comparable feature 5 Stars
  12. Hi I am pretty sure, it should be possible by worksheet formula without script, is somebody long enough work on that Formula. I first attempt could be a hard-coded formula (one Formula for one parameter in one PIO) =TEILSTRING(TEILSTRING('MarionetteObject2D'.'NodeDef_OIPControls', ',', 6), ':', 2) While "Teilstring" is "SubString" and in Germany ';' must be used as delimiters instead of commas i guess. But it returns the Width of the Marionette Object. Also the reversed procedure should by possible by concat worksheet formulas. Never thought about this. 2 is the second parameter and 6 is the value. Edit: Hm reversed procedure could be tricky by writing at all data from a formula on the object
  13. Great Guys How cool is That! I will for sure use it soon to lay floor-panels soon in my basement hobby-room. Don't forget to share in the gallery.
  14. This kind of behavior is quite common. Often we need a "ResetObject" or a "ResetBBox" after some commands. I would not say this is a Bug or an error because it can be smart to not reset and recalculate everything in every single Node/Step of a script to keep it fast. The "GroupNode" resets the BBox. Also the Geometry-Grouping of Marionette Network resets the BBox of the PolyGroup by accident. You can reproduce the same behavior with a Script. h = vs.FSActLayer() num, polyGroup = vs.TrueTypeToPoly(h) bbox = vs.GetBBox(polyGroup) vs.AlrtDialog(str(bbox)) vs.ResetBBox(polyGroup) bbox = vs.GetBBox(polyGroup) vs.AlrtDialog(str(bbox)) The vs.TrueTypeToPoly() returns a group with zero size Bounding Box. We have to first reset the bbox to get the bbox size correctly. Or in the Script: Unfortunately, resetBBox (also ResetObject which is also a common needed Node) are not part of the standard Node-Content.
  15. Agree with Antonio. Alternatively set Text Properties to middle and then set Orientation to your point.
  16. Hi I wrote "low effort" so I triggered myself to try it. Here your example. I count here every 20th pixel. this is the input "Rasterabstand". What is not solved is, that the blue pixels as example not have exactly the same value. Also it counts also the white pixels. But it is a base, just to answer the initial question. Oh yes, Marionette can. counting pixel.vwx The Picture have 51 different colors. Here the counts:
  17. You can count pixels of an image by using the pillow library for python. You could install that library in 2023 with the new installer from Marionette. Some of the earlier installation nodes (from me and others) fails because of different reasons (wrong wheele Files, ssl incompatibilities etc.) But once your pillow library was working you can do that. You cant count the pixels and colors. Maybe you have to "round" color because not every green pixels have the same green etc. but it is possible with low or maximum medium effort. Some existing examples: 1. How to digitizing an Image: It counts the pixels and the the rgb values. 2. An Example how to seperate Clusters of Points. 3. An Example how to create a Hull around a "cloud" of Points. If you have generated points out of your image, you could make a shape out of this points with that. A note about Example #2 and #3. This is perfectly already solved by using an external Library like shapely etc. They can generate convex and concave shapes out of points. Also There are many other Libraries that can vectorize your images pretty good.
  18. 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.
  19. 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. 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.
  20. 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🙂 The other thread about the Transform MAtrix: Custom Part Entity.vwx
  21. 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.
  22. 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()
  23. This one would update or create new textures: import os def put_bitmap_in_texture(hTexture, hPaint, image_size): #hTexture Resource, hPaint hImage = vs.CreateImageFromPaint(hPaint, 'Just_a_name') hShaderRec = vs.CreateShaderRecord(hTexture, 1, 41) #1 = Color image hTextureBitMap = vs.CreateTextureBitmapD( hShaderRec) 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, image_size) #size units return hTextureBitMap major, minor, maintenance, platform = vs.GetVersion() isMac = False if platform == 1: isMac = True # define a location to import the images importPt = (0,0) image_size = 10 symCreatedCnt = 0 err, dirPath = vs.GetFolder( 'Select a Folder' ) if err == 0: # no-error hsfDirPath = dirPath if isMac: ok, hsfDirPath = vs.ConvertPosix2HSFPath( dirPath ) name_counter = 1 fileIndex = 1 while True: # loop the files fileName = vs.GetFilesInFolder( hsfDirPath, fileIndex ) fileIndex += 1 if fileName == '': # no more files break name, ext = os.path.splitext( fileName ) if ext.lower() == '.png' or ext.lower() == '.jpg': imagePath = os.path.join( dirPath, fileName ) hPaint = vs.ImportImageFile(imagePath, 0,0) #Needs to be deleted afterwards texture_name = name + "_tex" existing_obj_handle = vs.GetObject(texture_name) update_tex = False if existing_obj_handle != vs.Handle(0): #object already exists obj_type = vs.GetTypeN(existing_obj_handle) if obj_type == 97: #object is already a texture > Update hTexture = existing_obj_handle update_tex = True else: #object exists but is not a texture hTexture = vs.CreateTexture() texture_name = name + str(name_counter) +'_tex' name_counter += 1 hTextureBitMap = put_bitmap_in_texture(hTexture, hPaint, image_size) vs.UpdateThumbnailPreview(hTexture) else: #new texture hTexture = vs.CreateTexture() hTextureBitMap = put_bitmap_in_texture(hTexture, hPaint, image_size) if not update_tex: vs.SetName(hTexture, texture_name) vs.DelObject(hPaint)
  24. 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
×
×
  • Create New...