internal static Fastener PolynomialTrendDetector(TessellatedSolid solid) { // Assumptions: // 1. In fasteners, length is longer than width. var obb = BoundingGeometry.OrientedBoundingBoxDic[solid]; //if (!solid.Name.Contains("STLB ASM")) return true; const int k = 500; PolygonalFace f1; PolygonalFace f2; var longestSide = GeometryFunctions.LongestPlaneOfObbDetector(obb, out f1, out f2); var partitions = new FastenerBoundingBoxPartition(solid, longestSide[0], 50); // 1. Take the middle point of the smallest edge of each triangle. Or the points of the 2nd longest edge of a side triangle // 2. Generate k points between them with equal distances. // 3. Generate rays using generated points. var midPoint1 = ShortestEdgeMidPointOfTriangle(longestSide[0]); var midPoint2 = ShortestEdgeMidPointOfTriangle(longestSide[1]); var kPointsBetweenMidPoints = KpointBtwPointsGenerator(midPoint1, midPoint2, k); double longestDist; var distancePointToSolid = PointToSolidDistanceCalculatorWithPartitioning(solid, partitions.Partitions, kPointsBetweenMidPoints, longestSide[0].Normal.multiply(-1.0), out longestDist); // one more step: Merge points with equal distances. List <int> originalInds; distancePointToSolid = MergingEqualDistances(distancePointToSolid, out originalInds, 0.001); int numberOfThreads; int[] threadStartEndPoints; if (ContainsThread(distancePointToSolid, out numberOfThreads, out threadStartEndPoints)) { //PlotInMatlab(distancePointToSolid); var startEndThreadPoints = Math.Abs(originalInds[threadStartEndPoints[0] + 2] - originalInds[threadStartEndPoints[1] - 2]); return(new Fastener { Solid = solid, NumberOfThreads = numberOfThreads, FastenerType = FastenerTypeEnum.Bolt, RemovalDirection = FastenerDetector.RemovalDirectionFinderUsingObb(solid, BoundingGeometry.OrientedBoundingBoxDic[solid]), OverallLength = GeometryFunctions.SortedLengthOfObbEdges(BoundingGeometry.OrientedBoundingBoxDic[solid])[2], EngagedLength = (startEndThreadPoints + (startEndThreadPoints * 2) / (double)numberOfThreads) * (GeometryFunctions.DistanceBetweenTwoVertices(midPoint1, midPoint2) / ((double)k + 1)), Diameter = DiameterOfFastenerFinderUsingPolynomial(distancePointToSolid, threadStartEndPoints, longestSide[0], solid, longestDist), Certainty = 1.0 }); } // Plot: //if (hasThread) //PlotInMatlab(distancePointToSolid); return(null); }
internal NutBoundingCylinderPartition(TessellatedSolid solid, int numberOfPartitions) { this.NumberOfPartitions = numberOfPartitions; this.Solid = solid; Vertex[] startingVerts; double[] partnCreationVect; var faceFromObbSide = GeometryFunctions.BoundingCylindertoFaceOnObbRespectiveSide(solid, out startingVerts, out partnCreationVect); this.Partitions = CreatePartitions(startingVerts, partnCreationVect, this.NumberOfPartitions); FastenerBoundingBoxPartition.SolidTrianglesOfPartitions(this.Partitions, solid, faceFromObbSide); }
internal static List <double> PointToSolidDistanceCalculatorWithPartitioning(TessellatedSolid solid, List <FastenerAndNutPartition> partitions, List <double[]> kPointsBetweenMidPoints, double[] vector, out double longestDist) { var distList = new List <double>(); foreach (var point in kPointsBetweenMidPoints) { var ray = new Ray(new Vertex(point), vector); var minDis = double.PositiveInfinity; var prtn = FastenerBoundingBoxPartition.PartitionOfThePoint(partitions, point); foreach (var face in prtn.FacesOfSolidInPartition) { double[] hittingPoint; bool outer; if (!GeometryFunctions.RayIntersectsWithFace(ray, face, out hittingPoint, out outer) || !outer) { continue; } var dis = GeometryFunctions.DistanceBetweenTwoVertices(hittingPoint, point); if (dis < minDis) { minDis = dis; } } if (minDis != double.PositiveInfinity) { distList.Add(minDis); } } // Normalizing: var longestDis = distList.Max(); longestDist = longestDis; return(distList.Select(d => d / longestDis).ToList()); }