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); }
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); } }
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); }
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); }
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; } }
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; }
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; }
//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; } }