private static bool SlotHeadBolt(TessellatedSolid solid, List <PrimitiveSurface> solidPrim, Dictionary <TemporaryFlat, List <TemporaryFlat> > equalPrimitives, List <TessellatedSolid> repeated) { repeated.Add(solid); var twoFlat = FastenerDetector.EqualPrimitivesFinder(equalPrimitives, 2); if (!twoFlat.Any()) { return(false); } foreach (var candidateHex in twoFlat) { var candidateHexVal = equalPrimitives[candidateHex]; var cos = (candidateHexVal[0]).Normal.dotProduct((candidateHexVal[1]).Normal); if (!(Math.Abs(-1 - cos) < 0.0001)) { continue; } // I will add couple of conditions here: // 1. If the number of solid vertices in front of each flat is equal to another // 2. If the summation of the vertices in 1 is greater than the total # of verts // 3. and I also need to add some constraints for the for eample the area of the cylinder var leftVerts = VertsInfrontOfFlat(solid, candidateHexVal[0]); var rightVerts = VertsInfrontOfFlat(solid, candidateHexVal[1]); if (Math.Abs(leftVerts - rightVerts) > 2 || leftVerts + rightVerts <= solid.Vertices.Length) { continue; } if (!solidPrim.Where(p => p is Cylinder).Cast <Cylinder>().Any(c => c.IsPositive)) { continue; } var lengthAndRadius = FastenerEngagedLengthAndRadiusNoThread(solid, solidPrim); foreach (var repeatedSolid in repeated) { var fastener = new Fastener { Solid = repeatedSolid, FastenerType = FastenerTypeEnum.Bolt, Tool = Tool.FlatBlade, RemovalDirection = //RemovalDirectionFinderForSlot(candidateHexVal.Cast<Flat>().ToList(), // solidPrim.Where(p => p is Flat).Cast<Flat>().ToList()), FastenerDetector.RemovalDirectionFinderUsingObb(repeatedSolid, BoundingGeometry.OrientedBoundingBoxDic[repeatedSolid]), OverallLength = GeometryFunctions.SortedLengthOfObbEdges(BoundingGeometry.OrientedBoundingBoxDic[solid])[2], EngagedLength = lengthAndRadius[0], Diameter = lengthAndRadius[1] * 2.0, Certainty = 1.0 }; lock (FastenerDetector.Fasteners) FastenerDetector.Fasteners.Add(fastener); } return(true); } return(false); }
internal static int CommonHeadCheck(TessellatedSolid solid, List <PrimitiveSurface> solidPrim, Dictionary <TemporaryFlat, List <TemporaryFlat> > equalPrimitives, out double toolSize) { // 0: false (doesnt have any common head shape) // 1: HexBolt or Nut // 2: Allen // 3: Phillips // 4: Slot // 5: Phillips and Slot combo toolSize = 0.0; // check for hex bolt, nut and allen ------------------------------------------------------------- var sixFlat = FastenerDetector.EqualPrimitivesFinder(equalPrimitives, 6); var eightFlat = FastenerDetector.EqualPrimitivesFinder(equalPrimitives, 8); var twoFlat = FastenerDetector.EqualPrimitivesFinder(equalPrimitives, 2); var fourFlat = FastenerDetector.EqualPrimitivesFinder(equalPrimitives, 4); //if (!sixFlat.Any()) return 0; foreach (var candidateHex in sixFlat) { var candidateHexVal = equalPrimitives[candidateHex]; var cos = new List <double>(); var firstPrimNormal = (candidateHexVal[0]).Normal; for (var i = 1; i < candidateHexVal.Count; i++) { cos.Add(firstPrimNormal.dotProduct((candidateHexVal[i]).Normal)); } // if it is a hex or allen bolt, the cos list must have two 1/2, two -1/2 and one -1 if (cos.Count(c => Math.Abs(0.5 - c) < 0.0001) != 2 || cos.Count(c => Math.Abs(-0.5 - c) < 0.0001) != 2 || cos.Count(c => Math.Abs(-1 - c) < 0.0001) != 1) { continue; } toolSize = AutoNonthreadedFastenerDetection.ToolSizeFinder(candidateHexVal); if (AutoNonthreadedFastenerDetection.IsItAllen(candidateHexVal)) { return(2); } return(1); } foreach (var candidateHex in eightFlat) { var candidateHexVal = equalPrimitives[candidateHex]; var cos = new List <double>(); var firstPrimNormal = (candidateHexVal[0]).Normal; for (var i = 1; i < candidateHexVal.Count; i++) { cos.Add(firstPrimNormal.dotProduct((candidateHexVal[i]).Normal)); } var oneFlat = FastenerDetector.EqualPrimitivesFinder(equalPrimitives, 1); // Any flat that is adjacent to all of these eights? // if it is philips head, the cos list must have four 0, two -1 and one 1 foreach (var sh in oneFlat) { if (candidateHexVal.All(f => f.OuterEdges.Any(sh.OuterEdges.Contains))) { return(3); } } /*if (cos.Count(c => Math.Abs(0.0 - c) < 0.0001) != 4 || * cos.Count(c => Math.Abs(-1 - c) < 0.0001) != 2 || * cos.Count(c => Math.Abs(1 - c) < 0.0001) != 1) continue; * return 3;*/ continue; } foreach (var candidateHex in twoFlat) { var candidateHexVal = equalPrimitives[candidateHex]; var cos = (candidateHexVal[0]).Normal.dotProduct((candidateHexVal[1]).Normal); if (!(Math.Abs(-1 - cos) < 0.0001)) { continue; } // I will add couple of conditions here: // 1. If the number of solid vertices in front of each flat is equal to another // 2. If the summation of the vertices in 1 is greater than the total # of verts // 3. and I also need to add some constraints for the for eample the area of the cylinder var leftVerts = AutoNonthreadedFastenerDetection.VertsInfrontOfFlat(solid, candidateHexVal[0]); var rightVerts = AutoNonthreadedFastenerDetection.VertsInfrontOfFlat(solid, candidateHexVal[1]); if (Math.Abs(leftVerts - rightVerts) > 10 || leftVerts + rightVerts <= solid.Vertices.Length) { continue; } return(4); } var eachSlot = 0; var flats = new List <TemporaryFlat>(); foreach (var candidateHex in fourFlat) { var candidateHexVal = equalPrimitives[candidateHex]; var cos = new List <double>(); var firstPrimNormal = (candidateHexVal[0]).Normal; for (var i = 1; i < candidateHexVal.Count; i++) { cos.Add(firstPrimNormal.dotProduct((candidateHexVal[i]).Normal)); } // if it is a slot and phillips combo the cos list must have two -1 and one 1 // and this needs to appear 2 times. if (cos.Count(c => Math.Abs(-1 - c) < 0.0001) != 2 || cos.Count(c => Math.Abs(1 - c) < 0.0001) != 1) { continue; } flats.AddRange(candidateHexVal); eachSlot++; } if (eachSlot == 2) { return(5); } return(0); }
private static bool PhillipsSlotComboHeadBolt(TessellatedSolid solid, List <PrimitiveSurface> solidPrim, Dictionary <TemporaryFlat, List <TemporaryFlat> > equalPrimitives, List <TessellatedSolid> repeated) { repeated.Add(solid); var fourFlat = FastenerDetector.EqualPrimitivesFinder(equalPrimitives, 4); if (fourFlat.Count < 2) { return(false); } var eachSlot = 0; var flats = new List <TemporaryFlat>(); foreach (var candidateHex in fourFlat) { var candidateHexVal = equalPrimitives[candidateHex]; var cos = new List <double>(); var firstPrimNormal = (candidateHexVal[0]).Normal; for (var i = 1; i < candidateHexVal.Count; i++) { cos.Add(firstPrimNormal.dotProduct((candidateHexVal[i]).Normal)); } // if it is a slot and phillips combo the cos list must have two -1 and one 1 // and this needs to appear 2 times. if (cos.Count(c => Math.Abs(-1 - c) < 0.0001) != 2 || cos.Count(c => Math.Abs(1 - c) < 0.0001) != 1) { continue; } if (!solidPrim.Where(p => p is Cylinder).Cast <Cylinder>().Any(c => c.IsPositive)) { continue; } flats.AddRange(candidateHexVal); eachSlot++; } if (eachSlot != 2) { return(false); } var lengthAndRadius = FastenerEngagedLengthAndRadiusNoThread(solid, solidPrim); foreach (var repeatedSolid in repeated) { var fastener = new Fastener { Solid = repeatedSolid, FastenerType = FastenerTypeEnum.Bolt, Tool = Tool.PhillipsBlade, RemovalDirection = //RemovalDirectionFinderForAllenHexPhillips(flats.Cast<Flat>().ToList(), // BoundingGeometry.OrientedBoundingBoxDic[solid]), FastenerDetector.RemovalDirectionFinderUsingObb(repeatedSolid, BoundingGeometry.OrientedBoundingBoxDic[repeatedSolid]), OverallLength = GeometryFunctions.SortedLengthOfObbEdges(BoundingGeometry.OrientedBoundingBoxDic[solid])[2], EngagedLength = lengthAndRadius[0], Diameter = lengthAndRadius[1] * 2.0, Certainty = 1.0 }; lock (FastenerDetector.Fasteners) FastenerDetector.Fasteners.Add(fastener); } return(true); }
private static bool PhillipsHeadBolt(TessellatedSolid solid, List <PrimitiveSurface> solidPrim, Dictionary <TemporaryFlat, List <TemporaryFlat> > equalPrimitives, List <TessellatedSolid> repeated) { repeated.Add(solid); var eightFlat = FastenerDetector.EqualPrimitivesFinder(equalPrimitives, 8); if (!eightFlat.Any()) { // before I return false, I will take the ones with 4 faces that have a close area and merge them. /*var fourEqual1 = FastenerDetector.EqualPrimitivesFinder(equalPrimitives, 4); * var closeArea1 = new List<TemporaryFlat[]>(); * for (var i = 0; i < fourEqual1.Count - 1; i++) * { * for (var j = i + 1; j < fourEqual1.Count; j++) * { * if (Math.Abs(fourEqual1[i].Area - fourEqual1[j].Area) < 0.1 * fourEqual1[i].Area) * { * closeArea1.Add(new[] { fourEqual1[i], fourEqual1[j] }); * break; * } * } * } * foreach (var cA in closeArea1) * { * equalPrimitives[cA[0]].AddRange(equalPrimitives[cA[1]]); * } * return PhillipsHeadBolt(solid, solidPrim, equalPrimitives, repeated);*/ return(false); } foreach (var candidateHex in eightFlat) { var candidateHexVal = equalPrimitives[candidateHex]; var cos = new List <double>(); var firstPrimNormal = (candidateHexVal[0]).Normal; for (var i = 1; i < candidateHexVal.Count; i++) { cos.Add(firstPrimNormal.dotProduct((candidateHexVal[i]).Normal)); } // if it is philips head, the cos list must have four 0, two -1 and one 1 if (cos.Count(c => Math.Abs(0.0 - c) < 0.025) != 4 || cos.Count(c => Math.Abs(-1 - c) < 0.025) != 2 || cos.Count(c => Math.Abs(1 - c) < 0.001) != 1) { continue; } var lengthAndRadius = FastenerEngagedLengthAndRadiusNoThread(solid, solidPrim); foreach (var repeatedSolid in repeated) { var fastener = new Fastener { Solid = repeatedSolid, FastenerType = FastenerTypeEnum.Bolt, Tool = Tool.PhillipsBlade, RemovalDirection = //RemovalDirectionFinderForAllenHexPhillips(candidateHexVal.Cast<Flat>().ToList(), // BoundingGeometry.OrientedBoundingBoxDic[solid]), FastenerDetector.RemovalDirectionFinderUsingObb(repeatedSolid, BoundingGeometry.OrientedBoundingBoxDic[repeatedSolid]), OverallLength = GeometryFunctions.SortedLengthOfObbEdges(BoundingGeometry.OrientedBoundingBoxDic[solid])[2], EngagedLength = lengthAndRadius[0], Diameter = lengthAndRadius[1] * 2.0, Certainty = 1.0 }; lock (FastenerDetector.Fasteners) FastenerDetector.Fasteners.Add(fastener); } return(true); } // before I return false, I will take the ones with 4 faces that have a close area and merge them. /*var fourEqual = FastenerDetector.EqualPrimitivesFinder(equalPrimitives, 4); * var closeArea = new List<TemporaryFlat[]>(); * for (var i = 0; i < fourEqual.Count - 1; i++) * { * for (var j = i+1; j < fourEqual.Count; j++) * { * if (Math.Abs(fourEqual[i].Area - fourEqual[j].Area) < 0.01*fourEqual[i].Area) * { * closeArea.Add(new []{ fourEqual[i] , fourEqual[j] }); * break; * } * } * } * foreach (var cA in closeArea) * { * equalPrimitives[cA[0]].AddRange(equalPrimitives[cA[1]]); * } * return PhillipsHeadBolt(solid, solidPrim, equalPrimitives, repeated);*/ return(false); }
private static bool HexBoltNutAllen(TessellatedSolid solid, List <PrimitiveSurface> solidPrim, Dictionary <TemporaryFlat, List <TemporaryFlat> > equalPrimitives, List <TessellatedSolid> repeated) { repeated.Add(solid); var sixFlat = FastenerDetector.EqualPrimitivesFinder(equalPrimitives, 6); if (!sixFlat.Any()) { return(false); } foreach (var candidateHex in sixFlat) { var candidateHexVal = equalPrimitives[candidateHex]; var cos = new List <double>(); var firstPrimNormal = (candidateHexVal[0]).Normal; for (var i = 1; i < candidateHexVal.Count; i++) { cos.Add(firstPrimNormal.dotProduct((candidateHexVal[i]).Normal)); } // if it is a hex or allen bolt, the cos list must have two 1/2, two -1/2 and one -1 if (cos.Count(c => Math.Abs(0.5 - c) < 0.0001) != 2 || cos.Count(c => Math.Abs(-0.5 - c) < 0.0001) != 2 || cos.Count(c => Math.Abs(-1 - c) < 0.0001) != 1) { continue; } var lengthAndRadius = FastenerEngagedLengthAndRadiusNoThread(solid, solidPrim); if (IsItAllen(candidateHexVal)) { // this is a socket bolt (allen) foreach (var repeatedSolid in repeated) { var fastener = new Fastener { Solid = repeatedSolid, FastenerType = FastenerTypeEnum.Bolt, Tool = Tool.Allen, ToolSize = ToolSizeFinder(candidateHexVal), RemovalDirection = //RemovalDirectionFinderForAllenHexPhillips(candidateHexVal.Cast<Flat>().ToList(), // BoundingGeometry.OrientedBoundingBoxDic[solid]), FastenerDetector.RemovalDirectionFinderUsingObb(repeatedSolid, BoundingGeometry.OrientedBoundingBoxDic[repeatedSolid]), OverallLength = GeometryFunctions.SortedLengthOfObbEdges(BoundingGeometry.OrientedBoundingBoxDic[solid])[2], EngagedLength = lengthAndRadius[0], Diameter = lengthAndRadius[1] * 2.0, Certainty = 1.0 }; lock (FastenerDetector.Fasteners) FastenerDetector.Fasteners.Add(fastener); } return(true); } // else: it is a hex bolt or nut if (IsItNut(solidPrim.Where(p => p is Cylinder).Cast <Cylinder>().ToList(), solid)) { foreach (var repeatedSolid in repeated) { lock (FastenerDetector.Nuts) FastenerDetector.Nuts.Add(new Nut { NutType = NutType.Hex, Solid = repeatedSolid, ToolSize = ToolSizeFinder(candidateHexVal), OverallLength = lengthAndRadius[0], Diameter = lengthAndRadius[1] * 2.0, Certainty = 1.0 }); } return(true); } foreach (var repeatedSolid in repeated) { lock (FastenerDetector.Fasteners) FastenerDetector.Fasteners.Add(new Fastener { Solid = repeatedSolid, FastenerType = FastenerTypeEnum.Bolt, Tool = Tool.HexWrench, ToolSize = ToolSizeFinder(candidateHexVal), RemovalDirection = //RemovalDirectionFinderForAllenHexPhillips(candidateHexVal.Cast<Flat>().ToList(), // BoundingGeometry.OrientedBoundingBoxDic[solid]), FastenerDetector.RemovalDirectionFinderUsingObb(repeatedSolid, BoundingGeometry.OrientedBoundingBoxDic[repeatedSolid]), OverallLength = GeometryFunctions.SortedLengthOfObbEdges(BoundingGeometry.OrientedBoundingBoxDic[solid]) [2], EngagedLength = lengthAndRadius[0], Diameter = lengthAndRadius[1] * 2.0, Certainty = 1.0 }); } return(true); } return(false); }