Beispiel #1
0
        public static MemorySafe_ADOpeningDefinitions convert2ADMemorySafeOpening(OpeningDefinitions opening)
        {
            List <Vector.MemorySafe_CartCoord> surfaceCoords = new List <Vector.MemorySafe_CartCoord>();

            Vector.CartVect dummy = new Vector.CartVect();
            dummy.X = -999;
            dummy.Y = -999;
            dummy.Z = -999;
            Vector.MemorySafe_CartVect memSafeRHR = Vector.convertToMemorySafeVector(dummy);
            string openingType     = "N/A";
            double parentAzimuth   = 0;
            double parentTilt      = 0;
            string outsideBoundary = "Outdoors";
            double viewFactor      = 0;
            double az          = -999;
            double tilt        = -999;
            int    numvertices = 4;
            double area        = opening.height * opening.length;
            MemorySafe_ADOpeningDefinitions memOpening = new MemorySafe_ADOpeningDefinitions(opening.nameId,
                                                                                             openingType, opening.parentSurfaceNameId,
                                                                                             parentAzimuth, parentTilt, outsideBoundary, viewFactor,
                                                                                             opening.shadeControlSch, surfaceCoords, az, tilt, memSafeRHR,
                                                                                             opening.constructionName, opening.frameAndDividerName, opening.multiplier, numvertices,
                                                                                             opening.area, opening.X, opening.Z, opening.height, opening.length);

            return(memOpening);
        }
Beispiel #2
0
            public MemorySafe_ADOpeningDefinitions(string nameId, string openType, string parentSurf, double parentAz, double parentTilt,
                                                   string oBCond, double vF, string shadeCntrlSch, List <Vector.MemorySafe_CartCoord> coordList, double az,
                                                   double tilt, Vector.MemorySafe_CartVect RHR, string constName, string frameandDivider, int mult, int numVert, double area,
                                                   double x, double z, double height, double length)
            {
                _nameId              = nameId;
                _openingType         = openType;
                _parentSurfaceNameId = parentSurf;
                _parentAzimuth       = parentAz;
                _parentTilt          = parentTilt;

                _outsideBoundaryConditionObj = oBCond;
                _viewFactortoGround          = vF;
                _shadeControlSch             = shadeCntrlSch;
                _coordinateList = coordList;
                _Azimuth        = az;
                _Tilt           = tilt;
                Vector.MemorySafe_CartVect _rHRVector = RHR;
                _constructionName = constName;

                _frameAndDividerName = frameandDivider;
                _multiplier          = mult;
                _numVertices         = numVert;
                _area   = area;
                _x      = x;
                _z      = z;
                _height = height;
                _length = length;
            }
        public static LLRet GetLLForFloor(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(smallest Y), then most left (largest 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 floor
            }

            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);
        }
        static public double FindTilt(Vector.MemorySafe_CartVect normalVector)
        {
            double calculatedTilt = -999;
            //may need to also take into account other factors that, at this stage, seem to not be important
            //building Direction of Relative North
            //zone Direction of Relative North
            //GlobalGeometryRules coordinate system
            //I may need to know this in the future then rotate the axis vectors I am making below

            //x-axis [1 0 0] points east, y-axis [0 1 0] points north, z-axis[0 0 1] points up to the sky
            //alignment with y axis means north pointing, alignment with z-axis means it is pointing up to the sky (like a flat roof)
            double nX = 0;
            double nY = 1;
            double nZ = 0;

            Vector.MemorySafe_CartVect northVector = new Vector.MemorySafe_CartVect(nX, nY, nZ);

            double uX = 0;
            double uY = 0;
            double uZ = 1;

            Vector.MemorySafe_CartVect upVector = new Vector.MemorySafe_CartVect(uX, uY, uZ);

            //rotate the axis vectors for the future

            //ensure the vector passed into the function is a unit vector
            normalVector = Vector.UnitVector(normalVector);
            //get tilt:  cross product of normal vector and upVector
            //dot product equal to -1 is sign of antiparallelism
            double dot = Vector.DotProductMag(upVector, normalVector);

            if (dot + 1 < .001)
            {
                calculatedTilt = 180;
                return(calculatedTilt);
            }
            else
            {
                Vector.MemorySafe_CartVect tiltVector = Vector.CrossProduct(normalVector, upVector);
                double tiltVectorMagnitude            = Vector.VectorMagnitude(tiltVector);
                calculatedTilt = Math.Round(Math.Asin(tiltVectorMagnitude) * 180 / Math.PI, 2);
                return(calculatedTilt);
            }
        }
Beispiel #5
0
        public static MemorySafe_OpeningDefinitions convert2MemorySafeOpening(OpeningDefinitions opening)
        {
            List <Vector.MemorySafe_CartCoord> surfaceCoords = new List <Vector.MemorySafe_CartCoord>();

            foreach (Vector.CartCoord coord in opening.coordinateList)
            {
                Vector.MemorySafe_CartCoord surfaceCoord = new Vector.MemorySafe_CartCoord(coord.X, coord.Y, coord.Z);
                surfaceCoords.Add(surfaceCoord);
            }
            Vector.MemorySafe_CartVect memSafeRHR = Vector.convertToMemorySafeVector(opening.rHRVector);

            MemorySafe_OpeningDefinitions memOpening = new MemorySafe_OpeningDefinitions(opening.nameId,
                                                                                         opening.openingType, opening.parentSurfaceNameId,
                                                                                         opening.parentAzimuth, opening.parentTilt, opening.outsideBoundaryConditionObj, opening.viewFactortoGround,
                                                                                         opening.shadeControlSch, surfaceCoords, opening.Azimuth, opening.Tilt, memSafeRHR,
                                                                                         opening.constructionName, opening.frameAndDividerName, opening.multiplier, opening.numVertices,
                                                                                         opening.area);

            return(memOpening);
        }
Beispiel #6
0
            public MemorySafe_OpeningDefinitions(MemorySafe_OpeningDefinitions previousOpening, int multiplier)
            {
                _nameId                      = previousOpening.nameId;
                _openingType                 = previousOpening.openingType;
                _parentSurfaceNameId         = previousOpening.parentSurfaceNameId;
                _parentAzimuth               = previousOpening.parentAzimuth;;
                _parentTilt                  = previousOpening.parentTilt;
                _outsideBoundaryConditionObj = previousOpening.outsideBoundaryConditionObj;
                _viewFactortoGround          = previousOpening.viewFactortoGround;
                _shadeControlSch             = previousOpening.shadeControlSch;
                _coordinateList              = previousOpening.coordinateList;
                _Azimuth                     = previousOpening.Azimuth;
                _Tilt             = previousOpening.Tilt;
                _rHRVector        = previousOpening.rHRVector;
                _constructionName = previousOpening.constructionName;

                _frameAndDividerName = previousOpening.frameAndDividerName;
                _multiplier          = multiplier;
                _numVertices         = previousOpening.numVertices;
                _area = previousOpening.area;
            }
        static public double FindAzimuth(Vector.MemorySafe_CartVect normalVector)
        {
            double calculatedAzimuth = -999;

            //may need to also take into account other factors that, at this stage, seem to not be important
            //building Direction of Relative North
            //zone Direction of Relative North
            //GlobalGeometryRules coordinate system
            //I may need to know this in the future then rotate the axis vectors I am making below

            //x-axis [1 0 0] points east, y-axis [0 1 0] points north, z-axis[0 0 1] points up to the sky
            //alignment with y axis means north pointing, alignment with z-axis means it is pointing up to the sky (like a flat roof)

            Vector.MemorySafe_CartVect northVector = new Vector.MemorySafe_CartVect(0, 1, 0);

            Vector.MemorySafe_CartVect southVector = new Vector.MemorySafe_CartVect(0, -1, 0);

            Vector.MemorySafe_CartVect eastVector = new Vector.MemorySafe_CartVect(1, 0, 0);

            Vector.MemorySafe_CartVect westVector = new Vector.MemorySafe_CartVect(-1, 0, 0);

            Vector.MemorySafe_CartVect upVector = new Vector.MemorySafe_CartVect(0, 0, 1);

            //rotate the axis vectors for the future

            //ensure the vector passed into the function is a unit vector
            normalVector = Vector.UnitVector(normalVector);
            //get X-Y projection of the normal vector
            //normalVector.Z = 0;
            //get azimuth:  cross product of normal vector x-y projection and northVector
            //2-14-2014 we added last two statements to deal with normal
            //1st quadrant
            if ((normalVector.X == 0 && normalVector.Y == 1) || (normalVector.X == 1 && normalVector.Y == 0) || (normalVector.X > 0 && normalVector.Y > 0) || (normalVector.X > 0 && normalVector.Z != 0) || (normalVector.Y > 0 && normalVector.Z != 0))
            {
                //get azimuth:  cross product of normal vector x-y projection and northVector
                Vector.MemorySafe_CartVect azVector = Vector.CrossProduct(normalVector, northVector);
                double azVectorMagnitude            = Vector.VectorMagnitude(azVector);

                //modification for when the vector is in different quadrants
                calculatedAzimuth = Math.Round(Math.Asin(azVectorMagnitude) * 180 / Math.PI, 2);
                return(calculatedAzimuth);
            }
            //second quadrant
            else if ((normalVector.X < 0 && normalVector.Y > 0))
            {
                Vector.MemorySafe_CartVect azVector = Vector.CrossProduct(normalVector, westVector);
                double azVectorMagnitude            = Vector.VectorMagnitude(azVector);

                //modification for when the vector is in different quadrants
                calculatedAzimuth = Math.Round(Math.Asin(azVectorMagnitude) * 180 / Math.PI, 2) + 270;
                return(calculatedAzimuth);
            }
            //quadrant 3
            else if ((normalVector.X < 0 && normalVector.Y < 0) || (normalVector.X == -1 && normalVector.Y == 0) || (normalVector.X < 0 && normalVector.Z != 0))
            {
                Vector.MemorySafe_CartVect azVector = Vector.CrossProduct(normalVector, southVector);
                double azVectorMagnitude            = Vector.VectorMagnitude(azVector);

                //modification for when the vector is in different quadrants
                calculatedAzimuth = Math.Round(Math.Asin(azVectorMagnitude) * 180 / Math.PI, 2) + 180;
                return(calculatedAzimuth);
            }
            //quadrant 4
            else if ((normalVector.X > 0 && normalVector.Y < 0) || (normalVector.X == 0 && normalVector.Y == -1) || (normalVector.Y < 0 && normalVector.Z != 0))
            {
                Vector.MemorySafe_CartVect azVector = Vector.CrossProduct(normalVector, eastVector);
                double azVectorMagnitude            = Vector.VectorMagnitude(azVector);

                //modification for when the vector is in different quadrants
                calculatedAzimuth = Math.Round(Math.Asin(azVectorMagnitude) * 180 / Math.PI, 2) + 90;
                return(calculatedAzimuth);
            }
            //this will happen to vectors that point straight down or straight up because we are only interested in the X-Y projection and set the Z to zero anyways
            else if (normalVector.X == 0 && normalVector.Y == 0)
            {
                calculatedAzimuth = 0;
                return(calculatedAzimuth);
            }

            //get the

            return(calculatedAzimuth);
        }
