MarcelP102 Posted September 18, 2024 Share Posted September 18, 2024 (edited) I'm using the below script to let a user draw a square, name it and delete everything outside that object using LOC criteria. Unfortunately it also deletes polygon's that are within the square but it center point is outside it. That happens a lot with unregular shaped polygon, like the polygon representing multiple connected streets. I've tried everything but I'm unable to keep all the objects within the square. Basically I want it to work the same as the 2D selection tool while holding ALT. Any help? See attached file for a sample project. PROCEDURE DrawToDelete; VAR H1, dummyH :HANDLE; BEGIN Locus(0,0); dummyH := LNewObj; CallTool(-203); h1 := NextObj (dummyH); SetName(h1, 'MySelectionPolygon'); DSelectAll; SelectObj(INSYMBOL & INOBJECT & (LOC<>'MySelectionPolygon')); DeleteObjs; DSelectAll; DelObject(h1); DelObject(dummyH); ReDrawAll; END; LOCproblem.vwx Something else I've tried is to call the selection tool and use that to draw a box to delete. Only thing is that I don't know a way to script the ALT pressing, is that possible? PROCEDURE DrawToDelete; PROCEDURE DeleteThem(h :HANDLE); BEGIN DelObject(h); END; BEGIN DSelectAll; CallToolWithMode(-240,3,1); ForEachObject(DeleteThem, SEL=FALSE); END; Edited September 18, 2024 by MarcelP102 Quote Link to comment
Marionette Maven Marissa Farrell Posted September 18, 2024 Marionette Maven Share Posted September 18, 2024 Without testing - could you try using the coordinates of the corners of a bounding box to remove some items from your list to delete? I'm thinking GetBBox and maybe PtInPoly? Quote Link to comment
Pat Stanford Posted September 18, 2024 Share Posted September 18, 2024 @MarcelP102 It is not that LOC is not reliable, it is just that it does not do what you want. 😉 As you have discovered, LOC only returns objects that have the "insertion point" (insertion point, bounding box center, maybe a few other cases) of the object within the LOC object. For your case you probably are going to have to write your own function. Similar to the Maven's idea, but I would suggest checking all four points of the bounding box and the object center as well. And even that might not be enough depending on the size of your LOC object and the complexity of the objects that an are overlapping. I can certainly see cases where the corners and center of the BB would be outside the LOC but still have lines that pass through. I don't think there is really a good option for what you want. Another possibility might be to take each object and duplicate and "explode" it and then compare each of the items from the expose to the LOC. If any one of them matches then mark the unexploded version as needing to not be deleted. Then go back and delete all of the "exploded" parts. You will need to mark the exploded versions somehow either via class or by attaching a record to allow you to find them later to delete. And I can imaging edge cases where even that will not be 100% correct. It is a hard problem. One that your human brain can handle easily but that is very difficult for a computer algorithm to handle. Basic idea: Get LOC object handle and coordinates. Compare the bounding box of every object in the drawing to the LOC coordinates. Delete those objects that don't overlap at all with the LOC. Use the LOC to get the objects that are known to be within the LOC. Mark them somehow so you don't have to test them again. Probably by attaching a record. For the remaining objects in the drawing, duplicate and "explode" them. This could be a Convert to Group or possibly multiple Convert to Group. You will have to consider what is needed based on your object types. Enter the group and mark all the objects for later deleting. Compare the bounding box and center of each object to the bounding box of LOC. PtInPoly is probably the best way. If you find s point that is inside the LOC, then stop processing the rest of those exploded objects and delete them. Add the original unexploded to the Do Not Delete List. If none of the objects are within in the LOC then delete the exploded objects and the unexploded version. Repeat with every object in the drawing. Because you are going to have to do a lot of comparisons, this is likely going to be a very slow process. Good Luck. HTH Quote Link to comment
MarcelP102 Posted September 18, 2024 Author Share Posted September 18, 2024 (edited) Thnx, got it working for now with the script below. Will test more later. PROCEDURE DrawToDelete; VAR H1, dummyH :HANDLE; PROCEDURE SelectThem(h :HANDLE); VAR vertX, vertY :REAL; i :INTEGER; BOOl :BOOLEAN; BEGIN FOR i := 1 to GetVertNum(h) DO BEGIN GetPolyPt(h, i, vertX, vertY); BOOL := PtInPoly(vertX, vertY, h1); IF BOOL = TRUE THEN BEGIN SetSelect(h); END; END; END; PROCEDURE DeleteThem(h :HANDLE); BEGIN DelObject(h); END; BEGIN Locus(0,0); dummyH := LNewObj; CallTool(-203); h1 := NextObj (dummyH); SetName(h1, 'MySelectionPolygon'); DSelectAll; ForEachObject(SelectThem, ALL); ForEachObject(DeleteThem, SEL=FALSE); DelObject(h1); DelObject(dummyH); DSelectAll; END; Run(DrawToDelete); Edited September 18, 2024 by MarcelP102 1 Quote Link to comment
Thomas W Posted September 19, 2024 Share Posted September 19, 2024 @MarcelP102 Thanks for sharing! I will test your example as soon as possible. If it can give you any ideas I made a script with the advice of @Pat Stanford to select elements in a rectangle and certain elements which have their insertion points in this rectangle, you will find the script at the end of this post: 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.