WhoCanDo Posted June 17, 2019 Share Posted June 17, 2019 Hi, I wish to add a Field Name value to a Wall item within the perimeter of a 2D polygon object. At the moment, I have given the polygon a Name and then .. ForEachObject (Record_Data, (Loc = 'Tmp') & ((T = Wall) or (T = RoundWall))); However, some of the Wall items lie within the perimeter of a group of polygons. The group, for example contains one large polygon and another smaller polygon within it's boundaries (representing a cutout). Now, how do I do the same as above for a group? Quote Link to comment
Pat Stanford Posted June 17, 2019 Share Posted June 17, 2019 Give them both separate names and use LOC Is Within Big Poly & LOC is Not Within Little Poly? But I don't think that will get you an object the partially overlaps the small poly. You will probably have to manually compare the bounding boxes of the small poly to each object inside the large poly to check for overlap. Quote Link to comment
WhoCanDo Posted June 17, 2019 Author Share Posted June 17, 2019 (edited) Thanks Pat, No problem finding the bigger polygon, but (Loc = 'Tmp') does not seem to work on a group. procedure Test_2; var x : integer; h, hG : handle; NetArea : real; IsGroup : boolean; procedure Count (hC : handle); begin x := x + 1; end; begin h := FSActLayer; IsGroup := False; if (GetTypeN (h) = 11 { Group }) then begin SetDSelect (h); DelName ('Tmp'); hG := FInGroup (h); NetArea := HArea (hG); DoMenuTextByName ('Copy', 0); hG := NextObj (hG); while (hG <> Nil) do begin if (NetArea < HArea (hG)) then begin NetArea := HArea (hG); DoMenuTextByName ('Copy', 0); end; hG := NextObj (hG); end; DoMenuTextByName ('Paste In Place', 0); h := LNewObj; IsGroup := True; end; DelName ('Tmp'); SetName (h, 'Tmp'); ForEachObject (Count, (Loc = 'Tmp') & ((T = Wall) or (T = RoundWall))); message (x); end; run (Test_2); Edited June 17, 2019 by WhoCanDo Add Image Quote Link to comment
Pat Stanford Posted June 17, 2019 Share Posted June 17, 2019 LOC only works for 2D objects (polys, rects, ovals, etc.) and spaces as far as I know. It does not work for Groups or 3D objects (other than spaces) or other PIOs (there are probably some exceptions, but I don't know them.) But it does work even when the objects are INSIDE of groups. So you can't set the Group to be TMP, but you can enter the group, name the big poly and then exit the group and LOC will still work. Does that help? 1 Quote Link to comment
WhoCanDo Posted June 19, 2019 Author Share Posted June 19, 2019 Got it Pat, I think I was heading toward Naming something other than the group but your suggestion of Naming something within a group worked perfectly. Thanks 😃 Quote Link to comment
WhoCanDo Posted September 24, 2019 Author Share Posted September 24, 2019 Moving on, now I can't locate a concaved wall within the perimeter of a polygon. For the following, create the polygon first, and then the walls. The idea being, the polygon is the first selected object. Pick all the objects and run this macro... procedure test; var hMKP : handle; procedure Record_Data (h : handle); begin AlrtDialog (Num2Str (0, GetTypeN (h))); end; begin DelName ('Tmp'); hMKP := FSActLayer; SetName (hMKP, 'Tmp'); SetDSelect (hMKP); ForEachObject (Record_Data, (Loc = 'Tmp') & (Sel = True) & ((T = Wall) or (T = RoundWall))); end; run (test); The result is AlrtDialog will return 68 (straight wall), 89 (round wall) & 89 in any order. However, there are three 89's and the wall on the right is not recognised as being within the perimeter of the polygon. I would suggest that this is a bug with "Loc=" but can anyone suggest another solution to please? Quote Link to comment
Pat Stanford Posted September 24, 2019 Share Posted September 24, 2019 There is a very thin line between a bug and WAD (working as designed). 😉 It appears that LOC uses the "insertion point" of the round wall i.e. the center of the radius as the point it checks to see if the object is in the LOC or not. You should probably file a bug, but I would bet this is working as designed but is just a bad design. Or just add it to the Wish List forum. No real work around other then to create a dummy object to use as the LOC that does not have the concave portion. Quote Link to comment
twk Posted September 25, 2019 Share Posted September 25, 2019 (edited) Havent tested, but you could use the WallFootPrint(WallHandle) function to create a dummy polygon of the outline of the curved wall. And check if that polygon is within LOC, then delete this dummy polygon. May create memory overhead with creating and deleting objects. Again, havent tested. Edited September 25, 2019 by twk Quote Link to comment
MullinRJ Posted September 25, 2019 Share Posted September 25, 2019 @WhoCanDo, I mocked up your second drawing and it worked perfectly; one straight wall (68) and three round walls (89) were reported. The centers of the two exterior round walls were snapped to the Poly so they both tested to be INSIDE the Poly boundary. @Pat Stanford is correct about LOC using the arc center of the round walls for its testing. You might see a positional discrepancy if you changed your units to show 10 decimal places, but Real numbers in VW carry ~15 decimal places of accuracy, so it's possible that the center could be outside the Poly boundary by 3.8e-12 to 3.9e-11 drawing units and fail your test while not displaying a visible positional difference with 10 decimals displayed. This is where VectorScript (or VectorPython) can help you see what the OIP won't show. Displaying REAL values with the Message() or Concat() commands will show up to 15 decimals, if they exist. Try the following script and see if you can identify your problem. PROCEDURE test; { Name the Poly "Tmp", and select the rightmost RoundWall before running this script. } { If the RoundWall center is "outside" the BBox of the "Tmp" object, you will see different } { values in the first two lines of the AlrtDialog(), and the third line will return TRUE. } { If the delta between the values is <3.8e-12 units, the third line will return FALSE. } CONST CR = chr(13); VAR H :Handle; X :Real; P, Pc :Vector; BEGIN DSelectObj(N = 'Tmp'); { Pick round wall and get its Center point } HCenter(FSActLayer, Pc.x, Pc.y); { get Right Side X value of 'Tmp' object } X := RightBoundN(N = 'Tmp'); AlrtDialog(concat(' Right side of ''Tmp'': ', X, CR, 'Wall Center X Value: ', Pc.x, CR, CR, 'Wall Center is OUTSIDE the right edge of ''Tmp'' = ', Pc.x > X)); END; Run (test); HTH, Raymond Quote Link to comment
Pat Stanford Posted September 25, 2019 Share Posted September 25, 2019 @MullinRJHow did you mock up the area? I drew a rectangle and then drew a circle at the top and a circle at the right. I added the rectangle and the top circle. I subtracted the poly and the right circle. For me, this puts the counterpoint of the round wall on the right OUTSIDE of the poly and therefore not found by LOC. What did we do different? Quote Link to comment
MullinRJ Posted September 25, 2019 Share Posted September 25, 2019 Hi Pat, I did not draw the poly correctly. When I look at the drawing again I see the the thin pink line hugging the round walls. That definitely puts the right round wall OUTSIDE the poly by a distance of the wall's radius since, as you said, the round wall's center point is what is being tested. So, NO, it is not a matter of decimal precision. My bad. If someone wants to test the "solid" part of a round wall for inclusion in a Poly's interior, they will have to write a separate routine to test the endpoints and at least one point along the wall for inclusion. Doable, but tedious. The "LOC=" criteria is inadequate for this task. Just now I tested the straight wall, curious how it would test if one endpoint is OUTSIDE the Poly. It tested as INSIDE, until I pulled the endpoint enough that the center point of the straight wall was also OUTSIDE the poly. Then it tested as OUTSIDE. So it seems "LOC=" is only testing center points of objects for inclusion, and not edges. That's a significant caveat. Programmer beware!!! Here's another interesting scenario: draw a straight wall with both endpoints OUTSIDE the poly, so that only its center point is inside one of the poly's corners. It will test as being INSIDE using the "LOC=" criteria. Thanks Pat. Raymond 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.