//March15 2013
        //by CHarriman Senior Product Manager Carmel Software Corporation
        //this is a function only used internally.  It is used to verify if a surface object only has four coordinates, and if those coordinates form
        //a square or rectangle.
        private static bool IsSurfaceRegular(SurfaceDefinitions Surface)
        {
            //tests to see if all candidate surfaces and the standard surface are regular (rectangular polygons)

            bool isRegularPolygon = true;
            //see if the standard surface has four coordinates defining its polyloop (one marker of a rectangle)
            int standSurfaceCoordinateCount = Surface.PlCoords.Count;
            if (standSurfaceCoordinateCount == 4)
            {
                //check the two potentially parallel sides, to ensure they are indeed parallel
                Vector.CartVect v1 = Vector.CreateVector(Surface.PlCoords[0], Surface.PlCoords[1]);
                Vector.CartVect v2 = Vector.CreateVector(Surface.PlCoords[2], Surface.PlCoords[3]);
                Vector.CartVect v1xv2 = Vector.CrossProduct(v1, v2);
                v1xv2 = Vector.UnitVector(v1xv2);
                double magnitudev1xv2 = Vector.VectorMagnitude(v1xv2);
                Vector.CartVect v3 = Vector.CreateVector(Surface.PlCoords[1], Surface.PlCoords[2]);
                Vector.CartVect v4 = Vector.CreateVector(Surface.PlCoords[3], Surface.PlCoords[0]);
                Vector.CartVect v3xv4 = Vector.CrossProduct(v3, v4);
                v3xv4 = Vector.UnitVector(v3xv4);
                double magnitudev3xv4 = Vector.VectorMagnitude(v3xv4);
                //the unit vector will not be a number NaN if the Cross product detects a zero vector (indicating parallel vectors)
                if (double.IsNaN(magnitudev1xv2) && double.IsNaN(magnitudev3xv4))
                {
                    isRegularPolygon = true;
                }
                else
                {
                    isRegularPolygon = false;
                }
            }
            else
            {
                //might as well stop here because 
                isRegularPolygon = false;
                return isRegularPolygon;
            }
            return isRegularPolygon;

        }
        private static double GetSurfaceArea(SurfaceDefinitions surface, double areaConversion)
        {
            
            logger.Debug("STARTING SUBROUTINE: GetSurfaceArea.");
            logger.Debug("PROGAMMER'S NOTE: PolyLoop coordinates will be used to calculate the area.");
            double area = -1;
            //there are two basic cases, one where we get the area using greens theorem when the surface is parallel
            //to one of the axes of the project global reference frame
            //and the second where the surface is not parallel to one of the axes of the global reference frame
            //Surface normal Parallel to global reference frame X Axis
            if (Math.Abs(surface.PlRHRVector.X) == 1 && surface.PlRHRVector.Y == 0 && surface.PlRHRVector.Z == 0)
            {
                List<Vector.MemorySafe_CartCoord> coordList = new List<Vector.MemorySafe_CartCoord>();
                foreach (Vector.MemorySafe_CartCoord coord in surface.PlCoords)
                {
                    //only take the Y and Z coordinates and throw out the X because we can assume that they are all the same
                    //create new
                    Vector.MemorySafe_CartCoord c2 = new Vector.MemorySafe_CartCoord(0, coord.Y, coord.Z);
                    coordList.Add(c2);

                }
                area = GetAreaFrom2DPolyLoop(coordList);
                if (area == -999)
                {
                    logger.Debug("The coordinates of the standard file polyloop has been incorrectly defined.");
                    logger.Debug("The coordinates should be 2D and could not be translated to 2D");
                    logger.Fatal("ATTENTION: Attempting to calculate surface area.  Test may be inaccurate and requires gbXML.org support");
                }
            }
            //Surface normal Parallel to global reference frame y Axis
            else if (surface.PlRHRVector.X == 0 && Math.Abs(surface.PlRHRVector.Y) == 1 && surface.PlRHRVector.Z == 0)
            {
                List<Vector.MemorySafe_CartCoord> coordList = new List<Vector.MemorySafe_CartCoord>();
                foreach (Vector.MemorySafe_CartCoord coord in surface.PlCoords)
                {
                    //only take the X and Z coordinates and throw out the Y because we can assume that they are all the same
                    Vector.MemorySafe_CartCoord c2 = new Vector.MemorySafe_CartCoord(coord.X, 0, coord.Z);
                    coordList.Add(c2);

                }
                area = GetAreaFrom2DPolyLoop(coordList);
                if (area == -999)
                {
                    logger.Debug("The coordinates of the standard file polyloop has been incorrectly defined.");
                    logger.Debug("The coordinates should be 2D and could not be translated to 2D");
                    logger.Fatal("ATTENTION: Attempting to calculate surface area.  Test may be inaccurate and requires gbXML.org support");

                }
            }
            else if (surface.PlRHRVector.X == 0 && surface.PlRHRVector.Y == 0 && Math.Abs(surface.PlRHRVector.Z) == 1)
            {
                List<Vector.MemorySafe_CartCoord> coordList = new List<Vector.MemorySafe_CartCoord>();
                foreach (Vector.MemorySafe_CartCoord coord in surface.PlCoords)
                {
                    //only take the X and Y coordinates and throw out the Z because we can assume that they are all the same
                    Vector.MemorySafe_CartCoord c2 = new Vector.MemorySafe_CartCoord(coord.X, coord.Y, 0);
                    coordList.Add(c2);

                }
                area = GetAreaFrom2DPolyLoop(coordList);
                if (area == -999)
                {
                    logger.Debug("The coordinates of the standard file polyloop has been incorrectly defined.");
                    logger.Debug("The coordinates should be 2D and could not be translated to 2D");
                    logger.Fatal("ATTENTION: Attempting to calculate surface area.  Test may be inaccurate and requires gbXML.org support");

                }
                
               
                        
            }
            //the surface is not aligned with one of the reference frame axes, which requires a bit more work to determine the right answer.
            else
            {
                logger.Debug("The standard surface is not aligned along an axis, and will be rotated into a new coordinate frame");
                //New Z Axis for this plane is the normal vector, does not need to be created
                //Get New Y Axis which is the surface Normal Vector cross the original global reference X unit vector (all unit vectors please
                Vector.CartVect globalReferenceX = new Vector.CartVect();
                globalReferenceX.X = 1;
                globalReferenceX.Y = 0;
                globalReferenceX.Z = 0;
                Vector.MemorySafe_CartVect localY = Vector.UnitVector(Vector.CrossProductMSRetMSNV(surface.PlRHRVector, globalReferenceX));


                //new X axis is the localY cross the surface normal vector
                Vector.MemorySafe_CartVect localX = Vector.UnitVector(Vector.CrossProduct(localY, surface.PlRHRVector));

                //convert the polyloop coordinates to a local 2-D reference frame
                //using a trick employed by video game programmers found here http://stackoverflow.com/questions/1023948/rotate-normal-vector-onto-axis-plane
                List<Vector.MemorySafe_CartCoord> translatedCoordinates = new List<Vector.MemorySafe_CartCoord>();
                Vector.MemorySafe_CartCoord newOrigin = new Vector.MemorySafe_CartCoord(0, 0, 0);
                translatedCoordinates.Add(newOrigin);
                for (int j = 1; j < surface.PlCoords.Count; j++)
                {
                    //randomly assigns the first polyLoop coordinate as the origin
                    Vector.MemorySafe_CartCoord origin = surface.PlCoords[0];
                    //captures the components of a vector drawn from the new origin to the 
                    Vector.CartVect distance = new Vector.CartVect();
                    distance.X = surface.PlCoords[j].X - origin.X;
                    distance.Y = surface.PlCoords[j].Y - origin.Y;
                    distance.Z = surface.PlCoords[j].Z - origin.Z;

                    //x coordinate is distance vector dot the new local X axis
                    double tX = distance.X * localX.X + distance.Y * localX.Y + distance.Z * localX.Z;
                    //y coordinate is distance vector dot the new local Y axis
                    double tY = distance.X * localY.X + distance.Y * localY.Y + distance.Z * localY.Z;
                    double tZ = 0;
                    Vector.MemorySafe_CartCoord translatedPt = new Vector.MemorySafe_CartCoord(tX, tY, tZ);
                    translatedCoordinates.Add(translatedPt);

                }
                area = GetAreaFrom2DPolyLoop(translatedCoordinates);
                if (area == -999)
                {
                    logger.Debug("The coordinates of the standard file polyloop has been incorrectly defined.");
                    logger.Debug("The coordinates should be 2D and could not be translated to 2D");
                    logger.Fatal("ATTENTION: Attempting to calculate surface area.  Test may be inaccurate and requires gbXML.org support");
                }
            }
            logger.Debug("ENDING SUBROUTINE: GetSurfaceArea");
            logger.Debug("Area:" + Math.Abs(area).ToString());
            if (area != -1 || area != -999)
            {
                return Math.Abs(area * areaConversion);
            }
            else return area;
        }
 private static bool IsHighTiltSurface(SurfaceDefinitions surface)
 {
     bool isHighTilt = false;
     if (surface.SurfaceType == "InteriorFloor" || surface.SurfaceType == "RaisedFloor" || surface.SurfaceType == "SlabOnGrade" || surface.SurfaceType == "UndergroundSlab" || surface.SurfaceType == "ExposedFloor") isHighTilt = true;
     return isHighTilt;
 }
        private static DOEgbXMLReportingObj GetPolyLoopCoordMatch(Vector.MemorySafe_CartCoord standardPolyLoopCoord, SurfaceDefinitions testSurface, DOEgbXMLReportingObj report, string standardSurfaceId, double testlengthConversion, double standardlengthConversion)
        {
            List<Vector.MemorySafe_CartCoord> possibleMatch = new List<Vector.MemorySafe_CartCoord>();
            List<Vector.MemorySafe_CartCoord> exactMatch = new List<Vector.MemorySafe_CartCoord>();
            report.MessageList.Add("Testing Polyloop coordinates for Standard surface " + standardSurfaceId);
            report.MessageList.Add(" X: " + standardPolyLoopCoord.X.ToString() + ", Y: " + standardPolyLoopCoord.Y.ToString() + ", Z: " + standardPolyLoopCoord.Z.ToString());
            foreach (Vector.MemorySafe_CartCoord testPolyLoopCoord in testSurface.PlCoords)
            {

                //find an appropriate match
                double diffX = Math.Abs((testPolyLoopCoord.X * testlengthConversion) - (standardPolyLoopCoord.X * standardlengthConversion));
                if (diffX < DOEgbXMLBasics.Tolerances.SurfacePLCoordTolerance)
                {
                    //found a perfect X Match
                    if (diffX == 0)
                    {
                        //test Y
                        double diffY = Math.Abs((testPolyLoopCoord.Y * testlengthConversion) - (standardPolyLoopCoord.Y*standardlengthConversion));
                        if (diffY < DOEgbXMLBasics.Tolerances.SurfacePLCoordTolerance)
                        {
                            //perfect Y Match
                            if (diffY == 0)
                            {
                                double diffZ = Math.Abs((testPolyLoopCoord.Z * testlengthConversion) - (standardPolyLoopCoord.Z*standardlengthConversion));
                                if (diffZ < DOEgbXMLBasics.Tolerances.SurfacePLCoordTolerance)
                                {
                                    //perfect Z match
                                    if (diffZ == 0)
                                    {
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId + ": Found polyLoop coordinate that matches Standard Surface " + standardSurfaceId + " exactly");
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId);
                                        report.MessageList.Add(" X: " + testPolyLoopCoord.X.ToString() + ", Y: " + testPolyLoopCoord.Y.ToString() + ", Z: " + testPolyLoopCoord.Z.ToString());
                                        exactMatch.Add(testPolyLoopCoord);
                                    }
                                    else
                                    {
                                        //not a perfect Z match but within bounds
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId + ": Found polyLoop coordinate that matches Standard Surface " + standardSurfaceId + " X and Y coordinates exactly.  Z coordinate within allowable tolerance.");
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId);
                                        report.MessageList.Add(" X: " + testPolyLoopCoord.X.ToString() + ", Y: " + testPolyLoopCoord.Y.ToString() + ", Z: " + testPolyLoopCoord.Z.ToString());
                                        possibleMatch.Add(testPolyLoopCoord);
                                    }
                                }
                                else
                                {
                                    //z coordinate not within tolerance
                                    continue;
                                }
                            }
                            //Y Match is within the allowable tolerance
                            else
                            {
                                double diffZ = Math.Abs((testPolyLoopCoord.Z * testlengthConversion) - (standardPolyLoopCoord.Z*standardlengthConversion));
                                if (diffZ < DOEgbXMLBasics.Tolerances.SurfacePLCoordTolerance)
                                {
                                    //perfect Z match
                                    if (diffZ == 0)
                                    {
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId + ": Found polyLoop coordinate that matches Standard Surface " + standardSurfaceId + " in the X and Z coordinates, exactly.  Y coordinate is within tolerance.");
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId);
                                        report.MessageList.Add(" X: " + testPolyLoopCoord.X.ToString() + ", Y: " + testPolyLoopCoord.Y.ToString() + ", Z: " + testPolyLoopCoord.Z.ToString());
                                        possibleMatch.Add(testPolyLoopCoord);
                                    }
                                    else
                                    {
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId + ": Found polyLoop coordinate that matches Standard Surface " + standardSurfaceId + " X exactly.  Y and Z coordinates are within tolerance.");
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId);
                                        report.MessageList.Add(" X: " + testPolyLoopCoord.X.ToString() + ", Y: " + testPolyLoopCoord.Y.ToString() + ", Z: " + testPolyLoopCoord.Z.ToString());
                                        possibleMatch.Add(testPolyLoopCoord);
                                    }
                                }
                                else
                                {
                                    //z coordinate is not within tolerance
                                    continue;
                                }
                            }
                        }
                        else
                        {
                            //a y match could not be found within tolerance
                            continue;
                        }

                    }
                    else
                    {
                        //not a perfect X match, but within tolerance
                        //test Y
                        double diffY = Math.Abs((testPolyLoopCoord.Y * testlengthConversion) - (standardPolyLoopCoord.Y*standardlengthConversion));
                        if (diffY < DOEgbXMLBasics.Tolerances.SurfacePLCoordTolerance)
                        {
                            //perfect Y Match
                            if (diffY == 0)
                            {
                                double diffZ = Math.Abs((testPolyLoopCoord.Z * testlengthConversion) - (standardPolyLoopCoord.Z*standardlengthConversion));
                                if (diffZ < DOEgbXMLBasics.Tolerances.SurfacePLCoordTolerance)
                                {
                                    //perfect Z match
                                    if (diffZ == 0)
                                    {
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId + ": Found polyLoop coordinate that matches Standard Surface " + standardSurfaceId + " Y and Z coordinate exactly.  X is within tolerance.");
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId);
                                        report.MessageList.Add(" X: " + testPolyLoopCoord.X.ToString() + ", Y: " + testPolyLoopCoord.Y.ToString() + ", Z: " + testPolyLoopCoord.Z.ToString());
                                        possibleMatch.Add(testPolyLoopCoord);
                                    }
                                    else
                                    {
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId + ": Found polyLoop coordinate that matches Standard Surface " + standardSurfaceId + " Y coordinate exactly.  X and Z is within tolerance.");
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId);
                                        report.MessageList.Add(" X: " + testPolyLoopCoord.X.ToString() + ", Y: " + testPolyLoopCoord.Y.ToString() + ", Z: " + testPolyLoopCoord.Z.ToString());
                                        possibleMatch.Add(testPolyLoopCoord);
                                    }
                                }
                                else
                                {
                                    //z is not matched so continue
                                    continue;
                                }
                            }
                            // the Y match is not perfect but within tolerance
                            else
                            {
                                double diffZ = Math.Abs((testPolyLoopCoord.Z * testlengthConversion) - (standardPolyLoopCoord.Z*standardlengthConversion));
                                if (diffZ < DOEgbXMLBasics.Tolerances.SurfacePLCoordTolerance)
                                {
                                    //perfect Z match
                                    if (diffZ == 0)
                                    {
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId + ": Found polyLoop coordinate that matches Standard Surface " + standardSurfaceId + " Z coordinate exactly.  The X and Y coordinates are within tolerance.");
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId);
                                        report.MessageList.Add(" X: " + testPolyLoopCoord.X.ToString() + ", Y: " + testPolyLoopCoord.Y.ToString() + ", Z: " + testPolyLoopCoord.Z.ToString());
                                        possibleMatch.Add(testPolyLoopCoord);
                                    }
                                    else
                                    {
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId + ": Found polyLoop coordinate that matches Standard Surface " + standardSurfaceId + ".  The X, Y, and Z coordinates are within tolerance.");
                                        report.MessageList.Add("Test Surface " + testSurface.SurfaceId);
                                        report.MessageList.Add(" X: " + testPolyLoopCoord.X.ToString() + ", Y: " + testPolyLoopCoord.Y.ToString() + ", Z: " + testPolyLoopCoord.Z.ToString());
                                        possibleMatch.Add(testPolyLoopCoord);
                                    }
                                }
                                // no match found for the Z
                                else
                                {
                                    continue;
                                }
                            }
                        }
                        //no match could be found for the Y
                        else
                        {
                            continue;
                        }
                    }
                }
                else
                {
                    //not a match found for the X and continue
                    continue;
                }
            }
            if (exactMatch.Count > 1)
            {
                report.MessageList.Add("Error, overlapping polyLoop coordinates found in the Test Surface PolyLoop.");
                report.passOrFail = false;
                return report;
            }
            else if (exactMatch.Count == 1)
            {
                report.MessageList.Add("One coordinate candidate found.  Exact match");
                report.passOrFail = true;
                return report;
            }
            if (possibleMatch.Count > 1)
            {
                report.MessageList.Add("No exact solution for a match of the polyLoop coordinate.  More than one coordinate candidate found.");
                report.passOrFail = false;
                return report;
            }
            else if (possibleMatch.Count == 1)
            {
                report.MessageList.Add("One coordinate candidate found.");
                report.passOrFail = true;
                return report;
            }
            else
            {
                report.MessageList.Add("No coordinate candidate found.");
                report.passOrFail = false;
                return report;
            }

        }
 //designed to be passed a pre-vetted surface definition from a Standard File
 private static bool IsLowTiltSurface(SurfaceDefinitions surface)
 {
     bool isLowTilt = false;
     if (surface.SurfaceType == "Ceiling" || surface.SurfaceType == "Roof" || surface.SurfaceType == "UndergroundCeiling")
     {
         isLowTilt = true;
     }
     return isLowTilt;
 }
        private DOEgbXMLReportingObj GetPossibleSurfaceMatches(SurfaceDefinitions surface, List<SurfaceDefinitions> TestSurfaces, DOEgbXMLReportingObj report, Conversions.lengthUnitEnum standardLengthUnits, Conversions.lengthUnitEnum testLengthUnits, double testlengthConversion, double standardlengthConversion, Conversions.areaUnitEnum standardAreaUnits, Conversions.areaUnitEnum testAreaUnits, double testareaConversion, double standardareaConversion)
        {
            //this summary is text that describes to a lay user what this test does, and how it works functionally.  The user should have some familiarity with the basic knowledge of gbXML 
            //added Mar 14 2013
            report.testSummary = "This test tries to match each Surface element in the standard file with an equivalent in your test file";
            report.testSummary += "  To be as flexible about what constitutes a \"Good Match\", this test finds a pool of possible candidate ";
            report.testSummary += "surfaces in your test file and then begins to eliminate them as they fail different tests.";
            report.testSummary += "  At the end, there should be only one surface candidate remaining that constitutes a good match.  ";
            report.testSummary += "You can see the result of this filtering process by reviewing the mini-report that is provided for you below.";
            report.testSummary += "</br>";
            //this summary is text that describes to a lay user what this test does, and how it works functionally.  The user should have some familiarity with the basic knowledge of gbXML 
            //added March 14 2013
            report.testSummary += "  The search routine first tries to find all surfaces that have the same SurfaceType and adjacentSpaceIds.";
            report.testSummary += "  Everytime there is a match found in the test file, meeting these criteria, a message will appear in the ";
            report.testSummary += "mini-report, indicating that a match has been found.";
            report.testSummary += "  There may be more than one match in your test file.";
            report.testSummary += "  If there are no matches found for SurfaceType and AdjacencyId, this message will be printed (and the test will end as failed):";
            report.testSummary += "  In the test file, no matches could be found in the standard file that have the same AdjacentSpaceId(s) and SurfaceType.";
            report.testSummary += "</br>";
            report.testSummary += "  If this set of tests is successful, the routine next tries to remove those surfaces that do not meet";
            report.testSummary += " the tilt and azimuth tolerances.  Let's pretend for example that the tilt and azimuth for the standard surface";
            report.testSummary += " in question are both 90 degrees.  If the tilt and azimuth test tolerance are 1 degree, then the search";
            report.testSummary += " routine will only keep those walls that have 89<=tilt<=91 && <=89azimuth<=91 && match the SurfaceType and";
            report.testSummary += " adjacency relationships.";
            report.testSummary += " The mini-report will let you know which surfaces pass the tilt and azimuth test and which do not.";
            report.testSummary += "</br>";
            report.testSummary += "  Next the search routine takes any of the remaining surface candidates that have passed all the tests so far, ";
            report.testSummary += "and tries to determine if the Surface Areas defined by the polyLoops match to within a pre-defined % tolerance.";
            report.testSummary += "</br>";
            report.testSummary += " the final tests are to physically test the coordinates of the polyloop and insertion point to make sure";
            report.testSummary += " that a match for the standard surface can be found.";
            report.testSummary += " You should see additional messages telling you which surface in your test file matches, or doesn't match";
            report.testSummary += " the standard surface being searched against.  If there is no match, the mini-report tells you.";
            report.testSummary += "  By making the tests this way, it is hoped that you can see exactly why your test file is failing against";
            report.testSummary += " the standard file's surface definitions.";

            try
            {
                report.MessageList.Add("Standard Surface Id: " + surface.SurfaceId);
                report.MessageList.Add("</br>");
                //initialize the return list
                //alternate between these two to filter out bad matches
                List<SurfaceDefinitions> possiblesList1 = new List<SurfaceDefinitions>();
                List<SurfaceDefinitions> possiblesList2 = new List<SurfaceDefinitions>();

                bool adjSpaceIdMatch = false;
                bool isLowTiltObject = false;
                bool isHighTiltObject = false;
                bool interiorWallFlipped = false;
                bool issurfaceRegular = false;
                bool istestSurfaceRegular = false;
                //try to find a surface in the test file that has the same:
                //adjacent space Id signature
                //surfaceType
                //free list is 1
                //list 2 is not used
                for(int ts = 0; ts<TestSurfaces.Count;ts++)
                {
                    SurfaceDefinitions testSurface = TestSurfaces[ts];
                    //has to have the same number of Adjacent Space Ids
                    if (testSurface.AdjSpaceId.Count == surface.AdjSpaceId.Count)
                    {
                        //an exception for a shading device
                        if (surface.AdjSpaceId.Count == 0) { adjSpaceIdMatch = true; }

                        //has to have the same order of adjacent space id strings to qualify.  This method assumes the strings are identical
                        if(surface.AdjSpaceId.Count == 1)
                        {
                            if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[0]) { adjSpaceIdMatch = true; }
                        }
                        if(surface.AdjSpaceId.Count == 2)
                        {
                            if(surface.SurfaceType == "Ceiling" && testSurface.SurfaceType == "InteriorFloor")
                            {
                                if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[1] && surface.AdjSpaceId[1] == testSurface.AdjSpaceId[0])
                                {
                                    adjSpaceIdMatch = true;
                                }
                            }
                            else if (surface.SurfaceType == "InteriorFloor"  && testSurface.SurfaceType == "Ceiling")
                            {
                                if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[1] && surface.AdjSpaceId[1] == testSurface.AdjSpaceId[0])
                                {
                                    adjSpaceIdMatch = true;
                                }
                            }
                            else if (surface.SurfaceType == "InteriorWall" && testSurface.SurfaceType == "InteriorWall")
                            {
                                if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[0] && surface.AdjSpaceId[1] == testSurface.AdjSpaceId[1])
                                {
                                    adjSpaceIdMatch = true;
                                }
                                if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[1] && surface.AdjSpaceId[1] == testSurface.AdjSpaceId[0])
                                {
                                    adjSpaceIdMatch = true;
                                    interiorWallFlipped = true;
                                }
                            }
                            else
                            {
                                if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[0] && surface.AdjSpaceId[1] == testSurface.AdjSpaceId[1])
                                {
                                    adjSpaceIdMatch = true;
                                }
                            }
                        }
                        //if adjacent space Ids match and the surface types match, note this 
                        if (adjSpaceIdMatch)
                        {
                            if(!IsHighTiltSurface(surface) && !IsLowTiltSurface(surface))
                            {
                                if(surface.SurfaceType == testSurface.SurfaceType)
                                {
                                    report.MessageList.Add("AdjancentSpaceId(s) and surfaceType Match.");
                                    report.MessageList.Add("Surface id: " + testSurface.SurfaceId + " is a candidate.");
                                    report.MessageList.Add("</br>");
                                    possiblesList1.Add(testSurface);
                                }
                            }
                            else
                            {
                                if(IsLowTiltSurface(surface)) isLowTiltObject = true;
                                if (IsHighTiltSurface(surface)) isHighTiltObject = true;
                                if(surface.SurfaceType == testSurface.SurfaceType)
                                {
                                    report.MessageList.Add("AdjancentSpaceId(s) and surfaceType Match.");
                                    report.MessageList.Add("Surface id: " + testSurface.SurfaceId + " is a candidate.");
                                    report.MessageList.Add("</br>");
                                    possiblesList1.Add(testSurface);
                                }
                            }
                            
                        }
                    }
                }
                if (possiblesList1.Count == 1)
                {
                    report.MessageList.Add("Based on a comparison of the surface Type and Adjacent SpaceIds, there is " + possiblesList1.Count.ToString() + " surface in the test file that is a possible match for " + surface.SurfaceId + " of the Standard File.");
                    report.MessageList.Add("<br/>");
                }
                else if (possiblesList1.Count > 1)
                {
                    report.MessageList.Add("Based on a comparison of the surface Type and Adjacent SpaceIds, there are " + possiblesList1.Count.ToString() + " surface in the test file that are possible matches for " + surface.SurfaceId + " of the Standard File.");
                    report.MessageList.Add("<br/>");
                }
                else
                {
                    report.longMsg = "In the test file, no matches could be found in the standard file that have the same AdjacentSpaceId(s) and SurfaceType.";
                    report.passOrFail = false;
                    return report;
                }
                //begin to filter back this list
                //tilt
                //azimuth
                //list 1 is analyzed
                //list 2 is free

                if (possiblesList1.Count > 0)
                {
                    foreach (SurfaceDefinitions testSurface in possiblesList1)
                    {
                        double tiltDifference = 0;
                        double azimuthDifference = Math.Abs(testSurface.Azimuth - surface.Azimuth);
                        if(isLowTiltObject)
                        {
                            if(IsLowTiltSurface(testSurface)) //they are the same, both have small tils
                            {
                                tiltDifference = Math.Abs(testSurface.Tilt - surface.Tilt);
                            }
                            else //they are 180 degrees different, and the test surface is a high tilt while the standard is low tilt
                            {
                                if (testSurface.SurfaceType == "InteriorFloor")
                                {
                                    tiltDifference = Math.Abs(Math.Abs(testSurface.Tilt - 180) - surface.Tilt);
                                }
                                else
                                {
                                    report.MessageList.Add("Test file's Surface id: " + testSurface.SurfaceId + " azimuth and tilt match FAILED: ");
                                    report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                    report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                    report.MessageList.Add(testSurface.SurfaceId + " has been removed as a candidate for matching.");
                                    report.MessageList.Add("</br>");
                                    continue;
                                }
                            }

                            //no azimuth tests
                            if (tiltDifference > DOEgbXMLBasics.Tolerances.SurfaceTiltTolerance) //azimuth no longer matters for these surfaces
                            {
                                if(surface.Tilt != 0)
                                {
                                    if(azimuthDifference > DOEgbXMLBasics.Tolerances.SurfaceAzimuthTolerance)
                                    {
                                        report.MessageList.Add("Test file's Surface id: " + testSurface.SurfaceId + " azimuth and tilt match FAILED: ");
                                        report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                        report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                        report.MessageList.Add(testSurface.SurfaceId + " has been removed as a candidate for matching.");
                                        report.MessageList.Add("</br>");
                                        continue;
                                    }
                                }
                                else
                                {
                                    report.MessageList.Add("Test file's Surface id: " + testSurface.SurfaceId + " azimuth and tilt match FAILED: ");
                                    report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                    report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                    report.MessageList.Add(testSurface.SurfaceId + " has been removed as a candidate for matching.");
                                    report.MessageList.Add("</br>");
                                    continue;
                                }
                                
                            }
                            //if the tilt and azimuth is within tolerance
                            else
                            {
                                //add to the free List
                                if (surface.Tilt == 0)
                                {
                                    possiblesList2.Add(testSurface);
                                    if (tiltDifference == 0)
                                    {
                                        report.MessageList.Add("Test surface with id: " + testSurface.SurfaceId + " matches the standard surface tilt and azimuth exactly.");
                                        report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                        report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString());

                                        report.MessageList.Add("</br>");
                                    }
                                    else
                                    {
                                        report.MessageList.Add("Test surface with id: " + testSurface.SurfaceId + " is within the azimuth and tilt tolerances of " + DOEgbXMLBasics.Tolerances.SurfaceAzimuthTolerance + " and " + DOEgbXMLBasics.Tolerances.SurfaceTiltTolerance + ", respectively.  It matches the standard file surface within the allowable tolerance.");
                                        report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                        report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString());

                                        report.MessageList.Add("</br>");
                                    }
                                }
                                else
                                {
                                    //check the azimuth
                                    if (tiltDifference > DOEgbXMLBasics.Tolerances.SurfaceTiltTolerance || azimuthDifference > DOEgbXMLBasics.Tolerances.SurfaceAzimuthTolerance)
                                    {
                                        report.MessageList.Add("Test file's Surface id: " + testSurface.SurfaceId + " azimuth and tilt match FAILED: ");
                                        report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                        report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString());
                                        report.MessageList.Add(testSurface.SurfaceId + " has been removed as a candidate for matching.");
                                        report.MessageList.Add("</br>");
                                        continue;
                                    }
                                    //if the tilt and azimuth is within tolerance
                                    else
                                    {
                                        //add to the free List
                                        possiblesList2.Add(testSurface);
                                        if (tiltDifference == 0 && azimuthDifference == 0)
                                        {
                                            report.MessageList.Add("Test surface with id: " + testSurface.SurfaceId + " matches the standard surface tilt and azimuth exactly.");
                                            report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                            report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString());

                                            report.MessageList.Add("</br>");
                                        }
                                        else
                                        {
                                            report.MessageList.Add("Test surface with id: " + testSurface.SurfaceId + " is within the azimuth and tilt tolerances of " + DOEgbXMLBasics.Tolerances.SurfaceAzimuthTolerance + " and " + DOEgbXMLBasics.Tolerances.SurfaceTiltTolerance + ", respectively.  It matches the standard file surface within the allowable tolerance.");
                                            report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                            report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString());

                                            report.MessageList.Add("</br>");
                                        }
                                    }
                                }
                            }
                        }
                        else if (isHighTiltObject)
                        {
                            if(IsHighTiltSurface(testSurface)) //both high tilt interior surfaces
                            {
                                tiltDifference = Math.Abs(testSurface.Tilt - surface.Tilt);
                            }
                            else //standard is high tilt, test is low tilt
                            {
                                if(testSurface.SurfaceType == "Ceiling")
                                {
                                    tiltDifference = Math.Abs(Math.Abs(testSurface.Tilt - 180) - surface.Tilt);
                                }
                                else
                                {
                                    report.MessageList.Add("Test file's Surface id: " + testSurface.SurfaceId + " azimuth and tilt match FAILED: ");
                                    report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                    report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                    report.MessageList.Add(testSurface.SurfaceId + " has been removed as a candidate for matching.");
                                    report.MessageList.Add("</br>");
                                    continue;
                                }
                            }

                            //no azimuth tests
                            if (tiltDifference > DOEgbXMLBasics.Tolerances.SurfaceTiltTolerance) //azimuth no longer matters for these surfaces
                            {
                                report.MessageList.Add("Test file's Surface id: " + testSurface.SurfaceId + " azimuth and tilt match FAILED: ");
                                report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString());
                                report.MessageList.Add(testSurface.SurfaceId + " has been removed as a candidate for matching.");
                                report.MessageList.Add("</br>");
                                continue;
                            }
                            //if the tilt and azimuth is within tolerance
                            else
                            {
                                //add to the free List
                                possiblesList2.Add(testSurface);
                                if (tiltDifference == 0)
                                {
                                    report.MessageList.Add("Test surface with id: " + testSurface.SurfaceId + " matches the standard surface tilt and azimuth exactly.");
                                    report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                    report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString());

                                    report.MessageList.Add("</br>");
                                }
                                else
                                {
                                    report.MessageList.Add("Test surface with id: " + testSurface.SurfaceId + " is within the azimuth and tilt tolerances of " + DOEgbXMLBasics.Tolerances.SurfaceAzimuthTolerance + " and " + DOEgbXMLBasics.Tolerances.SurfaceTiltTolerance + ", respectively.  It matches the standard file surface within the allowable tolerance.");
                                    report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                    report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString());

                                    report.MessageList.Add("</br>");
                                }
                            }
                        }
                        else
                        {
                            azimuthDifference = Math.Abs(testSurface.Azimuth - surface.Azimuth);
                            if (interiorWallFlipped) //both high tilt interior surfaces
                            {
                                
                                azimuthDifference = Math.Abs(Math.Abs(testSurface.Azimuth - surface.Azimuth) - 180); //180 is needed because they should be separated by 180
                            }
                            tiltDifference = Math.Abs(testSurface.Tilt - surface.Tilt);
                            
                            //if the tilt and azimuth is outside of tolerance
                            if (tiltDifference > DOEgbXMLBasics.Tolerances.SurfaceTiltTolerance || azimuthDifference > DOEgbXMLBasics.Tolerances.SurfaceAzimuthTolerance)
                            {
                                report.MessageList.Add("Test file's Surface id: " + testSurface.SurfaceId + " azimuth and tilt match FAILED: ");
                                report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString());
                                report.MessageList.Add(testSurface.SurfaceId + " has been removed as a candidate for matching.");
                                report.MessageList.Add("</br>");
                                continue;
                            }
                            //if the tilt and azimuth is within tolerance
                            else
                            {
                                //add to the free List
                                possiblesList2.Add(testSurface);
                                if (tiltDifference == 0 && azimuthDifference == 0)
                                {
                                    report.MessageList.Add("Test surface with id: " + testSurface.SurfaceId + " matches the standard surface tilt and azimuth exactly.");
                                    report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                    report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString());

                                    report.MessageList.Add("</br>");
                                }
                                else
                                {
                                    report.MessageList.Add("Test surface with id: " + testSurface.SurfaceId + " is within the azimuth and tilt tolerances of " + DOEgbXMLBasics.Tolerances.SurfaceAzimuthTolerance + " and " + DOEgbXMLBasics.Tolerances.SurfaceTiltTolerance + ", respectively.  It matches the standard file surface within the allowable tolerance.");
                                    report.MessageList.Add("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                    report.MessageList.Add("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString());

                                    report.MessageList.Add("</br>");
                                }
                            }
                        }
                        
                    }
                }
                // report to the user that no matches could be found
                else
                {
                    report.longMsg = "In the test file, surfaces could be found that match the standard file's AdjacentSpaceId and SurfaceType, but of these matches, none could be identified that also have a tilt or azimuth that exactly matches the standard file's, or is within the allowable tolerance.";
                    report.passOrFail = false;
                    return report;
                }

                //clear the first list
                possiblesList1.Clear();
                //start to loop through the new refined list
                //generally want to look at the polyLoop coordinates
                //list 2 is analyzed
                //list 1 is free
                report.MessageList.Add("Starting Surface Area Match tests......");
                report.MessageList.Add("</br>");
                if (possiblesList2.Count > 0)
                {
                    //simple method from this point forward is just to simply start doing a polyloop check
                    //check the standard surface PolyLoop and the test Surface(s) polyloop(s)
                    //check the absolute coordinates of the testSurface(s) polyloop(s)

                    if (possiblesList2.Count == 1)
                    {
                        report.MessageList.Add("Only one Surface Candidate remaining from the original test pool.");
                        report.MessageList.Add("<br/>");
                        //meaning there is only one candidate still available
                        //go on to test the polyLoop coordinates and the insertion point
                        possiblesList1.Add(possiblesList2[0]);


                    }
                    //more than one candidate still exists even after the adjacency test, surfaceType test, and tilt and azimuth tests, so filter through
                    else
                    {
                        //The user should be able to determine, based on output which surfaces are left for consideration
                        //Option 1:  (easiest) find the one best candidate
                        //do so based on an area match, matching the area of the test surface with the area of the test surface 
                        //(without regard for absolute polyloop coordinates)

                        //We find the area using area formulas for both regular polygons and irregular polygons
                        //first we check for the type of surface that it is (regular polygon or not), and we then take it from there
                        //in the case of a rectangular polygon, we only count rectangles or squares as regular, everything else is 
                        //assumed to be irregular, though this does not fit the classic definition of a classic polygon.  
                        //The language is just semantics

                        //first try to find if the standard file has a regular rectangular or square profile
                        report.MessageList.Add("Checking if the surface is a square or rectangle.");
                        issurfaceRegular = IsSurfaceRegular(surface);
                        foreach (SurfaceDefinitions regSurface in possiblesList2)
                        {
                            //ensures likewise that all the test surface candidates are regular, 
                            //TODO:  if they are not, then the entire set is assumed to be irregular (this could be improved)
                            istestSurfaceRegular = IsSurfaceRegular(regSurface);
                            if (istestSurfaceRegular == false) break;
                        }
                        if (issurfaceRegular && istestSurfaceRegular)
                        {
                            //we take a shortcut and use the width and height as a way to simplify the area checking scheme
                            //we assume that the width and height are properly entered in this simplified case
                            report.MessageList.Add("Rectangle or Square = TRUE");
                            report.MessageList.Add("Comparisons of the Width and Height values will be used as a proxy for surface Area.");
                            foreach (SurfaceDefinitions testsurface in possiblesList2)
                            {
                                //it first analyzes the test file to see if slivers are present.  If they are, it will fail the test
                                //if slivers are not allowed for the test.  This is the first time we check for slivers
                                //TODO:  consider removing or giving a feature to allow this to be overridded.
                                if (testsurface.Width <= DOEgbXMLBasics.Tolerances.SliverDimensionTolerance || testsurface.Height <= DOEgbXMLBasics.Tolerances.SliverDimensionTolerance)
                                {
                                    if (!DOEgbXMLBasics.SliversAllowed)
                                    {
                                        report.MessageList.Add("This test does not allow slivers less than " + DOEgbXMLBasics.Tolerances.SliverDimensionTolerance + " ft.  A sliver has been detected.  Test surface id: " + testsurface.SurfaceId + " is a sliver.");
                                        report.passOrFail = false;
                                        return report;
                                    }
                                }
                                //otherwise, if the sliver test passes
                                double widthDiff = Math.Abs((testlengthConversion * testsurface.Width) - surface.Width * standardlengthConversion);
                                if(widthDiff > DOEgbXMLBasics.Tolerances.SurfaceWidthTolerance)
                                {
                                    widthDiff = Math.Abs((testlengthConversion * testsurface.Height) - surface.Width * standardlengthConversion);
                                    if(widthDiff < DOEgbXMLBasics.Tolerances.SurfaceWidthTolerance)
                                    {
                                        //we will swap them
                                        double heightDiff = Math.Abs((testlengthConversion * testsurface.Width) - surface.Height * standardlengthConversion);
                                        if (heightDiff > DOEgbXMLBasics.Tolerances.SurfaceHeightTolerance)
                                        {
                                            report.MessageList.Add("Test file's Surface id: " + testsurface.SurfaceId + " width and height do not both match the standard file surface id: " + surface.SurfaceId + ".  This surface has been removed as a candidate.");
                                            continue;
                                        }
                                        else
                                        {
                                            //this surface is a candidate
                                            possiblesList1.Add(testsurface);
                                            if (widthDiff == 0 && heightDiff == 0)
                                            {
                                                report.MessageList.Add("Test file surface with id: " + testsurface.SurfaceId + " have has the width and height swapped, but the width and height exactly match the standard file.");
                                                //go ahead and now check the polyLoop coordinates, and then the insertion point
                                            }
                                            else
                                            {
                                                report.MessageList.Add("Test file surface with id: " + testsurface.SurfaceId + " have been swapped, but are within the width and height tolerances of " + DOEgbXMLBasics.Tolerances.SurfaceWidthTolerance + standardLengthUnits + " and " + DOEgbXMLBasics.Tolerances.SurfaceHeightTolerance + standardLengthUnits + ", respectively.");
                                                //go ahead and now check the polyloop coordinates, and then the insertion point
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    //we won't swap them
                                    double heightDiff = Math.Abs((testlengthConversion * testsurface.Height) - surface.Height * standardlengthConversion);
                                    if (widthDiff > DOEgbXMLBasics.Tolerances.SurfaceWidthTolerance ||
                                        heightDiff > DOEgbXMLBasics.Tolerances.SurfaceHeightTolerance)
                                    {
                                        report.MessageList.Add("Test file's Surface id: " + testsurface.SurfaceId + " width and height do not both match the standard file surface id: " + surface.SurfaceId + ".  This surface has been removed as a candidate.");
                                        continue;
                                    }
                                    else
                                    {
                                        //this surface is a candidate
                                        possiblesList1.Add(testsurface);
                                        if (widthDiff == 0 && heightDiff == 0)
                                        {
                                            report.MessageList.Add("Test file surface with id: " + testsurface.SurfaceId + " matches the width and height exactly of the standard file.");
                                            //go ahead and now check the polyLoop coordinates, and then the insertion point
                                        }
                                        else
                                        {
                                            report.MessageList.Add("Test file surface with id: " + testsurface.SurfaceId + " is within the width and height tolerances of " + DOEgbXMLBasics.Tolerances.SurfaceWidthTolerance + standardLengthUnits + " and " + DOEgbXMLBasics.Tolerances.SurfaceHeightTolerance + standardLengthUnits + ", respectively.");
                                            //go ahead and now check the polyloop coordinates, and then the insertion point
                                        }
                                    }
                                }
                            }
                        }
                        //It is not "regular".  Find the one surface with the area that most closely matches, and then check its polyloops
                        //1. get the polyloop area of the standard file's surface polyloops
                        //2. get the area of the test file surface candidates using the polyloop coordinates
                        else
                        {
                            report.MessageList.Add("The surface is not a square or rectangle.");
                            report.MessageList.Add("PolyLoop coordinates will be used to calculate the area.");
                            //there are two basic cases, one where we get the area using greens theorem when the surface is parallel
                            //to one of the axes of the project global reference frame
                            //and the second where the surface is not parallel to one of the axes of the global reference frame
                            //Surface normal Parallel to global reference frame X Axis
                            if (Math.Abs(surface.PlRHRVector.X) == 1 && surface.PlRHRVector.Y == 0 && surface.PlRHRVector.Z == 0)
                            {
                                List<Vector.MemorySafe_CartCoord> coordList = new List<Vector.MemorySafe_CartCoord>();
                                foreach (Vector.MemorySafe_CartCoord coord in surface.PlCoords)
                                {
                                    //only take the Y and Z coordinates and throw out the X because we can assume that they are all the same
                                    //create new
                                    Vector.MemorySafe_CartCoord c2 = new Vector.MemorySafe_CartCoord(0, coord.Y, coord.Z);
                                    coordList.Add(c2);

                                }
                                double area = GetAreaFrom2DPolyLoop(coordList);
                                if (area == -999)
                                {
                                    report.MessageList.Add("The coordinates of the standard file polyloop has been incorrectly defined.");
                                    report.MessageList.Add("The coordinates should be 2D and could not be translated to 2D");
                                    report.MessageList.Add("Test may be inaccurate and requires gbXML.org support");

                                }
                                double testSurfacesArea = 0;

                                foreach (SurfaceDefinitions testSurface in possiblesList2)
                                {
                                    if (Math.Abs(testSurface.PlRHRVector.X) == 1 && testSurface.PlRHRVector.Y == 0 &&
                                        testSurface.PlRHRVector.Z == 0)
                                    {
                                        List<Vector.MemorySafe_CartCoord> testCoordList = new List<Vector.MemorySafe_CartCoord>();
                                        foreach (Vector.MemorySafe_CartCoord coord in testSurface.PlCoords)
                                        {
                                            Vector.MemorySafe_CartCoord c2 = new Vector.MemorySafe_CartCoord(0, coord.Y, coord.Z);
                                            testCoordList.Add(c2);
                                        }
                                        testSurfacesArea = GetAreaFrom2DPolyLoop(testCoordList);
                                        if (testSurfacesArea == -999)
                                        {
                                            report.MessageList.Add("The coordinates of the test file polyloop has been incorrectly defined.");
                                            report.MessageList.Add("The coordinates should be 2D and could not be translated to 2D");
                                        }
                                        //convert from the test units to the standard units

                                        double difference = Math.Abs((area*standardareaConversion) - (testSurfacesArea * testareaConversion));
                                        if (difference < area * DOEgbXMLBasics.Tolerances.SurfaceAreaPercentageTolerance)
                                        {
                                            possiblesList1.Add(testSurface);
                                            if (difference == 0)
                                            {
                                                //then it perfectly matches, go on to check the poly loop coordinates
                                                //then check the insertion point
                                                report.MessageList.Add("The test surface: " + testSurface.SurfaceId + " polyloop surface area matches the polyLoop surface area of the standard surface: " + surface.SurfaceId + " exactly.");
                                            }
                                            else
                                            {
                                                report.MessageList.Add("The test surface: " + testSurface.SurfaceId + " polyloop surface area matches the polyLoop surface area of the standard surface: " + surface.SurfaceId + " within the allowable area percentage tolerance.");
                                            }
                                        }
                                        else
                                        {
                                            report.MessageList.Add("The test surface cannot find a match for its surface area as defined in the polyLoop coordinates");
                                            //don't return here, it will be returned below
                                        }
                                    }
                                    else
                                    {
                                        //do nothing, it will be handled by the more general case and then translated to a 2-D surface
                                    }
                                }


                            }
                            //Surface normal Parallel to global reference frame y Axis
                            else if (surface.PlRHRVector.X == 0 && Math.Abs(surface.PlRHRVector.Y) == 1 && surface.PlRHRVector.Z == 0)
                            {
                                List<Vector.MemorySafe_CartCoord> coordList = new List<Vector.MemorySafe_CartCoord>();
                                foreach (Vector.MemorySafe_CartCoord coord in surface.PlCoords)
                                {
                                    //only take the X and Z coordinates and throw out the Y because we can assume that they are all the same
                                    Vector.MemorySafe_CartCoord c2 = new Vector.MemorySafe_CartCoord(coord.X, 0, coord.Z);
                                    coordList.Add(c2);

                                }
                                double area = GetAreaFrom2DPolyLoop(coordList);
                                if (area == -999)
                                {
                                    report.MessageList.Add("The coordinates of the standard file polyloop has been incorrectly defined.");
                                    report.MessageList.Add("The coordinates should be 2D and could not be translated to 2D");
                                    report.MessageList.Add("Test may be inaccurate and requires gbXML.org support");

                                }
                                double testSurfacesArea = 0;

                                foreach (SurfaceDefinitions testSurface in possiblesList2)
                                {
                                    if (Math.Abs(testSurface.PlRHRVector.X) == 0 && Math.Abs(testSurface.PlRHRVector.Y) == 1 && testSurface.PlRHRVector.Z == 0)
                                    {
                                        List<Vector.MemorySafe_CartCoord> testCoordList = new List<Vector.MemorySafe_CartCoord>();
                                        foreach (Vector.MemorySafe_CartCoord coord in testSurface.PlCoords)
                                        {
                                            Vector.MemorySafe_CartCoord c2 = new Vector.MemorySafe_CartCoord(coord.X, 0, coord.Z);
                                            testCoordList.Add(c2);
                                        }
                                        testSurfacesArea = GetAreaFrom2DPolyLoop(testCoordList);
                                        if (testSurfacesArea == -999)
                                        {
                                            report.MessageList.Add("The coordinates of the test file polyloop has been incorrectly defined.");
                                            report.MessageList.Add("The coordinates should be 2D and could not be translated to 2D");
                                        }
                                        //convert the testSurfaceArea
                                        double difference = Math.Abs((area*standardareaConversion) - (testSurfacesArea * testareaConversion));
                                        if (difference < area * DOEgbXMLBasics.Tolerances.SurfaceAreaPercentageTolerance)
                                        {
                                            possiblesList1.Add(testSurface);
                                            if (difference == 0)
                                            {
                                                //then it perfectly matches, go on to check the poly loop coordinates
                                                //then check the insertion point
                                                report.MessageList.Add("The test surface: " + testSurface.SurfaceId + " polyloop surface area matches the polyLoop surface area of the standard surface: " + surface.SurfaceId + " exactly.");
                                            }
                                            else
                                            {
                                                report.MessageList.Add("The test surface: " + testSurface.SurfaceId + " polyloop surface area matches the polyLoop surface area of the standard surface: " + surface.SurfaceId + " within the allowable area percentage tolerance.");
                                            }
                                        }
                                        else
                                        {
                                            report.MessageList.Add("The test surface cannot find a match for its surface area as defined in the polyLoop coordinates");
                                            //don't return here, it will be returned below
                                        }
                                    }
                                    else
                                    {
                                        //do nothing, it will be handled by the more general code below and translated to 2D
                                    }
                                }
                            }
                            else if (surface.PlRHRVector.X == 0 && surface.PlRHRVector.Y == 0 && Math.Abs(surface.PlRHRVector.Z) == 1)
                            {
                                List<Vector.MemorySafe_CartCoord> coordList = new List<Vector.MemorySafe_CartCoord>();
                                foreach (Vector.MemorySafe_CartCoord coord in surface.PlCoords)
                                {
                                    //only take the X and Y coordinates and throw out the Z because we can assume that they are all the same
                                    Vector.MemorySafe_CartCoord c2 = new Vector.MemorySafe_CartCoord(coord.X, coord.Y, 0);
                                    coordList.Add(c2);

                                }
                                double area = GetAreaFrom2DPolyLoop(coordList);
                                if (area == -999)
                                {
                                    report.MessageList.Add("The coordinates of the standard file polyloop has been incorrectly defined.");
                                    report.MessageList.Add("The coordinates should be 2D and could not be translated to 2D");
                                    report.MessageList.Add("Test may be inaccurate and requires gbXML.org support");

                                }
                                double testSurfacesArea = 0;

                                foreach (SurfaceDefinitions testSurface in possiblesList2)
                                {
                                    if (Math.Abs(testSurface.PlRHRVector.X) == 0 && testSurface.PlRHRVector.Y == 0 && Math.Abs(testSurface.PlRHRVector.Z) == 1)
                                    {
                                        List<Vector.MemorySafe_CartCoord> testCoordList = new List<Vector.MemorySafe_CartCoord>();
                                        foreach (Vector.MemorySafe_CartCoord coord in testSurface.PlCoords)
                                        {
                                            
                                            Vector.MemorySafe_CartCoord c2 = new Vector.MemorySafe_CartCoord(coord.X, coord.Y, 0);
                                            testCoordList.Add(c2);
                                        }
                                        testSurfacesArea = GetAreaFrom2DPolyLoop(testCoordList);
                                        if (testSurfacesArea == -999)
                                        {
                                            report.MessageList.Add("The coordinates of the test file polyloop has been incorrectly defined.");
                                            report.MessageList.Add("The coordinates should be 2D and could not be translated to 2D");
                                        }
                                        //provide area conversion
                                        double difference = Math.Abs((area*standardareaConversion) - (testSurfacesArea * testareaConversion));
                                        if (difference < area * DOEgbXMLBasics.Tolerances.SurfaceAreaPercentageTolerance)
                                        {
                                            possiblesList1.Add(testSurface);
                                            if (difference == 0)
                                            {
                                                //then it perfectly matches, go on to check the poly loop coordinates
                                                //then check the insertion point
                                                report.MessageList.Add("The test surface: " + testSurface.SurfaceId + " polyloop surface area matches the polyLoop surface area of the standard surface: " + surface.SurfaceId + " exactly.");
                                            }
                                            else
                                            {
                                                report.MessageList.Add("The test surface: " + testSurface.SurfaceId + " polyloop surface area matches the polyLoop surface area of the standard surface: " + surface.SurfaceId + " within the allowable area percentage tolerance.");
                                            }
                                        }
                                        else
                                        {
                                            report.MessageList.Add("The test surface cannot find a match for its surface area as defined in the polyLoop coordinates");
                                            //don't return here, it will be returned below
                                        }
                                    }
                                    else
                                    {
                                        //do nothing.  The code below will handle the more general case where it is not aligned with reference frame axes
                                    }
                                }
                            }
                            //the surface is not aligned with one of the reference frame axes, which requires a bit more work to determine the right answer.
                            else
                            {
                                report.MessageList.Add("The standard surface is not aligned along an axis, and will be rotated into a new coordinate frame");
                                //New Z Axis for this plane is the normal vector, does not need to be created
                                //Get New Y Axis which is the surface Normal Vector cross the original global reference X unit vector (all unit vectors please
                                Vector.CartVect globalReferenceX = new Vector.CartVect();
                                globalReferenceX.X = 1;
                                globalReferenceX.Y = 0;
                                globalReferenceX.Z = 0;
                                Vector.MemorySafe_CartVect localY = Vector.UnitVector(Vector.CrossProductMSRetMSNV(surface.PlRHRVector, globalReferenceX));
                                

                                //new X axis is the localY cross the surface normal vector
                                Vector.MemorySafe_CartVect localX = Vector.UnitVector(Vector.CrossProduct(localY, surface.PlRHRVector));

                                //convert the polyloop coordinates to a local 2-D reference frame
                                //using a trick employed by video game programmers found here http://stackoverflow.com/questions/1023948/rotate-normal-vector-onto-axis-plane
                                List<Vector.MemorySafe_CartCoord> translatedCoordinates = new List<Vector.MemorySafe_CartCoord>();
                                Vector.MemorySafe_CartCoord newOrigin = new Vector.MemorySafe_CartCoord(0,0,0);
                                translatedCoordinates.Add(newOrigin);
                                for (int j = 1; j < surface.PlCoords.Count; j++)
                                {
                                    //randomly assigns the first polyLoop coordinate as the origin
                                    Vector.MemorySafe_CartCoord origin = surface.PlCoords[0];
                                    //captures the components of a vector drawn from the new origin to the 
                                    Vector.CartVect distance = new Vector.CartVect();
                                    distance.X = surface.PlCoords[j].X - origin.X;
                                    distance.Y = surface.PlCoords[j].Y - origin.Y;
                                    distance.Z = surface.PlCoords[j].Z - origin.Z;
                                    
                                    //x coordinate is distance vector dot the new local X axis
                                    double tX = distance.X * localX.X + distance.Y * localX.Y + distance.Z * localX.Z;
                                    //y coordinate is distance vector dot the new local Y axis
                                    double tY = distance.X * localY.X + distance.Y * localY.Y + distance.Z * localY.Z;
                                    double tZ = 0;
                                    Vector.MemorySafe_CartCoord translatedPt = new Vector.MemorySafe_CartCoord(tX,tY,tZ);
                                    translatedCoordinates.Add(translatedPt);

                                }
                                double area = GetAreaFrom2DPolyLoop(translatedCoordinates);
                                if (area == -999)
                                {
                                    report.MessageList.Add("The coordinates of the standard file polyloop has been incorrectly defined.");
                                    report.MessageList.Add("The coordinates should be 2D and could not be translated to 2D");
                                    report.MessageList.Add("Test may be inaccurate and requires gbXML.org support");

                                }
                                //get the area of the test candidates using the polyloop coordinates
                                foreach (SurfaceDefinitions testSurface in possiblesList2)
                                {
                                    Vector.CartVect testglobalReferenceX = new Vector.CartVect();
                                    globalReferenceX.X = 1;
                                    globalReferenceX.Y = 0;
                                    globalReferenceX.Z = 0;
                                    Vector.MemorySafe_CartVect testlocalY = Vector.UnitVector(Vector.CrossProductMSRetMSNV(surface.PlRHRVector, testglobalReferenceX));

                                    //new X axis is the localY cross the surface normal vector
                                    Vector.MemorySafe_CartVect testlocalX = Vector.UnitVector(Vector.CrossProduct(testlocalY, surface.PlRHRVector));

                                    //convert the polyloop coordinates to a local 2-D reference frame
                                    //using a trick employed by video game programmers found here http://stackoverflow.com/questions/1023948/rotate-normal-vector-onto-axis-plane
                                    List<Vector.MemorySafe_CartCoord> testtranslatedCoordinates = new List<Vector.MemorySafe_CartCoord>();
                                    Vector.MemorySafe_CartCoord newOriginTest = new Vector.MemorySafe_CartCoord(0,0,0);
                                    testtranslatedCoordinates.Add(newOriginTest);
                                    for (int j = 1; j < surface.PlCoords.Count; j++)
                                    {
                                        //randomly assigns the first polyLoop coordinate as the origin
                                        Vector.MemorySafe_CartCoord origin = testSurface.PlCoords[0];
                                        //captures the components of a vector drawn from the new origin to the 
                                        Vector.CartVect distance = new Vector.CartVect();
                                        distance.X = testSurface.PlCoords[j].X - origin.X;
                                        distance.Y = testSurface.PlCoords[j].Y - origin.Y;
                                        distance.Z = testSurface.PlCoords[j].Z - origin.Z;
                                        
                                        //x coordinate is distance vector dot the new local X axis
                                        double tX = distance.X * localX.X + distance.Y * localX.Y + distance.Z * localX.Z;
                                        //y coordinate is distance vector dot the new local Y axis
                                        double tY = distance.X * localY.X + distance.Y * localY.Y + distance.Z * localY.Z;
                                        double tZ = 0;
                                        Vector.MemorySafe_CartCoord translatedPt = new Vector.MemorySafe_CartCoord(tX,tY,tZ);
                                        testtranslatedCoordinates.Add(translatedPt);

                                    }
                                    double testarea = GetAreaFrom2DPolyLoop(translatedCoordinates);
                                    if (testarea == -999)
                                    {
                                        report.MessageList.Add("The coordinates of the test file polyloop has been incorrectly defined.");
                                        report.MessageList.Add("The coordinates should be 2D and could not be translated to 2D");
                                    }
                                    //convert to the standard units
                                    double difference = Math.Abs((area*standardareaConversion) - (testarea * testareaConversion));
                                    if (difference < area * DOEgbXMLBasics.Tolerances.SurfaceAreaPercentageTolerance)
                                    {
                                        possiblesList1.Add(testSurface);
                                        //within reason
                                        if (difference == 0)
                                        {
                                            report.MessageList.Add
                                                ("The test surface: " + testSurface.SurfaceId +
                                                " polyloop surface area matches the polyLoop surface area of the standard surface: "
                                                + surface.SurfaceId + " exactly.");
                                        }
                                        else
                                        {
                                            report.MessageList.Add
                                                ("The test surface: " + testSurface.SurfaceId +
                                                " polyloop surface area matches the polyLoop surface area of the standard surface: "
                                                + surface.SurfaceId + " within the allowable area percentage tolerance.");
                                        }
                                    }
                                    else
                                    {
                                        //not within reason, so the test will fail
                                        //don't return yet, it will be returned below when possiblesList1 is found empty
                                    }
                                }
                            }
                        }
                    }

                    possiblesList2.Clear();
                    //polyLoop absolute coordinates
                    //list 1 is analyzed
                    //list 2 is free
                    report.MessageList.Add("</br>");
                    report.MessageList.Add("Starting PolyLoop coordinate comparisons.......");
                    report.MessageList.Add("</br>");
                    if (possiblesList1.Count > 0)
                    {

                        foreach (SurfaceDefinitions testSurface in possiblesList1)
                        {
                            //check the polyLoop coordinates
                            foreach (Vector.MemorySafe_CartCoord standardPolyLoopCoord in surface.PlCoords)
                            {
                                report = GetPolyLoopCoordMatch(standardPolyLoopCoord, testSurface, report, surface.SurfaceId, testlengthConversion, standardlengthConversion);
                                if (report.passOrFail)
                                {
                                    continue;
                                }
                                else
                                {
                                    report.MessageList.Add("Could not find a coordinate match in the test surface polyloop.");
                                    break;
                                }
                            }
                            if (report.passOrFail)
                            {
                                possiblesList2.Add(testSurface);
                            }
                        }
                    }
                    else
                    {
                        report.longMsg = "In the test file, no surfaces could be found that match standard file;s Surface Id: " + surface.SurfaceId + " AdjacentSpaceId(s), SurfaceType, Tilt, Azimuth, and Surface Area.  Failed when attempting to match the surface area.";
                        report.passOrFail = false;
                        return report;
                    }
                    possiblesList1.Clear();
                    report.MessageList.Add("</br>");
                    if(!isHighTiltObject && !isLowTiltObject && issurfaceRegular) //no point in doing this if thing is not square and regular
                    {
                        report.MessageList.Add("Starting Insertion Point Coordinate comparisons.......");
                        report.MessageList.Add("</br>");
                        if (possiblesList2.Count > 0)
                        {
                            //check the insertion point coordinate
                            foreach (SurfaceDefinitions testSurface in possiblesList2)
                            {
                                //now match the differences
                                double insPtXDiff = Math.Abs((testSurface.InsertionPoint.X * testlengthConversion) - (surface.InsertionPoint.X*standardlengthConversion));
                                double insPtYDiff = Math.Abs((testSurface.InsertionPoint.Y * testlengthConversion) - (surface.InsertionPoint.Y*standardlengthConversion));
                                double insPtZDiff = Math.Abs((testSurface.InsertionPoint.Z * testlengthConversion) - (surface.InsertionPoint.Z*standardlengthConversion));
                                if(interiorWallFlipped)
                                {
                                    report.MessageList.Add("The azimuths are flipped.  Looking to see if the test surface has properly defined the insertion point it has.");
                                    report.MessageList.Add("</br>");
                                    //find the complimenting insertion point
                                    for(int pt = 0; pt<testSurface.PlCoords.Count; pt++)
                                    {
                                        if(Math.Abs((surface.InsertionPoint.Z*standardlengthConversion) - (testSurface.PlCoords[pt].Z * testlengthConversion)) < DOEgbXMLBasics.Tolerances.SurfaceInsPtZTolerance)
                                        {
                                            //this is a potential candidate
                                            if(Math.Abs((surface.InsertionPoint.X*standardlengthConversion) - testSurface.PlCoords[pt].X * testlengthConversion) < DOEgbXMLBasics.Tolerances.SurfaceInsPtXTolerance)
                                            {
                                                if(Math.Abs((surface.InsertionPoint.Y*standardlengthConversion) - testSurface.PlCoords[pt].Y * testlengthConversion) < DOEgbXMLBasics.Tolerances.SurfaceInsPtYTolerance)
                                                {
                                                    //a match
                                                    insPtXDiff = Math.Abs((testSurface.PlCoords[pt].X * testlengthConversion) - (surface.InsertionPoint.X*standardlengthConversion));
                                                    insPtYDiff = Math.Abs((testSurface.PlCoords[pt].Y * testlengthConversion) - (surface.InsertionPoint.Y*standardlengthConversion));
                                                    insPtZDiff = Math.Abs((testSurface.PlCoords[pt].Z * testlengthConversion) - (surface.InsertionPoint.Z*standardlengthConversion));
                                                }
                                                else
                                                {
                                                    //didn't find a candidate
                                                }
                                            }
                                            else
                                            {
                                                if (Math.Abs((surface.InsertionPoint.Y*standardlengthConversion) - testSurface.PlCoords[pt].Y * testlengthConversion) < DOEgbXMLBasics.Tolerances.SurfaceInsPtYTolerance)
                                                {
                                                    //didn't find a candidate
                                                }
                                                else
                                                {
                                                    //didn't find a candidate
                                                }
                                            }
                                        }
                                    }
                                }
                                if (insPtXDiff > DOEgbXMLBasics.Tolerances.SurfaceInsPtXTolerance || insPtYDiff > DOEgbXMLBasics.Tolerances.SurfaceInsPtYTolerance || insPtZDiff > DOEgbXMLBasics.Tolerances.SurfaceInsPtZTolerance)
                                {
                                    report.MessageList.Add("Test file's Surface id: " + testSurface.SurfaceId + " insertion point coordinates do not both match the standard file surface id: " + surface.SurfaceId + ".  It has been removed as a candidate.");
                                    continue;
                                }
                                else
                                {
                                    //possible match
                                    possiblesList1.Add(testSurface);
                                    if (insPtXDiff == 0 && insPtYDiff == 0 && insPtZDiff == 0)
                                    {
                                        //perfect match
                                        report.MessageList.Add("Test file's Surface with id: " + testSurface.SurfaceId + " matches the insertion point in the standard file exactly.");
                                    }
                                    else
                                    {
                                        //perfect match
                                        report.MessageList.Add(" Test file's Surface with id: " + testSurface.SurfaceId + " has an insertion point that is within the allowable tolerances of X:" + DOEgbXMLBasics.Tolerances.SurfaceInsPtXTolerance + " ft, Y:" + DOEgbXMLBasics.Tolerances.SurfaceInsPtYTolerance + "ft, Z:" + DOEgbXMLBasics.Tolerances.SurfaceInsPtZTolerance + "ft.");
                                    }
                                }

                            }
                        }
                        else
                        {
                            report.longMsg = "In the test file, no surfaces could be found that match standard file;s Surface Id: " + surface.SurfaceId + " AdjacentSpaceId(s), SurfaceType, Tilt, Azimuth, Surface Area, and PolyLoop Coordinates.  Failed when matching PolyLoop coordinates.";
                            report.passOrFail = false;
                            return report;
                        }
                        if (possiblesList1.Count == 1)
                        {
                            report.longMsg = "Advanced Surface Test found a match for Standard file surface id: " + surface.SurfaceId + " in the test file.  Only one match was found to be within all the tolerances allowed.  Surface id: " + possiblesList2[0].SurfaceId + ".";
                            report.passOrFail = true;
                            List<string> testFileSurfIds = new List<string>();
                            foreach (SurfaceDefinitions surf in possiblesList1) { testFileSurfIds.Add(surf.SurfaceId); }

                            globalMatchObject.MatchedSurfaceIds.Add(surface.SurfaceId, testFileSurfIds);
                            return report;
                        }
                        else if (possiblesList1.Count == 0)
                        {
                            report.longMsg = "In the test file, no surfaces could be found that match standard file;s Surface Id: " + surface.SurfaceId + " AdjacentSpaceId(s), SurfaceType, Tilt, Azimuth, Surface Area, PolyLoop Coordinates, and Insertion Point.  Failed when attempting to match the insertion point coordinates.";
                            report.passOrFail = false;
                            return report;
                        }
                        else if (possiblesList1.Count > 1)
                        {
                            report.longMsg = "Advanced Surface Test found more than one match for Standard file surface id: " + surface.SurfaceId + " in the test file.  It was not possible to determine only one unique surface.";
                            report.passOrFail = false;
                            //List<string> testFileSurfIds = new List<string>();
                            //foreach (SurfaceDefinitions surf in possiblesList1) { testFileSurfIds.Add(surf.SurfaceId); }
                            //report.MatchedSurfaceIds.Add(surface.SurfaceId, testFileSurfIds);
                            return report;
                        }
                        return report;
                    }
                    else
                    {
                        //we do not conduct insertion point tests for horizontal surfaces
                        if (possiblesList2.Count == 1)
                        {
                            report.longMsg = "Advanced Surface Test found a match for Standard file surface id: " + surface.SurfaceId + " in the test file.  Only one match was found to be within all the tolerances allowed.  Surface id: " + possiblesList2[0].SurfaceId + ".";
                            report.passOrFail = true;
                            List<string> testFileSurfIds = new List<string>();
                            foreach (SurfaceDefinitions surf in possiblesList2) { testFileSurfIds.Add(surf.SurfaceId); }

                            globalMatchObject.MatchedSurfaceIds.Add(surface.SurfaceId, testFileSurfIds);
                            return report;
                        }
                        else if (possiblesList2.Count == 0)
                        {
                            report.longMsg = "In the test file, no surfaces could be found that match standard file;s Surface Id: " + surface.SurfaceId + " AdjacentSpaceId(s), SurfaceType, Tilt, Azimuth, Surface Area, PolyLoop Coordinates, and Insertion Point.  Failed when attempting to match the insertion point coordinates.";
                            report.passOrFail = false;
                            return report;
                        }
                        else if (possiblesList2.Count > 1)
                        {
                            report.longMsg = "Advanced Surface Test found more than one match for Standard file surface id: " + surface.SurfaceId + " in the test file.  It was not possible to determine only one unique surface.";
                            report.passOrFail = false;
                            //List<string> testFileSurfIds = new List<string>();
                            //foreach (SurfaceDefinitions surf in possiblesList1) { testFileSurfIds.Add(surf.SurfaceId); }
                            //report.MatchedSurfaceIds.Add(surface.SurfaceId, testFileSurfIds);
                            return report;
                        }
                        return report;
                    }
                }
                return report;

            }
            catch (Exception e)
            {
                report.longMsg = (e.ToString());
                return report;
            }
        }
        private bool DoesSurfaceContainSurface(SurfaceDefinitions surface, SurfaceDefinitions testSurface, double testlengthConversion, double standardlengthConversion)
        {
            logger.Info("Starting to check if test surface " + testSurface.SurfaceId + " lies within surface " + surface.SurfaceId);
            int coordcount = testSurface.PlCoords.Count();
            try
            {
                List<List<Vector.MemorySafe_CartCoord>> surfaceTriangles = new List<List<Vector.MemorySafe_CartCoord>>();
                if(IsSurfaceRegular(surface))
                {
                    //triangulate in a very simple way
                    List<Vector.MemorySafe_CartCoord> triangle1 = surface.PlCoords.GetRange(0, 3);
                    List<Vector.MemorySafe_CartCoord> triangle2 = surface.PlCoords.GetRange(2, 2);
                    triangle2.Add(surface.PlCoords[0]); //note this is a little hack to get back to the zero index.
                    surfaceTriangles.Add(triangle1);
                    surfaceTriangles.Add(triangle2);
                }
                else
                {
                    //is the surface already a triangle?
                    if(surface.PlCoords.Count == 3)
                    {
                        logger.Info("Surface " + surface.SurfaceId + " is a triangle.");
                        surfaceTriangles.Add(surface.PlCoords);
                    }
                    else
                    {
                        //is the surface still a quadrilateral?
                        if(surface.PlCoords.Count == 4)
                        {
                            //triangulate in a very simple way (as above)
                            List<Vector.MemorySafe_CartCoord> triangle1 = surface.PlCoords.GetRange(0, 3);
                            List<Vector.MemorySafe_CartCoord> triangle2 = surface.PlCoords.GetRange(2, 2);
                            triangle2.Add(surface.PlCoords[0]); //note this is a little hack to get back to the zero index.
                            surfaceTriangles.Add(triangle1);
                            surfaceTriangles.Add(triangle2);
                        }
                        else
                        {
                            //perform some advanced triangulation.
                            logger.Info("PROGRAMMER'S NOTE: NEW CODE PATH YET TO BE DEFINED : Advanced Triangulation");
                        }
                        

                    }
                }
                foreach(Vector.MemorySafe_CartCoord coord in testSurface.PlCoords)
                {
                    foreach(List<Vector.MemorySafe_CartCoord> triangle in surfaceTriangles)
                    {
                        if(IsTestCoordMatchSurface(coord, triangle, surface.SurfaceId, testlengthConversion, standardlengthConversion))
                        {
                            coordcount--;
                            logger.Info("Test surface coord "+ coord.X+","+coord.Y+","+coord.Z+" matches exactly.");
                            break;
                        }
                        else
                        {
                            //use the fact that the sum of angles for a point that subdivides a rectangle should be 2pi
                            Vector.CartVect p1_p = Vector.UnitVector(Vector.CreateVector(coord,triangle[0]));
                            Vector.CartVect p2_p = Vector.UnitVector(Vector.CreateVector(coord,triangle[1]));
                            Vector.CartVect p3_p = Vector.UnitVector(Vector.CreateVector(coord,triangle[2]));

                            double angle_a1 = Math.Acos(p1_p.X*p2_p.X + p1_p.Y*p2_p.Y + p1_p.Z*p2_p.Z);
                            double angle_a2 = Math.Acos(p2_p.X*p3_p.X + p2_p.Y+p3_p.Y + p2_p.Z+p3_p.Z);
                            double angle_a3 = Math.Acos(p3_p.X*p1_p.X + p3_p.Y*p1_p.Y + p3_p.Z*p3_p.Z);
                            if((angle_a1+angle_a2+angle_a3)*180 / Math.PI < 0.01) //TODO:  this is hardcoded and needs to be updated.
                            {
                                coordcount--;
                                logger.Info("Test surface "+ coord.X+","+coord.Y+","+coord.Z+" is inside of the test surface.");
                                break;
                            }
                        }
                    }
                    
                }
                if(coordcount == 0) return true;
                else return false;
            }
            catch(Exception e)
            {
                logger.Error("Exception thrown in method Does SurfaceContainSurface.");
                return false;
            }
        }
        //Created July 2016 by Chien Si Harriman.  Note the area tolerance checks are based on percentage tolerances and not absolute tolerances.
        private void GetSurfaceMatches(SurfaceDefinitions surface, List<SurfaceDefinitions> TestSurfaces, ref DetailedSurfaceSummary ssSummary,Conversions.lengthUnitEnum standardLengthUnits, Conversions.lengthUnitEnum testLengthUnits, double testlengthConversion, double standardlengthConversion, Conversions.areaUnitEnum standardAreaUnits, Conversions.areaUnitEnum testAreaUnits, double testareaConversion, double standardareaConversion) 
        {
            try{
                List<SurfaceDefinitions> possiblesList1 = new List<SurfaceDefinitions>();
                List<SurfaceDefinitions> possiblesList2 = new List<SurfaceDefinitions>();

                bool adjSpaceIdMatch = false;
                bool isLowTiltObject = false;
                bool isHighTiltObject = false;
                bool interiorWallFlipped = false;
                bool issurfaceRegular = false;
                bool istestSurfaceRegular = false;
                //try to find a surface in the test file that has the same:
                //adjacent space Id signature
                //surfaceType
                //free list is 1
                //list 2 is not used
                ssSummary.ID = surface.SurfaceId;
                ssSummary.AreaUnits = "SquareFeet"; //TODO, try to remove this hardcoding.
                ssSummary.TotalSurfaceArea = GetSurfaceArea(surface,standardareaConversion);
#region
                logger.Info("SURFACE ID: " + surface.SurfaceId);
                logger.Info("START SUBTEST: AdjacencyId check.");
                for(int ts = 0; ts<TestSurfaces.Count;ts++)
                {
                    SurfaceDefinitions testSurface = TestSurfaces[ts];
                    //has to have the same number of Adjacent Space Ids
                    if (testSurface.AdjSpaceId.Count == surface.AdjSpaceId.Count)
                    {
                        //an exception for a shading device
                        if (surface.AdjSpaceId.Count == 0) { 
                            adjSpaceIdMatch = true; //must be set to true for if statements below to work.
                            logger.Info("SHADING EXCEPTION: " + surface.SurfaceId + " is a shading device.  No AdjacencyId checks performed.");
                        }
                        //has to have the same order of adjacent space id strings to qualify.  This method assumes the strings are identical
                        if(surface.AdjSpaceId.Count == 1)
                        {
                            if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[0]) { adjSpaceIdMatch = true; logger.Info("TEST SURFACE: "+ testSurface.SurfaceId+ " AdjacencyID MATCH SUCCESS"); }
                            else { logger.Info("TEST SURFACE: "+ testSurface.SurfaceId + " AdjacencyID MATCH FAILED"); }
                        }
                        if(surface.AdjSpaceId.Count == 2)
                        {
                            if(surface.SurfaceType == "Ceiling" && testSurface.SurfaceType == "InteriorFloor")
                            {
                                if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[1] && surface.AdjSpaceId[1] == testSurface.AdjSpaceId[0])
                                {
                                    adjSpaceIdMatch = true;
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH SUCCESS");
                                }
                                else { logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH FAILED"); }
                            }
                            else if (surface.SurfaceType == "InteriorFloor"  && testSurface.SurfaceType == "Ceiling")
                            {
                                if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[1] && surface.AdjSpaceId[1] == testSurface.AdjSpaceId[0])
                                {
                                    adjSpaceIdMatch = true;
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH SUCCESS");
                                }
                                else { logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH FAILED"); }
                            }
                            else if (surface.SurfaceType == "InteriorWall" && testSurface.SurfaceType == "InteriorWall")
                            {
                                if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[0] && surface.AdjSpaceId[1] == testSurface.AdjSpaceId[1])
                                {
                                    adjSpaceIdMatch = true;
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH SUCCESS");
                                }
                                else if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[1] && surface.AdjSpaceId[1] == testSurface.AdjSpaceId[0])
                                {
                                    adjSpaceIdMatch = true;
                                    interiorWallFlipped = true;
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH SUCCESS");
                                }
                                else { logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH FAILED"); }
                            }
                            else
                            {
                                if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[0] && surface.AdjSpaceId[1] == testSurface.AdjSpaceId[1])
                                {
                                    adjSpaceIdMatch = true;
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH SUCCESS");
                                }
                                else { logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH FAILED"); }
                            }
                        }
                    }
                    else
                    {
                        if (surface.SurfaceType == "SlabOnGrade")  //slab on grade for some reason we see sometimes with two adjacent space ids, depending on the vendor
                        {
                            if(testSurface.AdjSpaceId.Count == 2 && surface.AdjSpaceId.Count == 2)
                            {
                                if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[0] && surface.AdjSpaceId[1] == testSurface.AdjSpaceId[1])
                                {
                                    adjSpaceIdMatch = true;
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH SUCCESS");
                                }
                                else { logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH FAILED"); }
                            }
                            else if (surface.AdjSpaceId.Count == 2)
                            {
                                if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[0] && surface.AdjSpaceId[1] == testSurface.AdjSpaceId[0]) 
                                {
                                    adjSpaceIdMatch = true;
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH SUCCESS");
                                }
                                else { logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH FAILED"); }
                            }
                            else
                            {
                                if (surface.AdjSpaceId[0] == testSurface.AdjSpaceId[0])
                                {
                                    adjSpaceIdMatch = true;
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH SUCCESS");
                                }
                                else { logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " AdjacencyID MATCH FAILED"); }
                            }
                        }
                        else
                        {
                            logger.Info("TEST SURFACE: AdjacencyID MATCH FAILED.  Surfaces should have the same number of Adjacent Space Ids, with the one allowance we give for Slab on Grade.");
                        }
                    }
                    if (adjSpaceIdMatch)
                    {
                        logger.Info("END SUBTEST: AdjacencyId check.");
                        logger.Info("START SUBTEST: surfaceType check.");
                        if(!IsHighTiltSurface(surface) && !IsLowTiltSurface(surface))
                        {
                            if(surface.SurfaceType == testSurface.SurfaceType)
                            {
                                logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " surfaceType MATCH SUCCESS");
                                possiblesList1.Add(testSurface);
                                
                            }
                            else { logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " surfaceType MATCH FAILED"); }
                        }
                        else
                        {
                            if(IsLowTiltSurface(surface)) isLowTiltObject = true;
                            if (IsHighTiltSurface(surface)) isHighTiltObject = true;
                            if(IsLowTiltSurface(testSurface) && isHighTiltObject)
                            {
                                if(testSurface.SurfaceType == "Ceiling" && surface.SurfaceType == "InteriorFloor")
                                {
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " surfaceType MATCH SUCCESS");
                                    possiblesList1.Add(testSurface);
                                }
                                else
                                {
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " surfaceType MATCH FAILED");
                                }
                            }
                            else if(IsHighTiltSurface(testSurface) && isHighTiltObject)
                            {
                                if(surface.SurfaceType == testSurface.SurfaceType)
                                {
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " surfaceType MATCH SUCCESS");
                                    possiblesList1.Add(testSurface);
                                
                                }
                                else { logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " surfaceType MATCH FAILED"); }
                            }
                            else if(IsLowTiltSurface(testSurface) && isLowTiltObject)
                            {
                                if (surface.SurfaceType == testSurface.SurfaceType)
                                {
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " surfaceType MATCH SUCCESS");
                                    possiblesList1.Add(testSurface);

                                }
                                else { logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " surfaceType MATCH FAILED"); }
                            }
                            else if (IsHighTiltSurface(testSurface) && isLowTiltObject)
                            {
                                if(testSurface.SurfaceType == "InteriorFloor" && surface.SurfaceType == "Ceiling")
                                {
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " surfaceType MATCH SUCCESS");
                                    possiblesList1.Add(testSurface);
                                }
                                else
                                {
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " surfaceType MATCH FAILED");
                                }
                            }
                        }
                        adjSpaceIdMatch = false; //must reset it to make sure it will find other valid surfaces for only the proper adjacency.                        
                    }
                }
                logger.Info("END SUBTEST: surfaceType check.");
                // #reporting
                if (possiblesList1.Count == 1)
                {
                    logger.Info("TEST SUMMARY: Based on a comparison of the surface Type and Adjacent SpaceIds, there is " + possiblesList1.Count.ToString() + " surface in the test file that is a possible match for " + surface.SurfaceId + " of the Standard File.");
                }
                else if (possiblesList1.Count > 1)
                {
                    logger.Info("TEST SUMMARY: Based on a comparison of the surface Type and Adjacent SpaceIds, there are " + possiblesList1.Count.ToString() + " surfaces in the test file that are possible matches for " + surface.SurfaceId + " of the Standard File.");
                }
                else
                {
                    logger.Error("TEST SUMMARY: In the vendor test file, no matches could be found for this surface that have the same AdjacentSpaceId(s) and SurfaceType.");
                    ssSummary.FoundMatch = false;
                    return;
                }