Beispiel #8
0
        public static double FindTilt(Vector.MemorySafe_CartVect normalVector)
        {
            double calculatedTilt = -999;
            //may need to also take into account other factors that, at this stage, seem to not be important
            //building Direction of Relative North
            //zone Direction of Relative North
            //GlobalGeometryRules coordinate system
            //I may need to know this in the future then rotate the axis vectors I am making below

            //x-axis [1 0 0] points east, y-axis [0 1 0] points north, z-axis[0 0 1] points up to the sky
            //alignment with y axis means north pointing, alignment with z-axis means it is pointing up to the sky (like a flat roof)
            double nX = 0;
            double nY = 1;
            double nZ = 0;
            Vector.MemorySafe_CartVect northVector = new Vector.MemorySafe_CartVect(nX, nY, nZ);

            double uX = 0;
            double uY = 0;
            double uZ = 1;
            Vector.MemorySafe_CartVect upVector = new Vector.MemorySafe_CartVect(uX, uY, uZ);

            //rotate the axis vectors for the future

            //ensure the vector passed into the function is a unit vector
            normalVector = Vector.UnitVector(normalVector);
            //get tilt:  cross product of normal vector and upVector
            //dot product equal to -1 is sign of antiparallelism
            double dot = Vector.DotProductMag(upVector, normalVector);
            if(dot+1 < .001)
            {
                calculatedTilt = 180;
                return calculatedTilt;
            }
            else
            {
                Vector.MemorySafe_CartVect tiltVector = Vector.CrossProduct(normalVector, upVector);
                double tiltVectorMagnitude = Vector.VectorMagnitude(tiltVector);
                calculatedTilt = Math.Round(Math.Asin(tiltVectorMagnitude) * 180 / Math.PI, 2);
                return calculatedTilt;
            }
        }
Beispiel #9
0
        public static double FindAzimuth(Vector.MemorySafe_CartVect normalVector)
        {
            double calculatedAzimuth = -999;
            //may need to also take into account other factors that, at this stage, seem to not be important
            //building Direction of Relative North
            //zone Direction of Relative North
            //GlobalGeometryRules coordinate system
            //I may need to know this in the future then rotate the axis vectors I am making below

            //x-axis [1 0 0] points east, y-axis [0 1 0] points north, z-axis[0 0 1] points up to the sky
            //alignment with y axis means north pointing, alignment with z-axis means it is pointing up to the sky (like a flat roof)

            Vector.MemorySafe_CartVect northVector = new Vector.MemorySafe_CartVect(0, 1, 0);

            Vector.MemorySafe_CartVect southVector = new Vector.MemorySafe_CartVect(0, -1, 0);

            Vector.MemorySafe_CartVect eastVector = new Vector.MemorySafe_CartVect(1, 0, 0);

            Vector.MemorySafe_CartVect westVector = new Vector.MemorySafe_CartVect(-1, 0, 0);

            Vector.MemorySafe_CartVect upVector = new Vector.MemorySafe_CartVect(0, 0, 1);

            //rotate the axis vectors for the future

            //ensure the vector passed into the function is a unit vector
            normalVector = Vector.UnitVector(normalVector);
            //get X-Y projection of the normal vector
            //normalVector.Z = 0;
            //get azimuth:  cross product of normal vector x-y projection and northVector
            //2-14-2014 we added last two statements to deal with normal
            //1st quadrant
            if ((normalVector.X == 0 && normalVector.Y == 1) || (normalVector.X == 1 && normalVector.Y == 0) || (normalVector.X > 0 && normalVector.Y > 0) || (normalVector.X > 0 && normalVector.Z != 0) || (normalVector.Y > 0 && normalVector.Z != 0))
            {
                //get azimuth:  cross product of normal vector x-y projection and northVector
                Vector.MemorySafe_CartVect azVector = Vector.CrossProduct(normalVector, northVector);
                double azVectorMagnitude = Vector.VectorMagnitude(azVector);

                //modification for when the vector is in different quadrants
                calculatedAzimuth = Math.Round(Math.Asin(azVectorMagnitude) * 180 / Math.PI, 2);
                return calculatedAzimuth;
            }
            //second quadrant
            else if ((normalVector.X < 0 && normalVector.Y > 0) )
            {
                Vector.MemorySafe_CartVect azVector = Vector.CrossProduct(normalVector, westVector);
                double azVectorMagnitude = Vector.VectorMagnitude(azVector);

                //modification for when the vector is in different quadrants
                calculatedAzimuth = Math.Round(Math.Asin(azVectorMagnitude) * 180 / Math.PI, 2) + 270;
                return calculatedAzimuth;
            }
            //quadrant 3
            else if ((normalVector.X < 0 && normalVector.Y < 0) || (normalVector.X == -1 && normalVector.Y == 0) || (normalVector.X < 0 && normalVector.Z !=0))
            {
                Vector.MemorySafe_CartVect azVector = Vector.CrossProduct(normalVector, southVector);
                double azVectorMagnitude = Vector.VectorMagnitude(azVector);

                //modification for when the vector is in different quadrants
                calculatedAzimuth = Math.Round(Math.Asin(azVectorMagnitude) * 180 / Math.PI, 2) + 180;
                return calculatedAzimuth;
            }
            //quadrant 4
            else if ((normalVector.X > 0 && normalVector.Y < 0) || (normalVector.X == 0 && normalVector.Y == -1) || (normalVector.Y < 0 && normalVector.Z != 0))
            {
                Vector.MemorySafe_CartVect azVector = Vector.CrossProduct(normalVector, eastVector);
                double azVectorMagnitude = Vector.VectorMagnitude(azVector);

                //modification for when the vector is in different quadrants
                calculatedAzimuth = Math.Round(Math.Asin(azVectorMagnitude) * 180 / Math.PI, 2) + 90;
                return calculatedAzimuth;
            }
            //this will happen to vectors that point straight down or straight up because we are only interested in the X-Y projection and set the Z to zero anyways
            else if (normalVector.X == 0 && normalVector.Y == 0)
            {
                calculatedAzimuth = 0;
                return calculatedAzimuth;
            }

            //get the

            return calculatedAzimuth;
        }
        public static Dictionary<int, DOEgbXMLBasics.EdgeFamily> FindMatchingEdges(List<SurfaceDefinitions> sblist)
        {

            Dictionary<int, DOEgbXMLBasics.EdgeFamily> uniqueedges = new Dictionary<int, DOEgbXMLBasics.EdgeFamily>();
            int distinctedges = 0;
            foreach (SurfaceDefinitions sb in sblist)
            {
                int coordcount = sb.PlCoords.Count;
                for (int i = 0; i < coordcount; i++)
                {
                    //initialize the edge being tested, the test edge
                    DOEgbXMLBasics.EdgeFamily currentedge = new DOEgbXMLBasics.EdgeFamily();
                    currentedge.sbdec = sb.SurfaceId;
                    currentedge.relatedEdges = new List<DOEgbXMLBasics.EdgeFamily>();
                    currentedge.startendpt = new List<Vector.MemorySafe_CartCoord>();
                    if (uniqueedges.Count == 0)
                    {
                        uniqueedges[distinctedges] = currentedge;
                        //get the first coord in this set, and the coord next to it
                        currentedge.startendpt.Add(sb.PlCoords[i]);
                        currentedge.startendpt.Add(sb.PlCoords[i + 1]);
                        distinctedges++;
                        continue;

                    }
                    //most edges work the same, in terms of the start and end point, except for the last edge (the else case)
                    if (i < coordcount - 1)
                    {
                        currentedge.startendpt.Add(sb.PlCoords[i]);
                        currentedge.startendpt.Add(sb.PlCoords[i + 1]);
                    }
                    else
                    {
                        currentedge.startendpt.Add(sb.PlCoords[i]);
                        currentedge.startendpt.Add(sb.PlCoords[0]);
                    }

                    //search through existing edges to try and find a perfect match
                    int edgecount = 0; //keeps track of how many guest edges in the dictionary I've searched through
                    foreach (KeyValuePair<int, DOEgbXMLBasics.EdgeFamily> kp in uniqueedges)
                    {

                        Vector.MemorySafe_CartCoord startpt = kp.Value.startendpt[0];
                        //looking for a perfect match of endpoints.  If both match, then the 
                        //current edge is added to the current key/value pair's related edges.
                        #region
                        double diffx = Math.Abs(startpt.X - currentedge.startendpt[0].X);
                        double diffy = Math.Abs(startpt.Y - currentedge.startendpt[0].Y);
                        double diffz = Math.Abs(startpt.Z - currentedge.startendpt[0].Z);
                        double tol = DOEgbXMLBasics.Tolerances.SurfacePLCoordTolerance;
                        if (diffx <= tol && diffy <= tol && diffz <= tol)
                        {
                            //found at least one perfect coordinate match, try to match the second
                            Vector.MemorySafe_CartCoord endpt = kp.Value.startendpt[1];
                            diffx = Math.Abs(endpt.X - currentedge.startendpt[1].X);
                            diffy = Math.Abs(endpt.Y - currentedge.startendpt[1].Y);
                            diffz = Math.Abs(endpt.Z - currentedge.startendpt[1].Z);
                            if (diffx <= tol && diffy <= tol && diffz <= tol)
                            {
                                //both match, means the match is perfect, so add it to the related surfaces list
                                kp.Value.relatedEdges.Add(currentedge);
                                break;
                                //key value pair break;
                            }
                            else
                            {
                                //the edge may be unique, though it could still have neighboring relationships
                                //draw vector A
                                double Ax = endpt.X - currentedge.startendpt[1].X;
                                double Ay = endpt.Y - currentedge.startendpt[1].Y;
                                double Az = endpt.Z - currentedge.startendpt[1].Z;
                                Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);
                                double Amag = Vector.VectorMagnitude(A);

                                //take cross product to see if they are even in same plane
                                double evX = endpt.X - startpt.X;
                                double evY = endpt.Y - startpt.Y;
                                double evZ = endpt.Z - startpt.Z;
                                Vector.MemorySafe_CartVect ev = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                                double evmag = Vector.VectorMagnitude(ev);
                                Vector.MemorySafe_CartVect cross = Vector.CrossProduct(A, ev);
                                //TODO: do we need to make this a unit vector?
                                double crossmag = Vector.VectorMagnitude(cross);
                                if (Math.Abs(crossmag) < DOEgbXMLBasics.Tolerances.crossProductTolerance)
                                {
                                    //then we are at least parallel or antiparallel, now see if the point resides on the edge or outside of it
                                    double Bx = startpt.X - currentedge.startendpt[1].X;
                                    double By = startpt.Y - currentedge.startendpt[1].Y;
                                    double Bz = startpt.Z - currentedge.startendpt[1].Z;
                                    Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);
                                    double Bmag = Vector.VectorMagnitude(B);
                                    //check to see if the test edge is inside the guest edge
                                    if (Amag < evmag && Bmag < evmag)
                                    {
                                        //this means it lies on the plane at least, so it shares, but it is also still independent because a perfect match wasn't found
                                        kp.Value.relatedEdges.Add(currentedge);
                                        //accumulate its own relationships
                                        currentedge.relatedEdges.Add(kp.Value);
                                        edgecount++;
                                        continue; //continue looping through unique edges, if any
                                    }

                                    double edgeX = currentedge.startendpt[1].X - currentedge.startendpt[0].X;
                                    double edgeY = currentedge.startendpt[1].Y - currentedge.startendpt[0].Y;
                                    double edgeZ = currentedge.startendpt[1].Z - currentedge.startendpt[0].Z;
                                    Vector.MemorySafe_CartVect edgevec = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                                    double edgemag = Vector.VectorMagnitude(edgevec);

                                    double Cx = startpt.X - currentedge.startendpt[1].X;
                                    double Cy = startpt.Y - currentedge.startendpt[1].Y;
                                    double Cz = startpt.Z - currentedge.startendpt[1].Z;
                                    Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                                    double Cmag = Vector.VectorMagnitude(C);

                                    double Dx = endpt.X - currentedge.startendpt[1].X;
                                    double Dy = endpt.Y - currentedge.startendpt[1].Y;
                                    double Dz = endpt.Z - currentedge.startendpt[1].Z;
                                    Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                                    double Dmag = Vector.VectorMagnitude(D);

                                    if (Dmag < edgemag && Cmag <= edgemag)
                                    {
                                        //this means the test edge is longer than the guest edge, but they overlap
                                        kp.Value.relatedEdges.Add(currentedge);
                                        //the edge is still unique but accumulates a neighbor
                                        currentedge.relatedEdges.Add(kp.Value);
                                        edgecount++;
                                        continue;
                                    }
                                }
                                else
                                {
                                    //this other point isn't relevant, and the edges don't coincide
                                    edgecount++;
                                    continue;
                                }
                            }
                        } //end situation where first points match, next test if end points match
                        #endregion
                        else if (Math.Abs(startpt.X-currentedge.startendpt[1].X) < tol && Math.Abs(startpt.Y-currentedge.startendpt[1].Y)<tol && Math.Abs(startpt.Z-currentedge.startendpt[1].Z) < tol)
                        {
                            //found at least one perfect coordinate match, try to match the second
                            Vector.MemorySafe_CartCoord endpt = kp.Value.startendpt[1];
                            diffx = Math.Abs(endpt.X - currentedge.startendpt[0].X);
                            diffy = Math.Abs(endpt.Y - currentedge.startendpt[0].Y);
                            diffz = Math.Abs(endpt.Z - currentedge.startendpt[0].Z);

                            if (diffx < tol && diffy < tol && diffz < tol)
                            {
                                //both match, means the match is perfect, so add it to the related surfaces list
                                kp.Value.relatedEdges.Add(currentedge);
                                break;
                            }
                            else
                            {
                                //the edge may be unique, though it could still have neighboring relationships
                                double Ax = endpt.X - currentedge.startendpt[0].X;
                                double Ay = endpt.Y - currentedge.startendpt[0].Y;
                                double Az = endpt.Z - currentedge.startendpt[0].Z;
                                Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);
                                double Amag = Vector.VectorMagnitude(A);

                                //take cross product to see if they are even in same plane
                                double evX = endpt.X - startpt.X;
                                double evY = endpt.Y - startpt.Y;
                                double evZ = endpt.Z - startpt.Z;
                                Vector.MemorySafe_CartVect ev = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                                double evmag = Vector.VectorMagnitude(ev);
                                Vector.MemorySafe_CartVect cross = Vector.CrossProduct(A, ev);
                                //TODO: do we need to make this a unit vector?
                                double crossmag = Vector.VectorMagnitude(cross);
                                if (Math.Abs(crossmag) < DOEgbXMLBasics.Tolerances.crossProductTolerance)
                                {
                                    //then we are at least parallel or antiparallel, now see if the point resides on the edge or outside of it
                                    double Bx = startpt.X - currentedge.startendpt[0].X;
                                    double By = startpt.Y - currentedge.startendpt[0].Y;
                                    double Bz = startpt.Z - currentedge.startendpt[0].Z;
                                    Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);
                                    double Bmag = Vector.VectorMagnitude(B);
                                    //check to see if the test edge is inside the guest edge
                                    if (Amag < evmag && Bmag < evmag)
                                    {
                                        //this means it lies on the plane at least, so it shares, but it is also still independent because a perfect match wasn't found
                                        kp.Value.relatedEdges.Add(currentedge);
                                        //accumulate its own relationships
                                        currentedge.relatedEdges.Add(kp.Value);
                                        edgecount++;
                                        continue;
                                    }

                                    double edgeX = currentedge.startendpt[1].X - currentedge.startendpt[0].X;
                                    double edgeY = currentedge.startendpt[1].Y - currentedge.startendpt[0].Y;
                                    double edgeZ = currentedge.startendpt[1].Z - currentedge.startendpt[0].Z;
                                    Vector.MemorySafe_CartVect edgevec = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                                    double edgemag = Vector.VectorMagnitude(edgevec);

                                    double Cx = startpt.X - currentedge.startendpt[0].X;
                                    double Cy = startpt.Y - currentedge.startendpt[0].Y;
                                    double Cz = startpt.Z - currentedge.startendpt[0].Z;
                                    Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                                    double Cmag = Vector.VectorMagnitude(C);

                                    double Dx = endpt.X - currentedge.startendpt[0].X;
                                    double Dy = endpt.Y - currentedge.startendpt[0].Y;
                                    double Dz = endpt.Z - currentedge.startendpt[0].Z;
                                    Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                                    double Dmag = Vector.VectorMagnitude(D);

                                    if (Dmag < edgemag && Cmag <= edgemag)
                                    {
                                        //this means the test edge is longer than the guest edge, but they overlap
                                        kp.Value.relatedEdges.Add(currentedge);
                                        //the edge is still unique but accumulates a neighbor
                                        currentedge.relatedEdges.Add(kp.Value);
                                        edgecount++;
                                        continue;
                                    }
                                }
                                else
                                {
                                    //this other point isn't relevant, and the edges don't coincide
                                    edgecount++;
                                    continue;
                                }
                            }

                        }
                        //neither points perfectly coincide, so we do an exhaustive overlap check.
                        else
