Select to view content in your preferred language

Programmatically tell if a polygon is a parallelogram

924
3
04-09-2012 10:44 AM
DanielLaidlaw
Deactivated User
How can I programmatically tell if a polygon feature is a parallelogram??

Appreciate the help
vb
0 Kudos
3 Replies
MaraStoica1
Deactivated User
Get the vertices, calculate the length of each side and then check that the opposite sides are equal.
0 Kudos
BrianBottoms
Emerging Contributor
Hi,

Below is one possibility. The console app code could use some cleanup (it's even a little hard for me to follow and I wrote it). However, it does work.

The code basically runs around the polygon from vertex to vertex to find the 4 straight lines regardless of how many vertices make the line. It then checks opposite side lengths. If all is well then IsParallelogram returns true.

You can�??t just get the vertices and check the sides because I can digitize a parallelogram with 20 vertices, for example digitize a square then right click and insert an extra vertex - it's still a parallelogram. Also, if you just looked at the vertices you might miss that the vertices are actually connected with a Bezier curve or some type of arc. I'm not sure if I accounted for everything, but I did digitize a bunch of shapes and it returned the correct answer.

Brian


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesGDB;
using System.Collections;

namespace TestParallelogram
{
    class Program
    {
        static void Main(string[] args)
        {
            //Get license.
            ESRI.ArcGIS.RuntimeManager.BindLicense(ESRI.ArcGIS.ProductCode.EngineOrDesktop);
            //Get workspace.
            IWorkspaceFactory wsfact = new FileGDBWorkspaceFactoryClass();
            IFeatureWorkspace featws = (IFeatureWorkspace)wsfact.OpenFromFile("C:\\temp\\Shapes.gdb", 0);
            //Get polygon layer and loop features testing for parallelogram.
            IFeatureClass fc = featws.OpenFeatureClass("Shapes");
            IFeatureCursor fcursor = fc.Search(null, false);
            IFeature feat = fcursor.NextFeature();
            Console.WriteLine("Press any key to continue...");
            Console.WriteLine();
            Console.WriteLine("Is feature a parallelogram true/false?");
            while (feat != null)
            {
                Console.WriteLine("Feature OID = " + feat.OID + " " + IsParallelogram((IPolygon)feat.Shape));
                feat = fcursor.NextFeature();
            }
            
            Console.ReadKey();
        }

        private static bool IsParallelogram(IPolygon pPoly)
        {
            bool passesTest = true;
            pPoly.SimplifyPreserveFromTo();

            //Check for arcs/bezier type curves in the polygon.
            ISegmentCollection segmentCollection = (ISegmentCollection)pPoly;
            for (int x = 0; x <= segmentCollection.SegmentCount - 1; x++)
            {
                if (segmentCollection.get_Segment(x).GeometryType != esriGeometryType.esriGeometryLine)
                {
                    passesTest = false;
                }
            }

            //If no curves found keep going
            if (passesTest == true)
            {
                Double pi = Math.Round(3.14159250439667, 4);
                //al holds straight segments of poly i.e. vertex to vertex
                ArrayList al = new ArrayList();
                //alFinal holds final 4 segments of poly after removing vertices that
                //don't create an angle i.e. a straight line with a vertex in the middle.
                ArrayList alFinal = new ArrayList();

                //create lines from vertex to vertex around polygon.
                IPointCollection ptcol = (IPointCollection)pPoly;
                ILine pLine;
                for (int x = 1; x != ptcol.PointCount; x++)
                {
                    pLine = new LineClass();
                    pLine.PutCoords(ptcol.get_Point(x - 1), ptcol.get_Point(x));
                    al.Add(pLine);
                }

                //Try to account for 4 straight lines around polygon.
                ILine line1;
                ILine line2;
                if (al.Count >= 4)//If less than 4 then it is a circle, ellipse or possibly a triangle.
                {
                    GeometryEnvironment geometryEnvironment = new GeometryEnvironment();
                    IConstructAngle constructAngle = geometryEnvironment as IConstructAngle;
                    ILine straightLine;

                    line1 = (ILine)al[0];
                    line2 = (ILine)al[1];
                    int n = 1;
                    while (n < al.Count)
                    {
                        //Console.WriteLine(constructAngle.ConstructThreePoint(line1.FromPoint, line2.FromPoint, line2.ToPoint));

                        //Check if angle changes between 2 segments going around the poly.
                        if (Math.Abs(Math.Round(constructAngle.ConstructThreePoint(line1.FromPoint, line2.FromPoint, line2.ToPoint), 4)) == Math.Abs(pi))
                        {
                            //No change in angle so vertex splits poly edge, but
                            //line doesn't change direction - go to next segment.
                            n++;
                            line2 = (ILine)al;
                        }
                        else
                        {
                            //Line changes direction so add segment to final line group.
                            straightLine = new LineClass();
                            straightLine.PutCoords(line1.FromPoint, line2.FromPoint);
                            alFinal.Add(straightLine);
                            //Increment n for next set of lines
                            line1 = line2;
                            n++;
                            if (n == al.Count)//Reached last line segment in poly so just add to final group.
                            {
                                straightLine = new LineClass();
                                straightLine.PutCoords(line2.ToPoint, line2.FromPoint);
                                alFinal.Add(straightLine);
                            }
                            else
                            {
                                line2 = (ILine)al; //Go to next segment in poly
                            }
                        }

                    }

                }
                else //less than 4 segments not enough segments to make a parallelogram.
                {
                    passesTest = false;
                }

                //Check that you have 4 straight lines.
                if (alFinal.Count == 4)
                {
                    //Check that opposite sides are equal length.
                    //I'm rounding because if you digitize a rectangle their opposite lengths don't actually match!
                    line1 = (ILine)alFinal[0];
                    line2 = (ILine)alFinal[2];
                    if (Math.Round(line1.Length, 1) != Math.Round(line2.Length, 1)) passesTest = false;
                    line1 = (ILine)alFinal[1];
                    line2 = (ILine)alFinal[3];
                    if (Math.Round(line1.Length, 1) != Math.Round(line2.Length, 1)) passesTest = false;
                }
                else //Too many polygon edges.
                {
                    passesTest = false;
                }
            }

            

            return passesTest;
        }
       

    }
}
0 Kudos
DuncanHornby
MVP Notable Contributor
You could always use the Parallelogram law disussed in wikipedia here?
0 Kudos