Select to view content in your preferred language

How to calculate relative position of each edge of rectangle

2992
14
03-19-2018 12:46 PM
deleted-user-kYCocWVdqfTG
New Contributor II

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.

0 Kudos
14 Replies
DanPatterson_Retired
MVP Emeritus

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. ]])
deleted-user-kYCocWVdqfTG
New Contributor II

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)

deleted-user-kYCocWVdqfTG
New Contributor II

the above scripts can work very well for townships 

0 Kudos
DanPatterson_Retired
MVP Emeritus

so good! essentially a radial sort relative to the centroid

0 Kudos
deleted-user-kYCocWVdqfTG
New Contributor II

Many thanks, Dan,  for your very useful suggestions and interests in this questions!

0 Kudos