#region
                        {
                            Vector.MemorySafe_CartCoord endpt = kp.Value.startendpt[1];
                            //are the two vectors even parallel?  because if they are not, no need to get more complex
                            double evX = endpt.X - startpt.X;
                            double evY = endpt.Y - startpt.Y;
                            double evZ = endpt.Z - startpt.Z;
                            Vector.MemorySafe_CartVect ev = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                            double edgeX = currentedge.startendpt[1].X - currentedge.startendpt[0].X;
                            double edgeY = currentedge.startendpt[1].Y - currentedge.startendpt[0].Y;
                            double edgeZ = currentedge.startendpt[1].Z - currentedge.startendpt[0].Z;
                            Vector.MemorySafe_CartVect edgev = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                            if (Vector.VectorMagnitude(Vector.CrossProduct(ev, edgev)) > DOEgbXMLBasics.Tolerances.crossProductTolerance)
                            {
                                //they are not even parallel so move on
                                edgecount++;
                                continue;
                            }

                            //is one of the points inside of the edge?
                            //test edge point 1
                            double Ax = endpt.X - currentedge.startendpt[0].X;
                            double Ay = endpt.Y - currentedge.startendpt[0].Y;
                            double Az = endpt.Z - currentedge.startendpt[0].Z;
                            Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);
                            double Amag = Vector.VectorMagnitude(A);

                            //TODO: Remove
                            //evX = endpt.X - startpt.X;
                            //evY = endpt.Y - startpt.Y;
                            //evZ = endpt.Z - startpt.Z;
                            double uniqueMag = Vector.VectorMagnitude(ev);

                            double Bx = startpt.X - currentedge.startendpt[0].X;
                            double By = startpt.Y - currentedge.startendpt[0].Y;
                            double Bz = startpt.Z - currentedge.startendpt[0].Z;
                            Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);
                            double Bmag = Vector.VectorMagnitude(B);
                            //check to see if the test edge's first point (index 0) is totally inside the guest edge
                            // start x ---------- 0 --------------x end
                            if (Amag + Bmag  - uniqueMag < DOEgbXMLBasics.Tolerances.SurfacePLCoordTolerance)
                            {
                                //this is enough to prove that the two edges overlap, because we've already proven the two vectors are parallel
                                //then it is inside as well, and test vector is engulfed by guest vector
                                kp.Value.relatedEdges.Add(currentedge);
                                //but the edge is still itself unique
                                currentedge.relatedEdges.Add(kp.Value);
                                edgecount++;
                                continue;
                            }
                            //test edge point 2
                            double Cx = endpt.X - currentedge.startendpt[1].X;
                            double Cy = endpt.Y - currentedge.startendpt[1].Y;
                            double Cz = endpt.Z - currentedge.startendpt[1].Z;
                            Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                            double Cmag = Vector.VectorMagnitude(C);

                            //we are at least parallel, now to check for a real intersection
                            double Dx = startpt.X - currentedge.startendpt[1].X;
                            double Dy = startpt.Y - currentedge.startendpt[1].Y;
                            double Dz = startpt.Z - currentedge.startendpt[1].Z;
                            Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                            double Dmag = Vector.VectorMagnitude(D);
                            // start x ---------- 1 --------------x end
                            if (Cmag + Dmag - uniqueMag < DOEgbXMLBasics.Tolerances.SurfacePLCoordTolerance)
                            {
                                //this is enough to prove that the two edges overlap, because we've already proven the two vectors are parallel
                                //then it is inside as well, and test vector is engulfed by guest vector
                                kp.Value.relatedEdges.Add(currentedge);
                                //but the edge is still itself unique
                                currentedge.relatedEdges.Add(kp.Value);
                                edgecount++;
                                continue;
                            }

                            //now check to see if the two points overlap the edge and contain it completely, this is also a valid condition
                            // 0 -------xstart------------------xend-------1
                            double edgeMag = Vector.VectorMagnitude(edgev);
                            //use A,B
                            if(Amag + Bmag - edgeMag < DOEgbXMLBasics.Tolerances.SurfacePLCoordTolerance)
                            {
                                //this is enough to prove that the two edges overlap, because we've already proven the two vectors are parallel
                                //then it is inside as well, and test vector is engulfed by guest vector
                                kp.Value.relatedEdges.Add(currentedge);
                                //but the edge is still itself unique
                                currentedge.relatedEdges.Add(kp.Value);
                                edgecount++;
                                continue;
                            }
                            //use C,D
                            if (Cmag + Dmag - edgeMag < DOEgbXMLBasics.Tolerances.SurfacePLCoordTolerance)
                            {
                                //this is enough to prove that the two edges overlap, because we've already proven the two vectors are parallel
                                //then it is inside as well, and test vector is engulfed by guest vector
                                kp.Value.relatedEdges.Add(currentedge);
                                //but the edge is still itself unique
                                currentedge.relatedEdges.Add(kp.Value);
                                edgecount++;
                                continue;
                            }

                            //no matches were found.  log the issue and increase the edgecount nonetheless
                            //logger.Info("Edge (" + currentedge.startendpt[0].X + "," + currentedge.startendpt[0].Y + "," + currentedge.startendpt[0].Z + ")->(" + currentedge.startendpt[0].X + "," + currentedge.startendpt[0].Y + "," + currentedge.startendpt[0].Z + ") has not found a match.");
                            edgecount++;
                        }
