Jump to content
Developer Wiki and Function Reference Links ×

Finding objects within a perimeter


Recommended Posts

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?
 

Link to comment

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.

Link to comment

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);

image.thumb.png.bc04d030eb31f01c149c90361d75826e.png

Edited by WhoCanDo
Add Image
Link to comment

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?

 

  • Like 1
Link to comment
  • 3 months later...

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.

 

92050311_Annotation2019-09-24125023.thumb.jpg.f3d9e24becfd383adcb6c4069267efa5.jpg

 

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?

 

Link to comment

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.

Link to comment

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 by twk
Link to comment

@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

Link to comment

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

Link to comment

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...