Jump to content

DomC

Member
  • Posts

    664
  • Joined

  • Last visited

Everything posted by DomC

  1. You could open both virtual poly where it starts. While the original scrip calculates and is not geometry related
  2. Looked a little deeper. A pragmatic solution could be, we have a virtual outer and inner contour. which have a regular shape. Then we create the points on this contours: Connecting to the existing script will modell the stair and intersect the shape: One point left, it does not stop by the final contour if it is infinite like this: To use this in a PIO you have to make control-geometry a group and order the elements in the right order: Extract them in the right order important keep order. Otherwise you will mess it up. I took order here in this example 1. VirtualShapeOut 2. VirtualShapeIn 3. Final Form. Then wrap and convert to pio You have to bound the shape ad the escape step. What is missing is the 2D Geometry, which has to many lines now. But it is makable. Not worth to go further if it is not clear if anyway the geometry methode is fitting the requirements. Connect to local Distributor ComputerWorks. They can help. If it takes longer it will be not costless. But maybe this start would help you. Oval Individual Focus points.vwx
  3. Hi First you should think about a rule which is available. Mostly this is the bigger issue than making the some code is thinking how about you think by designing and how to convert it to an algorithm. 1. The rule could be, every step line is "designed" by human (user) - Then maybe the control geometry could contain just inner and outer countur and lines which are created by user and the script would model the 3D stari 2. A logic adaptable rule as example. On the inner countur we need 15cm minimum measurement. this gives us an amount of steps we could use maximum and the vector of the step-line it through this inner minumum point and the walking line of the stair. Problem could be, that every inner distance is the same on the contour and if the countour is not symmetric the steps are not symmetric. But in your case the Stair "eye" is symmetric so this could work. Yes could work. + Symmetrical - But because the out contour and the inner contour have not the same shape as the walking line it is maybe not the best solution. + Walking line could be parallel to outer contour to make the walking path more ergonomic + Relative easy to script. repacing the center through the point which are paired to the other point. 3. The inner virtual center could be defined independent on a contour (similar to the original example but not a center just unique points but not on the contour) + This would result in nice flow of the stair because of similar shampe outer and inner center points - Different distances on the real contour. + Usefull if inner contour is not symmetric. as example Picture one - Looks line best Solution but harder to script. We need points on the outer and virtual contour (easy). Then we need sectionpoints between polyline final inner contour. This is harder. I do not know the good solution for this. Maybe through intersecting line with inner shape etc. Or have you another requirement which could be defined? If i look at your specific stair the rule is like Solution A. Individual drawn steps in 2D. I can not see a rule for calculating the inner points? Generally i think, a stair is one of the last design-peaces an architect can be creative. So maybe it is the right thing to just model individually it take too long to make an algorithm for it.
  4. Hi I searched the Forum but had no luck. So sorry if i ask again what maybe have been asked in past. I have several 3D Cabinet Elements which i want to export as single DWGs each. Automatically without user-interaction. So far, what i figured out and what works well is the following steps: 1. Creating several "unique name placeholder saved view names" by script. By example 200 peaces. 2. Saving a publishing sets which contains all of those views as a DWG Export. 3. Delete the saved views. The Publishing sets keeps stored on the document. 4. Later in the Export routine, save view, which just shows the element i want in a single DWG (hide other object) 5. Doing this for all Objects i have and create a saved view with the same name as the placeholder views. 6. Publish the set. It will export all saved views that exists in real from the saved sets. 7. purging the saved views. Works fantastic and i am glad that i found a solution at all. But: I do not like it, because i have to litter the template file with the "dummy-saved-views". and the export is addicted to the right template file. I need the objects on that specific template with the set. Or i have to create the set manually and then use it. So the question is. Is there a way to write the publish-set by Script? Also it would be useful generally to be able to transport things like this from one document to another one.
  5. Thanks for reply I know a command for getting the cutPlane of the Design-Layer: def vs.GetLayerCutPlane(layer):    return REAL The Walls in 2026 have got a new option to individually set the cut plane of a single wall. Here we can switch from design layer cut plane to cut Plane per Wall. End-Target would be to finde 0-height walls with a worksheet script. It would show, wich walls have 0 height and/or cutplane is 0. Also it would be a good option, to change cutplane from 0-height (wich is default but make no sense) to 0.5mm (middle of a 0-height wall which has always 1mm minimum height). Projects are quite big and it is hard to see what changed and it will be a lot of work to search all walls in every symbol in every annotation inside every group and layers. So it would be the target to search walls with 0-height and set cutplane to 0.5mm which would make them visible again. I think the possible workflow could be to search layer cutplane and change from 0 to 0.5mm. Unfortunately it is not clear what happens with walls inside symbols or annotations. There the script should deactivate the checkbox and then set the cutplane. Problem is just giving 0-height walls a height would not be enough, because cut-plane of zero would not generate a wall section if the wall bottom bound at zero. End Result would be a "Wall Heal Helper Worksheet" and some scripts to fix legacy symbols and wall settings.
  6. Hi Has anyone already found the selector (object variable) or command to access the Wall Cut Plan Options?
  7. Hi I am working on an automated process to create and maintain kitchen cabinets. I already have the basic data, which includes around 10,000 items, some of which are surcharges or variants. All of them need to be included, and the system with the Cabinets PlugIn catalogs seems very well suited for this purpose. Creating the catalog data works, and in combination with the XML (IDM) you can make a variety of useful settings. The filter dialog is dynamically linked to the XML, which is of course very flexible. The goal now is to have about 350 base variants visible as styles, while the rest (variants, etc.) would be accessible through the catalog. So far, everything can be automated – except for creating the styles. What I am missing is the following knowledge: Where is the front layout stored? There doesn’t seem to be a data field for it. From the catalog, the front layout can be loaded (not linked), but it doesn’t seem possible to load the catalog entry via script – only through the dialog window. Likewise, I cannot link the style to the catalog without a dialog window. But dialog windows are of course the end of any automation attempt. At least the workflow with the catalog is theoretically possible: create a single PIO and link it to the catalog. However, I still see the problem that I would like to replace, for example, all cabinets in the Projects through another catalog or variants with cabinets from another catalog entry – and for that, the script would need to be able to directly assign the catalog entry data. I know there are records with data. I can see nearly everything of the cabinet PIO record but exactly not the front information which would be most useful. Also i looked at invisible fields and records. So the information must be stored somewhere hidden. Has anyone had experience with this issue or a useful tip? Would be great. Screenshot (Blurred text and some cabinets. Reason of discretion ) shows, how it looks like if i create the library with extrudes. also possible but not what i like to have at the end. I want to have cabinet PIOs.
  8. Hi I found something which would creates the path independent from VW Version and works with the recommended vs.GetVWRString(res_path, '1') method. Files without extensions: res_path = os.path.join(exe_path, "Vectorworks", "Strings", "210 Folder") and the exe_path with vs.GetFolderPath(1) certainly on Windows. On May i have to use the os.sys because someone could rename the application. Edit: Best solution so far. One single line cross-platform: mep_folder = vs.GetVWRString("Vectorworks/Strings/210 Folder.vwstrings", 297)
  9. I see different ways to get a resource string. I am uncertain if i should use vs.GetResourceString('210 Folder', '1') or "vs.GetVWRString(res_path, '1')" Because GetResourceString has not much entries here in the forum and on github there is written somewhere " GetVWRString replaces GetResourceString" https://github.com/Vectorworks/developer-scripting/blob/main/Function Reference/Functions/GetVWRString.md And "depricated since 215" I think this could maybe be in context if the res_file changes from Vectorworks.vwr to someting else where the resource file path would have to be changed with SetVSResourceFile https://github.com/Vectorworks/developer-scripting/blob/main/Function Reference/Functions/GetResourceString.md What i want to reach is, getting the localised string of the Workspace Folder as example. Or the Localised Folder Name of MEP Tools. If i would use GetVWRString i had to tinker the path and dive into the zipped res folder on windows. Where GetResourceString seems to refer directly to a cached list of Vectorworks string resources. import os import sys import vs exe_path = os.path.dirname(sys.executable) (major, minor, maintenance, platform) = vs.GetVersion() if sys.platform == "darwin": # macOS res_path = os.path.join(exe_path, "..", "Resources", "Vectorworks.vwr", "Strings", "210 Folder.vwstrings") else: # Windows res_path = os.path.join(exe_path, "Vectorworks.vwr", "Strings", "210 Folder.vwstrings") res_path = os.path.normpath(res_path) # Test with localised workspace folder name # works cross-platform without path but # maybe issue, if resource file changes result_GetResourceString = vs.GetResourceString('210 Folder', '1') result_GetVWRString = vs.GetVWRString(res_path, '1') # Ausgabe mit f-String vs.AlrtDialog( f"Exe path: {exe_path}\n" f"VW Version: {major}.{minor}.{maintenance} (Platform: {platform})\n" f"Resource path: {res_path}\n" f"GetResourceString: {result_GetResourceString}\n" f"GetVWRString: {result_GetVWRString}" )
  10. Hi Very useful, thanks for. Maybe it is possible the add Localised Names to the output for a next version? Many users have Localised strings and see nowhere the universal name in the UI. Attached my modified Node for the Localised String Print Parametric Record LocalisedNames v2025.vwx
  11. Hi I think, it crashes because of the icon_path parameter the following work here. Creating Tools Set in Tools and then add a Tool import vs # Start editing workspace vs.wsEditBegin("View") # Get Basic palette path (index 0) pName = vs.ws2GetToolAt("", 1) vs.AlrtDialog(f"Basic palette name: {pName}") result, outDisplayName, outShortcutKey, outShortcutKeyModifier, outResourceID = vs.ws2GetToolInfo(pName) vs.AlrtDialog(str([result, outDisplayName, outShortcutKey, outShortcutKeyModifier, outResourceID, pName])) tsPath = pName universalName = 'universal_name_f01b8' setName = 'NewSet' vs.AlrtDialog(str([tsPath, universalName, setName])) icon_path = os.path.join(vs.GetFolderPath(1), 'Vectorworks 2025.app', 'Contents', 'mock-texture-overall.png') ok = vs.ws2CreateToolSet(tsPath, universalName, setName, icon_path) vs.AlrtDialog(f"Tool add success: {ok}") toolPath = f"{tsPath}/{universalName}" vs.AlrtDialog(f"tool Path: {toolPath}") # Add tool to Basic palette ok = vs.ws2CreateTool(toolPath, "Blindfold", 2) vs.AlrtDialog(f"Tool add success: {ok}") vs.wsEditEnd(False) # Save and end session vs.ws2CommitChanges(False, True) Edit: It seems, that if ToolSet is not exists it needs an icon path even the icon was not found empty string let it crash. Also None crash. It seems to work with False, aString as the icon_path but not with None or empty string.
  12. Hi Not in that matter right now. Minimum i can confirm it crashes 😁 missing icon path or missing wsEditBegin or wsEditEnd. The above Test worked in 2022 and 2023. Maybe there was changed something in the meantime.
  13. Hello Sorry for digging up this old thread. For those who, like me, didn’t know yet: there is a Function option in the worksheet. ObjectData('parameter', 'YourParameterName') I tested it—and it works! It is even bidirectionally linked to the Marionette parameter.
  14. After a brief search in the forum, I couldn’t find any information on this topic. When using Data Mapping in the Data Manager, we can set the option “By Mapping” for Vectorworks Records using the function: vs.SetRFieldOpt(h, record, field, isEmpty, isDataLinked) This results in the arrow icon appearing in the Object Info Palette, indicating that the field is linked to the Data Manager mapping. Is there a similar command available for custom IFC Property Sets (ifcPsets)? That would be extremely helpful. Our general recommendation is to maintain an internal office data structure using a standard user-defined Record Format (the default Vectorworks Record Format). The custom ifcPsets are typically project-specific additions, and we map the values from the VW Record into the ifcPsets. It would be great to have the ability to switch all fields that are mapped in the Data Manager to the “By Mapping” option in bulk. Custom (manually entered) values should remain untouched. This process works for records using a script, but I haven’t found a solution for custom ifcPsets yet.
  15. DomC

    Time Delay

    Hi Try with vs.ReDrawAll() inside your breaks. At the end the workflow could be exporting images and combine to a movie to make visible your script. Like here i dumped the results in graphics and combined after to a movie: But I would say, it could work. With some luck and vs.ReDrawAll() in the code. Look attached File (Sound is deactivated but animation is visible, imagine the holy night christmas song ...). Also as example this script would show an animated rectangle: Animation.mp4 The christmas animation directly in Vectorworks https://youtu.be/MexEualOq7g And this one with exported graphic and merged together to a movie: https://youtu.be/V_-apzxOTXM For Samichlaus2 v2025.vwx
  16. Hi Sam I would get the distance between the two points. Than draw a 2D Dimension and place with SetEntityMatrix. But i just used it for orthogonal 3 Dimension not "free rotated in space" #then to make it 3D vs.SetPlanarRef(inObj, refID) # then to place in 3d space _bool = b = vs.SetEntityMatrix(inObj, offset, rotAng[0], rotAng[1], rotAng[2]) # if your points are orthogonal it was easy. If not you need the euler angles and so you need 3 points to calculate. snipped how i use it: def create_dimension_by_direction(p, l, dim_type, angle, direction = (0, 0, 0), dim_off = 150, standard='RS ISO 1x', text_size=3, text_offset = 1): try: if l > 0.1: x_dir, y_dir, z_dir = direction vs.LinearDim((0,0),(l,0), dim_off,dim_type,769,True,0) dim = vs.LNewObj() vs.SetPlanarRef(dim, -1) (dx, dy), parallel_p2 = find_parallel_line_from_angle((p[0], p[1]), angle, l, 30, clockwise=True) _bool = vs.SetEntityMatrix(dim, (dx, dy, p[2]), x_dir, y_dir, z_dir) # vs.SetObjectVariableString(dim, 27, standard) #dim standard vs.SetObjectVariableReal(dim, 40, text_size) #font size vs.SetObjectVariableReal(dim, 43, text_offset) #text offset vs.ResetObject(dim) except: pass return vs.LNewObj() dim = create_dimension_by_direction((p1[0], p1[1], 0), n_height, 4, b, dim_off = -300, direction = (b-90,-90, 180)) #text under the dimension line vs.SetObjectVariableString(dim, 1233, f"{s_group}-{short_uid}-{arg_dict['index'] + start_index}-Höhe")
  17. Solvable this way: vs.DSelectAll() for item in vp_list: vp_handle, l, i, vertex_angle = item vs.SetObjectVariableBoolean(vp_handle, 1004, True) #set vp out of date vs.SetSelect(vp_handle) #vs.UpdateVP(vp_handle) this does not do the job # not beauty, but it works vs.DoMenuTextByName("Updated Selected Viewports", 0) vs.Wait(1) vs.DoMenuTextByName("Updated Selected Viewports", 0)
  18. I try to get the right selector for that menu Command vs.DoMenuTextByName('Update Selected Viewport', 0) Background is, that i fail with vs.UpdateVP() when i want to have hidden line render it somehow shows elements from hidden class. if i update viewport by menu it looks all right after that. I pasted some code but it is try and error code. In Main i 1. hide all classes 2. hide classes which are mandatory for object size 3. UpdateVP to measure size of the minimal vp crop size 4. show rest of classes i want to see 5. Update vp again I am sure, somewhere i had to reset a cache, an object variable etc. It works with Shaded View but not with hidden line. I just need a pragmatic solution so DoMenuTextByName whould do the job. code vp_handle = vs.CreateVP(layout_handle) set_vp_scale(vp_handle, scale) hide_classes_by_keword(vp_handle, 'RS_Mobiliar') #vs.UpdateVP(vp_handle) hide_classes_by_keword(vp_handle, 'RS_Wand-') ##_bool = vs.SetVPClassVisibility(vp_handle, 'RS_Mobiliar', -1) #vs.UpdateVP(vp_handle) class_name = 'RS_Wand-' + space_name + '_' + str(i) class_name_last = None class_wall = 'RS_Wand-' + space_name + '_gesamt' if i == len(segment_lengths) - 1: class_name_last = 'RS_Wand-' + space_name + '_' + str( i + 1) #_bool = vs.SetVPClassVisibility(vp_handle, class_name_last, 0) visible_classes = visible_classes_construction_netto + [class_name, class_name_last, class_wall] set_class_visibility(vp_handle, visible_classes, invisible_classes_construction_netto) _bool = vs.SetVPLayerVisibility(vp_handle, space_layer, 0) _bool = vs.SetEntityMatrix(vp_handle, (pos, 0,0), 0, 0, 0) vs.SetViewMatrix(vp_handle, (0,0,0), -90, -vertex_angles[i], 0) vs.SetObjectVariableInt(vp_handle, 1000, 0) vs.SetObjectVariableInt(vp_handle, 1001, 6) #hidden line background 1036 # hier sind Klassen ausgeblendet, die übger den VP hinausschauen. Damit die BBox sauber ist, muss das so aktualisiert werden vs.UpdateVP(vp_handle) vp_cache = vs.GetVPGroup(vp_handle, 3) tl, br = vs.GetBBox(vp_cache) w = br[0] - tl[0] bl = tl[0], br[1] vs.RectangleN(bl[0], bl[1], 1, 0, w, 4000) rect = vs.LNewObj() vs.SetPlanarRef(rect, 0) # Und hier kommen diese Klassen vom Rand wieder dazu. Z_.B. Eckv erbindung guckt ja auch überr die BBox der Wand raus oder Bemassungen _bool = vs.SetVPCropObject(vp_handle, rect) visible_classes = visible_classes_construction_final + [class_wall] set_class_visibility(vp_handle, visible_classes, []) set_vp_class_colors(vp_handle) vs.SetObjectVariableInt(vp_handle, 1001, 0) #wireframe vs.SetObjectVariableInt(vp_handle, 1001, 6) #hidden line #vs.SetObjectVariableInt(vp_handle, 1006, 0) #foreground #vs.SetObjectVariableInt(vp_handle, 1036, 3) #hidden line ovViewportForegroundRenderType 1036 #vs.UpdateVP(vp_handle) #vs.SetObjectVariableInt(vp_handle, 1036, 6) #hidden line ovViewportForegroundRenderType 1036 #vs.ResetObject(vp_handle) vs.SetObjectVariableBoolean(vp_handle, 1167, True) vs.ResetObject(vp_handle) vs.UpdateVP(vp_handle) vs.ReDraw() #vs.HMove(vp_handle, pos, 0) l = w / scale #(segment_lengths[i] + 68) / scale vp_list.append([vp_handle, l, i, vertex_angles[i]]) What it does: Taking the modell After vs.UpdateVP i have the result "Before Update". After Menu Command Update i have result "After Update" I Tried a lot (vs.SetObjectVariableBoolean(vp_handle, 1167, True) etc. ) but seems not the right things ...
  19. Clever and elegant. Thanks for that input!
  20. OK, i solved like this (maybe still errors but so far is should work like this): A column with the last publishing date: =VERKETTEN(IF('Title Block Issue Data-1'.'Date'<>'', 'Title Block Issue Data-1'.'Date', IF('Title Block Issue Data-2'.'Date'<>'', 'Title Block Issue Data-2'.'Date', IF('Title Block Issue Data-3'.'Date'<>'', 'Title Block Issue Data-3'.'Date', IF('Title Block Issue Data-4'.'Date'<>'', 'Title Block Issue Data-4'.'Date', IF('Title Block Issue Data-5'.'Date'<>'', 'Title Block Issue Data-5'.'Date', '-')))))) And then a column for comparison the last Revision with the publishing date: =IF(TEILSTRING('Title Block Revision Data-1'.'Date', '.', 1)>TEILSTRING(M5, '.', 1), 'neu', IF(TEILSTRING('Title Block Revision Data-1'.'Date', '.', 2)>TEILSTRING(M5, '.', 2), 'neu', IF(TEILSTRING('Title Block Revision Data-1'.'Date', '.', 3)>TEILSTRING(M5, '.', 3), 'neu', 'alt'))) TEILSTRING is same as SUBSTRING
  21. Hi Somebody have experience converting the date string into a number? I want to 1. Compare and take the last Date. Which also works like this but is not very elegant: =IF('Title Block Issue Data-1'.'Date'<>'', 'Title Block Issue Data-1'.'Date', IF('Title Block Issue Data-2'.'Date'<>'', 'Title Block Issue Data-2'.'Date', IF('Title Block Issue Data-3'.'Date'<>'', 'Title Block Issue Data-3'.'Date', IF('Title Block Issue Data-4'.'Date'<>'', 'Title Block Issue Data-4'.'Date', IF('Title Block Issue Data-5'.'Date'<>'', 'Title Block Issue Data-5'.'Date', '-'))))) 2. I want to compare revision is newer than approved I could split the date into year, month and day and then compare each to find if one is newer than the other. But maybe there is a direct way to convert a date into a number? i already tried int('Datestring') with different formats m/y/d, d/m/y etc. but that seems to fail Edit: It works with a plain cell with a date string. But not yet with a calculated date.
  22. I uploaded new Version 1.0.5 which rotates the fill of the Rectangles along the angle.
  23. Hi My idea is to create a web server, host a dialog there, and exchange data via the web directory of the hosted content. So far, I see the following possibilities: 1. **Dump the site from Vectorworks to a local file.** Local web content is restricted and, as far as I can see, cannot contain cross-references or multiple files. This is for security reasons, as a web application shouldn't control the local file system. One way to address this is by using a local development server (e.g., Python's `http.server`) to serve the content over HTTP, bypassing these restrictions. 2. **Launch an Apache server on macOS.** This works so far; the site is hosted in a machine directory that is accessible with root privileges. It's quite simple to do with a `subprocess sudo apachectl start`. This would work, and the web application could load and write data in the directory. However, this requires root access to start Apache. Or having to manipulate configuration files. 3. **Launch a web server via Python.** Here, it’s not possible to launch it directly within Vectorworks because the server would block the Vectorworks main thread, as Python’s default HTTP server runs synchronously. 4. **Launch a Python web server as a subprocess and access the embedded Python in Vectorworks.** This could be possible, but the environment variables in the OS might not handle the embedded Python properly. Explicitly configuring the subprocess environment or using isolated Python installations could help mitigate this issue. However, it's possible that the embedded Python content is designed to run exclusively within Vectorworks, making this option challenging. bash python3 -m http.server 8080 5. **Installing additional application in the OS.** This is also possible, but the solution should work like a portable standalone application rather than requiring content to be installed into the system. Tools like Docker or portable Python distributions could make this approach feasible without impacting the system setup. 6. **Using an external web application to handle everything.** In this approach, you send a token, the web application processes the data (e.g., sanitizes and validates it), builds the site, and writes results to a database. The local script can then retrieve the results using the temporary token. I’ve used this method for some projects, and it seems very flexible and powerful. However, it requires an external web service and isn’t lightweight at all. 7. Creating one single local web-page Merging everything in one file would work for pushing the content into the site. Still the issue then, that it is not possible to write something on the disk, which would work with the #2 apache webservice. I know an SDK-developed application could make direct access possible (anyway i never tried this, too much respect from the c++ environment), even with a non-blocking palette. But still there is the other question of hosting the site on the localhost. Does anyone have additional ideas for a simple, secure and clean workflow to host the web-content?
×
×
  • Create New...