#endregion
                        #region
                        //{
                        //    Vector.MemorySafe_CartCoord endpt = kp.Value.startendpt[1];
                        //    //are the two vectors even parallel?  because if they are not, no need to get more complex
                        //    double evX = endpt.X - startpt.X;
                        //    double evY = endpt.Y - startpt.Y;
                        //    double evZ = endpt.Z - startpt.Z;
                        //    Vector.MemorySafe_CartVect ev = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                        //    double edgeX = currentedge.startendpt[1].X - currentedge.startendpt[0].X;
                        //    double edgeY = currentedge.startendpt[1].Y - currentedge.startendpt[0].Y;
                        //    double edgeZ = currentedge.startendpt[1].Z - currentedge.startendpt[0].Z;
                        //    Vector.MemorySafe_CartVect edgev = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                        //    //TODO: add tolerance
                        //    if (Vector.VectorMagnitude(Vector.CrossProduct(ev, edgev)) != 0)
                        //    {
                        //        //they are not even parallel so move on
                        //        edgecount++;
                        //        continue;
                        //    }

                        //    //try to determine if the two edges are parallel
                        //    //test edge point 1
                        //    double Ax = endpt.X - currentedge.startendpt[0].X;
                        //    double Ay = endpt.Y - currentedge.startendpt[0].Y;
                        //    double Az = endpt.Z - currentedge.startendpt[0].Z;
                        //    Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);
                        //    double Amag = Vector.VectorMagnitude(A);

                        //    //take cross product to see if they are even in same plane
                        //    evX = endpt.X - startpt.X;
                        //    evY = endpt.Y - startpt.Y;
                        //    evZ = endpt.Z - startpt.Z;
                        //    Vector.MemorySafe_CartVect ev1 = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                        //    double guestmag = Vector.VectorMagnitude(ev1);
                        //    Vector.MemorySafe_CartVect cross1 = Vector.CrossProduct(A, ev1);
                        //    double crossmag = Vector.VectorMagnitude(cross1);
                        //    //tolerance?
                        //    if (crossmag == 0)
                        //    {
                        //        //we are at least parallel, now to check for a real intersection
                        //        double Bx = startpt.X - currentedge.startendpt[0].X;
                        //        double By = startpt.Y - currentedge.startendpt[0].Y;
                        //        double Bz = startpt.Z - currentedge.startendpt[0].Z;
                        //        Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);
                        //        double Bmag = Vector.VectorMagnitude(B);
                        //        //check to see if the test edge's first point (index 0) is totally inside the guest edge
                        //        if (Amag < guestmag && Bmag < guestmag)
                        //        #region
                        //        {
                        //            //the start point of the test edge is inside the guest edge
                        //            //test edge point 2 against guest edge point 2
                        //            double Cx = endpt.X - currentedge.startendpt[1].X;
                        //            double Cy = endpt.Y - currentedge.startendpt[1].Y;
                        //            double Cz = endpt.Z - currentedge.startendpt[1].Z;
                        //            Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                        //            double Cmag = Vector.VectorMagnitude(C);
                        //            Vector.MemorySafe_CartVect cross2 = Vector.CrossProduct(C, ev);
                        //            crossmag = Vector.VectorMagnitude(cross2);
                        //            if (crossmag == 0)
                        //            {
                        //                //we are at least parallel, in fact we have proven we are totall parallel, now intersect
                        //                double Dx = startpt.X - currentedge.startendpt[1].X;
                        //                double Dy = startpt.Y - currentedge.startendpt[1].Y;
                        //                double Dz = startpt.Z - currentedge.startendpt[1].Z;
                        //                Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                        //                double Dmag = Vector.VectorMagnitude(D);
                        //                if (Cmag < guestmag && Dmag < guestmag)
                        //                {
                        //                    //then it is inside as well, and test vector is engulfed by guest vector
                        //                    kp.Value.relatedEdges.Add(currentedge);
                        //                    //but the edge is still itself unique
                        //                    currentedge.relatedEdges.Add(kp.Value);
                        //                    edgecount++;
                        //                    continue;
                        //                }
                        //                else
                        //                {
                        //                    //I am pretty sure that by default, they are still neighbors and this is no difference
                        //                    //it simply extends beyond one of the ends of the guest vector
                        //                    kp.Value.relatedEdges.Add(currentedge);
                        //                    //but the edge is still itself unique
                        //                    currentedge.relatedEdges.Add(kp.Value);
                        //                    edgecount++;
                        //                    continue;
                        //                }


                        //            }
                        //            else
                        //            {
                        //                //we are not parallel, so this is not an adjacency match
                        //                edgecount++;
                        //                continue;
                        //            }
                        //        }

                        //        else
                        //        {
                        //            //if test edge start point [index 0] is outside, is one of the guest points inside?
                        //            //already computed B
                        //            double Cx = startpt.X - currentedge.startendpt[1].X;
                        //            double Cy = startpt.Y - currentedge.startendpt[1].Y;
                        //            double Cz = startpt.Z - currentedge.startendpt[1].Z;
                        //            Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                        //            double Cmag = Vector.VectorMagnitude(C);

                        //            edgeX = currentedge.startendpt[1].X - currentedge.startendpt[0].X;
                        //            edgeY = currentedge.startendpt[1].Y - currentedge.startendpt[0].Y;
                        //            edgeZ = currentedge.startendpt[1].Z - currentedge.startendpt[0].Z;
                        //            Vector.MemorySafe_CartVect edgevec = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                        //            double edgemag = Vector.VectorMagnitude(edgevec);

                        //            if (Cmag < edgemag && Bmag < edgemag)
                        //            {
                        //                //the guest edge's start point is inside the test edge
                        //                //guest edge point 2 
                        //                double Dx = endpt.X - currentedge.startendpt[1].X;
                        //                double Dy = endpt.Y - currentedge.startendpt[1].Y;
                        //                double Dz = endpt.Z - currentedge.startendpt[1].Z;
                        //                Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                        //                double Dmag = Vector.VectorMagnitude(D);
                        //                Vector.MemorySafe_CartVect cross3 = Vector.CrossProduct(D, edgevec);
                        //                crossmag = Vector.VectorMagnitude(cross3);
                        //                if (crossmag == 0)
                        //                {
                        //                    //then we know the two edges are totall parallel and lined up
                        //                    //determine if the guest edge point 2 is inside the test edge or outside of it
                        //                    double Ex = startpt.X - currentedge.startendpt[1].X;
                        //                    double Ey = startpt.Y - currentedge.startendpt[1].Y;
                        //                    double Ez = startpt.Z - currentedge.startendpt[1].Z;
                        //                    Vector.MemorySafe_CartVect E = new Vector.MemorySafe_CartVect(Ex, Ey, Ez);
                        //                    double Emag = Vector.VectorMagnitude(E);
                        //                    if (Dmag < edgemag && Emag < edgemag)
                        //                    {
                        //                        //it is inside
                        //                        kp.Value.relatedEdges.Add(currentedge);
                        //                        //but the edge is still itself unique
                        //                        currentedge.relatedEdges.Add(kp.Value);
                        //                        edgecount++;
                        //                        continue;
                        //                    }
                        //                    else
                        //                    {
                        //                        //it is outside 
                        //                        kp.Value.relatedEdges.Add(currentedge);
                        //                        //but the edge is still itself unique
                        //                        currentedge.relatedEdges.Add(kp.Value);
                        //                        edgecount++;
                        //                        continue;
                        //                    }
                        //                }
                        //                else
                        //                {
                        //                    //we are not parallel, so this is not an adjacency match
                        //                    edgecount++;
                        //                    continue;
                        //                }

                        //            }
                        //        }
                        //    }
                        //    else
                        //    {
                        //        //they are not even parallel, so it is likely best just to shove on
                        //        edgecount++;
                        //        continue;
                        //    }
                        //}
                                #endregion
                    }
                    //this determines if it found the current edge to be unique, or not.  
                    if (edgecount == uniqueedges.Count)
                    {
                        uniqueedges.Add(distinctedges, currentedge);
                        distinctedges++;
                    }

                }
            }
            return uniqueedges;
        }
        //this helps me to create an in-memory way to store the relationship between different edges.
        public static DOEgbXMLReportingObj FindMatchingEdges(DOEgbXML.gbXMLSpaces.ClosedShell cs, DOEgbXMLReportingObj report)
        {
            report.MessageList.Add("Starting test to find edge relationships for space closed shell polyloops.");
            try
            {
                Dictionary<int, DOEgbXMLBasics.EdgeFamily> edges = new Dictionary<int, DOEgbXMLBasics.EdgeFamily>();
                int distinctedges = 0;
                for (int plcount = 0; plcount < cs.ploops.Count(); plcount++)
                {
                    gbXMLSpaces.PolyLoop pl = cs.ploops[plcount];
                    int coordcount = pl.plcoords.Count;
                    for (int i = 0; i < coordcount; i++)
                    {
                        //test edge
                        DOEgbXMLBasics.EdgeFamily edge = new DOEgbXMLBasics.EdgeFamily();
                        edge.sbdec = plcount.ToString();
                        edge.relatedEdges = new List<DOEgbXMLBasics.EdgeFamily>();
                        edge.startendpt = new List<Vector.MemorySafe_CartCoord>();
                        if (edges.Count == 0)
                        {
                            edges[distinctedges] = edge;
                            edge.startendpt.Add(pl.plcoords[i]);
                            edge.startendpt.Add(pl.plcoords[i + 1]);
                            edge.sbdec = plcount.ToString();

                            distinctedges++;
                            continue;

                        }
                        //most edges work the same, in terms of the start and end point, except for the last edge (the else case)
                        if (i < coordcount - 1)
                        {
                            edge.startendpt.Add(pl.plcoords[i]);
                            edge.startendpt.Add(pl.plcoords[i + 1]);
                            //search through existing edges to try and find a perfect match
                            int edgecount = 0; //keeps track of how many guest edges in the dictionary I've searched through
                            foreach (KeyValuePair<int, DOEgbXMLBasics.EdgeFamily> kp in edges)
                            {

                                Vector.MemorySafe_CartCoord startpt = kp.Value.startendpt[0];
                                //tolerance needed?
                                if (startpt.X == edge.startendpt[0].X && startpt.Y == edge.startendpt[0].Y && startpt.Z == edge.startendpt[0].Z)
                                {
                                    //found at least one perfect coordinate match, try to match the second
                                    Vector.MemorySafe_CartCoord endpt = kp.Value.startendpt[1];
                                    if (endpt.X == edge.startendpt[1].X && endpt.Y == edge.startendpt[1].Y && endpt.Z == edge.startendpt[1].Z)
                                    {
                                        //both match, means the match is perfect, so add it to the related surfaces list
                                        kp.Value.relatedEdges.Add(edge);
                                        string startcoord = MakeCoordString(edge.startendpt[0]);
                                        string endcoord = MakeCoordString(edge.startendpt[1]);
                                        report.MessageList.Add("Edge "+startcoord+" , "+endcoord+" found a perfect match");
                                        break;
                                    }
                                    else
                                    {
                                        //the edge may be unique, though it could still have neighboring relationships
                                        //draw vector A
                                        double Ax = endpt.X - edge.startendpt[1].X;
                                        double Ay = endpt.Y - edge.startendpt[1].Y;
                                        double Az = endpt.Z - edge.startendpt[1].Z;
                                        Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);
                                        double Amag = Vector.VectorMagnitude(A);

                                        //take cross product to see if they are even in same plane
                                        double evX = endpt.X - startpt.X;
                                        double evY = endpt.Y - startpt.Y;
                                        double evZ = endpt.Z - startpt.Z;
                                        Vector.MemorySafe_CartVect ev = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                                        double evmag = Vector.VectorMagnitude(ev);
                                        Vector.MemorySafe_CartVect cross = Vector.CrossProduct(A, ev);
                                        double crossmag = Vector.VectorMagnitude(cross);
                                        //tolerance?
                                        if (crossmag == 0)
                                        {
                                            //then we are at least parallel or antiparallel, now see if the point resides on the edge or outside of it
                                            double Bx = startpt.X - edge.startendpt[1].X;
                                            double By = startpt.Y - edge.startendpt[1].Y;
                                            double Bz = startpt.Z - edge.startendpt[1].Z;
                                            Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);
                                            double Bmag = Vector.VectorMagnitude(B);
                                            //check to see if the test edge is inside the guest edge
                                            if (Amag < evmag && Bmag < evmag)
                                            {
                                                //this means it lies on the plane at least, so it shares, but it is also still independent because a perfect match wasn't found
                                                kp.Value.relatedEdges.Add(edge);
                                                //accumulate its own relationships
                                                edge.relatedEdges.Add(kp.Value);
                                                edgecount++;
                                                string startcoord = MakeCoordString(edge.startendpt[0]);
                                                string endcoord = MakeCoordString(edge.startendpt[1]);
                                                report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                continue;
                                            }

                                            double edgeX = edge.startendpt[1].X - edge.startendpt[0].X;
                                            double edgeY = edge.startendpt[1].Y - edge.startendpt[0].Y;
                                            double edgeZ = edge.startendpt[1].Z - edge.startendpt[0].Z;
                                            Vector.MemorySafe_CartVect edgevec = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                                            double edgemag = Vector.VectorMagnitude(edgevec);

                                            double Cx = startpt.X - edge.startendpt[1].X;
                                            double Cy = startpt.Y - edge.startendpt[1].Y;
                                            double Cz = startpt.Z - edge.startendpt[1].Z;
                                            Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                                            double Cmag = Vector.VectorMagnitude(C);

                                            double Dx = endpt.X - edge.startendpt[1].X;
                                            double Dy = endpt.Y - edge.startendpt[1].Y;
                                            double Dz = endpt.Z - edge.startendpt[1].Z;
                                            Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                                            double Dmag = Vector.VectorMagnitude(D);

                                            if (Dmag < edgemag && Cmag < edgemag)
                                            {
                                                //this means the test edge is longer than the guest edge, but they overlap
                                                kp.Value.relatedEdges.Add(edge);
                                                //the edge is still unique but accumulates a neighbor
                                                edge.relatedEdges.Add(kp.Value);
                                                edgecount++;
                                                string startcoord = MakeCoordString(edge.startendpt[0]);
                                                string endcoord = MakeCoordString(edge.startendpt[1]);
                                                report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                continue;
                                            }

                                        }
                                        else
                                        {
                                            //this other point isn't relevant, and the edges don't coincide
                                            edgecount++;
                                            continue;
                                        }

                                    }


                                }
                                else if (startpt.X == edge.startendpt[1].X && startpt.Y == edge.startendpt[1].Y && startpt.Z == edge.startendpt[1].Z)
                                {
                                    //found at least one perfect coordinate match, try to match the second
                                    Vector.MemorySafe_CartCoord endpt = kp.Value.startendpt[1];
                                    if (endpt.X == edge.startendpt[0].X && endpt.Y == edge.startendpt[0].Y && endpt.Z == edge.startendpt[0].Z)
                                    {
                                        //both match, means the match is perfect, so add it to the related surfaces list
                                        kp.Value.relatedEdges.Add(edge);
                                        string startcoord = MakeCoordString(edge.startendpt[0]);
                                        string endcoord = MakeCoordString(edge.startendpt[1]);
                                        report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a perfect match");
                                        break;

                                    }
                                    else
                                    {
                                        //the edge may be unique, though it could still have neighboring relationships
                                        double Ax = endpt.X - edge.startendpt[0].X;
                                        double Ay = endpt.Y - edge.startendpt[0].Y;
                                        double Az = endpt.Z - edge.startendpt[0].Z;
                                        Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);
                                        double Amag = Vector.VectorMagnitude(A);

                                        //take cross product to see if they are even in same plane
                                        double evX = endpt.X - startpt.X;
                                        double evY = endpt.Y - startpt.Y;
                                        double evZ = endpt.Z - startpt.Z;
                                        Vector.MemorySafe_CartVect ev = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                                        double evmag = Vector.VectorMagnitude(ev);
                                        Vector.MemorySafe_CartVect cross = Vector.CrossProduct(A, ev);
                                        double crossmag = Vector.VectorMagnitude(cross);
                                        //tolerance?
                                        if (crossmag == 0)
                                        {
                                            //then we are at least parallel or antiparallel, now see if the point resides on the edge or outside of it
                                            double Bx = startpt.X - edge.startendpt[0].X;
                                            double By = startpt.Y - edge.startendpt[0].Y;
                                            double Bz = startpt.Z - edge.startendpt[0].Z;
                                            Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);
                                            double Bmag = Vector.VectorMagnitude(B);
                                            //check to see if the test edge is inside the guest edge
                                            if (Amag < evmag && Bmag < evmag)
                                            {
                                                //this means it lies on the plane at least, so it shares, but it is also still independent because a perfect match wasn't found
                                                kp.Value.relatedEdges.Add(edge);
                                                //accumulate its own relationships
                                                edge.relatedEdges.Add(kp.Value);
                                                edgecount++;
                                                string startcoord = MakeCoordString(edge.startendpt[0]);
                                                string endcoord = MakeCoordString(edge.startendpt[1]);
                                                report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                continue;
                                            }

                                            double edgeX = edge.startendpt[1].X - edge.startendpt[0].X;
                                            double edgeY = edge.startendpt[1].Y - edge.startendpt[0].Y;
                                            double edgeZ = edge.startendpt[1].Z - edge.startendpt[0].Z;
                                            Vector.MemorySafe_CartVect edgevec = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                                            double edgemag = Vector.VectorMagnitude(edgevec);

                                            double Cx = startpt.X - edge.startendpt[0].X;
                                            double Cy = startpt.Y - edge.startendpt[0].Y;
                                            double Cz = startpt.Z - edge.startendpt[0].Z;
                                            Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                                            double Cmag = Vector.VectorMagnitude(C);

                                            double Dx = endpt.X - edge.startendpt[0].X;
                                            double Dy = endpt.Y - edge.startendpt[0].Y;
                                            double Dz = endpt.Z - edge.startendpt[0].Z;
                                            Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                                            double Dmag = Vector.VectorMagnitude(D);

                                            if (Dmag < edgemag && Cmag < edgemag)
                                            {
                                                //this means the test edge is longer than the guest edge, but they overlap
                                                kp.Value.relatedEdges.Add(edge);
                                                //the edge is still unique but accumulates a neighbor
                                                edge.relatedEdges.Add(kp.Value);
                                                edgecount++;
                                                string startcoord = MakeCoordString(edge.startendpt[0]);
                                                string endcoord = MakeCoordString(edge.startendpt[1]);
                                                report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                continue;
                                            }
                                        }
                                        else
                                        {
                                            //this other point isn't relevant, and the edges don't coincide
                                            edgecount++;
                                            continue;
                                        }
                                    }

                                }
                                //neither points perfectly coincide, so we do an exhaustive overlap check.
                                else
                                {
                                    Vector.MemorySafe_CartCoord endpt = kp.Value.startendpt[1];
                                    //are the two vectors even parallel?  because if they are not, no need to get more complex
                                    double evX = endpt.X - startpt.X;
                                    double evY = endpt.Y - startpt.Y;
                                    double evZ = endpt.Z - startpt.Z;
                                    Vector.MemorySafe_CartVect ev = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                                    double edgeX = edge.startendpt[1].X - edge.startendpt[0].X;
                                    double edgeY = edge.startendpt[1].Y - edge.startendpt[0].Y;
                                    double edgeZ = edge.startendpt[1].Z - edge.startendpt[0].Z;
                                    Vector.MemorySafe_CartVect edgev = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                                    if (Vector.VectorMagnitude(Vector.CrossProduct(ev, edgev)) != 0)
                                    {
                                        //they are not even parallel so move on
                                        edgecount++;
                                        continue;
                                    }

                                    //try to determine if the two edges are parallel
                                    //test edge point 1
                                    double Ax = endpt.X - edge.startendpt[0].X;
                                    double Ay = endpt.Y - edge.startendpt[0].Y;
                                    double Az = endpt.Z - edge.startendpt[0].Z;
                                    Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);
                                    double Amag = Vector.VectorMagnitude(A);

                                    //take cross product to see if they are even in same plane
                                    evX = endpt.X - startpt.X;
                                    evY = endpt.Y - startpt.Y;
                                    evZ = endpt.Z - startpt.Z;
                                    Vector.MemorySafe_CartVect ev1 = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                                    double guestmag = Vector.VectorMagnitude(ev1);
                                    Vector.MemorySafe_CartVect cross1 = Vector.CrossProduct(A, ev1);
                                    double crossmag = Vector.VectorMagnitude(cross1);
                                    //tolerance?
                                    if (crossmag == 0)
                                    {
                                        //we are at least parallel, now to check for a real intersection
                                        double Bx = startpt.X - edge.startendpt[0].X;
                                        double By = startpt.Y - edge.startendpt[0].Y;
                                        double Bz = startpt.Z - edge.startendpt[0].Z;
                                        Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);
                                        double Bmag = Vector.VectorMagnitude(B);
                                        //check to see if the test edge's first point (index 0) is totally inside the guest edge
                                        if (Amag < guestmag && Bmag < guestmag)
                                        {
                                            //the start point of the test edge is inside the guest edge
                                            //test edge point 2 against guest edge point 2
                                            double Cx = endpt.X - edge.startendpt[1].X;
                                            double Cy = endpt.Y - edge.startendpt[1].Y;
                                            double Cz = endpt.Z - edge.startendpt[1].Z;
                                            Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                                            double Cmag = Vector.VectorMagnitude(C);
                                            Vector.MemorySafe_CartVect cross2 = Vector.CrossProduct(C, ev);
                                            crossmag = Vector.VectorMagnitude(cross2);
                                            if (crossmag == 0)
                                            {
                                                //we are at least parallel, in fact we have proven we are totall parallel, now intersect
                                                double Dx = startpt.X - edge.startendpt[1].X;
                                                double Dy = startpt.Y - edge.startendpt[1].Y;
                                                double Dz = startpt.Z - edge.startendpt[1].Z;
                                                Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                                                double Dmag = Vector.VectorMagnitude(D);
                                                if (Cmag < guestmag && Dmag < guestmag)
                                                {
                                                    //then it is inside as well, and test vector is engulfed by guest vector
                                                    kp.Value.relatedEdges.Add(edge);
                                                    //but the edge is still itself unique
                                                    edge.relatedEdges.Add(kp.Value);
                                                    edgecount++;
                                                    string startcoord = MakeCoordString(edge.startendpt[0]);
                                                    string endcoord = MakeCoordString(edge.startendpt[1]);
                                                    report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                    continue;
                                                }
                                                else
                                                {
                                                    //I am pretty sure that by default, they are still neighbors and this is no difference
                                                    //it simply extends beyond one of the ends of the guest vector
                                                    kp.Value.relatedEdges.Add(edge);
                                                    //but the edge is still itself unique
                                                    edge.relatedEdges.Add(kp.Value);
                                                    edgecount++;
                                                    string startcoord = MakeCoordString(edge.startendpt[0]);
                                                    string endcoord = MakeCoordString(edge.startendpt[1]);
                                                    report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                    continue;
                                                }


                                            }
                                            else
                                            {
                                                //we are not parallel, so this is not an adjacency match
                                                edgecount++;
                                                continue;
                                            }
                                        }
                                        else
                                        {
                                            //if test edge start point [index 0] is outside, is one of the guest points inside?
                                            //already computed B
                                            double Cx = startpt.X - edge.startendpt[1].X;
                                            double Cy = startpt.Y - edge.startendpt[1].Y;
                                            double Cz = startpt.Z - edge.startendpt[1].Z;
                                            Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                                            double Cmag = Vector.VectorMagnitude(C);

                                            edgeX = edge.startendpt[1].X - edge.startendpt[0].X;
                                            edgeY = edge.startendpt[1].Y - edge.startendpt[0].Y;
                                            edgeZ = edge.startendpt[1].Z - edge.startendpt[0].Z;
                                            Vector.MemorySafe_CartVect edgevec = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                                            double edgemag = Vector.VectorMagnitude(edgevec);

                                            if (Cmag < edgemag && Bmag < edgemag)
                                            {
                                                //the guest edge's start point is inside the test edge
                                                //guest edge point 2 
                                                double Dx = endpt.X - edge.startendpt[1].X;
                                                double Dy = endpt.Y - edge.startendpt[1].Y;
                                                double Dz = endpt.Z - edge.startendpt[1].Z;
                                                Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                                                double Dmag = Vector.VectorMagnitude(D);
                                                Vector.MemorySafe_CartVect cross3 = Vector.CrossProduct(D, edgevec);
                                                crossmag = Vector.VectorMagnitude(cross3);
                                                if (crossmag == 0)
                                                {
                                                    //then we know the two edges are totall parallel and lined up
                                                    //determine if the guest edge point 2 is inside the test edge or outside of it
                                                    double Ex = startpt.X - edge.startendpt[1].X;
                                                    double Ey = startpt.Y - edge.startendpt[1].Y;
                                                    double Ez = startpt.Z - edge.startendpt[1].Z;
                                                    Vector.MemorySafe_CartVect E = new Vector.MemorySafe_CartVect(Ex, Ey, Ez);
                                                    double Emag = Vector.VectorMagnitude(E);
                                                    if (Dmag < edgemag && Emag < edgemag)
                                                    {
                                                        //it is inside
                                                        kp.Value.relatedEdges.Add(edge);
                                                        //but the edge is still itself unique
                                                        edge.relatedEdges.Add(kp.Value);
                                                        edgecount++;
                                                        string startcoord = MakeCoordString(edge.startendpt[0]);
                                                        string endcoord = MakeCoordString(edge.startendpt[1]);
                                                        report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                        continue;

                                                    }
                                                    else
                                                    {
                                                        //it is outside 
                                                        kp.Value.relatedEdges.Add(edge);
                                                        //but the edge is still itself unique
                                                        edge.relatedEdges.Add(kp.Value);
                                                        edgecount++;
                                                        string startcoord = MakeCoordString(edge.startendpt[0]);
                                                        string endcoord = MakeCoordString(edge.startendpt[1]);
                                                        report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                        continue;
                                                    }
                                                }
                                                else
                                                {
                                                    //we are not parallel, so this is not an adjacency match
                                                    edgecount++;
                                                    continue;
                                                }

                                            }
                                        }



                                    }
                                    else
                                    {
                                        //they are not even parallel, so it is likely best just to shove on
                                        edgecount++;
                                        continue;
                                    }


                                }
                            }
                            //this determines if it found a matching edge
                            if (edgecount == edges.Count)
                            {
                                edges.Add(distinctedges, edge);
                                distinctedges++;
                            }

                        }
                        //last edge end edge is the zero index   
                        else
                        {
                            edge.startendpt.Add(pl.plcoords[i]);
                            edge.startendpt.Add(pl.plcoords[0]);
                            int edgecount = 0; //keeps track of how many guest edges in the dictionary I've searched through
                            foreach (KeyValuePair<int, DOEgbXMLBasics.EdgeFamily> kp in edges)
                            {

                                Vector.MemorySafe_CartCoord startpt = kp.Value.startendpt[0];
                                //tolerance needed?
                                if (startpt.X == edge.startendpt[0].X && startpt.Y == edge.startendpt[0].Y && startpt.Z == edge.startendpt[0].Z)
                                {
                                    //found at least one perfect coordinate match, try to match the second
                                    Vector.MemorySafe_CartCoord endpt = kp.Value.startendpt[1];
                                    if (endpt.X == edge.startendpt[1].X && endpt.Y == edge.startendpt[1].Y && endpt.Z == edge.startendpt[1].Z)
                                    {
                                        //both match, means the match is perfect, so add it to the related surfaces list
                                        kp.Value.relatedEdges.Add(edge);
                                        string startcoord = MakeCoordString(edge.startendpt[0]);
                                        string endcoord = MakeCoordString(edge.startendpt[1]);
                                        report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a perfect match");
                                        break;
                                    }
                                    else
                                    {
                                        //the edge may be unique, though it could still have neighboring relationships
                                        //draw vector A
                                        double Ax = endpt.X - edge.startendpt[1].X;
                                        double Ay = endpt.Y - edge.startendpt[1].Y;
                                        double Az = endpt.Z - edge.startendpt[1].Z;
                                        Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);
                                        double Amag = Vector.VectorMagnitude(A);

                                        //take cross product to see if they are even in same plane
                                        double evX = endpt.X - startpt.X;
                                        double evY = endpt.Y - startpt.Y;
                                        double evZ = endpt.Z - startpt.Z;
                                        Vector.MemorySafe_CartVect ev = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                                        double evmag = Vector.VectorMagnitude(ev);
                                        Vector.MemorySafe_CartVect cross = Vector.CrossProduct(A, ev);
                                        double crossmag = Vector.VectorMagnitude(cross);
                                        //tolerance?
                                        if (crossmag == 0)
                                        {
                                            //then we are at least parallel or antiparallel, now see if the point resides on the edge or outside of it
                                            double Bx = startpt.X - edge.startendpt[1].X;
                                            double By = startpt.Y - edge.startendpt[1].Y;
                                            double Bz = startpt.Z - edge.startendpt[1].Z;
                                            Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);
                                            double Bmag = Vector.VectorMagnitude(B);
                                            //check to see if the test edge is inside the guest edge
                                            if (Amag < evmag && Bmag < evmag)
                                            {
                                                //this means it lies on the plane at least, so it shares, but it is also still independent because a perfect match wasn't found
                                                kp.Value.relatedEdges.Add(edge);
                                                //accumulate its own relationships
                                                edge.relatedEdges.Add(kp.Value);
                                                edgecount++;
                                                string startcoord = MakeCoordString(edge.startendpt[0]);
                                                string endcoord = MakeCoordString(edge.startendpt[1]);
                                                report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                continue;
                                            }

                                            double edgeX = edge.startendpt[1].X - edge.startendpt[0].X;
                                            double edgeY = edge.startendpt[1].Y - edge.startendpt[0].Y;
                                            double edgeZ = edge.startendpt[1].Z - edge.startendpt[0].Z;
                                            Vector.MemorySafe_CartVect edgevec = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                                            double edgemag = Vector.VectorMagnitude(edgevec);

                                            double Cx = startpt.X - edge.startendpt[1].X;
                                            double Cy = startpt.Y - edge.startendpt[1].Y;
                                            double Cz = startpt.Z - edge.startendpt[1].Z;
                                            Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                                            double Cmag = Vector.VectorMagnitude(C);

                                            double Dx = endpt.X - edge.startendpt[1].X;
                                            double Dy = endpt.Y - edge.startendpt[1].Y;
                                            double Dz = endpt.Z - edge.startendpt[1].Z;
                                            Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                                            double Dmag = Vector.VectorMagnitude(D);

                                            if (Dmag < edgemag && Cmag < edgemag)
                                            {
                                                //this means the test edge is longer than the guest edge, but they overlap
                                                kp.Value.relatedEdges.Add(edge);
                                                //the edge is still unique but accumulates a neighbor
                                                edge.relatedEdges.Add(kp.Value);
                                                edgecount++;
                                                string startcoord = MakeCoordString(edge.startendpt[0]);
                                                string endcoord = MakeCoordString(edge.startendpt[1]);
                                                report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                continue;
                                            }

                                        }
                                        else
                                        {
                                            //this other point isn't relevant, and the edges don't coincide
                                            edgecount++;
                                            continue;
                                        }

                                    }


                                }
                                else if (startpt.X == edge.startendpt[1].X && startpt.Y == edge.startendpt[1].Y && startpt.Z == edge.startendpt[1].Z)
                                {
                                    //found at least one perfect coordinate match, try to match the second
                                    Vector.MemorySafe_CartCoord endpt = kp.Value.startendpt[1];
                                    if (endpt.X == edge.startendpt[0].X && endpt.Y == edge.startendpt[0].Y && endpt.Z == edge.startendpt[0].Z)
                                    {
                                        //both match, means the match is perfect, so add it to the related surfaces list
                                        kp.Value.relatedEdges.Add(edge);
                                        string startcoord = MakeCoordString(edge.startendpt[0]);
                                        string endcoord = MakeCoordString(edge.startendpt[1]);
                                        report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a perfect match");
                                        break;

                                    }
                                    else
                                    {
                                        //the edge may be unique, though it could still have neighboring relationships
                                        double Ax = endpt.X - edge.startendpt[0].X;
                                        double Ay = endpt.Y - edge.startendpt[0].Y;
                                        double Az = endpt.Z - edge.startendpt[0].Z;
                                        Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);
                                        double Amag = Vector.VectorMagnitude(A);

                                        //take cross product to see if they are even in same plane
                                        double evX = endpt.X - startpt.X;
                                        double evY = endpt.Y - startpt.Y;
                                        double evZ = endpt.Z - startpt.Z;
                                        Vector.MemorySafe_CartVect ev = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                                        double evmag = Vector.VectorMagnitude(ev);
                                        Vector.MemorySafe_CartVect cross = Vector.CrossProduct(A, ev);
                                        double crossmag = Vector.VectorMagnitude(cross);
                                        //tolerance?
                                        if (crossmag == 0)
                                        {
                                            //then we are at least parallel or antiparallel, now see if the point resides on the edge or outside of it
                                            double Bx = startpt.X - edge.startendpt[0].X;
                                            double By = startpt.Y - edge.startendpt[0].Y;
                                            double Bz = startpt.Z - edge.startendpt[0].Z;
                                            Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);
                                            double Bmag = Vector.VectorMagnitude(B);
                                            //check to see if the test edge is inside the guest edge
                                            if (Amag < evmag && Bmag < evmag)
                                            {
                                                //this means it lies on the plane at least, so it shares, but it is also still independent because a perfect match wasn't found
                                                kp.Value.relatedEdges.Add(edge);
                                                //accumulate its own relationships
                                                edge.relatedEdges.Add(kp.Value);
                                                edgecount++;
                                                string startcoord = MakeCoordString(edge.startendpt[0]);
                                                string endcoord = MakeCoordString(edge.startendpt[1]);
                                                report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                continue;
                                            }

                                            double edgeX = edge.startendpt[1].X - edge.startendpt[0].X;
                                            double edgeY = edge.startendpt[1].Y - edge.startendpt[0].Y;
                                            double edgeZ = edge.startendpt[1].Z - edge.startendpt[0].Z;
                                            Vector.MemorySafe_CartVect edgevec = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                                            double edgemag = Vector.VectorMagnitude(edgevec);

                                            double Cx = startpt.X - edge.startendpt[0].X;
                                            double Cy = startpt.Y - edge.startendpt[0].Y;
                                            double Cz = startpt.Z - edge.startendpt[0].Z;
                                            Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                                            double Cmag = Vector.VectorMagnitude(C);

                                            double Dx = endpt.X - edge.startendpt[0].X;
                                            double Dy = endpt.Y - edge.startendpt[0].Y;
                                            double Dz = endpt.Z - edge.startendpt[0].Z;
                                            Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                                            double Dmag = Vector.VectorMagnitude(D);

                                            if (Dmag < edgemag && Cmag < edgemag)
                                            {
                                                //this means the test edge is longer than the guest edge, but they overlap
                                                kp.Value.relatedEdges.Add(edge);
                                                //the edge is still unique but accumulates a neighbor
                                                edge.relatedEdges.Add(kp.Value);
                                                edgecount++;
                                                string startcoord = MakeCoordString(edge.startendpt[0]);
                                                string endcoord = MakeCoordString(edge.startendpt[1]);
                                                report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                continue;
                                            }
                                        }
                                        else
                                        {
                                            //this other point isn't relevant, and the edges don't coincide
                                            edgecount++;
                                            continue;
                                        }
                                    }

                                }
                                //neither points perfectly coincide, so we do an exhaustive overlap check.
                                else
                                {
                                    Vector.MemorySafe_CartCoord endpt = kp.Value.startendpt[1];
                                    //are the two vectors even parallel?  because if they are not, no need to get more complex
                                    double evX = endpt.X - startpt.X;
                                    double evY = endpt.Y - startpt.Y;
                                    double evZ = endpt.Z - startpt.Z;
                                    Vector.MemorySafe_CartVect ev = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                                    double edgeX = edge.startendpt[1].X - edge.startendpt[0].X;
                                    double edgeY = edge.startendpt[1].Y - edge.startendpt[0].Y;
                                    double edgeZ = edge.startendpt[1].Z - edge.startendpt[0].Z;
                                    Vector.MemorySafe_CartVect edgev = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                                    if (Vector.VectorMagnitude(Vector.CrossProduct(ev, edgev)) != 0)
                                    {
                                        //they are not even parallel so move on
                                        edgecount++;
                                        continue;
                                    }
                                    //try to determine if the two edges are parallel

                                    //test edge point 1
                                    double Ax = endpt.X - edge.startendpt[0].X;
                                    double Ay = endpt.Y - edge.startendpt[0].Y;
                                    double Az = endpt.Z - edge.startendpt[0].Z;
                                    Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);
                                    double Amag = Vector.VectorMagnitude(A);

                                    //take cross product to see if they are even in same plane
                                    evX = endpt.X - startpt.X;
                                    evY = endpt.Y - startpt.Y;
                                    evZ = endpt.Z - startpt.Z;
                                    Vector.MemorySafe_CartVect ev1 = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                                    double guestmag = Vector.VectorMagnitude(ev);
                                    Vector.MemorySafe_CartVect cross1 = Vector.CrossProduct(A, ev);
                                    double crossmag = Vector.VectorMagnitude(cross1);
                                    //tolerance?
                                    if (crossmag == 0)
                                    {
                                        //we are at least parallel, now to check for a real intersection
                                        double Bx = startpt.X - edge.startendpt[0].X;
                                        double By = startpt.Y - edge.startendpt[0].Y;
                                        double Bz = startpt.Z - edge.startendpt[0].Z;
                                        Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);
                                        double Bmag = Vector.VectorMagnitude(B);
                                        //check to see if the test edge's first point (index 0) is totally inside the guest edge
                                        if (Amag < guestmag && Bmag < guestmag)
                                        {
                                            //the start point of the test edge is inside the guest edge
                                            //test edge point 2 against guest edge point 2
                                            double Cx = endpt.X - edge.startendpt[1].X;
                                            double Cy = endpt.Y - edge.startendpt[1].Y;
                                            double Cz = endpt.Z - edge.startendpt[1].Z;
                                            Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                                            double Cmag = Vector.VectorMagnitude(C);
                                            Vector.MemorySafe_CartVect cross2 = Vector.CrossProduct(C, ev);
                                            crossmag = Vector.VectorMagnitude(cross2);
                                            if (crossmag == 0)
                                            {
                                                //we are at least parallel, in fact we have proven we are totall parallel, now intersect
                                                double Dx = startpt.X - edge.startendpt[1].X;
                                                double Dy = startpt.Y - edge.startendpt[1].Y;
                                                double Dz = startpt.Z - edge.startendpt[1].Z;
                                                Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                                                double Dmag = Vector.VectorMagnitude(D);
                                                if (Cmag < guestmag && Dmag < guestmag)
                                                {
                                                    //then it is inside as well, and test vector is engulfed by guest vector
                                                    kp.Value.relatedEdges.Add(edge);
                                                    //but the edge is still itself unique
                                                    edge.relatedEdges.Add(kp.Value);
                                                    edgecount++;
                                                    string startcoord = MakeCoordString(edge.startendpt[0]);
                                                    string endcoord = MakeCoordString(edge.startendpt[1]);
                                                    report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                    continue;
                                                }
                                                else
                                                {
                                                    //I am pretty sure that by default, they are still neighbors and this is no difference
                                                    //it simply extends beyond one of the ends of the guest vector
                                                    kp.Value.relatedEdges.Add(edge);
                                                    //but the edge is still itself unique
                                                    edge.relatedEdges.Add(kp.Value);
                                                    edgecount++;
                                                    string startcoord = MakeCoordString(edge.startendpt[0]);
                                                    string endcoord = MakeCoordString(edge.startendpt[1]);
                                                    report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                    continue;
                                                }


                                            }
                                            else
                                            {
                                                //we are not parallel, so this is not an adjacency match
                                                edgecount++;
                                                continue;
                                            }
                                        }
                                        else
                                        {
                                            //if test edge start point [index 0] is outside, is one of the guest points inside?
                                            //already computed B
                                            double Cx = startpt.X - edge.startendpt[1].X;
                                            double Cy = startpt.Y - edge.startendpt[1].Y;
                                            double Cz = startpt.Z - edge.startendpt[1].Z;
                                            Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                                            double Cmag = Vector.VectorMagnitude(C);

                                            edgeX = edge.startendpt[1].X - edge.startendpt[0].X;
                                            edgeY = edge.startendpt[1].Y - edge.startendpt[0].Y;
                                            edgeZ = edge.startendpt[1].Z - edge.startendpt[0].Z;
                                            Vector.MemorySafe_CartVect edgevec = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                                            double edgemag = Vector.VectorMagnitude(edgevec);

                                            if (Cmag < edgemag && Bmag < edgemag)
                                            {
                                                //the guest edge's start point is inside the test edge
                                                //guest edge point 2 
                                                double Dx = endpt.X - edge.startendpt[1].X;
                                                double Dy = endpt.Y - edge.startendpt[1].Y;
                                                double Dz = endpt.Z - edge.startendpt[1].Z;
                                                Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                                                double Dmag = Vector.VectorMagnitude(D);
                                                Vector.MemorySafe_CartVect cross3 = Vector.CrossProduct(D, edgevec);
                                                crossmag = Vector.VectorMagnitude(cross3);
                                                if (crossmag == 0)
                                                {
                                                    //then we know the two edges are totall parallel and lined up
                                                    //determine if the guest edge point 2 is inside the test edge or outside of it
                                                    double Ex = startpt.X - edge.startendpt[1].X;
                                                    double Ey = startpt.Y - edge.startendpt[1].Y;
                                                    double Ez = startpt.Z - edge.startendpt[1].Z;
                                                    Vector.MemorySafe_CartVect E = new Vector.MemorySafe_CartVect(Ex, Ey, Ez);
                                                    double Emag = Vector.VectorMagnitude(E);
                                                    if (Dmag < edgemag && Emag < edgemag)
                                                    {
                                                        //it is inside
                                                        kp.Value.relatedEdges.Add(edge);
                                                        //but the edge is still itself unique
                                                        edge.relatedEdges.Add(kp.Value);
                                                        edgecount++;
                                                        string startcoord = MakeCoordString(edge.startendpt[0]);
                                                        string endcoord = MakeCoordString(edge.startendpt[1]);
                                                        report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                        continue;
                                                    }
                                                    else
                                                    {
                                                        //it is outside 
                                                        kp.Value.relatedEdges.Add(edge);
                                                        //but the edge is still itself unique
                                                        edge.relatedEdges.Add(kp.Value);
                                                        edgecount++;
                                                        string startcoord = MakeCoordString(edge.startendpt[0]);
                                                        string endcoord = MakeCoordString(edge.startendpt[1]);
                                                        report.MessageList.Add("Edge " + startcoord + " , " + endcoord + " found a match");
                                                        continue;
                                                    }
                                                }
                                                else
                                                {
                                                    //we are not parallel, so this is not an adjacency match
                                                    edgecount++;
                                                    continue;
                                                }

                                            }
                                        }



                                    }
                                    else
                                    {
                                        //they are not even parallel, so it is likely best just to shove on
                                        edgecount++;
                                        continue;
                                    }


                                }
                            }
                            //this determines if it found a matching edge
                            if (edgecount == edges.Count)
                            {
                                edges.Add(distinctedges, edge);
                                distinctedges++;
                            }
                        }

                    }
                }
            }
            catch (Exception e)
            {
                report.longMsg = e.ToString();
                report.MessageList.Add("This test has failed unexpectedly.");
                report.passOrFail = false;
                return report;
            }

            return report;
        }