#endregion
                //there is at least one surface that matches the above criteria
                //now checking for tilt and azimuth criteria, as these have to match
                //TODO: consider removing, minor clean up
                if (possiblesList1.Count > 0)
                {
                    logger.Info("START SUBTEST: Azimuth and Tilt check.");
                    foreach (SurfaceDefinitions testSurface in possiblesList1)
                    {
                        double tiltDifference = 0;
                        double azimuthDifference = Math.Abs(testSurface.Azimuth - surface.Azimuth);
#region
                        if(isLowTiltObject)
                        {
                            if(IsLowTiltSurface(testSurface)) //they are the same, both have small tilts
                            {
                                tiltDifference = Math.Abs(testSurface.Tilt - surface.Tilt);
                            }
                            else //they are 180 degrees different, and the test surface is a high tilt while the standard is low tilt
                            {
                                if (testSurface.SurfaceType == "InteriorFloor")
                                {
                                    tiltDifference = Math.Abs(Math.Abs(testSurface.Tilt - 180) - surface.Tilt);
                                }
                                else
                                {
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Tilt MATCH FAILED");
                                    logger.Info("PROGRAMMER'S NOTE: Expecting test surface type to be Interior Floor");
                                    logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                    logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                    logger.Info("TEST SURFACE: "+testSurface.SurfaceId + " has been removed as a candidate for matching.");
                                    continue;
                                }
                            }

                            //no azimuth tests for horizontal surfaces
                            if (tiltDifference > DOEgbXMLBasics.Tolerances.SurfaceTiltTolerance) 
                            {
                                logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Tilt MATCH FAILED");
                                logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " has been removed as a candidate for matching.");
                                continue;
                            }
                            //if the is within tolerance
                            else
                            {
                                //if the surface is horizontal, just add to the free List because we don't check for azimuth in this case
                                if (surface.Tilt == 0)
                                {
                                    possiblesList2.Add(testSurface);
                                    if (tiltDifference == 0)
                                    {
                                        logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Tilt MATCH SUCCESS:PERFECT");
                                        logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                        logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                    }
                                    else
                                    {
                                        logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Tilt MATCH SUCCESS");
                                        logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                        logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                    }
                                }
                                else
                                {
                                    logger.Info("START SUBTEST: azimuth checks.");
                                    //check the azimuth
                                    if (azimuthDifference > DOEgbXMLBasics.Tolerances.SurfaceAzimuthTolerance)
                                    {
                                        logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Azimuth MATCH FAILED");
                                        logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                        logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                        logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " has been removed as a candidate for matching.");
                                        continue;
                                    }
                                    //if the tilt and azimuth is within tolerance
                                    else
                                    {
                                        //add to the free List
                                        possiblesList2.Add(testSurface);
                                        if (tiltDifference == 0 && azimuthDifference == 0)
                                        {
                                             logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Azimuth MATCH SUCCESS:PERFECT");
                                            logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                            logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                        }
                                        else
                                        {
                                             logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Azimuth MATCH SUCCESS");
                                            logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                            logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                        }
                                    }
                                }
                            }
                        }
                        else if (isHighTiltObject)
                        {
                            if(IsHighTiltSurface(testSurface)) //both high tilt interior surfaces
                            {
                                tiltDifference = Math.Abs(testSurface.Tilt - surface.Tilt);
                            }
                            else //standard is high tilt, test is low tilt
                            {
                                if(testSurface.SurfaceType == "Ceiling")
                                {
                                    tiltDifference = Math.Abs(Math.Abs(testSurface.Tilt - 180) - surface.Tilt);
                                }
                                else
                                {
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Tilt MATCH FAILED");
                                    logger.Info("PROGRAMMER' NOTE: Expected surfaceType to be Ceiling.");
                                    logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                    logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " has been removed as a candidate for matching.");
                                    continue;
                                }
                            }

                            //no azimuth tests
                            if (tiltDifference > DOEgbXMLBasics.Tolerances.SurfaceTiltTolerance) //azimuth no longer matters for these surfaces
                            {
                                logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Tilt MATCH FAILED");
                                logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " has been removed as a candidate for matching.");
                                continue;
                            }
                            //if the tilt and azimuth is within tolerance
                            else
                            {
                                //if the surface is horizontal, just add to the free List because we don't check for azimuth in this case
                                if (surface.Tilt == 180)
                                {
                                    possiblesList2.Add(testSurface);
                                    if (tiltDifference == 0)
                                    {
                                        logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Tilt MATCH SUCCESS:PERFECT");
                                        logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                        logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                    }
                                    else
                                    {
                                        logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Tilt MATCH PERFECT");
                                        logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                        logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                    }
                                }
                                else
                                {
                                    //check the azimuth
                                    if (azimuthDifference > DOEgbXMLBasics.Tolerances.SurfaceAzimuthTolerance)
                                    {
                                        logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Azimuth MATCH FAILED");
                                        logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                        logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                        logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " has been removed as a candidate for matching.");
                                        continue;
                                    }
                                    //if the tilt and azimuth is within tolerance
                                    else
                                    {
                                        //add to the free List
                                        possiblesList2.Add(testSurface);
                                        if (tiltDifference == 0 && azimuthDifference == 0)
                                        {
                                            logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Azimuth MATCH SUCCESS:PERFECT");
                                            logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                            logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                        }
                                        else
                                        {
                                            logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Azimuth MATCH SUCCESS");
                                            logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                            logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                        }
                                    }
                                }
                            }
                        }
