//this is a support tool for TestShellGeomPLRHR
        public static Dictionary<string, List<VectorMath.Vector.MemorySafe_CartCoord>> GetShellGeomPts(XmlNode closedShell)
        {
            Dictionary<string, List<VectorMath.Vector.MemorySafe_CartCoord>> PtsDict = new Dictionary<string, List<Vector.MemorySafe_CartCoord>>();

            string spaceId = "none";

            int cartPtCount;
            try
            {
                //get the name of the space for which this point is defined
                XmlNode spaceNode = closedShell.ParentNode;
                XmlAttributeCollection spaceAtts = spaceNode.Attributes;
                foreach (XmlAttribute at in spaceAtts)
                {
                    if (at.Name == "id")
                    {
                        spaceId = at.Value;
                        break;
                    }

                }
                //keep track of the number of polyloops in the closed shell
                int pLCount = 1;
                //store the geometry points
                foreach (XmlNode PolyLoops in closedShell)
                {
                    List<VectorMath.Vector.MemorySafe_CartCoord> vCoords = new List<VectorMath.Vector.MemorySafe_CartCoord>();
                    List<Vector.CartCoord> PtsList = new List<Vector.CartCoord>();
                    cartPtCount = 0;
                    foreach (XmlNode cartesianPoints in PolyLoops)
                    {
                        //reset surface area and unitRHR (this is how I know that there may be a problem 
                        //and these values are returned as points.  It is not perfect
                        Vector.CartCoord Pts = new Vector.CartCoord();
                        Pts.X = -999;
                        Pts.Y = -999;
                        Pts.Z = -999;
                        PtsList.Add(Pts);
                        int crdCount = 1;
                        //gets a set of XYZ coordinates, one at a time
                        foreach (XmlNode coordinate in cartesianPoints.ChildNodes)
                        {
                            double coord = Convert.ToDouble(coordinate.InnerText);
                            switch (crdCount)
                            {
                                case 1:

                                    PtsList[cartPtCount].X = coord;
                                    break;
                                case 2:

                                    PtsList[cartPtCount].Y = coord;
                                    break;
                                case 3:

                                    PtsList[cartPtCount].Z = coord;
                                    break;
                                default:
                                    break;

                            }
                            crdCount++;
                        }
                        cartPtCount++;
                    }
                    string spaceSurface = spaceId + "/" + pLCount.ToString();
                    //create memory safe points list
                    List<Vector.MemorySafe_CartCoord> mptsList = new List<Vector.MemorySafe_CartCoord>();
                    foreach(Vector.CartCoord cd in PtsList)
                    {
                        mptsList.Add(new Vector.MemorySafe_CartCoord(cd.X, cd.Y, cd.Z));
                    }
                    PtsDict.Add(spaceSurface, mptsList);
                    pLCount++;
                    //PtsList.Clear();
                }
            }
            catch (Exception e)
            {

            }
            //I may want to test the number of coordinates to make sure it matches, or if it has a minimum number of coords
            return PtsDict;
        }
        //<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;
            }

        }
        public static LLRet GetLLForRoof(List<Vector.MemorySafe_CartCoord> surfacecoords)
        {
            LLRet ll = new LLRet();
            ll.indices = new List<int>();
            int surfindex = -1;
            CartesianPoint cp = new CartesianPoint();

            Vector.CartCoord llsurf = new Vector.CartCoord();

            Vector.MemorySafe_CartVect RHRVector = Vector.GetMemRHR(surfacecoords);
            if (Math.Abs(RHRVector.X) == 0 && RHRVector.Y == 0 && RHRVector.Z == 1)
            {

                for (int sccount = 0; sccount < surfacecoords.Count; sccount++)
                {
                    if (sccount == 0)
                    {
                        llsurf.X = surfacecoords[sccount].X;
                        llsurf.Y = surfacecoords[sccount].Y;
                        llsurf.Z = surfacecoords[sccount].Z;
                        surfindex = sccount;
                        continue;

                    }
                    //get lower left...most low(largest Y), then most left (smallest X)
                    if (surfacecoords[sccount].Y >= llsurf.Y)
                    {
                        if (surfacecoords[sccount].X < llsurf.X)
                        {
                            llsurf.X = surfacecoords[sccount].X;
                            llsurf.Y = surfacecoords[sccount].Y;
                            llsurf.Z = surfacecoords[sccount].Z;
                            surfindex = sccount;
                        }
                    }
                }
            }
            else
            {
                //special procedure for this type of roof
            }
            Vector.MemorySafe_CartCoord LLeft = new Vector.MemorySafe_CartCoord(llsurf.X, llsurf.Y, llsurf.Z);
            cp = makegbCartesianPt(LLeft);
            ll.cp = cp;
            ll.indices.Add(surfindex);
            return ll;
        }
        private List<OpeningDefinitions> GetFileOpeningDefs(XmlDocument TestFile, XmlNamespaceManager TestNSM)
        {
            List<OpeningDefinitions> openings = new List<OpeningDefinitions>();
            try
            {

                XmlNodeList nodes = TestFile.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Surface/gbXMLv5:Opening", TestNSM);
                foreach (XmlNode openingNode in nodes)
                {
                    //initialize a new instance of the class
                    OpeningDefinitions openingDef = new OpeningDefinitions();

                    openingDef.PlCoords = new List<Vector.MemorySafe_CartCoord>();

                    //get parent id
                    XmlAttributeCollection parentSurfaceAttributes = openingNode.ParentNode.Attributes;
                    foreach (XmlAttribute parentAt in parentSurfaceAttributes)
                    {
                        if (parentAt.Name == "id")
                        {
                            openingDef.ParentSurfaceId = parentAt.Value;
                            break;
                        }
                    }
                    //get Parent Azimuth and Tilt
                    XmlNode surfaceParentNode = openingNode.ParentNode;
                    if (surfaceParentNode.HasChildNodes)
                    {
                        XmlNodeList surfaceParentNodesChillun = surfaceParentNode.ChildNodes;
                        foreach (XmlNode chileNode in surfaceParentNodesChillun)
                        {
                            if (chileNode.Name == "RectangularGeometry")
                            {
                                if (chileNode.HasChildNodes)
                                {
                                    foreach (XmlNode grandchileNode in chileNode)
                                    {
                                        if (grandchileNode.Name == "Tilt") { openingDef.ParentTilt = Convert.ToDouble(grandchileNode.InnerText); }
                                        else if (grandchileNode.Name == "Azimuth") { openingDef.ParentAzimuth = Convert.ToDouble(grandchileNode.InnerText); }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {

                    }
                    //get surface Id and Opening Type
                    XmlAttributeCollection openingAtts = openingNode.Attributes;
                    foreach (XmlAttribute at in openingAtts)
                    {
                        if (at.Name == "id")
                        {
                            openingDef.OpeningId = at.Value;
                        }
                        else if (at.Name == "openingType")
                        {
                            openingDef.OpeningType = at.Value;
                        }
                    }
                    if (openingNode.HasChildNodes)
                    {
                        XmlNodeList surfChildNodes = openingNode.ChildNodes;
                        foreach (XmlNode node in surfChildNodes)
                        {

                            if (node.Name == "RectangularGeometry")
                            {
                                if (node.HasChildNodes)
                                {
                                    XmlNodeList rectGeomChildren = node.ChildNodes;
                                    foreach (XmlNode rgChildNode in rectGeomChildren)
                                    {
                                        if (rgChildNode.Name == "Azimuth") { openingDef.Azimuth = Convert.ToDouble(rgChildNode.InnerText); }
                                        else if (rgChildNode.Name == "CartesianPoint")
                                        {
                                            if (rgChildNode.HasChildNodes)
                                            {
                                                XmlNodeList coordinates = rgChildNode.ChildNodes;
                                                int pointCount = 1;
                                                Vector.CartCoord od = new Vector.CartCoord();
                                                foreach (XmlNode coordinate in coordinates)
                                                {
                                                    switch (pointCount)
                                                    {
                                                        case 1:
                                                            od.X = Convert.ToDouble(coordinate.InnerText);
                                                            break;
                                                        case 2:
                                                            od.Y = Convert.ToDouble(coordinate.InnerText);
                                                            break;
                                                        case 3:
                                                            od.Z = Convert.ToDouble(coordinate.InnerText);
                                                            break;
                                                    }
                                                    pointCount++;
                                                }
                                                openingDef.InsertionPoint = new Vector.MemorySafe_CartCoord(od.X, od.Y, od.Z);
                                            }
                                        }
                                        else if (rgChildNode.Name == "Tilt") { openingDef.Tilt = Convert.ToDouble(rgChildNode.InnerText); }
                                        else if (rgChildNode.Name == "Height") { openingDef.Height = Convert.ToDouble(rgChildNode.InnerText); }
                                        else if (rgChildNode.Name == "Width") { openingDef.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++;
                                            }
                                            openingDef.PlCoords.Add(new Vector.MemorySafe_CartCoord(coord.X,coord.Y,coord.Z));
                                        }
                                    }
                                }
                            }
                        }
                    }
                    Vector.MemorySafe_CartVect plRHRVect = GetPLRHR(openingDef.PlCoords);
                    openingDef.PlRHRVector = new Vector.MemorySafe_CartVect(plRHRVect.X, plRHRVect.Y, plRHRVect.Z);
                    //may want to forego the above since the orientation is embedded in the parent object.  It may be smarter to just include the azimuth and tilt of the parent object?
                    openings.Add(openingDef);
                }

                return openings;
            }
            catch (Exception e)
            {
                return openings;
            }
        }
 //April 14, 2014 - Deprecated as not useful or within scope
 //private static Dictionary<Vector.CartCoord, Tuple<List<string>, List<bool>>> GetSBVertices(XmlNamespaceManager nsm, XmlDocument zexml)
 //{
 //    Dictionary<Vector.CartCoord,Tuple<List<string>,List<bool>>> sbdict = new Dictionary<Vector.CartCoord, Tuple<List<string>,List<bool>>>();
 //    //get each space boundary
 //    XmlNodeList nodes = zexml.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:Space/gbXMLv5:SpaceBoundary", nsm);
 //    int sbcount = 0;
 //    foreach (XmlNode sbnode in nodes)
 //    {
 //        //record the name of the space boundary
 //        string sbname="";
 //        XmlAttributeCollection spaceAtts = sbnode.Attributes;
 //        foreach (XmlAttribute at in spaceAtts)
 //        {
 //            if (at.Name == "surfaceIdRef")
 //            {
 //                sbname = at.Value;
 //                break;
 //            }
 //        }
 //        //create list of unique vertices
 //        XmlNode closedshell = sbnode.FirstChild;
 //        XmlNode PL = closedshell.FirstChild;
 //        foreach (XmlNode cp in PL)
 //        {
 //            if (cp.Name == "CartesianPoint")
 //            {
 //                sbdict = AddCoordinate(sbcount, sbname, sbdict, cp);
 //            }
 //        }
 //        //XmlNodeList cnodes = sbnode.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:Space/gbXMLv5:SpaceBoundary/gbXMLv5:PlanarGeometry//gbXMLv5:PolyLoop", nsm);
 //        sbcount++;
 //    }
 //    return sbdict;
 //}
 //private static Dictionary<Vector.CartCoord, Tuple<List<string>, List<bool>>> GetSurfVertices(XmlNamespaceManager nsm, XmlDocument zexml)
 //{
 //    Dictionary<Vector.CartCoord, Tuple<List<string>, List<bool>>> surfdict = new Dictionary<Vector.CartCoord, Tuple<List<string>, List<bool>>>();
 //    //get each space boundary
 //    XmlNodeList nodes = zexml.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Surface", nsm);
 //    int surfcount = 0;
 //    foreach (XmlNode surfnode in nodes)
 //    {
 //        //record the name of the space boundary
 //        string surfname = "";
 //        XmlAttributeCollection spaceAtts = surfnode.Attributes;
 //        foreach (XmlAttribute at in spaceAtts)
 //        {
 //            if (at.Name == "id")
 //            {
 //                surfname = at.Value;
 //                break;
 //            }
 //        }
 //        //create list of unique vertices
 //        foreach (XmlNode childnode in surfnode)
 //        {
 //            if (childnode.Name == "PlanarGeometry")
 //            {
 //                XmlNode PL = childnode.FirstChild;
 //                foreach (XmlNode cp in PL)
 //                {
 //                    if (cp.Name == "CartesianPoint")
 //                    {
 //                        surfdict = AddCoordinate(surfcount, surfname, surfdict, cp);
 //                    }
 //                }
 //                surfcount++;
 //            }
 //        }
 //    }
 //    return surfdict;
 //}
 private static Vector.CartCoord makeCoord(XmlNode cartesianPoint)
 {
     Vector.CartCoord coordinst = new Vector.CartCoord();
     if (cartesianPoint.HasChildNodes)
     {
         XmlNodeList coordinates = cartesianPoint.ChildNodes;
         int pointCount = 1;
         foreach (XmlNode coordinate in coordinates)
         {
             switch (pointCount)
             {
                 case 1:
                     coordinst.X = Convert.ToDouble(coordinate.InnerText);
                     break;
                 case 2:
                     coordinst.Y = Convert.ToDouble(coordinate.InnerText);
                     break;
                 case 3:
                     coordinst.Z = Convert.ToDouble(coordinate.InnerText);
                     break;
             }
             pointCount++;
         }
     }
     return coordinst;
 }
        //Reminder to factor in CADAzimuth if appropriate
        public static LLRet GetLLForOpening(List<Vector.MemorySafe_CartCoord> surfacecoords, List<Vector.MemorySafe_CartCoord> openingcoords)
        {
            LLRet ll = new LLRet();
            ll.indices = new List<int>();
            int surfindex=-1;
            int opindex=-1;
            CartesianPoint cp = new CartesianPoint();

            //we want to verify that this is indeed correct
            //west-facing

            Vector.MemorySafe_CartVect RHRVector = Vector.GetMemRHR(surfacecoords);
            if (Math.Abs(RHRVector.X) == -1 && RHRVector.Y == 0 && RHRVector.Z == 0)
            {

                Vector.CartCoord llsurf = new Vector.CartCoord();
                for (int sccount = 0; sccount < surfacecoords.Count; sccount++)
                {
                    if (sccount == 0)
                    {
                        llsurf.X = surfacecoords[sccount].X;
                        llsurf.Y = surfacecoords[sccount].Y;
                        llsurf.Z = surfacecoords[sccount].Z;
                        surfindex = sccount;
                        continue;
                    }
                    //get lower left...most lowest(smallest Z), then most left (largest Y)
                    if (surfacecoords[sccount].Z <= llsurf.Z)
                    {
                        if(surfacecoords[sccount].Y > llsurf.Y)
                        {
                            llsurf.X = surfacecoords[sccount].X;
                            llsurf.Y = surfacecoords[sccount].Y;
                            llsurf.Z = surfacecoords[sccount].Z;
                            surfindex = sccount;
                        }
                    }
                }

                Vector.CartCoord llopening = new Vector.CartCoord();
                for (int occount = 0; occount < openingcoords.Count; occount++)
                {
                    if (occount == 0)
                    {
                        llopening.X = openingcoords[occount].X;
                        llopening.Y = openingcoords[occount].Y;
                        llopening.Z = openingcoords[occount].Z;
                        opindex = occount;
                        continue;
                    }
                    //get lower left...most low(lowest Z), then most left (largest Y)
                    if (openingcoords[occount].Z <= llopening.Z)
                    {
                        if(openingcoords[occount].Y > llopening.Y)
                        {
                            llopening.X = openingcoords[occount].X;
                            llopening.Y = openingcoords[occount].Y;
                            llopening.Z = openingcoords[occount].Z;
                            opindex = occount;
                        }
                    }
                }
                double diffX = Math.Abs(llsurf.Y - llopening.Y);
                double diffY = Math.Abs(llopening.Z - llsurf.Z);
                Vector.MemorySafe_CartCoord LLeft = new Vector.MemorySafe_CartCoord(diffX,diffY,0);
                cp = makegbCartesianPt(LLeft);
            }
            //north-facing
            else if (Math.Abs(RHRVector.X) == 0 && RHRVector.Y == 1 && RHRVector.Z == 0)
            {

                Vector.CartCoord llsurf = new Vector.CartCoord();
                for (int sccount = 0; sccount < surfacecoords.Count; sccount++)
                {
                    if (sccount == 0)
                    {
                        llsurf.X = surfacecoords[sccount].X;
                        llsurf.Y = surfacecoords[sccount].Y;
                        llsurf.Z = surfacecoords[sccount].Z;
                        surfindex = sccount;
                        continue;
                    }
                    //get lower left...most low(smallest Z), then most left (largest X)
                    if (surfacecoords[sccount].Z <= llsurf.Z)
                    {
                        if(surfacecoords[sccount].X > llsurf.X)
                        {
                            llsurf.X = surfacecoords[sccount].X;
                            llsurf.Y = surfacecoords[sccount].Y;
                            llsurf.Z = surfacecoords[sccount].Z;
                            surfindex = sccount;
                        }
                    }
                }

                Vector.CartCoord llopening = new Vector.CartCoord();
                for (int occount = 0; occount < openingcoords.Count; occount++)
                {
                    if (occount == 0)
                    {
                        llopening.X = openingcoords[occount].X;
                        llopening.Y = openingcoords[occount].Y;
                        llopening.Z = openingcoords[occount].Z;
                        opindex = occount;
                        continue;
                    }
                    //get lower left...most low(smallest Z), then most left (largest X)
                    if (openingcoords[occount].Z <= llopening.Z)
                    {
                        if(openingcoords[occount].X > llopening.X)
                        {
                            llopening.X = openingcoords[occount].X;
                            llopening.Y = openingcoords[occount].Y;
                            llopening.Z = openingcoords[occount].Z;
                            opindex = occount;
                        }
                    }
                }
                double diffX = Math.Abs(llsurf.X - llopening.X);
                double diffY = Math.Abs(llsurf.Z - llopening.Z);
                Vector.MemorySafe_CartCoord LLeft = new Vector.MemorySafe_CartCoord(diffX,diffY,0);
                cp= makegbCartesianPt(LLeft);
            }
            //south-facing
            else if (Math.Abs(RHRVector.X) == 0 && RHRVector.Y == -1 && RHRVector.Z == 0)
            {
                Vector.CartCoord llsurf = new Vector.CartCoord();
                for (int sccount = 0; sccount < surfacecoords.Count; sccount++)
                {
                    if (sccount == 0)
                    {
                        llsurf.X = surfacecoords[sccount].X;
                        llsurf.Y = surfacecoords[sccount].Y;
                        llsurf.Z = surfacecoords[sccount].Z;
                        surfindex = sccount;
                        continue;
                    }
                    //get lower left...most low(smaller Z), then most left (smallest X)
                    if (surfacecoords[sccount].Z <= llsurf.Z)
                    {
                        if(surfacecoords[sccount].X < llsurf.X)
                        {
                            llsurf.X = surfacecoords[sccount].X;
                            llsurf.Y = surfacecoords[sccount].Y;
                            llsurf.Z = surfacecoords[sccount].Z;
                            surfindex = sccount;
                        }
                    }
                }

                Vector.CartCoord llopening = new Vector.CartCoord();
                for (int occount = 0; occount < openingcoords.Count; occount++)
                {
                    if (occount == 0)
                    {
                        llopening.X = openingcoords[occount].X;
                        llopening.Y = openingcoords[occount].Y;
                        llopening.Z = openingcoords[occount].Z;
                        opindex = occount;
                        continue;
                    }
                    //get lower left...most low(smallest Z), then most left (smallest X)
                    if (openingcoords[occount].Z <= llopening.Z)
                    {
                        if(openingcoords[occount].X < llopening.X)
                        {
                            llopening.X = openingcoords[occount].X;
                            llopening.Y = openingcoords[occount].Y;
                            llopening.Z = openingcoords[occount].Z;
                            opindex = occount;
                        }
                    }
                }
                double diffX = Math.Abs(llsurf.X - llopening.X);
                double diffY = Math.Abs(llsurf.Z - llopening.Z);
                Vector.MemorySafe_CartCoord LLeft = new Vector.MemorySafe_CartCoord(diffX,diffY,0);
                cp = makegbCartesianPt(LLeft);
            }

            //east-facing
            else if (Math.Abs(RHRVector.X) == 1 && RHRVector.Y == 0 && RHRVector.Z == 0)
            {
                Vector.CartCoord llsurf = new Vector.CartCoord();
                for (int sccount = 0; sccount < surfacecoords.Count; sccount++)
                {
                    if (sccount == 0)
                    {
                        llsurf.X = surfacecoords[sccount].X;
                        llsurf.Y = surfacecoords[sccount].Y;
                        llsurf.Z = surfacecoords[sccount].Z;
                        surfindex = sccount;
                        continue;
                    }
                    //get lower left...most low(smaller Z), then most left (smallest Y)
                    if (surfacecoords[sccount].Z <= llsurf.Z)
                    {
                        if(surfacecoords[sccount].Y < llsurf.Y)
                        {
                            llsurf.X = surfacecoords[sccount].X;
                            llsurf.Y = surfacecoords[sccount].Y;
                            llsurf.Z = surfacecoords[sccount].Z;
                            surfindex = sccount;
                        }
                    }
                }

                Vector.CartCoord llopening = new Vector.CartCoord();
                for (int occount = 0; occount < openingcoords.Count; occount++)
                {
                    if (occount == 0)
                    {
                        llopening.X = openingcoords[occount].X;
                        llopening.Y = openingcoords[occount].Y;
                        llopening.Z = openingcoords[occount].Z;
                        opindex = occount;
                        continue;
                    }
                    //get lower left...most low(smallest Z), then most left (smallest Y)
                    if (openingcoords[occount].Z <= llopening.Z)
                    {
                        if(openingcoords[occount].Y < llopening.Y)
                        {
                            llopening.X = openingcoords[occount].X;
                            llopening.Y = openingcoords[occount].Y;
                            llopening.Z = openingcoords[occount].Z;
                            opindex = occount;
                        }
                    }
                }
                double diffX = Math.Abs(llsurf.Y - llopening.Y);
                double diffY = Math.Abs(llsurf.Z - llopening.Z);
                Vector.MemorySafe_CartCoord LLeft = new Vector.MemorySafe_CartCoord(diffX,diffY,0);
                cp = makegbCartesianPt(LLeft);
            }

            //floors
            else if (Math.Abs(RHRVector.X) == 0 && RHRVector.Y == 0 && RHRVector.Z == -1)
            {

                Vector.CartCoord llsurf = new Vector.CartCoord();
                LLRet llroof = GetLLForFloor(surfacecoords);
                llsurf.X = Convert.ToDouble(llroof.cp.Coordinate[0]);
                llsurf.Y = Convert.ToDouble(llroof.cp.Coordinate[1]);
                llsurf.Z = Convert.ToDouble(llroof.cp.Coordinate[2]);
                surfindex = llroof.indices[0];

                Vector.CartCoord llopening = new Vector.CartCoord();
                for (int occount = 0; occount < openingcoords.Count; occount++)
                {
                    if (occount == 0)
                    {
                        llopening.X = openingcoords[occount].X;
                        llopening.Y = openingcoords[occount].Y;
                        llopening.Z = openingcoords[occount].Z;
                        opindex = occount;

                        continue;
                    }
                    //get lower left...most low(smallest Y), then most left (largest X)
                    if (openingcoords[occount].Y <= llopening.Y)
                    {
                        if (openingcoords[occount].X > llopening.X)
                        {
                            llopening.X = openingcoords[occount].X;
                            llopening.Y = openingcoords[occount].Y;
                            llopening.Z = openingcoords[occount].Z;
                            opindex = occount;

                        }
                    }
                }
                double diffX = Math.Abs(llsurf.X - llopening.X);
                double diffY = Math.Abs(llsurf.Y - llopening.Y);
                Vector.MemorySafe_CartCoord LLeft = new Vector.MemorySafe_CartCoord(diffX, diffY, 0);
                cp = makegbCartesianPt(LLeft);
            }
            //flat roof
            else if (Math.Abs(RHRVector.X) == 0 && RHRVector.Y == 0 && RHRVector.Z == 1)
            {
                Vector.CartCoord llsurf = new Vector.CartCoord();
                LLRet llroof = GetLLForRoof(surfacecoords);
                llsurf.X = Convert.ToDouble(llroof.cp.Coordinate[0]);
                llsurf.Y = Convert.ToDouble(llroof.cp.Coordinate[1]);
                llsurf.Z = Convert.ToDouble(llroof.cp.Coordinate[2]);
                surfindex = llroof.indices[0];

                Vector.CartCoord llopening = new Vector.CartCoord();
                for (int occount = 0; occount < openingcoords.Count; occount++)
                {
                    if (occount == 0)
                    {
                        llopening.X = openingcoords[occount].X;
                        llopening.Y = openingcoords[occount].Y;
                        llopening.Z = openingcoords[occount].Z;
                        opindex = occount;
                        continue;
                    }
                    //get lower left...most low(largest Y), then most left (smallest X)
                    if (openingcoords[occount].Y >= llopening.Y)
                    {
                        if (openingcoords[occount].X < llopening.X)
                        {
                            llopening.X = openingcoords[occount].X;
                            llopening.Y = openingcoords[occount].Y;
                            llopening.Z = openingcoords[occount].Z;
                            opindex = occount;

                        }
                    }
                }
                double diffX = Math.Abs(llsurf.X - llopening.X);
                double diffY = Math.Abs(llsurf.Y - llopening.Y);
                Vector.MemorySafe_CartCoord LLeft = new Vector.MemorySafe_CartCoord(diffX, diffY, 0);
                cp = makegbCartesianPt(LLeft);
            }
            //plane does not reside on a primary axis
            else
            {
                //I will deal with this later
                //have to factor in what is a "roof" or "floor" or "wall" based on the default tilt settings
            }
            ll.cp = cp;
            ll.indices.Add(surfindex);
            ll.indices.Add(opindex);
            return ll;
        }
        //April 11, 2014
        //This is the algorithm that attempts to find matches of edges on the enclosure.  It is used by all the Check Enclosure routines.
        //by Chien Harriman - Carmel Software Corporation
        public static DOEgbXMLPhase2Report MatchEdges(Dictionary<int, Vector.EdgeFamily> uniqueedges, List<string> ml, DOEgbXMLPhase2Report report, string spaceid)
        {
            try
            {
                int totaledgect = 0;
                int matchededges = 0;
                string lastedgenm = "";
                int surfedgect = 0;
                foreach (KeyValuePair<int, Vector.EdgeFamily> edgekp in uniqueedges)
                {
                    //a way to count edges
                    if (edgekp.Value.sbdec != lastedgenm)
                    {
                        //reset
                        lastedgenm = edgekp.Value.sbdec;
                        surfedgect = 0;
                    }
                    //here is the easiest case where there is only one related edge
                    //we know this must be a perfect match, or entirely envelopes the edge
                    if (edgekp.Value.relatedEdges.Count() == 1)
                    {
                        Vector.MemorySafe_CartCoord edgestart = edgekp.Value.startendpt[0];
                        Vector.MemorySafe_CartCoord edgeend = edgekp.Value.startendpt[1];
                        Vector.MemorySafe_CartCoord relstart = edgekp.Value.relatedEdges[0].startendpt[0];
                        Vector.MemorySafe_CartCoord relend = edgekp.Value.relatedEdges[0].startendpt[1];
                        //if the lengths are the same, then they should match perfectly.
                        //this is a valid conclusion because we already have identified that they aligh and
                        //are in the same space.
                        double edgeX = edgestart.X - edgeend.X;
                        double edgeY = edgestart.Y - edgeend.Y;
                        double edgeZ = edgestart.Z - edgeend.Z;
                        Vector.MemorySafe_CartVect edgev = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                        double edgemag = Vector.VectorMagnitude(edgev);

                        double relX = relstart.X - relend.X;
                        double relY = relstart.Y - relend.Y;
                        double relZ = relstart.Z - relend.Z;
                        Vector.MemorySafe_CartVect relv = new Vector.MemorySafe_CartVect(relX, relY, relZ);
                        double relmag = Vector.VectorMagnitude(relv);
                        //do the check here to see if the two edges (current and related) are the same length
                        if (Math.Abs(relmag - edgemag) < report.coordtol)
                        {

                            //should match perfectly
                            ml.Add(edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " should have perfectly matched coordinates.");
                            List<bool> match = new List<bool>();
                            double tol = report.tolerance;
                            for (int i = 0; i < 2; i++)
                            {
                                Vector.MemorySafe_CartCoord p1 = edgekp.Value.relatedEdges[0].startendpt[i];
                                for (int j = 0; j < 2; j++)
                                {
                                    string x = p1.X.ToString();
                                    string y = p1.Y.ToString();
                                    string z = p1.Z.ToString();
                                    string coordstr = "(" + x + "," + y + "," + z + ")";
                                    Vector.MemorySafe_CartCoord p2 = edgekp.Value.startendpt[j];
                                    if (p2.X == p1.X && p2.Y == p1.Y && p2.Z == p1.Z)
                                    {
                                        match.Add(true);
                                        ml.Add("PERFECT MATCH: " + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " Coordinate " + coordstr);
                                    }
                                    else if (Math.Abs(p2.X - p1.X) < tol && Math.Abs(p2.Y - p1.Y) < report.coordtol && Math.Abs(p2.Z - p1.Z) < report.coordtol)
                                    {
                                        match.Add(true);
                                        ml.Add("MATCH: " + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " Coordinate " + coordstr);
                                        report.passOrFail = false;
                                    }
                                }
                            }
                            if (match.Count() == 2)
                            {
                                ml.Add("PASS: "******" Edge " + surfedgect.ToString() + " forms a tight enclosure with its neighbor.");
                                report.passOrFail = true;
                                //we +2 here because the related edge is not recorded
                                totaledgect += 2;
                                matchededges += 2;
                            }
                            else
                            {
                                ml.Add("FAIL: " + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " does not form a tight enclosure with its neighbor.");
                                report.passOrFail = false;
                                //we +2 here because the related edge is not recorded
                                totaledgect += 2;
                                matchededges += 0;
                            }
                        }
                        //April 7 2014
                        //it is safe to conclude that the the two are related, but they overlap.  In this case, since there is only one neighbor
                        //it should be the case that one edge entirely envelops the other edge.
                        //this edge, has to be the one that is enveloped, because it only has one related edge, by convention
                        else
                        {
                            ml.Add(edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " should be enclosed by its neighboring edge.");
                            //es--------------ee
                            //rs-------------------re
                            if (Math.Abs(edgestart.X - relstart.X) <= report.coordtol && Math.Abs(edgestart.Y - relstart.Y) <= report.coordtol && Math.Abs(edgestart.Z - relstart.Z) <= coordtol)
                            {
                                string x = edgestart.X.ToString();
                                string y = edgestart.Y.ToString();
                                string z = edgestart.Z.ToString();
                                string coordstr = "(" + x + "," + y + "," + z + ")";
                                ml.Add("MATCH: " + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " Coordinate " + coordstr);
                                double Cx = edgeend.X - relstart.X;
                                double Cy = edgeend.Y - relstart.Y;
                                double Cz = edgeend.Z - relstart.Z;
                                Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);

                                double Dx = edgeend.X - relend.X;
                                double Dy = edgeend.Y - relend.Y;
                                double Dz = edgeend.Z - relend.Z;
                                Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);

                                double dotend = Vector.DotProductMag(C, D);
                                //both of these dot products should point in opposite directions, proving the edge is entirely enveloped
                                if (Math.Abs(dotend) - 1 <= report.vectorangletol)
                                {
                                    ml.Add("PASS" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor forms a tight enclosure with its neighbor.");
                                }
                                else
                                {
                                    ml.Add("FAIL" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + "overlapping neighbor does not form a tight enclosure with its neighbor.");
                                    report.passOrFail = false;
                                }
                            }
                            //es-----------------ee
                            //re--------------------------rs
                            else if (Math.Abs(edgestart.X - relend.X) <= report.coordtol && Math.Abs(edgestart.Y - relend.Y) <= report.coordtol && Math.Abs(edgestart.Z - relend.Z) <= coordtol)
                            {
                                string x = edgestart.X.ToString();
                                string y = edgestart.Y.ToString();
                                string z = edgestart.Z.ToString();
                                string coordstr = "(" + x + "," + y + "," + z + ")";
                                ml.Add("MATCH: " + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " Coordinate " + coordstr);
                                double Cx = edgeend.X - relstart.X;
                                double Cy = edgeend.Y - relstart.Y;
                                double Cz = edgeend.Z - relstart.Z;
                                Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);

                                double Dx = edgeend.X - relend.X;
                                double Dy = edgeend.Y - relend.Y;
                                double Dz = edgeend.Z - relend.Z;
                                Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);

                                double dotend = Vector.DotProductMag(C, D);
                                //both of these dot products should point in opposite directions, proving the edge is entirely enveloped
                                if (Math.Abs(dotend) - 1 <= report.vectorangletol)
                                {
                                    ml.Add("PASS" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor forms a tight enclosure with its neighbor.");
                                    totaledgect += 1;
                                    matchededges += 1;
                                }
                                else
                                {
                                    ml.Add("FAIL" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor does not form a tight enclosure with its neighbor.");
                                    report.passOrFail = false;
                                    totaledgect += 1;
                                    matchededges += 0;
                                }
                            }
                            //ee-----------------es
                            //rs--------------------------re
                            else if (Math.Abs(edgeend.X - relstart.X) <= report.coordtol && Math.Abs(edgeend.Y - relstart.Y) <= report.coordtol && Math.Abs(edgeend.Z - relstart.Z) <= coordtol)
                            {
                                string x = edgeend.X.ToString();
                                string y = edgeend.Y.ToString();
                                string z = edgeend.Z.ToString();
                                string coordstr = "(" + x + "," + y + "," + z + ")";
                                ml.Add("MATCH: " + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " Coordinate " + coordstr);
                                double Ax = edgestart.X - relstart.X;
                                double Ay = edgestart.Y - relstart.Y;
                                double Az = edgestart.Z - relstart.Z;
                                Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);

                                double Bx = edgestart.X - relend.X;
                                double By = edgestart.Y - relend.Y;
                                double Bz = edgestart.Z - relend.Z;
                                Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);

                                double dotstart = Vector.DotProductMag(A, B);
                                //both of these dot products should point in opposite directions, proving the edge is entirely enveloped
                                if (Math.Abs(dotstart) - 1 <= report.vectorangletol)
                                {
                                    ml.Add("PASS" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor forms a tight enclosure with its neighbor.");
                                    totaledgect += 1;
                                    matchededges += 1;
                                }
                                else
                                {
                                    ml.Add("FAIL" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor does not form a tight enclosure with its neighbor.");
                                    report.passOrFail = false;
                                    totaledgect += 1;
                                    matchededges += 0;
                                }
                            }
                            //ee-----------------es
                            //re--------------------------rs
                            else if (Math.Abs(edgeend.X - relend.X) <= report.coordtol && Math.Abs(edgeend.Y - relend.Y) <= report.coordtol && Math.Abs(edgeend.Z - relend.Z) <= coordtol)
                            {
                                string x = edgeend.X.ToString();
                                string y = edgeend.Y.ToString();
                                string z = edgeend.Z.ToString();
                                string coordstr = "(" + x + "," + y + "," + z + ")";
                                ml.Add("MATCH: " + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " Coordinate " + coordstr);
                                double Ax = edgestart.X - relstart.X;
                                double Ay = edgestart.Y - relstart.Y;
                                double Az = edgestart.Z - relstart.Z;
                                Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);

                                double Bx = edgestart.X - relend.X;
                                double By = edgestart.Y - relend.Y;
                                double Bz = edgestart.Z - relend.Z;
                                Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);

                                double dotstart = Vector.DotProductMag(A, B);
                                //both of these dot products should point in opposite directions, proving the edge is entirely enveloped
                                if (Math.Abs(dotstart) - 1 <= report.vectorangletol)
                                {
                                    ml.Add("PASS" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor forms a tight enclosure with its neighbor.");
                                    totaledgect += 1;
                                    matchededges += 1;
                                }
                                else
                                {
                                    ml.Add("FAIL" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor does not form a tight enclosure with its neighbor.");
                                    report.passOrFail = false;
                                    totaledgect += 1;
                                    matchededges += 0;
                                }
                            }
                            //overlapping edges
                            else
                            {
                                ml.Add(edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " is overlapped at both ends by its neighboring edge.");
                                double Ax = edgestart.X - relstart.X;
                                double Ay = edgestart.Y - relstart.Y;
                                double Az = edgestart.Z - relstart.Z;
                                Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);

                                double Bx = edgestart.X - relend.X;
                                double By = edgestart.Y - relend.Y;
                                double Bz = edgestart.Z - relend.Z;
                                Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);

                                double Cx = edgeend.X - relstart.X;
                                double Cy = edgeend.Y - relstart.Y;
                                double Cz = edgeend.Z - relstart.Z;
                                Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);

                                double Dx = edgeend.X - relend.X;
                                double Dy = edgeend.Y - relend.Y;
                                double Dz = edgeend.Z - relend.Z;
                                Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);

                                double dotstart = Vector.DotProductMag(A, B);
                                double dotend = Vector.DotProductMag(C, D);
                                //both of these dot products should point in opposite directions, proving the edge is entirely enveloped
                                if (Math.Abs(dotstart) - 1 <= report.vectorangletol && Math.Abs(dotend) - 1 <= report.vectorangletol)
                                {
                                    ml.Add("PASS" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor forms a tight enclosure with its neighbor.");
                                    totaledgect += 1;
                                    matchededges += 1;
                                }
                                else
                                {
                                    ml.Add("FAIL" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor does not form a tight enclosure with its neighbor.");
                                    report.passOrFail = false;
                                    totaledgect += 1;
                                    matchededges += 0;
                                }
                            }
                        }

                    }
                    else if (edgekp.Value.relatedEdges.Count() > 1)
                    {
                        ml.Add(edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " has " + edgekp.Value.relatedEdges.Count() + " neighboring edges.");
                        //more robust testing
                        Vector.EdgeFamily[] orderededges = new Vector.EdgeFamily[edgekp.Value.relatedEdges.Count()];
                        //align the related edges
                        orderededges = AlignEdges(orderededges, edgekp.Value, coordtol);

                        int coordcount = 0;
                        double segmentslength = 0;
                        int lastct = edgekp.Value.relatedEdges.Count() * 2 - 2;
                        Vector.CartCoord st = new Vector.CartCoord();
                        Vector.CartCoord end = new Vector.CartCoord();
                        foreach (Vector.EdgeFamily edge in orderededges)
                        {

                            if (coordcount == 0)
                            {
                                st.X = edge.startendpt[0].X;
                                st.Y = edge.startendpt[0].Y;
                                st.Z = edge.startendpt[0].Z;
                            }

                            if (coordcount == lastct)
                            {
                                end.X = edge.startendpt[1].X;
                                end.Y = edge.startendpt[1].Y;
                                end.Z = edge.startendpt[1].Z;
                            }
                            Vector.MemorySafe_CartVect v = Vector.CreateMemorySafe_Vector(edge.startendpt[0], edge.startendpt[1]);
                            double mag = Vector.VectorMagnitude(v);
                            segmentslength += mag;
                            coordcount += 2;
                        }
                        Vector.MemorySafe_CartVect v2 = Vector.CreateMemorySafe_Vector(edgekp.Value.startendpt[0], edgekp.Value.startendpt[1]);
                        double mag2 = Vector.VectorMagnitude(v2);
                        if (Math.Abs(segmentslength - mag2) < report.lengthtol)
                        {
                            ml.Add(edgekp.Value.sbdec + ":PASS:Multiple Overlapping edges properly match.");
                        }
                        else
                        {
                            //then something is wrong.
                            ml.Add(edgekp.Value.sbdec + ":FAIL:Overlapping edges do not match as expected.");
                            report.passOrFail = false;
                        }

                    }
                    else if (edgekp.Value.relatedEdges.Count() == 0)
                    {
                        //something is wrong
                        ml.Add(edgekp.Value.sbdec + "FAIL:" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " has no reported neighboring edges.");
                        report.passOrFail = false;
                    }
                    surfedgect += 1;
                }
                report.MessageList[spaceid] = ml;
                //all edges align = true
                if (report.passOrFail)
                {
                    report.longMsg = "TEST PASSED: " + totaledgect + " edges in the gbXML file.  " + matchededges + " edges found with ideal alignment.";
                }
                //all edges align = false
                else
                {
                    report.longMsg = "TEST FAILED: " + totaledgect + " edges in the gbXML file.  " + matchededges + " edges found with ideal alignment.";
                }
                return report;

            }
            catch (Exception e)
            {
                report.longMsg = ("ERROR, we have run into an unexpected issue:" + e.ToString());
                report.passOrFail = false;
                return report;
            }
        }
        private DOEgbXMLReportingObj GetPossibleOpeningMatches(OpeningDefinitions standardOpening, List<OpeningDefinitions> TestOpenings, DOEgbXMLReportingObj report)
        {
            report.testSummary = "This test checks the geometric accuracy of each opening in your test file against the standard file.";
            report.testSummary += "  For each opening (window, door, skylight) this validator seeks out a similar opening in your test file and";
            //match surfaces at this stage so we know which surface is associated with the window
            report.testSummary += "  The validator first seeks to find all openings that have a parent surface (roof, external wall, etc.) with";
            report.testSummary += " the same azimuth and tilt.  If it finds more than one opening candidate that matches the parent surface tilt and azimuth,";
            report.testSummary += " the validator will make all of these openings possible candidates.";
            report.testSummary += "  The validator then takes these candidates and looks at their polyloop coordinates. ";
            report.testSummary += " and will keep only those openings that have similar polyLoop coordinates";
            report.testSummary += " Next it matches the area, then the width and height, if applicable, and finally checks the insertion";
            report.testSummary += " point coordinates.  If all of these come back within tolerance, the opening has found a match.";
            report.testSummary += "  Otherwise, the test will fail.";
            report.testSummary += "  The summary at the bottom of the page will show the logic of how the test arrived at its conclusion.";


            bool matchedParentAz = false;
            bool matchedParentTilt = false;
            bool matchedPolyLoopCoords = false;

            List<OpeningDefinitions> possibleMatches = new List<OpeningDefinitions>();
            List<OpeningDefinitions> possibleMatches2 = new List<OpeningDefinitions>();
            try
            {
                //find match of parent surface 
                //try matching based on the surface matches
                //if that does not work, then just try to match the parent tilt and parent azimuth to one another
                int i = 0;
                report.MessageList.Add("Starting Parent Azimuth and Tilt Match test....");
                report.MessageList.Add("</br>");
                while (true)
                {
                    //reset
                    matchedParentAz = false;
                    matchedParentTilt = false;
                    OpeningDefinitions testOpening = TestOpenings[i];
                    if (testOpening.ParentAzimuth == standardOpening.ParentAzimuth && testOpening.ParentTilt == standardOpening.ParentTilt)
                    {
                        report.MessageList.Add("Candidate Found.  Test file opening has EXACTLY matched its parent surface azimuth and tilt with the standard opening parent surface azimuth and tilt.");
                        report.MessageList.Add("Test Opening " + testOpening.OpeningId + "'s [parent, azimuth, tilt]: [" + testOpening.ParentSurfaceId + ", " + testOpening.ParentAzimuth + ", " + testOpening.ParentTilt + "]");
                        report.MessageList.Add("Standard Opening " + standardOpening.OpeningId + "'s [parent, azimuth, tilt]: [" + standardOpening.ParentSurfaceId + "," + standardOpening.ParentAzimuth + ", " + standardOpening.ParentTilt + "]");

                        matchedParentAz = true;
                        matchedParentTilt = true;
                    }
                    else
                    {
                        double azDifference = Math.Abs(testOpening.ParentAzimuth - standardOpening.ParentAzimuth);
                        double tiltDifference = Math.Abs(testOpening.ParentTilt - standardOpening.ParentTilt);
                        if (azDifference < DOEgbXMLBasics.Tolerances.SurfaceAzimuthTolerance && tiltDifference < DOEgbXMLBasics.Tolerances.SurfaceTiltTolerance)
                        {
                            report.MessageList.Add("Candidate found.  Test file opening HAS matched WITHIN ALLOWABLE TOLERANCE its parent surface azimuth and tilt with the standard opening parent surface azimuth and tilt.");
                            report.MessageList.Add("Test Opening " + testOpening.OpeningId + "'s [parent, azimuth, tilt]: [" + testOpening.ParentSurfaceId + ", " + testOpening.ParentAzimuth + ", " + testOpening.ParentTilt + "]");
                            report.MessageList.Add("Standard Opening " + standardOpening.OpeningId + "'s [parent, azimuth, tilt]: [" + standardOpening.ParentSurfaceId + "," + standardOpening.ParentAzimuth + ", " + standardOpening.ParentTilt + "]");

                            matchedParentAz = true;
                            matchedParentTilt = true;
                        }
                        else
                        {
                            report.MessageList.Add("Candidate rejected.  Test file opening HAS NOT matched WITHIN ALLOWABLE TOLERANCE its parent surface azimuth and tilt with the standard opening parent surface azimuth and tilt.");
                            report.MessageList.Add("Test Opening " + testOpening.OpeningId + "'s [parent, azimuth, tilt]: [" + testOpening.ParentSurfaceId + ", " + testOpening.ParentAzimuth + ", " + testOpening.ParentTilt + "]");
                            report.MessageList.Add("Standard Opening " + standardOpening.OpeningId + "'s [parent, azimuth, tilt]: [" + standardOpening.ParentSurfaceId + "," + standardOpening.ParentAzimuth + ", " + standardOpening.ParentTilt + "]");
                            report.MessageList.Add("</br>");
                        }
                    }

                    if (matchedParentAz && matchedParentTilt)
                    {
                        possibleMatches.Add(testOpening);
                        report.MessageList.Add("Successful Match Candidate Identified.");
                        report.MessageList.Add("</br>");
                    }
                    i++;

                    if (i == TestOpenings.Count)
                    {
                        if (possibleMatches.Count == 0)
                        {
                            //no candidates found
                            report.MessageList.Add("No candidates found in the test file to match standard file opening " + standardOpening.OpeningId);
                            report.passOrFail = false;
                            report.longMsg = "Test to find suitable opening candidate in the test file has failed.  Parent Tilt and Azimuth matches could not be established.";
                            //no need to go further
                            return report;
                        }
                        break;
                    }

                }
                report.MessageList.Add("</br>");
                report.MessageList.Add("Starting Opening PolyLoop Coordinate Match test.........");
                i = 0;
                while (true)
                {
                    OpeningDefinitions testOpening = possibleMatches[i];
                    //continue to next test

                    //continue the next batch of tests
                    //polyloop absolute coordinates
                    //check the polyLoop coordinates
                    foreach (Vector.MemorySafe_CartCoord standardPolyLoopCoord in standardOpening.PlCoords)
                    {
                        report = GetOpeningPolyLoopCoordMatch(standardPolyLoopCoord, testOpening, report, standardOpening.OpeningId);
                        if (report.passOrFail)
                        {
                            matchedPolyLoopCoords = true;
                            continue;
                        }
                        else
                        {
                            report.MessageList.Add("Could not find a coordinate match in the test opening polyloop.");
                            matchedPolyLoopCoords = false;
                            break;
                        }
                    }
                    //if matchePolyLoopCoords comes back true, then a candidate has been found that matches all polyloop coords within tolerance
                    if (matchedPolyLoopCoords == true)
                    {
                        possibleMatches2.Add(testOpening);
                    }
                    i++;

                    if (i == possibleMatches.Count)
                    {
                        if (possibleMatches2.Count == 0)
                        {
                            report.MessageList.Add("No candidates found in the test file to match standard file opening " + standardOpening.OpeningId);
                            report.passOrFail = false;
                            report.longMsg = "Test to find suitable opening candidate in the test file has failed.  Parent Tilt and Azimuth matches were established, but these candidates did not produce good polyLoop coordinate matches.";
                            //no need to go further
                            return report;
                        }
                        break;
                    }
                }
                //next set of tests 
                //polyloop area tests
                report.MessageList.Add("</br>");
                report.MessageList.Add("Starting Opening Surface Area Match test.........");
                possibleMatches.Clear();
                i = 0;
                while (true)
                {
                    #region
                    OpeningDefinitions testOpening = possibleMatches2[i];

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

                        }
                        double area = Math.Abs(GetAreaFrom2DPolyLoop(coordList));
                        standardOpening.surfaceArea = area;
                        if (area == -999)
                        {
                            //these messages should never occur and are a sign of some sort of serious, as of yet unknown error
                            //March 20 2013
                            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");
                            report.longMsg = "Fatal error.  Please contact gbXML administrator";
                            report.passOrFail = false;
                            return report;

                        }
                        double testOpeningArea = 0;

                        if (Math.Abs(testOpening.PlRHRVector.X) == 1 && testOpening.PlRHRVector.Y == 0 &&
                                testOpening.PlRHRVector.Z == 0)
                        {
                            List<Vector.MemorySafe_CartCoord> testCoordList = new List<Vector.MemorySafe_CartCoord>();
                            foreach (Vector.MemorySafe_CartCoord coord in testOpening.PlCoords)
                            {
                                Vector.MemorySafe_CartCoord simple = new Vector.MemorySafe_CartCoord(0, coord.Y, coord.Z);
                                testCoordList.Add(simple);
                            }
                            testOpeningArea = Math.Abs(GetAreaFrom2DPolyLoop(testCoordList));
                            testOpening.surfaceArea = testOpeningArea;
                            if (testOpeningArea == -999)
                            {
                                //these messages should never occur and are a sign of some sort of serious, as of yet unknown error
                                //March 20 2013
                                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");
                                report.longMsg = "Fatal error.  Please contact gbXML administrator";
                                report.passOrFail = false;
                                return report;
                            }
                            double difference = Math.Abs(area) - Math.Abs(testOpeningArea);
                            if (difference < Math.Abs(area) * DOEgbXMLBasics.Tolerances.OpeningAreaPercentageTolerance)
                            {

                                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 Opening: " + testOpening.OpeningId + " polyloop surface area matches the polyLoop surface area of the standard opening: " + standardOpening.OpeningId + " exactly.");
                                    possibleMatches.Add(testOpening);
                                }
                                else
                                {
                                    report.MessageList.Add("The test Opening: " + testOpening.OpeningId + " polyloop surface area matches the polyLoop surface area of the standard opening: " + standardOpening.OpeningId + " within the allowable area percentage tolerance.");
                                    possibleMatches.Add(testOpening);
                                }
                            }
                            else
                            {
                                report.MessageList.Add("The standard file opening cannot find a match for its surface area of opening: " + standardOpening.OpeningId + " through a comparison of its polyloop coordinates with test opening: " + testOpening.OpeningId);
                                //don't return here, it will be returned below
                            }
                        }
                        else
                        {
                            //by definition, the Window opening should always use coordinates that create a normal vector that points in the 
                            //positive or negative X direction.  If the test file does not do this, then this is in violation of the 
                            //gbXML spec
                            report.longMsg = ("This test has failed because the test opening" + testOpening.OpeningId + "has polyloop coordinates ");
                            report.longMsg += (" that do not have the same normal vector as the standard opening.");
                            report.passOrFail = false;
                        }
                    }
                    else if (standardOpening.PlRHRVector.X == 0 && Math.Abs(standardOpening.PlRHRVector.Y) == 1 && standardOpening.PlRHRVector.Z == 0)
                    {
                        List<Vector.MemorySafe_CartCoord> coordList = new List<Vector.MemorySafe_CartCoord>();
                        foreach (Vector.MemorySafe_CartCoord coord in standardOpening.PlCoords)
                        {
                            //only take the Y and Z coordinates and throw out the X because we can assume that they are all the same
                            Vector.MemorySafe_CartCoord simple = new Vector.MemorySafe_CartCoord(coord.X, 0, coord.Z);
                            coordList.Add(simple);

                        }
                        double area = Math.Abs(GetAreaFrom2DPolyLoop(coordList));
                        standardOpening.surfaceArea = area;
                        if (area == -999)
                        {
                            //these messages should never occur and are a sign of some sort of serious, as of yet unknown error
                            //March 20 2013
                            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");
                            report.longMsg = "Fatal error.  Please contact gbXML administrator";
                            report.passOrFail = false;
                            return report;

                        }
                        double testOpeningArea = 0;

                        if (testOpening.PlRHRVector.X == 0 && Math.Abs(testOpening.PlRHRVector.Y) == 1 &&
                                testOpening.PlRHRVector.Z == 0)
                        {
                            List<Vector.MemorySafe_CartCoord> testCoordList = new List<Vector.MemorySafe_CartCoord>();
                            foreach (Vector.MemorySafe_CartCoord coord in testOpening.PlCoords)
                            {
                                Vector.MemorySafe_CartCoord simple = new Vector.MemorySafe_CartCoord(coord.X, 0, coord.Z);
                                testCoordList.Add(simple);
                            }
                            testOpeningArea = Math.Abs(GetAreaFrom2DPolyLoop(testCoordList));
                            testOpening.surfaceArea = testOpeningArea;
                            if (testOpeningArea == -999)
                            {
                                //these messages should never occur and are a sign of some sort of serious, as of yet unknown error
                                //March 20 2013
                                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");
                                report.longMsg = "Fatal error.  Please contact gbXML administrator";
                                report.passOrFail = false;
                                return report;
                            }
                            double difference = Math.Abs(area) - Math.Abs(testOpeningArea);
                            if (difference < Math.Abs(area) * DOEgbXMLBasics.Tolerances.OpeningAreaPercentageTolerance)
                            {

                                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 Opening: " + testOpening.OpeningId + " polyloop surface area matches the polyLoop surface area of the standard Opening: " + standardOpening.OpeningId + " exactly.");
                                    possibleMatches.Add(testOpening);
                                }
                                else
                                {
                                    report.MessageList.Add("The test Opening: " + testOpening.OpeningId + " polyloop surface area matches the polyLoop surface area of the standard Opening: " + standardOpening.OpeningId + " within the allowable area percentage tolerance.");
                                    possibleMatches.Add(testOpening);
                                }
                            }
                            else
                            {
                                report.MessageList.Add("The standard file opening cannot find a match for its surface area of Opening: " + standardOpening.OpeningId + " through a comparison of its polyloop coordinates with test Opening: " + testOpening.OpeningId);
                                //don't return here, it will be returned below
                            }
                        }
                        else
                        {
                            //by definition, the Window opening should always use coordinates that create a normal vector that points in the 
                            //positive or negative X direction.  If the test file does not do this, then this is in violation of the 
                            //gbXML spec
                            report.longMsg = ("This test has failed because the test opening" + testOpening.OpeningId + "has polyloop coordinates ");
                            report.longMsg += (" that do not have the same normal vector as the standard opening.");
                            report.passOrFail = false;
                        }
                    }
                    else if (standardOpening.PlRHRVector.X == 0 && standardOpening.PlRHRVector.Y == 0 && Math.Abs(standardOpening.PlRHRVector.Z) == 1)
                    {
                        List<Vector.MemorySafe_CartCoord> coordList = new List<Vector.MemorySafe_CartCoord>();
                        foreach (Vector.MemorySafe_CartCoord coord in standardOpening.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 simple = new Vector.MemorySafe_CartCoord(coord.X, coord.Y, 0);
                            coordList.Add(simple);

                        }
                        double area = Math.Abs(GetAreaFrom2DPolyLoop(coordList));
                        standardOpening.surfaceArea = area;
                        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 testOpeningArea = 0;

                        if (testOpening.PlRHRVector.X == 0 && testOpening.PlRHRVector.Y == 0 &&
                                                        Math.Abs(testOpening.PlRHRVector.Z) == 1)
                        {
                            List<Vector.MemorySafe_CartCoord> testCoordList = new List<Vector.MemorySafe_CartCoord>();
                            foreach (Vector.MemorySafe_CartCoord coord in testOpening.PlCoords)
                            {
                                Vector.MemorySafe_CartCoord simple = new Vector.MemorySafe_CartCoord(coord.X, coord.Y, 0);
                                testCoordList.Add(simple);
                            }
                            testOpeningArea = Math.Abs(GetAreaFrom2DPolyLoop(testCoordList));
                            testOpening.surfaceArea = testOpeningArea;
                            if (testOpeningArea == -999)
                            {
                                //these messages should never occur and are a sign of some sort of serious, as of yet unknown error
                                //March 20 2013
                                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");
                                report.longMsg = "Fatal error.  Please contact gbXML administrator";
                                report.passOrFail = false;
                                return report;
                            }
                            double difference = Math.Abs(area) - Math.Abs(testOpeningArea);
                            if (difference < Math.Abs(area) * DOEgbXMLBasics.Tolerances.OpeningAreaPercentageTolerance)
                            {

                                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 Opening: " + testOpening.OpeningId + " polyloop surface area matches the polyLoop surface area of the standard Opening: " + standardOpening.OpeningId + " exactly.");
                                    possibleMatches.Add(testOpening);
                                }
                                else
                                {
                                    report.MessageList.Add("The test Opening: " + testOpening.OpeningId + " polyloop surface area matches the polyLoop surface area of the standard Opening: " + standardOpening.OpeningId + " within the allowable area percentage tolerance.");
                                    possibleMatches.Add(testOpening);
                                }
                            }
                            else
                            {
                                report.MessageList.Add("The standard file opening cannot find a match for its surface area of Opening: " + standardOpening.OpeningId + " through a comparison of its polyloop coordinates with test Opening: " + testOpening.OpeningId);
                                //don't return here, it will be returned below
                            }
                        }
                        else
                        {
                            //by definition, the Window opening should always use coordinates that create a normal vector that points in the 
                            //positive or negative X direction.  If the test file does not do this, then this is in violation of the 
                            //gbXML spec
                            report.longMsg = ("This test has failed because the test opening" + testOpening.OpeningId + "has polyloop coordinates ");
                            report.longMsg += (" that do not have the same normal vector as the standard opening.");
                            report.passOrFail = false;
                        }

                    }
                    //the opening is not aligned along a reference frame axis
                    else
                    {
                        report.MessageList.Add("This standard Opening is not aligned along a reference plane axis, and will be rotated into a new coordinate frame.");
                        report.MessageList.Add("Commencing rotation to 2-D.");
                        //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 tempY = new Vector.CartVect();
                        Vector.MemorySafe_CartVect globalReferenceX = new Vector.MemorySafe_CartVect(1,0,0);
                        tempY = Vector.CrossProductNVRetMSMS(standardOpening.PlRHRVector, globalReferenceX);
                        tempY = Vector.UnitVector(tempY);
                        Vector.MemorySafe_CartVect localY = Vector.convertToMemorySafeVector(tempY);

                        //new X axis is the localY cross the surface normal vector
                        Vector.CartVect tempX = new Vector.CartVect();
                        tempX = Vector.CrossProductNVRetMSMS(localY, standardOpening.PlRHRVector);
                        tempX = Vector.UnitVector(tempX);
                        Vector.MemorySafe_CartVect localX = Vector.convertToMemorySafeVector(tempX);

                        //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 < standardOpening.PlCoords.Count; j++)
                        {
                            //randomly assigns the first polyLoop coordinate as the origin
                            Vector.MemorySafe_CartCoord origin = standardOpening.PlCoords[0];
                            //captures the components of a vector drawn from the new origin to the 
                            Vector.CartVect distance = new Vector.CartVect();
                            distance.X = standardOpening.PlCoords[j].X - origin.X;
                            distance.Y = standardOpening.PlCoords[j].Y - origin.Y;
                            distance.Z = standardOpening.PlCoords[j].Z - origin.Z;
                            Vector.CartCoord translatedPt = new Vector.CartCoord();
                            //x coordinate is distance vector dot the new local X axis
                            translatedPt.X = distance.X * localX.X + distance.Y * localX.Y + distance.Z * localX.Z;
                            //y coordinate is distance vector dot the new local Y axis
                            translatedPt.Y = distance.X * localY.X + distance.Y * localY.Y + distance.Z * localY.Z;
                            translatedPt.Z = 0;
                            Vector.MemorySafe_CartCoord memsafetranspt = Vector.convertToMemorySafeCoord(translatedPt);
                            translatedCoordinates.Add(memsafetranspt);

                        }
                        double area = GetAreaFrom2DPolyLoop(translatedCoordinates);
                        standardOpening.surfaceArea = area;
                        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
                        Vector.CartVect testtempY = new Vector.CartVect();
                        Vector.MemorySafe_CartVect testglobalReferenceX = new Vector.MemorySafe_CartVect(1,0,0);

                        testtempY = Vector.CrossProductNVRetMSMS(testOpening.PlRHRVector, testglobalReferenceX);
                        testtempY = Vector.UnitVector(tempY);
                        Vector.MemorySafe_CartVect testlocalY = Vector.convertToMemorySafeVector(testtempY);
                        

                        //new X axis is the localY cross the surface normal vector
                        Vector.CartVect testtempX = new Vector.CartVect();
                        testtempX = Vector.CrossProductNVRetMSMS(testlocalY, testOpening.PlRHRVector);
                        testtempX = Vector.UnitVector(testtempX);
                        Vector.MemorySafe_CartVect testlocalX = Vector.convertToMemorySafeVector(testtempX);


                        //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 < testOpening.PlCoords.Count; j++)
                        {
                            //randomly assigns the first polyLoop coordinate as the origin
                            Vector.MemorySafe_CartCoord origin = testOpening.PlCoords[0];
                            //captures the components of a vector drawn from the new origin to the 
                            Vector.CartVect distance = new Vector.CartVect();
                            distance.X = testOpening.PlCoords[j].X - origin.X;
                            distance.Y = testOpening.PlCoords[j].Y - origin.Y;
                            distance.Z = testOpening.PlCoords[j].Z - origin.Z;
                            Vector.CartCoord translatedPt = new Vector.CartCoord();
                            //x coordinate is distance vector dot the new local X axis
                            translatedPt.X = distance.X * localX.X + distance.Y * localX.Y + distance.Z * localX.Z;
                            //y coordinate is distance vector dot the new local Y axis
                            translatedPt.Y = distance.X * localY.X + distance.Y * localY.Y + distance.Z * localY.Z;
                            translatedPt.Z = 0;
                            Vector.MemorySafe_CartCoord memsafetranspt = Vector.convertToMemorySafeCoord(translatedPt);
                            testtranslatedCoordinates.Add(memsafetranspt);

                        }
                        double testOpeningArea = GetAreaFrom2DPolyLoop(translatedCoordinates);
                        testOpening.surfaceArea = testOpeningArea;
                        if (testOpeningArea == -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");
                        }
                        double difference = Math.Abs(area) - Math.Abs(testOpeningArea);
                        if (difference < Math.Abs(area) * DOEgbXMLBasics.Tolerances.OpeningAreaPercentageTolerance)
                        {

                            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 Opening: " + testOpening.OpeningId + " polyloop surface area matches the polyLoop surface area of the standard Opening: " + standardOpening.OpeningId + " exactly.");
                                possibleMatches.Add(testOpening);
                            }
                            else
                            {
                                report.MessageList.Add("The test Opening: " + testOpening.OpeningId + " polyloop surface area matches the polyLoop surface area of the standard Opening: " + standardOpening.OpeningId + " within the allowable area percentage tolerance.");
                                possibleMatches.Add(testOpening);
                            }
                        }
                        else
                        {
                            report.MessageList.Add("The standard file opening cannot find a match for its surface area of Opening: " + standardOpening.OpeningId + " through a comparison of its polyloop coordinates with test Opening: " + testOpening.OpeningId);
                            //don't return here, it will be returned below
                        }

                    }
                    i++;
                    if (i == possibleMatches2.Count)
                    {
                        if (possibleMatches.Count == 0)
                        {
                            report.MessageList.Add("No area match could be found for standard opening: " + standardOpening.OpeningId + ".");
                            report.longMsg = "The search routine has ended and could not find a match for opening: " + standardOpening.OpeningId +
                                ".  Attempt to match the area of the standard file with test file openings failed.";
                            return report;

                        }
                        else
                        {
                            //you are good to go with some more matches
                            report.MessageList.Add("Area matching SUCCESS for standard file Opening id: " + standardOpening.OpeningId);
                            report.MessageList.Add("Commencing comparisons of height, width, and insertion point.");
                            break;
                        }
                    }

                    #endregion
                }
                //test the width and height, if applicable
                report.MessageList.Add("</br>");
                report.MessageList.Add("Starting Width and Height Match test.........");
                possibleMatches2.Clear();
                i = 0;
                //surface area using the coordinates of the polyloop.  We already assume that they are planar, as previously tested
                while (true)
                {
                    //see if the openings are regular
                    bool isStandardRegular = IsOpeningRegular(standardOpening);
                    bool isTestRegular = IsOpeningRegular(possibleMatches[i]);
                    //if they are...go ahead and use width and height, otherwise the values are not reliable
                    if (isStandardRegular)
                    {
                        //output something
                        if (isTestRegular)
                        {
                            //output something
                            //perform tests

                            OpeningDefinitions testOpening = possibleMatches[i];
                            double testWidth = testOpening.Width;
                            double standardWidth = standardOpening.Width;
                            double testHeight = testOpening.Height;
                            double standardHeight = standardOpening.Height;
                            double widthDifference = Math.Abs(testWidth - standardWidth);
                            double heightDiffefence = Math.Abs(testHeight - standardHeight);

                            if (widthDifference <= DOEgbXMLBasics.Tolerances.OpeningWidthTolerance)
                            {
                                if (widthDifference == 0)
                                {
                                    report.MessageList.Add("The test Opening: " + testOpening.OpeningId + " reported Width value matches the Width value of the standard Opening: " + standardOpening.OpeningId + " exactly.");
                                }
                                else
                                {
                                    report.MessageList.Add("The test Opening: " + testOpening.OpeningId + " reported Width value matches the Width value of the standard Opening: " + standardOpening.OpeningId + " within the allowable tolerance.");
                                }
                                //check the height
                                if (heightDiffefence <= DOEgbXMLBasics.Tolerances.OpeningHeightTolerance)
                                {
                                    if (heightDiffefence == 0)
                                    {
                                        report.MessageList.Add("The test Opening: " + testOpening.OpeningId + " reported Height value matches the Height value of the standard Opening: " + standardOpening.OpeningId + " exactly.");
                                        possibleMatches2.Add(testOpening);
                                    }
                                    else
                                    {
                                        report.MessageList.Add("The test Opening: " + testOpening.OpeningId + " reported Height value matches the Height value of the standard Opening: " + standardOpening.OpeningId + " within the allowable tolerance.");
                                        possibleMatches2.Add(testOpening);
                                    }
                                }
                                else
                                {
                                    //fail, did not match height
                                    report.MessageList.Add("The standard file Opening: " + standardOpening.OpeningId + "The standard file opening cannot find a match for its surface area of Opening: " + standardOpening.OpeningId + " after comparison its Height value with test opening: " + testOpening.OpeningId);
                                    report.passOrFail = false;
                                    continue;
                                }
                            }
                            else
                            {
                                //failed, did not match width
                                report.MessageList.Add("The standard file Opening: " + standardOpening.OpeningId + " cannot find a match for its width after comparison the width value of test Opening: " + testOpening.OpeningId);
                                report.passOrFail = false;
                                continue;
                            }
                        }
                        else
                        {
                            //let them know the the test opening is not a square or rectangle, but the standard file opening is
                            //go ahead and break out of the while loop because we aren't testing for width and height
                            report.MessageList.Add("The standard file Opening: " + standardOpening.OpeningId + " is a rectangle or square, but the test file Opening: " + standardOpening.OpeningId + " is not.  Cannot test for a valid width and height.");
                            report.MessageList.Add("Searching for another test Opening.");
                            continue;
                        }
                    }
                    else
                    {
                        //tell them that the widths and Heights will Not be checked
                        //because the standard file opening is not a square or rectangle
                        report.MessageList.Add("Will not be testing for the Width and Height values for standard Opening: " + standardOpening.OpeningId + ".  The Opening is not shaped like a rectangle or square.");
                        report.MessageList.Add("Going on to check insertion point accuracy.");
                        //needed to transfer values over to possibleMatches2, so deep copy
                        possibleMatches2 = new List<OpeningDefinitions>(possibleMatches);
                        break;
                    }
                    i++;
                    if (possibleMatches.Count == i)
                    {
                        //means that there is no match for width and height
                        if (possibleMatches2.Count == 0)
                        {
                            report.MessageList.Add("There is no match found for the width and height for Opening: " + standardOpening.OpeningId);
                            report.passOrFail = false;
                            report.longMsg = "The opening test has ended at the search for width and height values equal to standard Opening: " + standardOpening.OpeningId;
                            return report;
                        }
                        break;
                    }

                }
                report.MessageList.Add("</br>");
                report.MessageList.Add("Starting Insertion Point Coordinate Match test.........");
                possibleMatches.Clear();
                //test the insertion point coordinates
                i = 0;
                while (true)
                {
                    OpeningDefinitions testOpening = possibleMatches2[i];
                    double diffX = Math.Abs(testOpening.InsertionPoint.X - standardOpening.InsertionPoint.X);
                    double diffY = Math.Abs(testOpening.InsertionPoint.Y - standardOpening.InsertionPoint.Y);
                    double diffZ = Math.Abs(testOpening.InsertionPoint.Z - standardOpening.InsertionPoint.Z);

                    if (diffX <= DOEgbXMLBasics.Tolerances.OpeningSurfaceInsPtXTolerance && diffY <= DOEgbXMLBasics.Tolerances.OpeningSurfaceInsPtYTolerance &&
                        diffZ <= DOEgbXMLBasics.Tolerances.OpeningSurfaceInsPtZTolerance)
                    {
                        if (diffX == 0)
                        {
                            //perfect X coordinate match
                            report.MessageList.Add("Standard Opening: " + standardOpening.OpeningId + " has found a perfect match for its insertion point X-Coordinate when compared with test Opening: " + testOpening.OpeningId);
                            if (diffY == 0)
                            {
                                //perfect Y coordinate match
                                report.MessageList.Add("Standard Opening: " + standardOpening.OpeningId + " has found a perfect match for its insertion point Y-Coordinate when compared with test Opening: " + testOpening.OpeningId);
                                if (diffZ == 0)
                                {
                                    //perfect Z coordinate match
                                    report.MessageList.Add("Standard Opening: " + standardOpening.OpeningId + " has found a perfect match for its insertion point Z-Coordinate when compared with test Opening: " + testOpening.OpeningId);
                                    possibleMatches.Add(testOpening);

                                }
                                else
                                {
                                    // Z coordinate match
                                    report.MessageList.Add("Standard Opening: " + standardOpening.OpeningId + " has found a match within allowable tolerances for its insertion point Z-Coordinate when compared with Test opening: " + testOpening.OpeningId);
                                    //we continue because we search for other matches if there are any
                                    possibleMatches.Add(testOpening);

                                }
                            }
                            else
                            {
                                //y-coordinate is within tolerance
                                report.MessageList.Add("Standard Opening: " + standardOpening.OpeningId + " has found a match within allowable tolerances for its insertion point Y-Coordinate when compared with Test opening: " + testOpening.OpeningId);
                                if (diffZ == 0)
                                {
                                    //perfect Z coordinate match
                                    report.MessageList.Add("Standard Opening: " + standardOpening.OpeningId + " has found a perfect match for its insertion point Z-Coordinate when compared with Test opening: " + testOpening.OpeningId);
                                    possibleMatches.Add(testOpening);

                                }
                                else
                                {
                                    //perfect Z coordinate match
                                    report.MessageList.Add("Standard Opening: " + standardOpening.OpeningId + " has found a match within allowable tolerances for its insertion point Z-Coordinate when compared with test Opening: " + testOpening.OpeningId);
                                    //we continue because we search for other matches if there are any
                                    possibleMatches.Add(testOpening);

                                }
                            }

                        }
                        // X is within tolerance
                        else
                        {
                            report.MessageList.Add("Standard Opening: " + standardOpening.OpeningId + " has found a match within allowable tolerances for its insertion point X-Coordinate when compared with test Opening: " + testOpening.OpeningId);
                            if (diffY == 0)
                            {
                                //perfect Y coordinate match
                                report.MessageList.Add("Standard Opening: " + standardOpening.OpeningId + " has found a perfect match for its insertion point Y-Coordinate when compared with test Opening: " + testOpening.OpeningId);
                                if (diffZ == 0)
                                {
                                    //perfect Z coordinate match
                                    report.MessageList.Add("Standard Opening: " + standardOpening.OpeningId + " has found a perfect match for its insertion point Z-Coordinate when compared with test Opening: " + testOpening.OpeningId);
                                    possibleMatches.Add(testOpening);

                                }
                                else
                                {
                                    //perfect Z coordinate match
                                    report.MessageList.Add("Standard Opening: " + standardOpening.OpeningId + " has found a match within allowable tolerances for its insertion point Z-Coordinate when compared with test Opening: " + testOpening.OpeningId);
                                    //we continue because we search for other matches if there are any
                                    possibleMatches.Add(testOpening);

                                }
                            }
                            else
                            {
                                //y-coordinate is within tolerance
                                report.MessageList.Add("Standard Opening: " + standardOpening.OpeningId + " has found a match within allowable tolerances for its insertion point Y-Coordinate when compared with test Opening: " + testOpening.OpeningId);
                                if (diffZ == 0)
                                {
                                    //perfect Z coordinate match
                                    report.MessageList.Add("Standard Opening: " + standardOpening.OpeningId + " has found a perfect match for its insertion point Z-Coordinate when compared with test Opening: " + testOpening.OpeningId);
                                    possibleMatches.Add(testOpening);

                                }
                                else
                                {
                                    //perfect Z coordinate match
                                    report.MessageList.Add("Standard Opening: " + standardOpening.OpeningId + " has found a match within allowable tolerances for its insertion point Z-Coordinate when compared with test Opening: " + testOpening.OpeningId);
                                    //we continue because we search for other matches if there are any
                                    possibleMatches.Add(testOpening);

                                }
                            }
                        }
                    }
                    report.MessageList.Add("Standard Opening Ins Pt: (" + standardOpening.InsertionPoint.X.ToString() + "," + standardOpening.InsertionPoint.Y.ToString() + "," + standardOpening.InsertionPoint.Z.ToString() + ")");
                    report.MessageList.Add("Test File Opening Ins Pt: (" + testOpening.InsertionPoint.X.ToString() + "," + testOpening.InsertionPoint.Y.ToString() + "," + testOpening.InsertionPoint.Z.ToString() + ")");
                    i++;
                    if (possibleMatches2.Count == i)
                    {
                        if (possibleMatches.Count == 1)
                        {
                            List<string> openingMatch = new List<string>();
                            openingMatch.Add(possibleMatches[0].OpeningId);
                            report.MessageList.Add("Standard file Opening: " + standardOpening.OpeningId + " is matched to test file Opening: " + testOpening.OpeningId);
                            globalMatchObject.MatchedOpeningIds.Add(standardOpening.OpeningId, openingMatch);
                            report.passOrFail = true;
                            return report;
                        }
                        else
                        {
                            if (possibleMatches.Count == 0)
                            {
                                report.MessageList.Add("Standard file Opening: " + standardOpening.OpeningId + " found no match for insertion point in the test file of the remaining candidates.");
                                report.passOrFail = false;
                                return report;
                            }
                            else
                            {
                                report.MessageList.Add("Standard file Opening: " + standardOpening.OpeningId + " is matched to multiple openings:");
                                foreach (OpeningDefinitions opening in possibleMatches)
                                {
                                    report.MessageList.Add("Test Opening:" + opening.OpeningId + "matched insertion point");
                                }
                                //resolve by trying to match to the standard opening and test opening parent surfaces.
                                //for the standard opening
                                if (globalMatchObject.MatchedSurfaceIds.ContainsKey(standardOpening.ParentSurfaceId))
                                {
                                    List<string> possibleSurfaceMatches = globalMatchObject.MatchedSurfaceIds[standardOpening.ParentSurfaceId];
                                    if (possibleSurfaceMatches.Count == 1)
                                    {
                                        //then a match was found originally during get possible surface matches.  That is good, we only want one
                                        foreach (OpeningDefinitions openingRemaining in possibleMatches)
                                        {
                                            if (openingRemaining.ParentSurfaceId == possibleSurfaceMatches[0])
                                            {
                                                //this is the match we want
                                                //else we would have to continue
                                                report.MessageList.Add("The test Opening: " + openingRemaining.OpeningId + " has been matched to the standard Opening: " + standardOpening.OpeningId +
                                                    ".  Their parent surface ids have been matched.  Thus the conflict has been resolved.  (Standard opening parent surface Id, test opening parent surface Id" + standardOpening.ParentSurfaceId + "," + openingRemaining.ParentSurfaceId);
                                                report.passOrFail = true;
                                                List<string> openingMatch = new List<string>();
                                                openingMatch.Add(possibleMatches[0].OpeningId);
                                                globalMatchObject.MatchedOpeningIds.Add(standardOpening.OpeningId, openingMatch);
                                                return report;
                                            }
                                            else
                                            {
                                                //do nothing.  Maybe report that the parent Surface Id does not match the standard Opening
                                                report.MessageList.Add("Test Opening:" + openingRemaining.OpeningId + " does not match the standard Opening: " + standardOpening.OpeningId +
                                                    ".  Their parent surface ids do not coincide.  (Standard Opening parent surface id, test Opening parent surface id)" + standardOpening.ParentSurfaceId + "," + openingRemaining.ParentSurfaceId);
                                            }
                                        }
                                    }
                                }
                                report.passOrFail = false;
                                return report;
                            }
                        }
                    }

                }

                //finished

            }
            catch (Exception e)
            {
                report.longMsg = e.ToString();
            }
            return report;
        }
        private DOEgbXMLReportingObj GetPossibleSurfaceMatches(SurfaceDefinitions surface, List<SurfaceDefinitions> TestSurfaces, DOEgbXMLReportingObj report)
        {
            //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;
                //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
                foreach (SurfaceDefinitions testSurface in TestSurfaces)
                {
                    //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; }

                        foreach (string testAdjSpaceId in testSurface.AdjSpaceId)
                        {
                            //loop only returns true if all AdjSpaceIds in both surfaces are identical
                            adjSpaceIdMatch = false;
                            foreach (string standardAdjSpaceId in surface.AdjSpaceId)
                            {
                                if (testAdjSpaceId == standardAdjSpaceId) { adjSpaceIdMatch = true; }
                            }
                        }
                        //if adjacent space Ids match and the surface types match, note this 
                        if (adjSpaceIdMatch && testSurface.SurfaceType == surface.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 = Math.Abs(testSurface.Tilt - surface.Tilt);
                        double azimuthDifference = Math.Abs(testSurface.Azimuth - surface.Azimuth);
                        //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.");
                        bool isRegular = IsSurfaceRegular(surface);
                        foreach (SurfaceDefinitions regSurface in possiblesList2)
                        {
                            //ensures likewise that all the test surface candidates are regular, 
                            //if they are not, then the entire set is assumed to be irregular
                            isRegular = IsSurfaceRegular(regSurface);
                            if (isRegular == false) break;
                        }
                        if (isRegular)
                        {
                            //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
                                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(testsurface.Width - surface.Width);
                                double heightDiff = Math.Abs(testsurface.Height - surface.Height);
                                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 + " ft and " + DOEgbXMLBasics.Tolerances.SurfaceHeightTolerance + "ft, 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
                                    Vector.MemorySafe_CartCoord simplecoord = new Vector.MemorySafe_CartCoord(0,coord.Y,coord.Z);
                                    coordList.Add(simplecoord);

                                }
                                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 simple = new Vector.MemorySafe_CartCoord(0, coord.Y, coord.Z);
                                            testCoordList.Add(simple);
                                        }
                                        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");
                                        }
                                        double difference = Math.Abs(area - testSurfacesArea);
                                        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 simple = new Vector.MemorySafe_CartCoord(coord.X, 0, coord.Z);
                                    coordList.Add(simple);

                                }
                                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 simple = new Vector.MemorySafe_CartCoord(coord.X, 0, coord.Z);
                                            testCoordList.Add(simple);
                                        }
                                        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");
                                        }
                                        double difference = Math.Abs(area - testSurfacesArea);
                                        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 simple = new Vector.MemorySafe_CartCoord(coord.X, coord.Y, 0);
                                    coordList.Add(coord);

                                }
                                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 simple = new Vector.MemorySafe_CartCoord(coord.X, coord.Y, 0);
                                            testCoordList.Add(coord);
                                        }
                                        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");
                                        }
                                        double difference = Math.Abs(area - testSurfacesArea);
                                        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 tempY = new Vector.CartVect();
                                Vector.MemorySafe_CartVect globalReferenceX = new Vector.MemorySafe_CartVect(1,0,0);


                                tempY = Vector.CrossProductNVRetMSMS(surface.PlRHRVector, globalReferenceX);
                                tempY = Vector.UnitVector(tempY);
                                Vector.MemorySafe_CartVect localY = Vector.convertToMemorySafeVector(tempY);
                                

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

                                //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;
                                    Vector.CartCoord translatedPt = new Vector.CartCoord();
                                    //x coordinate is distance vector dot the new local X axis
                                    translatedPt.X = distance.X * localX.X + distance.Y * localX.Y + distance.Z * localX.Z;
                                    //y coordinate is distance vector dot the new local Y axis
                                    translatedPt.Y = distance.X * localY.X + distance.Y * localY.Y + distance.Z * localY.Z;
                                    translatedPt.Z = 0;
                                    Vector.MemorySafe_CartCoord memsafetranspt = Vector.convertToMemorySafeCoord(translatedPt);
                                    translatedCoordinates.Add(memsafetranspt);

                                }
                                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 testtempY = new Vector.CartVect();
                                    Vector.MemorySafe_CartVect testglobalReferenceX = new Vector.MemorySafe_CartVect(1,0,0);

                                    testtempY = Vector.CrossProductNVRetMSMS(surface.PlRHRVector, testglobalReferenceX);
                                    testtempY = Vector.UnitVector(testtempY);
                                    Vector.MemorySafe_CartVect testlocalY = Vector.convertToMemorySafeVector(testtempY);


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

                                    //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;
                                        Vector.CartCoord translatedPt = new Vector.CartCoord();
                                        //x coordinate is distance vector dot the new local X axis
                                        translatedPt.X = distance.X * localX.X + distance.Y * localX.Y + distance.Z * localX.Z;
                                        //y coordinate is distance vector dot the new local Y axis
                                        translatedPt.Y = distance.X * localY.X + distance.Y * localY.Y + distance.Z * localY.Z;
                                        translatedPt.Z = 0;
                                        Vector.MemorySafe_CartCoord memsafetranspt = Vector.convertToMemorySafeCoord(translatedPt);
                                        testtranslatedCoordinates.Add(memsafetranspt);

                                    }
                                    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");
                                    }
                                    double difference = Math.Abs(area - testarea);
                                    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);
                                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>");
                    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 - surface.InsertionPoint.X);
                            double insPtYDiff = Math.Abs(testSurface.InsertionPoint.Y - surface.InsertionPoint.Y);
                            double insPtZDiff = Math.Abs(testSurface.InsertionPoint.Z - surface.InsertionPoint.Z);
                            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;
                }
                return report;

            }
            catch (Exception e)
            {
                report.longMsg = (e.ToString());
                return report;
            }
        }
        public static List<gbXMLSpaces> getSimpleSpaces(XmlDocument xmldoc, XmlNamespaceManager xmlns)
        {
            List<gbXMLSpaces> retspaces = new List<gbXMLSpaces>();
            try
            {
                XmlNodeList nodes = xmldoc.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:Space", xmlns);

                foreach (XmlNode spaceNode in nodes)
                {
                    //initialize a new instance of the class
                    gbXMLSpaces space = new gbXMLSpaces();
                    space.spacebounds = new List<SpaceBoundary>();
                    //get id and space
                    XmlAttributeCollection spaceAtts = spaceNode.Attributes;
                    foreach (XmlAttribute at in spaceAtts)
                    {
                        if (at.Name == "id")
                        {
                            space.id = at.Value;
                            break;
                        }
                    }
                    if (spaceNode.HasChildNodes)
                    {
                        XmlNodeList childNodes = spaceNode.ChildNodes;
                        foreach (XmlNode node in childNodes)
                        {
                            if (node.Name == "PlanarGeometry")
                            {
                                space.pg = new PlanarGeometry();
                                XmlNodeList childnodes = node.ChildNodes;
                                foreach (XmlNode node2 in childnodes)
                                {
                                    if (node2.Name == "PolyLoop")
                                    {
                                        space.pg.pl = new PolyLoop();
                                        space.pg.pl.plcoords = new List<Vector.MemorySafe_CartCoord>();

                                        XmlNodeList cartPoints = node2.ChildNodes;
                                        foreach (XmlNode point in cartPoints)
                                        {
                                            if (point.Name == "CartesianPoint")
                                            {
                                                Vector.CartCoord coord = new Vector.CartCoord();
                                                XmlNodeList val = point.ChildNodes;
                                                int pointcount = 1;
                                                foreach (XmlNode cpoint in val)
                                                {
                                                    switch (pointcount)
                                                    {
                                                        case 1:
                                                            coord.X = Convert.ToDouble(cpoint.InnerText);
                                                            break;
                                                        case 2:
                                                            coord.Y = Convert.ToDouble(cpoint.InnerText);
                                                            break;
                                                        case 3:
                                                            coord.Z = Convert.ToDouble(cpoint.InnerText);
                                                            break;
                                                    }
                                                    pointcount++;
                                                }
                                                Vector.MemorySafe_CartCoord memsafecoord = Vector.convertToMemorySafeCoord(coord);
                                                space.pg.pl.plcoords.Add(memsafecoord);
                                            }
                                        }
                                    }
                                }
                            }
                            else if (node.Name == "ShellGeometry")
                            {
                                space.sg = new ShellGeometry();
                                XmlAttributeCollection sgAtts = spaceNode.Attributes;
                                foreach (XmlAttribute at in sgAtts)
                                {
                                    if (at.Name == "id")
                                    {
                                        space.sg.id = at.Value;
                                        break;
                                    }
                                }

                                XmlNodeList childnodes = node.ChildNodes;
                                foreach (XmlNode sgnode in childnodes)
                                {
                                    if (sgnode.Name == "ClosedShell")
                                    {
                                        space.sg.cs = new ClosedShell();
                                        space.sg.cs.ploops = new List<PolyLoop>();

                                        foreach (XmlNode pl in sgnode)
                                        {
                                            if (pl.Name == "PolyLoop")
                                            {
                                                PolyLoop sgpl = new PolyLoop();
                                                sgpl.plcoords = new List<Vector.MemorySafe_CartCoord>();
                                                XmlNodeList cartPoints = pl.ChildNodes;
                                                foreach (XmlNode point in cartPoints)
                                                {
                                                    if (point.Name == "CartesianPoint")
                                                    {
                                                        Vector.CartCoord coord = new Vector.CartCoord();
                                                        XmlNodeList val = point.ChildNodes;
                                                        int pointcount = 1;
                                                        foreach (XmlNode cpoint in val)
                                                        {
                                                            switch (pointcount)
                                                            {
                                                                case 1:
                                                                    coord.X = Convert.ToDouble(cpoint.InnerText);
                                                                    break;
                                                                case 2:
                                                                    coord.Y = Convert.ToDouble(cpoint.InnerText);
                                                                    break;
                                                                case 3:
                                                                    coord.Z = Convert.ToDouble(cpoint.InnerText);
                                                                    break;
                                                            }
                                                            pointcount++;
                                                        }
                                                        Vector.MemorySafe_CartCoord memsafecoord = Vector.convertToMemorySafeCoord(coord);
                                                        sgpl.plcoords.Add(memsafecoord);
                                                    }
                                                }
                                                space.sg.cs.ploops.Add(sgpl);
                                            }
                                        }
                                    }
                                }
                            }
                            else if (node.Name == "SpaceBoundary")
                            {
                                SpaceBoundary sb = new SpaceBoundary();
                                XmlAttributeCollection spbatts = node.Attributes;
                                foreach (XmlAttribute at in spbatts)
                                {
                                    if (at.Name == "surfaceIdRef")
                                    {
                                        sb.surfaceIdRef = at.Value;
                                        break;
                                    }
                                }
                                XmlNodeList sbchilds = node.ChildNodes;
                                foreach (XmlNode sbpnode in sbchilds)
                                {
                                    if (sbpnode.Name == "PlanarGeometry")
                                    {
                                        sb.sbplane = new PlanarGeometry();
                                        XmlNodeList pgchilds = sbpnode.ChildNodes;
                                        foreach (XmlNode pgchild in pgchilds)
                                        {
                                            if (pgchild.Name == "PolyLoop")
                                            {
                                                sb.sbplane.pl = new PolyLoop();

                                                sb.sbplane.pl.plcoords = new List<Vector.MemorySafe_CartCoord>();
                                                XmlNodeList cartPoints = pgchild.ChildNodes;
                                                foreach (XmlNode point in cartPoints)
                                                {
                                                    if (point.Name == "CartesianPoint")
                                                    {
                                                        Vector.CartCoord coord = new Vector.CartCoord();
                                                        XmlNodeList val = point.ChildNodes;
                                                        int pointcount = 1;
                                                        foreach (XmlNode cpoint in val)
                                                        {
                                                            switch (pointcount)
                                                            {
                                                                case 1:
                                                                    coord.X = Convert.ToDouble(cpoint.InnerText);
                                                                    break;
                                                                case 2:
                                                                    coord.Y = Convert.ToDouble(cpoint.InnerText);
                                                                    break;
                                                                case 3:
                                                                    coord.Z = Convert.ToDouble(cpoint.InnerText);
                                                                    break;
                                                            }
                                                            pointcount++;
                                                        }
                                                        Vector.MemorySafe_CartCoord memsafecoord = Vector.convertToMemorySafeCoord(coord);
                                                        sb.sbplane.pl.plcoords.Add(memsafecoord);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                //finally, add the thing here
                                space.spacebounds.Add(sb);
                            }
                        }
                    }
                    else
                    {
                        //throw something
                    }
                    retspaces.Add(space);
                }
            }
            catch (Exception e)
            {

            }
            return retspaces;
        }
        private static SpaceBoundary MakeSBPlanarGeometry(SpaceBoundary sb, XmlNodeList pgchilds)
        {
            try
            {

                foreach (XmlNode pgchild in pgchilds)
                {
                    if (pgchild.Name == "PolyLoop")
                    {
                        sb.sbplane.pl = new PolyLoop();

                        sb.sbplane.pl.plcoords = new List<Vector.MemorySafe_CartCoord>();
                        XmlNodeList cartPoints = pgchild.ChildNodes;
                        foreach (XmlNode point in cartPoints)
                        {
                            if (point.Name == "CartesianPoint")
                            {
                                Vector.CartCoord coord = new Vector.CartCoord();
                                XmlNodeList val = point.ChildNodes;
                                int pointcount = 1;
                                foreach (XmlNode cpoint in val)
                                {
                                    switch (pointcount)
                                    {
                                        case 1:
                                            coord.X = Convert.ToDouble(cpoint.InnerText);
                                            break;
                                        case 2:
                                            coord.Y = Convert.ToDouble(cpoint.InnerText);
                                            break;
                                        case 3:
                                            coord.Z = Convert.ToDouble(cpoint.InnerText);
                                            break;
                                    }
                                    pointcount++;
                                }
                                Vector.MemorySafe_CartCoord memsafecoord = Vector.convertToMemorySafeCoord(coord);
                                sb.sbplane.pl.plcoords.Add(memsafecoord);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {

            }
            return sb;
        }