Beispiel #12
0
        public static Dictionary<int, DOEgbXMLBasics.EdgeFamily> FindEdgeMatch(Dictionary<int, DOEgbXMLBasics.EdgeFamily> uniqueedges, DOEgbXMLBasics.EdgeFamily edge)
        {
            try
            {
                int edgeloopcounter = 0; //keeps track of how many guest edges in the unique edge dictionary I've searched through
                foreach (KeyValuePair<int, DOEgbXMLBasics.EdgeFamily> kp in uniqueedges)
                {
                    Vector.MemorySafe_CartCoord gueststartpt = kp.Value.startendpt[0];
                    //In the unique edge dictionary, I have located at least one point that is similar to my test edge, a tolerance needed?
                    if (gueststartpt.X == edge.startendpt[0].X && gueststartpt.Y == edge.startendpt[0].Y && gueststartpt.Z == edge.startendpt[0].Z)
                    {
                        //found at least one perfect coordinate match, try to match the second...get the endpoint of the unique edge in the dictionary
                        Vector.MemorySafe_CartCoord guestendpt = kp.Value.startendpt[1];
                        if (guestendpt.X == edge.startendpt[1].X && guestendpt.Y == edge.startendpt[1].Y && guestendpt.Z == edge.startendpt[1].Z)
                        {
                            //both match, means the match is perfect, so the unique edge has found it complement related edge.  Great!
                            kp.Value.relatedEdges.Add(edge);
                            //I am done searching this test edge, and I can start over again with the next edge in question
                            break;

                        }
                        else
                        {
                            //so far, I have found only one thing in common, sharing of one point, even though second point did not match, the edges could still align
                            //draw vector A
                            double Ax = guestendpt.X - edge.startendpt[1].X;
                            double Ay = guestendpt.Y - edge.startendpt[1].Y;
                            double Az = guestendpt.Z - edge.startendpt[1].Z;
                            Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);
                            double Amag = Vector.VectorMagnitude(A);

                            //take cross product to see if they are even in same plane
                            double evX = guestendpt.X - gueststartpt.X;
                            double evY = guestendpt.Y - gueststartpt.Y;
                            double evZ = guestendpt.Z - gueststartpt.Z;
                            Vector.MemorySafe_CartVect ev = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                            double evmag = Vector.VectorMagnitude(ev);
                            Vector.MemorySafe_CartVect cross = Vector.CrossProduct(A, ev);
                            double dot = Vector.DotProduct(A, ev);
                            double crossmag = Vector.VectorMagnitude(cross);
                            //If Vector A and ev are parallel, then the cross product magnitude should be zero, add a small tolerance?
                            if (dot == 1)
                            {
                                //then we are at least parallel but they are perfect matches
                                //now see if both points of the test edge resides ON the  guest edge or OUTSIDE of it
                                double Bx = gueststartpt.X - edge.startendpt[1].X;
                                double By = gueststartpt.Y - edge.startendpt[1].Y;
                                double Bz = gueststartpt.Z - edge.startendpt[1].Z;
                                Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);
                                double Bmag = Vector.VectorMagnitude(B);
                                //check to see if the test edge is inside the guest edge (shorter than)
                                //check to see if the test edge is outside of the guest edge (longer than)
                                //the first check is easier and should always yield an easy answer
                                if (Amag < evmag && Bmag < evmag)
                                {
                                    //true
                                    //we choose to create related edges relationship for test and guest edge because a perfect match wasn't found
                                    //so this test edge is added to the guest unique edge
                                    kp.Value.relatedEdges.Add(edge);
                                    //and the test edge itself accumulate its own relationships (it is seen as sort of unique)
                                    edge.relatedEdges.Add(kp.Value);
                                    //we will continue checking the unique guest edges to look for another match, since we have not found perfection
                                    edgeloopcounter++;
                                    continue;
                                }
                                //otherwise it does not fall inside the guest edge
                                //check now to see if the test edge falls outside of the guest edge
                                //it either overlaps it, or does not overlap it at all
                                //we know the two vectors are parallel and not antiparallel because of the dot product above
                                //now test the quality of their relationship
                            }
                            //some sort of tolerance here?
                            else if (dot == -1)
                            {
                                double testedgeX = edge.startendpt[1].X - edge.startendpt[0].X;
                                double testedgeY = edge.startendpt[1].Y - edge.startendpt[0].Y;
                                double testedgeZ = edge.startendpt[1].Z - edge.startendpt[0].Z;
                                Vector.MemorySafe_CartVect edgevec = new Vector.MemorySafe_CartVect(testedgeX, testedgeY, testedgeZ);
                                double testedgemag = Vector.VectorMagnitude(edgevec);

                                if (evmag < testedgemag)
                                {
                                    //this means the test edge is longer than the guest edge,
                                    //since we know they are parallel and share a common first point, we can conclude
                                    //they overlap but are not perfect matches.
                                    //so each accumulates a relationship
                                    kp.Value.relatedEdges.Add(edge);
                                    //the edge is still unique but accumulates a neighbor
                                    edge.relatedEdges.Add(kp.Value);
                                    edgeloopcounter++;
                                    continue;
                                }
                                //deprecated as not productive code on March 30, 2014

                                //double Cx = gueststartpt.X - edge.startendpt[1].X;
                                //double Cy = gueststartpt.Y - edge.startendpt[1].Y;
                                //double Cz = gueststartpt.Z - edge.startendpt[1].Z;
                                //Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                                //double Cmag = Vector.VectorMagnitude(C);

                                //double Dx = guestendpt.X - edge.startendpt[1].X;
                                //double Dy = guestendpt.Y - edge.startendpt[1].Y;
                                //double Dz = guestendpt.Z - edge.startendpt[1].Z;
                                //Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                                //double Dmag = Vector.VectorMagnitude(D);

                                //if (Dmag < testedgemag && Cmag < testedgemag)
                                //{
                                //    //this means the test edge is longer than the guest edge,
                                //    //since we know they are parallel and share a common first point, we can conclude
                                //    //they overlap but are not perfect matches.
                                //    //so each accumulates a relationship
                                //    kp.Value.relatedEdges.Add(edge);
                                //    //the edge is still unique but accumulates a neighbor
                                //    edge.relatedEdges.Add(kp.Value);
                                //    edgeloopcounter++;
                                //    continue;
                                //}

                            }//are the two lines parallel
                            else
                            {
                                //the two lines aren't parallel, so just move on
                                edgeloopcounter++;
                                continue;
                            }
                        }//else there is not a perfect match
                    } //if one coordinate has perfectly matched
                    //here the the start point of the guest edge matches the end point of the testedge, a switcheroo
                    else if (gueststartpt.X == edge.startendpt[1].X && gueststartpt.Y == edge.startendpt[1].Y && gueststartpt.Z == edge.startendpt[1].Z)
                    {
                        //found at least one perfect coordinate match, try to match the second
                        Vector.MemorySafe_CartCoord guestendpt = kp.Value.startendpt[1];
                        if (guestendpt.X == edge.startendpt[0].X && guestendpt.Y == edge.startendpt[0].Y && guestendpt.Z == edge.startendpt[0].Z)
                        {
                            //both match, means the match is perfect, so add it to the related surfaces list
                            kp.Value.relatedEdges.Add(edge);
                            break;

                        }
                        else
                        {
                            //the edge may be unique, though it could still have neighboring relationships
                            double Ax = guestendpt.X - edge.startendpt[0].X;
                            double Ay = guestendpt.Y - edge.startendpt[0].Y;
                            double Az = guestendpt.Z - edge.startendpt[0].Z;
                            Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);
                            double Amag = Vector.VectorMagnitude(A);

                            //take cross product to see if they are even in same plane
                            double evX = guestendpt.X - gueststartpt.X;
                            double evY = guestendpt.Y - gueststartpt.Y;
                            double evZ = guestendpt.Z - gueststartpt.Z;
                            Vector.MemorySafe_CartVect ev = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                            double evmag = Vector.VectorMagnitude(ev);
                            double dot = Vector.DotProduct(A, ev);
                            Vector.MemorySafe_CartVect cross = Vector.CrossProduct(A, ev);
                            double crossmag = Vector.VectorMagnitude(cross);
                            //tolerance?
                            //we know that they are parallel, and therefore that the test edge is shorter than the guest edge
                            if (dot == 1)
                            {
                                //we now verify if the point resides on the edge or outside of it
                                double Bx = gueststartpt.X - edge.startendpt[0].X;
                                double By = gueststartpt.Y - edge.startendpt[0].Y;
                                double Bz = gueststartpt.Z - edge.startendpt[0].Z;
                                Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);
                                double Bmag = Vector.VectorMagnitude(B);
                                //check to see if the test edge is inside the guest edge
                                if (Amag < evmag && Bmag < evmag)
                                {
                                    //this means it lies on the plane at least, so it shares, but it is also still independent because a perfect match wasn't found
                                    kp.Value.relatedEdges.Add(edge);
                                    //accumulate its own relationships
                                    edge.relatedEdges.Add(kp.Value);
                                    edgeloopcounter++;
                                    continue;
                                }
                            }
                            //we know the lines are antiparallel, meaning that the test edge is longer than the guest edge
                            else if (dot == -1)
                            {
                                double testedgeX = edge.startendpt[1].X - edge.startendpt[0].X;
                                double testedgeY = edge.startendpt[1].Y - edge.startendpt[0].Y;
                                double testedgeZ = edge.startendpt[1].Z - edge.startendpt[0].Z;
                                Vector.MemorySafe_CartVect edgevec = new Vector.MemorySafe_CartVect(testedgeX, testedgeY, testedgeZ);
                                double testedgemag = Vector.VectorMagnitude(edgevec);

                                //we verify
                                if (testedgemag > evmag)
                                {
                                    //this means the test edge is longer than the guest edge, but they overlap
                                    kp.Value.relatedEdges.Add(edge);
                                    //the edge is still unique but accumulates a neighbor
                                    edge.relatedEdges.Add(kp.Value);
                                    edgeloopcounter++;
                                    continue;
                                }
                                //deprecated as not productive code March 30 2014
                                //double Cx = gueststartpt.X - edge.startendpt[0].X;
                                //double Cy = gueststartpt.Y - edge.startendpt[0].Y;
                                //double Cz = gueststartpt.Z - edge.startendpt[0].Z;
                                //Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);
                                //double Cmag = Vector.VectorMagnitude(C);

                                //double Dx = guestendpt.X - edge.startendpt[0].X;
                                //double Dy = guestendpt.Y - edge.startendpt[0].Y;
                                //double Dz = guestendpt.Z - edge.startendpt[0].Z;
                                //Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);
                                //double Dmag = Vector.VectorMagnitude(D);

                                //if (Dmag < testedgemag && Cmag < testedgemag)
                                //{
                                //    //this means the test edge is longer than the guest edge, but they overlap
                                //    kp.Value.relatedEdges.Add(edge);
                                //    //the edge is still unique but accumulates a neighbor
                                //    edge.relatedEdges.Add(kp.Value);
                                //    edgeloopcounter++;
                                //    continue;
                                //}
                            }
                            else
                            {
                                //this other point isn't relevant, and the edges don't coincide
                                edgeloopcounter++;
                                continue;
                            }
                        }

                    }//second point matches first point
                    //neither points perfectly coincide, so we do an exhaustive overlap check.
                    else
                    {
                        Vector.MemorySafe_CartCoord guestendpt = kp.Value.startendpt[1];
                        //are the two vectors even parallel?  because if they are not, no need to get more complex
                        double evX = guestendpt.X - gueststartpt.X;
                        double evY = guestendpt.Y - gueststartpt.Y;
                        double evZ = guestendpt.Z - gueststartpt.Z;
                        Vector.MemorySafe_CartVect guestvec = new Vector.MemorySafe_CartVect(evX, evY, evZ);
                        double guestvecmag = Vector.VectorMagnitude(guestvec);

                        double edgeX = edge.startendpt[1].X - edge.startendpt[0].X;
                        double edgeY = edge.startendpt[1].Y - edge.startendpt[0].Y;
                        double edgeZ = edge.startendpt[1].Z - edge.startendpt[0].Z;
                        Vector.MemorySafe_CartVect testedgev = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                        //tolerance?
                        if (Vector.VectorMagnitude(Vector.CrossProduct(guestvec, testedgev)) != 0)
                        {
                            //they are not even parallel so move on
                            edgeloopcounter++;
                            continue;
                        }
                        //if the cross product is zero
                        //try to determine if the two edges are parallel or antiparallel
                        //test edge point 1

                        double Ax = gueststartpt.X - edge.startendpt[0].X;
                        double Ay = gueststartpt.Y - edge.startendpt[0].Y;
                        double Az = gueststartpt.Z - edge.startendpt[0].Z;
                        Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);
                        double Amag = Vector.VectorMagnitude(A);

                        //take cross product to see if they are even in same plane

                        Vector.MemorySafe_CartVect cross1 = Vector.CrossProduct(A, guestvec);
                        double crossA = Vector.VectorMagnitude(cross1);
                        //tolerance?
                        if (crossA == 0)
                        {
                            //we are at least parallel, now to check for a real intersection
                            double Bx = gueststartpt.X - edge.startendpt[1].X;
                            double By = gueststartpt.Y - edge.startendpt[1].Y;
                            double Bz = gueststartpt.Z - edge.startendpt[1].Z;
                            Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);
                            double Bmag = Vector.VectorMagnitude(B);
                            double crossB = Vector.VectorMagnitude(Vector.CrossProduct(B, guestvec));
                            //check to see if the test edge's first point (index 0) is totally inside the guest edge
                            if (crossB == 0)
                            {
                                //we know they are now surely parallel, and that they are on top of one another, question is, do they overlap?
                                Vector.PointVector guestPV = new Vector.PointVector(gueststartpt, guestendpt);
                                Vector.PointVector test1 = new Vector.PointVector(gueststartpt, edge.startendpt[0]);
                                Vector.PointVector test2 = new Vector.PointVector(gueststartpt, edge.startendpt[1]);

                                bool test1inside = false;
                                bool test2inside = false;
                                //tolerance?
                                if (Vector.DotProduct(guestPV.v, test1.v) == 1)
                                {
                                    //then pointed in the same direction

                                    double ratio = Amag / guestvecmag;
                                    if (ratio > 1)
                                    {
                                        //then this point is outside of evmag
                                    }
                                    else
                                    {
                                        //there is an intersection at the point of the test edge
                                        test1inside = true;
                                    }
                                }
                                //tolerance?
                                if (Vector.DotProduct(guestPV.v, test1.v) == 1)
                                {
                                    //then this second test edge point is in a straight line in the same direction as the vector formed by the test edge
                                    double ratio = Bmag / guestvecmag;
                                    if (ratio > 1)
                                    {
                                        //then this point is outside
                                    }
                                    else
                                    {
                                        //this is also inside
                                        test2inside = true;
                                    }

                                }

                                if (test1inside == true && test2inside == false)
                                {
                                    //make a temporary edge from just point 1 in the test edge
                                    //this should never happen for a single space, should it?

                                }
                                else if (test1inside == false && test2inside == true)
                                {
                                    //make a temporary edge from just point 2 in the test edge
                                    //this should never happen for a single space, should it?
                                }
                                else if (test1inside == true && test2inside == true)
                                {
                                    //the entire test edge is contained within
                                    //this means the test edge is longer than the guest edge, but they overlap
                                    kp.Value.relatedEdges.Add(edge);
                                    //the edge is still unique but accumulates a neighbor
                                    edge.relatedEdges.Add(kp.Value);
                                    edgeloopcounter++;
                                    continue;
                                }
                                else
                                {
                                    //do nothing because neither points reside inside.
                                }

                            }
                        }
                    }
                    int uniqueedgect = uniqueedges.Count() + 1;
                    uniqueedges[uniqueedgect] = edge;
                }

            }
            catch (Exception e)
            {

            }
            return uniqueedges;
        }
Beispiel #13
0
        //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;
            }
        }
        //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);
        }
        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;
            }
        }