#endregion              //the surface is neither a ceiling nor a floor, it is just something regular
                        else
                        {
                            azimuthDifference = Math.Abs(testSurface.Azimuth - surface.Azimuth);
                            if (interiorWallFlipped) //both high tilt interior surfaces
                            {
                                azimuthDifference = Math.Abs(Math.Abs(testSurface.Azimuth - surface.Azimuth) - 180); //180 is needed because they should be separated by 180
                            }
                            tiltDifference = Math.Abs(testSurface.Tilt - surface.Tilt);
                            
                            //if the tilt and azimuth is outside of tolerance
                            if (tiltDifference > DOEgbXMLBasics.Tolerances.SurfaceTiltTolerance || azimuthDifference > DOEgbXMLBasics.Tolerances.SurfaceAzimuthTolerance)
                            {
                                logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Tilt Or Azimuth MATCH FAILED");
                                logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " has been removed as a candidate for matching.");
                                continue;
                            }
                            //if the tilt and azimuth is within tolerance
                            else
                            {
                                //add to the free List
                                possiblesList2.Add(testSurface);
                                if (tiltDifference == 0 && azimuthDifference == 0)
                                {
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Tilt And Azimuth MATCH SUCCESS:PERFECT");
                                    logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                    logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                }
                                else
                                {
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Tilt And Azimuth MATCH SUCCESS");
                                    logger.Debug("Test file surface (Azimuth, Tilt): (" + testSurface.Azimuth.ToString() + "," + testSurface.Tilt.ToString() + ")");
                                    logger.Debug("Standard file surface (Azimuth, Tilt): (" + surface.Azimuth.ToString() + "," + surface.Tilt.ToString() + ")");
                                }
                            }
                        }
                        logger.Info("END SUBTEST: Azimuth and Tilt check.");
                    }
                }
                // //report to the user that no matches could be found
                else
                {
                    logger.Error("TEST SUMMARY:  In the test file, surfaces could be found that match the standard file's AdjacentSpaceId and SurfaceType, but of these matches, none could be identified that also have a tilt or azimuth that exactly matches the standard file's, or is within the allowable tolerance.");
                    ssSummary.FoundMatch = false;
                    return;
                }

                //clear the first list
                possiblesList1.Clear();
                //start to loop through the new refined list
                //generally want to look at the polyLoop coordinates
                //list 2 is analyzed
                //list 1 is free
                ;
                if (possiblesList2.Count > 0)
                {
                    //simple method from this point forward is just to simply start doing a polyloop check
                    //check the standard surface PolyLoop and the test Surface(s) polyloop(s)
                    //check the absolute coordinates of the testSurface(s) polyloop(s)

                    if (possiblesList2.Count == 1)
                    {
                        logger.Info("PROGRAMMER'S INFO:  Only one Surface Candidate remaining.");
                        //meaning there is only one candidate still available
                        //go on to test the polyLoop coordinates and the insertion point
                        possiblesList1.Add(possiblesList2[0]);
                        //this should mean theoretically that you can do a one for one comparison and do the simplistic check
                        possiblesList2.Clear();
                        //polyLoop absolute coordinates
                        //list 1 is analyzed
                        //list 2 is free
                        logger.Info("START SUBTEST: PolyLoop coordinate checks.");
                        #region
                        if (possiblesList1.Count > 0)
                        {
                            foreach (SurfaceDefinitions testSurface in possiblesList1)
                            {
                                //check the polyLoop coordinates
                                bool coordsMatch = false;
                                foreach (Vector.MemorySafe_CartCoord standardPolyLoopCoord in surface.PlCoords)
                                {
                                    coordsMatch = GetPolyLoopCoordMatch(standardPolyLoopCoord, testSurface, surface.SurfaceId, testlengthConversion, standardlengthConversion);
                                    if (coordsMatch)
                                    {
                                        continue;
                                    }
                                    else
                                    {
                                        logger.Info("TEST SURFACE: "+testSurface.SurfaceId+ " polyloop coordinate MATCH FAILED.  It has been removed from the candidate list.");
                                        break;
                                    }
                                }
                                if (coordsMatch)
                                {
                                    logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " polyloop coordinate MATCH SUCCESS.");
                                    possiblesList2.Add(testSurface);
                                }
                            }
                        }
                        else
                        {
                            logger.Error("TEST SUMMARY: In the test file, no surfaces could be found that match standard file;s Surface Id: " + surface.SurfaceId + " AdjacentSpaceId(s), SurfaceType, Tilt, Azimuth, and Surface Area.  Failed when attempting to match its polyloop coordinates.");
                            ssSummary.FoundMatch = false;
                            return;
                        }
                        logger.Info("END SUBTEST: PolyLoop coordinate checks.");
                        #endregion
                        possiblesList1.Clear();

                        issurfaceRegular = IsSurfaceRegular(surface);
                        //Insertion point tests.
                        if (!isHighTiltObject && !isLowTiltObject && issurfaceRegular) //no point in doing these checks if thing is not square and regular
                        #region
                        {
                            logger.Info("PROGRAMMER'S NOTE: Standard Surface is square or rectangle non-horizontal.  Assumption that test surface candidate should also be same type of shape.");
                            logger.Info("START SUBTEST: Insertion Point Coordinate check.");
                            if (possiblesList2.Count > 0)
                            {
                                //check the insertion point coordinate
                                foreach (SurfaceDefinitions testSurface in possiblesList2)
                                {
                                    //now match the differences
                                    double insPtXDiff = Math.Abs((testSurface.InsertionPoint.X * testlengthConversion) - (surface.InsertionPoint.X * standardlengthConversion));
                                    double insPtYDiff = Math.Abs((testSurface.InsertionPoint.Y * testlengthConversion) - (surface.InsertionPoint.Y * standardlengthConversion));
                                    double insPtZDiff = Math.Abs((testSurface.InsertionPoint.Z * testlengthConversion) - (surface.InsertionPoint.Z * standardlengthConversion));
                                    //TODO: this interior flipped algorithm could be improved vastly.  How to tell if in lower left has not been solved.
                                    if (interiorWallFlipped)
                                    {
                                        logger.Info("PROGRAMMER'S NOTE:  The azimuths are flipped.  Adjusting the insertion point test to factor this into account..");
                                        //find the complimenting insertion point
                                        for (int pt = 0; pt < testSurface.PlCoords.Count; pt++)
                                        {
                                            if (Math.Abs((surface.InsertionPoint.Z * standardlengthConversion) - (testSurface.PlCoords[pt].Z * testlengthConversion)) < DOEgbXMLBasics.Tolerances.SurfaceInsPtZTolerance)
                                            {
                                                if (Math.Abs((surface.InsertionPoint.X * standardlengthConversion) - testSurface.PlCoords[pt].X * testlengthConversion) < DOEgbXMLBasics.Tolerances.SurfaceInsPtXTolerance)
                                                {
                                                    if (Math.Abs((surface.InsertionPoint.Y * standardlengthConversion) - testSurface.PlCoords[pt].Y * testlengthConversion) < DOEgbXMLBasics.Tolerances.SurfaceInsPtYTolerance)
                                                    {
                                                        //a match
                                                        insPtXDiff = Math.Abs((testSurface.PlCoords[pt].X * testlengthConversion) - (surface.InsertionPoint.X * standardlengthConversion));
                                                        insPtYDiff = Math.Abs((testSurface.PlCoords[pt].Y * testlengthConversion) - (surface.InsertionPoint.Y * standardlengthConversion));
                                                        insPtZDiff = Math.Abs((testSurface.PlCoords[pt].Z * testlengthConversion) - (surface.InsertionPoint.Z * standardlengthConversion));
                                                        logger.Info("TEST SURFACE: " + testSurface.SurfaceId + "Insertion Point MATCH SUCCESS.");
                                                        possiblesList1.Add(testSurface);
                                                        break;
                                                    }
                                                    else
                                                    {
                                                        //didn't find a candidate
                                                        logger.Info("TEST SURFACE: " + testSurface.SurfaceId + "Insertion Point did not Match.");
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    else
                                    {
                                        if (insPtXDiff > DOEgbXMLBasics.Tolerances.SurfaceInsPtXTolerance || insPtYDiff > DOEgbXMLBasics.Tolerances.SurfaceInsPtYTolerance || insPtZDiff > DOEgbXMLBasics.Tolerances.SurfaceInsPtZTolerance)
                                        {
                                            logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Insertion Point MATCH FAILED.  It has been removed as a candidate.");
                                            continue;
                                        }
                                        else
                                        {
                                            //possible match
                                            if (insPtXDiff == 0 && insPtYDiff == 0 && insPtZDiff == 0)
                                            {
                                                //perfect match
                                                logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Insertion Point MATCH SUCCESS:PERFECT");
                                                possiblesList1.Add(testSurface);
                                            }
                                            else
                                            {
                                                logger.Info("TEST SURFACE: " + testSurface.SurfaceId + " Insertion Point MATCH SUCCESS");
                                                possiblesList1.Add(testSurface);
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                logger.Error("TEST SUMMARY: In the test file, no surfaces could be found that match standard file's Surface Id: " + surface.SurfaceId + " AdjacentSpaceId(s), SurfaceType, Tilt, Azimuth, Surface Area, and PolyLoop Coordinates.  Failed when matching PolyLoop coordinates.");
                                ssSummary.FoundMatch = false;
                                return;
                            }
                            possiblesList2.Clear();
                            logger.Info("END SUBTEST: Insertion point coordinate check.");

                            if (possiblesList1.Count == 1)
                            {
                                logger.Info("TEST SUMMARY: MATCH SUCCESS for Standard file surface id: " + surface.SurfaceId + " in the test file.  Only one match was found to be within all the tolerances allowed.");
                                List<string> testFileSurfIds = new List<string>();
                                foreach (SurfaceDefinitions surf in possiblesList1) { testFileSurfIds.Add(surf.SurfaceId); }

                                globalMatchObject.MatchedSurfaceIds.Add(surface.SurfaceId, testFileSurfIds);
                                ssSummary.FoundMatch = true;
                                ssSummary.TestSurfaceIDs = testFileSurfIds;
                                ssSummary.TotalTestSurfaceArea = GetSurfaceArea(possiblesList1[0],testareaConversion);
                                
                                return;
                            }
                            else if (possiblesList1.Count == 0)
                            {
                                logger.Error("TEST SUMMARY: No surfaces could be found that match standard file;s Surface Id: " + surface.SurfaceId + " AdjacentSpaceId(s), SurfaceType, Tilt, Azimuth, Surface Area, PolyLoop Coordinates, and Insertion Point.  Failed when attempting to match the insertion point coordinates.");
                                ssSummary.FoundMatch = false;
                                return;
                            }
                            else if (possiblesList1.Count > 1)
                            {
                                logger.Error("TEST SUMMARY: Advanced Surface Test found more than one match for Standard file surface id: " + surface.SurfaceId + " in the test file.  It was not possible to determine only one unique surface.");
                                ssSummary.FoundMatch = false;
                                return;
                            }
                            
                        }
                        #endregion
                        else
                        {
                            if (possiblesList2.Count == 1) //we do not check insertion points for horizontal surfaces.
                            {
                                possiblesList1 = possiblesList2; //this is just to keep the below code consistent with convention.

                                logger.Info("TEST FILE SUCCESS: for Standard file surface id: " + surface.SurfaceId + " in the test file.  Only one match was found to be within all the tolerances allowed.");
                                List<string> testFileSurfIds = new List<string>();
                                foreach (SurfaceDefinitions surf in possiblesList1) { testFileSurfIds.Add(surf.SurfaceId); }

                                globalMatchObject.MatchedSurfaceIds.Add(surface.SurfaceId, testFileSurfIds);
                                ssSummary.FoundMatch = true;
                                ssSummary.TestSurfaceIDs = testFileSurfIds;
                                ssSummary.TotalTestSurfaceArea = GetSurfaceArea(possiblesList1[0],testareaConversion);

                                return;
                            }
                            else if (possiblesList2.Count == 0)
                            {
                                logger.Error("TEST FILE FAILURE: No surfaces could be found that match standard file;s Surface Id: " + surface.SurfaceId + " AdjacentSpaceId(s), SurfaceType, Tilt, Azimuth, Surface Area, PolyLoop Coordinates, and Insertion Point.  Failed when attempting to match the insertion point coordinates.");
                                ssSummary.FoundMatch = false;
                                return;
                            }
                            else if (possiblesList2.Count > 1)
                            {
                                logger.Error("TEST FILE FAILRE: Advanced Surface Test found more than one match for Standard file surface id: " + surface.SurfaceId + " in the test file.  It was not possible to determine only one unique surface.");
                                ssSummary.FoundMatch = false;
                                return;
                            }
                        }
                    }
                    //more than one candidate still exists even after the adjacency test, surfaceType test, and tilt and azimuth tests, so filter through
#region
                    else
                    {
                        //check to see if the remaining area sums matches the standard surface area,
                        //and that the edges of the test surfaces do not overlap, etc.
                        //first try to find if the standard file has a regular rectangular or square profile
                        logger.Debug("More than one surface remains in the test subset.");
                        logger.Info("PROGRAMMER'S NOTE:  Performing advanced surface bondary tests.");
                        //checks to see if the testSurface vertices all lie within the standard surface polygonal boundary
                        foreach(SurfaceDefinitions testSurface in possiblesList2)
                        {
                            logger.Info("Testing test surface " +testSurface.SurfaceId);
                            if(DoesSurfaceContainSurface(surface,testSurface,testlengthConversion,standardlengthConversion))
                            {
                                possiblesList1.Add(testSurface);
                            }
                        }

                        //now we check to see which of the remaining surfaces and their edges form a coherent surface.
                        //do their edges overlap?  is the polygon self-intersecting?
                        //add the surface the the existing possibles list
                        possiblesList1.Insert(0, surface);
                        var edgeDict = FindMatchingEdges(possiblesList1);
                        if(EdgesAreValid(edgeDict))
                        {
                            //finally, we see if the total area of the remaining surfaces equals the area of the standard surface.  If all this above has passed, it should not be an issue.
                            double standardArea = ssSummary.TotalSurfaceArea;
                            double testArea = 0;
                            //remove the zero index surface, because this is the standard surface
                            possiblesList1.RemoveAt(0);
                            //these are the remaining candidates
                            foreach(var ts in possiblesList1)
                            {
                                testArea += GetSurfaceArea(ts,testareaConversion);
                            }

                            if(Math.Abs(standardArea - testArea)/standardArea < DOEgbXMLBasics.Tolerances.AreaPercentageTolerance)
                            {
                                logger.Info("TEST FILE SUCCESS: for Standard file surface id: " + surface.SurfaceId + " in the test file.   The wall candidates remaining meet the allowable gemoetry constraints.");
                                List<string> testFileSurfIds = new List<string>();
                                foreach (SurfaceDefinitions surf in possiblesList1) { testFileSurfIds.Add(surf.SurfaceId); }
                                ssSummary.FoundMatch = true;
                                ssSummary.TestSurfaceIDs = testFileSurfIds;
                                ssSummary.TotalTestSurfaceArea = testArea;
                            }
                            else
                            {
                                logger.Info("TEST FILE FAILURE: for Standard file surface id: " + surface.SurfaceId + " in the test file.   The wall candidates remaining did not pass the area test.");
                            }
                        }
                        else
                        {
                            //problem
                            logger.Info("TEST FILE FAILURE: for Standard file surface id: " + surface.SurfaceId + " in the test file.  The wall candidates remaining do not meet the allowable geometry constraints.");
                            List<string> testFileSurfIds = new List<string>();
                            foreach (SurfaceDefinitions surf in possiblesList1) { testFileSurfIds.Add(surf.SurfaceId); }

                            globalMatchObject.MatchedSurfaceIds.Add(surface.SurfaceId, testFileSurfIds);
                            ssSummary.FoundMatch = false;
                            ssSummary.TestSurfaceIDs = testFileSurfIds;
                        }
                        
                    }
#endregion
                }
            }
            catch(Exception e){
                logger.Fatal(e.ToString());
                return;
            }
            
        }
        //<Get Surface Definitions in a gbXML file>
        //Written Jan 31, 2013 by Chien Si Harriman, Senior Product Manager, Carmel Software Corporation
        //This method will take each surface element and convert the xml language into an instance of a SurfaceDefinition
        //Each surface is converted in this way, with the resulting instance being stored in a list that is returned for later use
        //----------------------</p>
        //This is an important method because it stores all of the information about a surface in a gbXML file in a list
        //This list can later be recalled to perform analytics on the surfaces and the data contained within
        private static List<SurfaceDefinitions> GetFileSurfaceDefs(XmlDocument xmldoc, XmlNamespaceManager xmlns)
        {
            List<SurfaceDefinitions> surfaces = new List<SurfaceDefinitions>();
            try
            {

                XmlNodeList nodes = xmldoc.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Surface", xmlns);
                foreach (XmlNode surfaceNode in nodes)
                {
                    //initialize a new instance of the class
                    SurfaceDefinitions surfDef = new SurfaceDefinitions();
                    surfDef.AdjSpaceId = new List<string>();
                    surfDef.PlCoords = new List<Vector.MemorySafe_CartCoord>();

                    //get id and surfaceType
                    XmlAttributeCollection spaceAtts = surfaceNode.Attributes;
                    foreach (XmlAttribute at in spaceAtts)
                    {
                        if (at.Name == "id")
                        {
                            surfDef.SurfaceId = at.Value;
                        }
                        else if (at.Name == "surfaceType")
                        {
                            surfDef.SurfaceType = at.Value;
                        }
                    }
                    if (surfaceNode.HasChildNodes)
                    {
                        XmlNodeList surfChildNodes = surfaceNode.ChildNodes;
                        foreach (XmlNode node in surfChildNodes)
                        {
                            if (node.Name == "AdjacentSpaceId")
                            {
                                XmlAttributeCollection adjSpaceIdAt = node.Attributes;
                                foreach (XmlAttribute at in adjSpaceIdAt)
                                {
                                    if (at.Name == "spaceIdRef")
                                    {
                                        surfDef.AdjSpaceId.Add(at.Value);
                                    }
                                }
                            }
                            else if (node.Name == "RectangularGeometry")
                            {
                                if (node.HasChildNodes)
                                {
                                    XmlNodeList rectGeomChildren = node.ChildNodes;
                                    foreach (XmlNode rgChildNode in rectGeomChildren)
                                    {
                                        if (rgChildNode.Name == "Azimuth") { surfDef.Azimuth = Convert.ToDouble(rgChildNode.InnerText); }
                                        else if (rgChildNode.Name == "CartesianPoint")
                                        {
                                            if (rgChildNode.HasChildNodes)
                                            {
                                                Vector.CartCoord cd = new Vector.CartCoord();
                                                XmlNodeList coordinates = rgChildNode.ChildNodes;
                                                int pointCount = 1;
                                                foreach (XmlNode coordinate in coordinates)
                                                {
                                                    switch (pointCount)
                                                    {
                                                        case 1:
                                                            cd.X = Convert.ToDouble(coordinate.InnerText);
                                                            break;
                                                        case 2:
                                                            cd.Y = Convert.ToDouble(coordinate.InnerText);
                                                            break;
                                                        case 3:
                                                            cd.Z = Convert.ToDouble(coordinate.InnerText);
                                                            break;
                                                    }
                                                    pointCount++;
                                                }
                                                surfDef.InsertionPoint = new VectorMath.Vector.MemorySafe_CartCoord(cd.X, cd.Y, cd.Z);
                                            }
                                        }
                                        else if (rgChildNode.Name == "Tilt") { surfDef.Tilt = Convert.ToDouble(rgChildNode.InnerText); }
                                        else if (rgChildNode.Name == "Height") { surfDef.Height = Convert.ToDouble(rgChildNode.InnerText); }
                                        else if (rgChildNode.Name == "Width") { surfDef.Width = Convert.ToDouble(rgChildNode.InnerText); }
                                    }
                                }
                            }
                            else if (node.Name == "PlanarGeometry")
                            {
                                XmlNode polyLoop = node.FirstChild;
                                if (polyLoop.HasChildNodes)
                                {
                                    XmlNodeList cartesianPoints = polyLoop.ChildNodes;
                                    foreach (XmlNode coordinatePt in cartesianPoints)
                                    {
                                        Vector.CartCoord coord = new Vector.CartCoord();
                                        if (coordinatePt.HasChildNodes)
                                        {
                                            XmlNodeList coordinates = coordinatePt.ChildNodes;
                                            int pointCount = 1;
                                            foreach (XmlNode coordinate in coordinatePt)
                                            {

                                                switch (pointCount)
                                                {
                                                    case 1:
                                                        coord.X = Convert.ToDouble(coordinate.InnerText);
                                                        break;
                                                    case 2:
                                                        coord.Y = Convert.ToDouble(coordinate.InnerText);
                                                        break;
                                                    case 3:
                                                        coord.Z = Convert.ToDouble(coordinate.InnerText);
                                                        break;
                                                }
                                                pointCount++;
                                            }

                                            surfDef.PlCoords.Add(new Vector.MemorySafe_CartCoord(coord.X, coord.Y, coord.Z));
                                        }
                                    }
                                }
                            }
                        }
                    }
                    Vector.MemorySafe_CartVect plRHRVect = GetPLRHR(surfDef.PlCoords);
                    surfDef.PlRHRVector = new Vector.MemorySafe_CartVect(plRHRVect.X,plRHRVect.Y,plRHRVect.Z);
                    surfaces.Add(surfDef);
                }
                return surfaces;
            }
            catch (Exception e)
            {
                return surfaces;
            }

        }