Hi everyone, here is a question, how can I know relative position of each edge of rectangle with arcpy script, i.e, top edge, bottom edge, left edge and right edge. The rectangle is defined at least 4 points,maybe 8 points,that means uncertain points. and then I need to know which edge any point is on. thank you.
Interesting... let's take a square an devolve it into compass sectors.
I just happened to use code I have using numpy.
There is no need for the points to be sorted initially.
The trick is to get the points, sort them radially, dissect them into generic compass orientations, then if you want to get fancy intersect the quadrants to return the corner points leaving the singletons to their quadrant.
Easily implemented for any geometry that can be converted to points... rectangular-ish objects are a snap since they will have common corners
# densified square, just unique points 'a_un'
a_un
array([[ 0. , 0. ],
[ 0. , 2.5],
[ 0. , 5. ],
[ 0. , 7.5],
[ 0. , 10. ],
[ 2.5, 10. ],
[ 5. , 10. ],
[ 7.5, 10. ],
[ 10. , 10. ],
[ 10. , 7.5],
[ 10. , 5. ],
[ 10. , 2.5],
[ 10. , 0. ],
[ 7.5, 0. ],
[ 5. , 0. ],
[ 2.5, 0. ]])
# --- get its centroid
a_cent
array([ 5., 5.])
# --- radially sort the points to get the angles, relative to the x-axis
ang
array([-135. , -153.43, 180. , 153.43, 135. , 116.57, 90. , 63.43,
45. , 26.57, 0. , -26.57, -45. , -63.43, -90. , -116.57])
# --- split them into W, N, E, S .... the corners belong to 2 axes (ie W, N for top-left
W = a_un[np.abs(ang)>= 135]
array([[ 0. , 0. ],
[ 0. , 2.5],
[ 0. , 5. ],
[ 0. , 7.5],
[ 0. , 10. ]])
N = a_un[np.logical_and(ang>=45, ang<=135)]
array([[ 0. , 10. ],
[ 2.5, 10. ],
[ 5. , 10. ],
[ 7.5, 10. ],
[ 10. , 10. ]])
E = a_un[np.logical_and(ang>=-45, ang<=45)]
array([[ 10. , 10. ],
[ 10. , 7.5],
[ 10. , 5. ],
[ 10. , 2.5],
[ 10. , 0. ]])
S = a_un[np.logical_and(ang>=-135, ang<=-45)]
array([[ 0. , 0. ],
[ 10. , 0. ],
[ 7.5, 0. ],
[ 5. , 0. ],
[ 2.5, 0. ]])
Here is my solution in Python script:
import math
# group vertexes into four edges, for rectangles only with less than 10 degree slope of horizontal edges
dflag=-1 #
sides=[]
for i in range(0,4):
sides.append([])
#0: south,1:north,2:west,3:east
apnts=row[1].getPart(0) # points of one polgyon
for i in range(1,len(row[1].getPart(0))):
a=math.atan((apnts.Y- apnts[i-1].Y)/( apnts.X- apnts[i-1].X))
ad=math.degrees(a)
if abs(ad)<10:
if apnts.Y<row[1].trueCentroid.Y:
dflagn=0
else:
dflagn=1
else:
if apnts.X<row[1].trueCentroid.X:
dflagn=2
else:
dflagn=3
if dflag!=dflagn:
sides[dflagn].append(apnts[i-1])
dflag=dflagn
sides[dflagn].append(apnts)
the above scripts can work very well for townships
so good! essentially a radial sort relative to the centroid
Many thanks, Dan, for your very useful suggestions and interests in this questions!