Etienne Azambre Posted February 12 Share Posted February 12 I am a beginner with the Marionette tool, but I would like to create a network that allows me to find collinear lines that either touch, overlap, or are superimposed within a group of objects, and then delete them and replace them with a single line covering the total distance. I'm not sure if I'm being clear ^^ Thanks in advance for your help! 1 Quote Link to comment
Marionette Maven Marissa Farrell Posted February 12 Marionette Maven Share Posted February 12 This sounds like a fun exercise! Could you clarify if the object types are actually all lines, or if they might be polylines/polygons? are they always 2D objects? This is definitely doable, but may require some custom nodes and edge-case handling. Happy to help you work through it! 3 Quote Link to comment
James Russell Posted February 13 Share Posted February 13 Hi Etienne, I'm so onboard with Marionette. I love it for all the visual things. I'm just not super all over it for Global Activities, like the one you're suggesting. I'm definitely not saying not to in this case, and the things that @Marissa Farrell continually changes my perspective on this I'm grateful for, however as a comparative math operation like this I typically do it in Vectorscript or Python. An example of which is below that I just whipped up and did some tests to take this: Into this [Purple are newly created merged lines]: Presuming this is your request understood correctly the Logic here is pretty straight forward; Find any two lines (H1 and H2 in this case). Find their Start and End Points. Find their Vectors (directions) If [ the Start AND End of H2 is within the Start and End of H1 ] AND [ the vector of H1 and H2 are the same ] then H2 can be deleted. If [ the Start OR End of H2 is within the Start and End of H1 ] AND [ the vector of H1 and H2 are the same ] the H2 must be a continuation of H1. Find out if H2 is the Start or End of H1 and then create a new line to cover the whole length. Rinse and repeat until there are no more line. Vectorscript Code Example: { James Russell FEB 2025 } { Math and logic by me, code layout thanks to ChatGTP... because I'm time poor. } PROCEDURE ConsolidateLines; VAR h1, h2, hNew: HANDLE; x1a, y1a, x2a, y2a: REAL; x1b, y1b, x2b, y2b: REAL; merged: BOOLEAN; FUNCTION HasSameVector(x1a, y1a, x2a, y2a, x1b, y1b, x2b, y2b: REAL): BOOLEAN; BEGIN { Two lines have the same vector if their direction vectors are proportional } HasSameVector := ((x2a - x1a) * (y2b - y1b) = (y2a - y1a) * (x2b - x1b)); END; FUNCTION FullyContains(x1a, y1a, x2a, y2a, x1b, y1b, x2b, y2b: REAL): BOOLEAN; BEGIN { Check if the second line is fully inside the first line and has the same vector } FullyContains := (x1b >= x1a) AND (y1b >= y1a) AND (x2b <= x2a) AND (y2b <= y2a) AND HasSameVector(x1a, y1a, x2a, y2a, x1b, y1b, x2b, y2b); END; FUNCTION Overlaps(x1a, y1a, x2a, y2a, x1b, y1b, x2b, y2b: REAL): BOOLEAN; VAR minAx, maxAx, minBx, maxBx, minAy, maxAy, minBy, maxBy: REAL; BEGIN { Get bounding values for both lines } minAx := Min(x1a, x2a); maxAx := Max(x1a, x2a); minBx := Min(x1b, x2b); maxBx := Max(x1b, x2b); minAy := Min(y1a, y2a); maxAy := Max(y1a, y2a); minBy := Min(y1b, y2b); maxBy := Max(y1b, y2b); { Overlaps if X and Y ranges intersect } Overlaps := (maxAx >= minBx) AND (maxBx >= minAx) AND (maxAy >= minBy) AND (maxBy >= minAy); END; BEGIN h1 := FInGroup(ActLayer); { First line } WHILE h1 <> NIL DO BEGIN IF GetType(h1) = 2 THEN BEGIN { Ensure it's a line object } GetSegPt1(h1, x1a, y1a); GetSegPt2(h1, x2a, y2a); h2 := FInGroup(ActLayer); { Second line } WHILE h2 <> NIL DO BEGIN IF (h1 <> h2) AND (GetType(h2) = 2) THEN BEGIN GetSegPt1(h2, x1b, y1b); GetSegPt2(h2, x2b, y2b); merged := FALSE; { If h2 is fully inside h1 and has the same vector, delete h2 } IF FullyContains(x1a, y1a, x2a, y2a, x1b, y1b, x2b, y2b) THEN BEGIN DelObject(h2); merged := TRUE; END; { If h2 overlaps h1 and shares the same vector, merge them } IF Overlaps(x1a, y1a, x2a, y2a, x1b, y1b, x2b, y2b) AND HasSameVector(x1a, y1a, x2a, y2a, x1b, y1b, x2b, y2b) THEN BEGIN MoveTo(Min(x1a, x1b), Min(y1a, y1b)); LineTo(Max(x2a, x2b), Max(y2a, y2b)); { Correctly get the last created object } hNew := LNewObj; { Ensure hNew is valid before applying color/thickness } { Remove this section if you don't want your lines coloured - I just did this for the example } IF hNew <> NIL THEN BEGIN SetPenFore(hNew, 50000, 0, 50000); { Purple } SetLW(hNew, 25); { 1pt Line Thickness } END; DelObject(h1); DelObject(h2); merged := TRUE; END; IF merged THEN BEGIN h1 := FInGroup(ActLayer); { Reset loop to check new lines } h2 := NIL; { Exit inner loop } END ELSE BEGIN h2 := NextObj(h2); { Move to next line } END; END ELSE BEGIN h2 := NextObj(h2); { Move to next object } END; END; END; h1 := NextObj(h1); { Move to next line } END; END; RUN(ConsolidateLines); * I'm very sure there are still fringe case in which this doesn't work. It's an example. ** It doesn't work on any curves. You could change it to operate on a different Layer/Group/Selection. *** I'd still very much like to see a Marionette Network that does this... and might build one later... Anyways, just an option to think about - great question though! Cheers, James 2 Quote Link to comment
Letti R Posted February 13 Share Posted February 13 Hello, @James Russell may i ask you for which part and how did you use ChatGPT, because last time i tried it failed to use the correct Vectorscript functions. Regards, Letti Quote Link to comment
Popular Post James Russell Posted February 13 Popular Post Share Posted February 13 Hi Letti, I'm using ChatGTP-4o with a Personalisation profile I have made / refined directly for Vectorscript within Vectorworks. Initial Script and Steering Ideally if you're planning this you should start a blank series of chats with Memory retention active and then be really specific with your initial instruction sets, with things like; I'm writing a Vectorscript for use in Vectorworks. Limit coding responses only with code and languages found in the Vectorscript Functions Libraries. Do not create or presume standard functions from Python. Then you need to be super specific with your initial brief. I helps that I personally have a fairly heavy math and coding background so I was able to get a fairly concise brief with both the approach and initial code chunks. I would suggest starting these projects small and I often will ask ChatGTP to re-describe my initial brief back to me before even starting the code base - to ensure that it understand clearly the goals of a project. You will always still encounter, what I refer to as, 'code ghosts' which are made-up creations which ChatGTP still retains and implements based on other coding languages (in particular Python as it's close enough to Vectorscript). This is where the ability to read the code it supplies is important to be able to identify made-up. Revisions and Adjustments Firstly, ChatGTP (and other natural language models) work really well with code. With Vectorscript you can feed the Script Errors directly back to it and it will 90% of the time be able to solve them. Hot Tip (Script Error Output): Instead of re-writing the Script Errors dialog, or taking a screen shot, you can find the raw text file this generates in your Application Support folder, for example (on Mac); yournamehere/Libraries/Application Support/Vectorworks/20XX/Error Output This means you're able to copy the raw text which is much better and easier for ChatGTP to manage. Additionally, when doing revisions, continually go back to previous versions and steer towards a different path. Don't be afraid to say: "I don't like this version, let's go back to [Copy Code Chunk] and then I want to try...". Everytime that I have a successful code chunk I save that version. You can do this iteratively through your resource manager and do version numbers. If you're getting nerdy... as I might sometime be... you'll use Visual Studio Code with a Vectorscript Language Plugin and versions in GIT or similar. Limitations Don't expect that ChatGTP, or any other natural language models, will be able to just generate a giant script instantly and perfectly without your interaction. The script above took 8 Chat GTP versions with me correcting manually 2 of them (in this case the "Whipped up" timeframe was 36 minutes from conception to final). I use natural language models to write significant portions of code now in all languages, or at least give me alternative code methods to each problem, and the biggest tip is to only do small portions which are relative to each other. This is where a modular function based approach works so well; refine one Function to do a specific task, continue with your natural language model refine this Function until it runs exactly how you want, and then start a fresh for the next Function - then tie them together at the very end with everything defined. Anyways, that's how I'm using Natural Language Models currently... thanks for coming to my TED Talk? Cheers, James 2 3 Quote Link to comment
Etienne Azambre Posted February 16 Author Share Posted February 16 Hello and thank you for your responses! Let me give you a bit of context about my work ^^. I’ve been working for two months in a french design office with eight draftsmen who use Vectorworks for a company that cuts PVC fabric and polyurethane foam to create all kinds of products (sports landing mats, ski slope protections, etc.). For now, I'm not as skilled as they are ^^', but even though each of them has their own specialty, they all go through the same final step in the drawing process: preparing the file for the fabric cutting machine, which cuts rolls of various widths and lengths. We have a blank Vectorworks file where we paste all our nested fabrics (like Tetris) as groups. They use Vectorworks classes to define the cutting priority order. - Class 0 is only for the draftsmen and is not taken into account by the machine. - Classes 8 and 9 are for pen markings on the fabrics before cutting. Then comes Class 30 for cutting, followed by Class 11, then Class 20, and finally Class 1 as the last cutting phase. Each of these classes has a specific color. I'm explaining all this for context because, ideally, I would like to create a Marionette network that follows these steps in this order : First, the network should recognize the name of the group from the total number of fabric groups. Then, a first check for the "laize" (the fabric roll width): if the group's width exceeds the predefined width set before executing the script, an error message should appear, and the process cannot continue. Next, the groups should be ungrouped once, followed by a second collision check for the subgroups: If the fabrics are just touching, it's OK. But if they overlap, it means there is a mistake in the nesting done by the draftsman. Once these two checks are completed, all objects should be ungrouped at least twice and decomposed to keep only lines, texts, arcs, and circles. After this, I would like to assign the different classes based on colors, but there is one important rule: The horizontal lines located at the very top or bottom of the width must be in Class 0 (which is not cut), to avoid breaking the machine. Finally, we reach the main goal: finding the collinear lines that touch, overlap, or are superimposed, as suggested by James Russel! These lines should be deleted and replaced by a single line of the same class. I know this is a lot to ask :S but you have no idea how much your answers will help me! However, I’m struggling with Python scripts… Could you send me a Vectorworks file with the Marionette network, or at least a screenshot of the network? Thank you so much in advance!!!! An example of a file for fabric cutting, ready to be sent in DXF. Quote Link to comment
James Russell Posted February 16 Share Posted February 16 Hi Etienne, The context here certainly helps, and it sounds like a wonderful process and product creation overall. The process you've outlined is similar to how I create files ready for laser cutting, where different Pen Colours (which for ease I also do Class Bindings) mean different processes or depths (Score Surface, Engrave Surface, Cut Surface, Double / Triple Pass Cut Surface, 10% Cut, 20% Cut, etc). Example of a Laser Cut and Engraved Access Point 'Coathanger' Design - J.Russell 2024 I personally think you're riding the line between a fairly diverse Standard Operating Procedure and an Automated Task (be it Python / Vectorscript / Marionette). The appeal of replacing or supplementing this series of tasks with an Automated Task is understandable, however I think you'll hit several barriers in niche situations in attempting to cover such a broad basis of possible designs / arrangements / objects. Certainly never wanting to deter creativity though, let's break your actions into some smaller steps! Name Recognition Although I don't fully understand this step there are so many possible recognitions available in script options that I'm sure this would be possible. Individual Objects in Vectorworks can be named. If you were working in a Symbol Basis they are named and can be recalled very easily. Ungrouping and further manipulation can also occur. Objects could have records attached and then be named and categorised in this way. Width (and/or Height & Depth) Again something that is done in so many different ways in Vectorworks. The most immediate is a concept called a 'Bounding Box' where the overall size of an object is measured and compared. You'll find this term in all the script options available to you. Once you have a Bounding Box of all your items you'd be able to compare this to your fabric rolls (which could be a populated list stored in the script or from CSV). Ungrouping and Collision Checks There's several methods of checking if a 2D Object is inside / touching another 2D Object, for example; GetPolyPt & PtInPoly are both used in scripting to assess points. Intersecting two objects will tell you if they overlap (and the result of this would be used as an indicator of overlap). Decomposition Totally possible via scripts, you'd just need to ensure it's decomposed to exactly the level / detail you wanted. Classing by Colours and Rules This is all just Criteria (defining things) and Classification (assigning things). Any of the rules you wish to choose are fine, you'll just have to find the preferential order of things. Collinear Lines (Touch, Overlap or Superimposed) We've covered this one - not in Marionette, and I'm still sure it's possible... probably. All of the above IS possible. I don't think you want a mega-script which just steamrolls from Step 1 to Step 6. I think you'd need to break each of the tasks down and create smaller scripts to optimise your workflow - as human interaction is still going to be both required and visually desired to ensure each step is working correctly. Next Steps: If you're really keen on learning Marionette then I think you should checkout the Vectorworks University, in particular the following courses; Introduction to Marionette https://university.vectorworks.net/mod/page/view.php?id=647 Advanced Marionette https://university.vectorworks.net/mod/overview/view.php?id=2483 If you're keen on learning either Vectorscript and/or Python then the resources directly related to Vectorworks are limited - only because, in particular Python, are so broadly applied. Boost Your Productivity with Scripts ( @michaelk so many Script flexes in one video...) https://university.vectorworks.net/course/view.php?id=320 Places like Codecademy or Brilliant come fairly highly recommended for Python beginners - however you'll still at some stage need to get familiar with the Developer Wiki; https://developer.vectorworks.net/index.php?title=Main_Page I know it's not the immediate solve you might be looking for however if you persist it can and will lead to the best solution for you and your company long term. Joining the forum however and asking questions is the first step - well done! Cheers, James Quote Link to comment
Etienne Azambre Posted February 18 Author Share Posted February 18 Thank you very much, James, for your response! It gives me a clear roadmap to build my network. Some steps are easier than others ^^' Could I get a bit more of help with the collinear lines part, please? At least to get a rough idea of how to tackle this step. Thanks again to everyone! Quote Link to comment
Etienne Azambre Posted April 29 Author Share Posted April 29 Hello everyone, I’ve made some progress toward my goal, but things aren’t perfect yet ^^ For now, I can detect colinear lines, but only the horizontal and vertical ones. Also, in some cases, the network works fine, but in others, it forgets to process some black lines. Could you please take a look? I also forgot to mention that I would really like to turn the finished network into a Marionette command, but I'm still having trouble correctly identifying the objects to process using VSEL=TRUE or SEL=TRUE. Thanks in advance! MARIONETTE FILE COOLINEAR LINES.vwx Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.