public static double CheckStabilityForReference(SubAssembly newSubAsm, FootprintFace f)
        {
            var refCOM = newSubAsm.Install.Reference.CenterOfMass;

            CenterOfMassProjectionOnFootprintFace(f, refCOM);

            f.MinDisNeaEdg = double.PositiveInfinity;
            var x02 = f.COMP.Position[0];
            var y02 = f.COMP.Position[1];
            var z02 = f.COMP.Position[2];

            f.Height = Math.Sqrt(Math.Pow(x02 - refCOM.Position[0], 2) +
                                 Math.Pow(y02 - refCOM.Position[1], 2) +
                                 Math.Pow(z02 - refCOM.Position[2], 2));
            foreach (var edge in f.OuterEdges)
            {
                var edgeVector = edge.From.Position.subtract(edge.To.Position).normalize();
                var distanceOfEdgeToComProj = GeometryFunctions.DistanceBetweenLineAndVertex(edgeVector,
                                                                                             edge.From.Position, f.COMP.Position);
                if (distanceOfEdgeToComProj < f.MinDisNeaEdg)
                {
                    f.MinDisNeaEdg    = distanceOfEdgeToComProj;
                    f.IsComInsideFace = IsTheProjectionInsideOfTheFace(f, edge);
                }
            }
            var spf = Math.Pow(((2 / Math.PI) * (Math.Atan(f.Height / f.MinDisNeaEdg))), 2);

            f.RefS = spf;
            return(f.RefS);
        }
Example #2
0
        private static double DetermineDistanceToSeparateHull(SubAssembly newSubAsm, Double[] insertionDirection)
        {
            var refMaxValue =
                GeometryFunctions.FindMaxPlaneHeightInDirection(newSubAsm.Install.Reference.CVXHull.Vertices,
                                                                insertionDirection);
            var refMinValue =
                GeometryFunctions.FindMinPlaneHeightInDirection(newSubAsm.Install.Reference.CVXHull.Vertices,
                                                                insertionDirection);

            var movingMaxValue =
                GeometryFunctions.FindMaxPlaneHeightInDirection(newSubAsm.Install.Moving.CVXHull.Vertices,
                                                                insertionDirection);
            var movingMinValue =
                GeometryFunctions.FindMinPlaneHeightInDirection(newSubAsm.Install.Moving.CVXHull.Vertices,
                                                                insertionDirection);

            var distanceToFree = Math.Abs(refMaxValue - movingMinValue);

            if (distanceToFree < 0)
            {
                distanceToFree = 0;
                throw new Exception("How is distance to free less than zero?");
            }
            return(distanceToFree + (movingMaxValue - movingMinValue) + (refMaxValue - refMinValue));
        }
Example #3
0
        private static bool IsTheLocalDirectionFinite(List <TessellatedSolid> blockingSubAssem, List <Ray> rays)
        {
            var fin = false;

            Parallel.ForEach(rays, (ray, state) =>
                             //foreach (var ray in rays)
            {
                foreach (var blockingSolid in blockingSubAssem)
                {
                    var memoFace           = new HashSet <PolygonalFace>();
                    var affectedPartitions =
                        NonadjacentBlockingWithPartitioning.AffectedPartitionsWithRayCvhOverlaps(
                            PartitioningSolid.Partitions[blockingSolid], ray);
                    foreach (var prtn in affectedPartitions)
                    {
                        foreach (var t in prtn.SolidTriangles.Where(t => !memoFace.Contains(t)))
                        {
                            memoFace.Add(t);
                            if (GeometryFunctions.RayIntersectsWithFaceFinInf(ray, t))
                            {
                                //return true;
                                fin = true;
                                state.Stop();
                            }
                        }
                    }
                }
            });
            //return false;
            return(fin);
        }
        internal static List <double> PointToSolidDistanceCalculator(TessellatedSolid solid,
                                                                     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;
                foreach (var face in solid.Faces)
                {
                    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());
        }
Example #5
0
        private static bool DontConcexHullsOverlapNonAdjacent(List <Ray> rays, TessellatedSolid solidBlocking)
        {
            var overlap = false;

            foreach (var ray in rays)
            {
                if (solidBlocking.ConvexHull.Faces.Any(f => GeometryFunctions.RayIntersectsWithFace(ray, f)))
                //now find the faces that intersect with the ray and find the distance between them
                {
                    foreach (
                        var blockingPolygonalFace in
                        solidBlocking.Faces.Where(f => GeometryFunctions.RayIntersectsWithFace(ray, f)).ToList())
                    {
                        var d = GeometryFunctions.DistanceBetweenVertexAndPlane(ray.Position, blockingPolygonalFace);
                        //if (d < distanceToTheClosestFace) distanceToTheClosestFace = d;
                        if (d < 0)
                        {
                            continue;
                        }
                        overlap = true;
                        break;
                    }
                    if (overlap)
                    {
                        break;
                    }
                }
            }
            return(overlap);
        }
Example #6
0
        private static bool ConvexHullOverlappNonAdjacent(List <Ray> rays, TessellatedSolid solid, TessellatedSolid solidBlocking, double[] direction)
        {
            var boo = false;

            foreach (var ray in rays)
            {
                foreach (
                    var blockingPolygonalFace in
                    solidBlocking.Faces.Where(f => GeometryFunctions.RayIntersectsWithFace(ray, f)).ToList())
                {
                    var d = GeometryFunctions.DistanceBetweenVertexAndPlane(ray.Position, blockingPolygonalFace);
                    //if (d < distanceToTheClosestFace) distanceToTheClosestFace = d;
                    if (d < 0)
                    {
                        continue;
                    }
                    boo = true;
                    break;
                }
                if (boo)
                {
                    var blocked = _2DProjectionCheck(solid, solidBlocking, direction);
                    if (!blocked)
                    {
                        boo = false;
                    }
                    break;
                }
            }
            return(boo);
        }
Example #7
0
 internal static void FiniteDirectionsBetweenConnectedParts(TessellatedSolid solid1, TessellatedSolid solid2, List <int> localDirInd, out List <int> finDirs, out List <int> infDirs)
 {
     // solid1 is Reference and solid2 is Moving
     finDirs = new List <int>();
     infDirs = new List <int>();
     foreach (var dir in localDirInd)
     {
         var direction = DisassemblyDirections.Directions[dir];
         var rays      = new List <Ray>();
         foreach (var vertex in solid2.ConvexHull.Vertices)
         {
             rays.Add(new Ray(new Vertex(new[] { vertex.Position[0], vertex.Position[1], vertex.Position[2] }),
                              new[] { direction[0], direction[1], direction[2] }));
         }
         var direction2 = DisassemblyDirections.Directions[dir].multiply(-1.0);
         var rays2      = new List <Ray>();
         foreach (var vertex in solid1.ConvexHull.Vertices)
         {
             rays2.Add(new Ray(new Vertex(new[] { vertex.Position[0], vertex.Position[1], vertex.Position[2] }),
                               new[] { direction2[0], direction2[1], direction2[2] }));
         }
         if (rays.Any(ray => solid1.Faces.Any(f => GeometryFunctions.RayIntersectsWithFace(ray, f) && GeometryFunctions.DistanceBetweenVertexAndPlane(ray.Position, f) > 0)))
         {
             finDirs.Add(dir);
         }
         else if (rays2.Any(ray => solid2.Faces.Any(f => GeometryFunctions.RayIntersectsWithFace(ray, f) && GeometryFunctions.DistanceBetweenVertexAndPlane(ray.Position, f) > 0)))
         {
             finDirs.Add(dir);
         }
         else
         {
             infDirs.Add(dir);
         }
     }
 }
        private static int RemovalDirectionFinderForAllenHexPhillips(List <Flat> flatPrims, BoundingBox solid)
        {
            // This function works for hex bolt, alle, philips and phillips and slot combo
            // For slot, it will be different
            var normalGuess     = NormalGuessFinder(flatPrims);
            var equInDirections =
                DisassemblyDirections.Directions.Where(d => Math.Abs(d.dotProduct(normalGuess) - 1) < 0.01).ToList()[0];
            // find the furthest vertex (b) to a vertex (a) from allen faces. if
            // Normal.dotproduct(a-b) must be positive. If it was negative, return
            // multiply(-1)
            var a           = flatPrims[0].Vertices[0];
            var farthestVer = flatPrims[0].Vertices[0];
            var dist        = 0.0;

            foreach (var ver in solid.CornerVertices)
            {
                var locDist = GeometryFunctions.DistanceBetweenTwoVertices(a.Position, ver.Position);
                if (locDist <= dist)
                {
                    continue;
                }
                farthestVer = new Vertex(ver.Position);
                dist        = locDist;
            }
            var reference = a.Position.subtract(farthestVer.Position);

            if (normalGuess.dotProduct(reference) > 0)
            {
                return(DisassemblyDirections.Directions.IndexOf(equInDirections));
            }
            return(DisassemblyDirections.Directions.IndexOf(equInDirections.multiply(-1.0)));
        }
        internal static double[] FastenerEngagedLengthAndRadiusNoThread(TessellatedSolid solid, List <PrimitiveSurface> solidPrim)
        {
            // the length and the radius of the longest cylinder
            //if (!solidPrim.Any(p => p is Cylinder))
            //    throw new Exception("the fastener does not have any cylinder");
            //[0] = length, [1] = radius
            if (!solidPrim.Any(p => p is Cylinder))
            {
                return new[]
                       { BoundingGeometry.BoundingCylinderDic[solid].Length, BoundingGeometry.BoundingCylinderDic[solid].Radius }
            }
            ;
            Cylinder longestCyl = null;
            var      length     = double.NegativeInfinity;

            foreach (Cylinder cylinder in solidPrim.Where(p => p is Cylinder))
            {
                var medLength = GeometryFunctions.SortedEdgeLengthOfTriangle(cylinder.Faces[0])[1];

                if (medLength <= length)
                {
                    continue;
                }
                length     = medLength;
                longestCyl = cylinder;
            }
            return(new[] { length, longestCyl.Radius });
        }
        private static bool RayIntersectsCVHOverlap(Partition[] partitions, Ray ray)
        {
            var memoFace           = new HashSet <PolygonalFace>();
            var affectedPartitions = AffectedPartitionsWithRayCvhOverlapsNABD(partitions, ray);

            foreach (var prtn in affectedPartitions)
            {
                if (prtn.InnerPartition != null)
                {
                    RayIntersectsCVHOverlap(prtn.InnerPartition, ray);
                }
                foreach (var tri in prtn.SolidTriangles.Where(t => !memoFace.Contains(t)))
                {
                    memoFace.Add(tri);
                    if (!GeometryFunctions.RayIntersectsWithFaceNABD(ray, tri))
                    {
                        continue;
                    }
                    return(true);
                }
            }
            return(false);
            //if (!NonadjacentBlockingDetermination._2DProjectionCheck(solidMoving, solidBlocking, direction))
            //    boo = false;
        }
Example #11
0
        internal static Gear GearDetectorEstimate(TessellatedSolid solid, List <PrimitiveSurface> solidPrimitives)
        {
            var flats =
                solidPrimitives.Where(
                    p => p is Flat && p.Faces.Count > BoltAndGearConstants.TriabglesInTheGearSideFaces).ToList();

            foreach (var flatPrim in flats)
            {
                var outerGearEdges = GearEdge.FromTVGLEdgeClassToGearEdgeClass(flatPrim.OuterEdges);
                var patches        = SortedConnectedPatches(outerGearEdges);
                foreach (var patch in patches)
                {
                    var cluster  = new List <GearEdge> [2];
                    var newPatch = new List <GearEdge>();
                    if (ClusteringDenseAndSparseEdges.ContainsDense(patch))
                    {
                        cluster = ClusteringDenseAndSparseEdges.ClusteringDenseSparse(patch);
                    }
                    if (cluster[0] != null && cluster[1].Count > BoltAndGearConstants.AcceptableNumberOfDenseEdges)
                    {
                        newPatch = ClusteringDenseAndSparseEdges.ReplacingDenseEdges(patch, cluster);
                    }
                    var crossP = new List <double[]>();
                    if (newPatch.Count == 0)
                    {
                        newPatch = patch;
                    }
                    for (var i = 0; i < newPatch.Count - 1; i++)
                    {
                        var cross = new[] { 0.0, 0, 0 };
                        var vec1  = newPatch[i].Vector.normalize();
                        var vec2  = newPatch[i + 1].Vector.normalize();
                        if (SmoothAngle(vec1, vec2))
                        {
                            continue;
                        }
                        cross = vec1.crossProduct(vec2);
                        crossP.Add(cross);
                    }
                    if (crossP.Count < 10)
                    {
                        continue;
                    }
                    var crossSign = GeometryFunctions.ConvertCrossProductToSign(crossP);
                    if (!IsGear(crossSign))
                    {
                        continue;
                    }
                    //Console.WriteLine("Is " + solid.Name + " a gear? 'y' or 'n'");
                    //var read = Convert.ToString(Console.ReadLine());
                    //if (read == "n")
                    //    continue;
                    return(new Gear {
                        Solid = solid, Axis = flatPrim.Faces[0].Normal
                    });
                }
            }
            return(null);
        }
 private static List <Partition> AffectedPartitionsWithRayNABD(Partition[] partition, Ray ray)
 {
     return
         (partition.Where(
              prtn =>
              prtn.SolidTriangles.Count > 0 &&
              prtn.Faces.Any(f => GeometryFunctions.RayIntersectsWithFaceNABD(ray, f))).ToList());
 }
        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 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);
 }
        private static List <double>[] PointToSolidDistanceCalculator(TessellatedSolid solid, List <double[]> kPointsOnSurface, BoundingCylinder bC, double section)
        {
            var distListOuter = new List <double>();
            var distListInner = new List <double>();
            var met           = bC.CenterLineVector.multiply(bC.Length * section);

            kPointsOnSurface =
                kPointsOnSurface.Select(p => p.add(met)).ToList();
            foreach (var point in kPointsOnSurface)
            {
                var rayVector   = (bC.PointOnTheCenterLine.add(met)).subtract(point);
                var ray         = new Ray(new Vertex(point), rayVector);
                var minDisOuter = double.PositiveInfinity;
                var minDisInner = double.PositiveInfinity;
                foreach (var face in solid.Faces)
                {
                    double[] hittingPoint;
                    bool     outerTriangle;
                    if (!GeometryFunctions.RayIntersectsWithFace(ray, face, out hittingPoint, out outerTriangle))
                    {
                        continue;
                    }
                    var dis = GeometryFunctions.DistanceBetweenTwoVertices(hittingPoint, point);
                    if (outerTriangle)
                    {
                        if (dis < minDisOuter)
                        {
                            minDisOuter = dis;
                        }
                    }
                    else
                    {
                        if (dis < minDisInner)
                        {
                            minDisInner = dis;
                        }
                    }
                }
                if (!double.IsPositiveInfinity(minDisOuter))
                {
                    distListOuter.Add(minDisOuter);
                }
                if (!double.IsPositiveInfinity(minDisInner))
                {
                    distListInner.Add(minDisOuter);
                }
            }
            // Normalizing:
            var longestDis1 = distListOuter.Max();
            var distanceToOuterTriangles = distListOuter.Select(d => d / longestDis1).ToList();
            var longestDis2 = distListInner.Max();
            var distanceToInnerTriangles = distListInner.Select(d => d / longestDis2).ToList();

            return(new[] { distanceToOuterTriangles, distanceToInnerTriangles });
        }
        internal static List <Partition> AffectedPartitionsWithRayCvhOverlaps(Partition[] partitions, Ray ray)
        {
            var affected = partitions.Where(
                prtn =>
                prtn.SolidTriangles.Count > 0 &&
                prtn.Faces.Any(f => GeometryFunctions.RayIntersectsWithFace(ray, f))).ToList();
            var currentPartition =
                partitions.Where(p => PartitioningSolid.IsVertexInsidePartition(p, new TVGL.Vertex(ray.Position)));

            affected.AddRange(currentPartition);
            return(affected);
        }
 private static void PreSelectedFastenerToFastenerClass(
     Dictionary <TessellatedSolid, List <PrimitiveSurface> > solidPrimitive,
     Dictionary <TessellatedSolid, List <TessellatedSolid> > multipleRefs)
 {
     foreach (var preFastener in FastenerDetector.PreSelectedFasteners)
     {
         var lengthAndRadius = FastenerEngagedLengthAndRadiusNoThread(preFastener, solidPrimitive[preFastener]);
         // if this part is repeated, add also those repeated parts to the fastener list
         var repeated             = new HashSet <TessellatedSolid>();
         var isAKeyInMultipleRefs = multipleRefs.Keys.Where(r => r == preFastener).ToList();
         if (isAKeyInMultipleRefs.Any())
         {
             repeated = new HashSet <TessellatedSolid>(multipleRefs[isAKeyInMultipleRefs[0]])
             {
                 preFastener
             }
         }
         ;
         else
         {
             // it is a part in a value list
             foreach (var key in multipleRefs.Keys)
             {
                 if (!multipleRefs[key].Contains(preFastener))
                 {
                     continue;
                 }
                 repeated = new HashSet <TessellatedSolid>(multipleRefs[key])
                 {
                     key
                 };
             }
         }
         foreach (var repeatedSolid in repeated)
         {
             var fastener = new Fastener
             {
                 Solid            = repeatedSolid,
                 FastenerType     = FastenerTypeEnum.Bolt,
                 RemovalDirection =
                     FastenerDetector.RemovalDirectionFinderUsingObb(preFastener,
                                                                     BoundingGeometry.OrientedBoundingBoxDic[preFastener]),
                 OverallLength =
                     GeometryFunctions.SortedLengthOfObbEdges(
                         BoundingGeometry.OrientedBoundingBoxDic[preFastener])[2],
                 EngagedLength = lengthAndRadius[0],
                 Diameter      = lengthAndRadius[1] * 2.0,
                 Certainty     = 1.0
             };
             FastenerDetector.Fasteners.Add(fastener);
         }
     }
 }
        private static double RadiusOfBoundingCylinder(TessellatedSolid solid, double[] faceCenters, double[] vector)
        {
            var maxDistance = double.NegativeInfinity;

            foreach (var vertex in solid.Vertices)
            {
                var dis = GeometryFunctions.DistanceBetweenLineAndVertex(vector, faceCenters, vertex.Position);
                if (dis > maxDistance)
                {
                    maxDistance = dis;
                }
            }
            return(maxDistance);
        }
Example #20
0
        private List <FastenerAndNutPartition> CreatePartitions(PolygonalFace faceFromLongestSide, int numberOfPartitions)
        {
            var sortedEdges                 = GeometryFunctions.SortedEdgesOfTriangle(faceFromLongestSide);
            var cornerVer                   = sortedEdges[0].First(sortedEdges[1].Contains);
            var otherVerShertestEdge        = sortedEdges[0].First(a => a != cornerVer);
            var partitionGeneratorDirection = sortedEdges[1].First(a => a != cornerVer).Position.subtract(cornerVer.Position);
            var stepVector                  = partitionGeneratorDirection.divide((double)numberOfPartitions);
            var partis = new List <FastenerAndNutPartition>();

            for (var i = 0; i < NumberOfPartitions; i++)
            {
                var prt = new FastenerAndNutPartition
                {
                    Edge1 =
                        new[]
                    {
                        new Vertex(cornerVer.Position.add(stepVector.multiply(i))),
                        new Vertex(otherVerShertestEdge.Position.add(stepVector.multiply(i)))
                    },
                    Edge2 =
                        new[]
                    {
                        new Vertex(cornerVer.Position.add(stepVector.multiply(i + 1))),
                        new Vertex(otherVerShertestEdge.Position.add(stepVector.multiply(i + 1)))
                    }
                };
                if (i == 0)
                {
                    prt.Edge1 = new[]
                    {
                        new Vertex(cornerVer.Position.add(stepVector.multiply(-0.1))),
                        new Vertex(otherVerShertestEdge.Position.add(stepVector.multiply(-0.1)))
                    };
                }
                if (i == NumberOfPartitions - 1)
                {
                    prt.Edge2 = new[]
                    {
                        new Vertex(cornerVer.Position.add(stepVector.multiply(i + 1.1))),
                        new Vertex(otherVerShertestEdge.Position.add(stepVector.multiply(i + 1.1)))
                    };
                }
                partis.Add(prt);
            }
            return(partis);
        }
        private static double DetermineTheMagnifier()
        {
            // Regardless of the actual size of the assembly, I will fit it in a box with
            // a diagonal length of 500,000
            var allVertices = Solids.SelectMany(p => p.Value).SelectMany(g => g.Vertices);
            var maxX        = (double)allVertices.Max(v => v.X);
            var maxY        = (double)allVertices.Max(v => v.Y);
            var maxZ        = (double)allVertices.Max(v => v.Z);

            var minX = (double)allVertices.Min(v => v.X);
            var minY = (double)allVertices.Min(v => v.Y);
            var minZ = (double)allVertices.Min(v => v.Z);

            var diagonalLength = GeometryFunctions.DistanceBetweenTwoVertices(new[] { maxX, maxY, maxZ },
                                                                              new[] { minX, minY, minZ });

            return(500000 / diagonalLength);
        }
Example #22
0
        internal static int RemovalDirectionFinderUsingObbWithTopPlane(TessellatedSolid solid, BoundingBox obb, out PolygonalFace topPlane)
        {
            // this is hard. it can be a simple threaded rod,or it can be a standard
            // bolt that could not be detected by other approaches.
            // If it is a rod, the removal direction is not really important,
            // but if not, it's important I still have no idea about how to detect it.
            // Idea: find any of the 4 longest sides of the OBB.
            //       find the closest vertex to this side. (if it's a rod,
            //       the closest vertex can be everywhere, but in a regular bolt,
            //       it's on the top (it's most definitely a vertex from the head))
            PolygonalFace facePrepToRD1;
            PolygonalFace facePrepToRD2;
            var           longestPlane      = GeometryFunctions.LongestPlaneOfObbDetector(obb, out facePrepToRD1, out facePrepToRD2);
            Vertex        closestVerToPlane = null;
            var           minDist           = double.PositiveInfinity;

            foreach (var ver in solid.ConvexHull.Vertices)
            {
                var dis = Math.Abs(GeometryFunctions.DistanceBetweenVertexAndPlane(ver.Position, longestPlane[0]));
                if (dis >= minDist)
                {
                    continue;
                }
                closestVerToPlane = ver;
                minDist           = dis;
            }
            // The closest vertex to plane is closer to which facePrepToRD?
            double[] normalGuess = null;
            if (Math.Abs(GeometryFunctions.DistanceBetweenVertexAndPlane(closestVerToPlane.Position, facePrepToRD1)) <
                Math.Abs(GeometryFunctions.DistanceBetweenVertexAndPlane(closestVerToPlane.Position, facePrepToRD2)))
            {
                normalGuess = facePrepToRD1.Normal;
                topPlane    = facePrepToRD1;
            }
            else
            {
                normalGuess = facePrepToRD2.Normal;
                topPlane    = facePrepToRD2;
            }
            var equInDirections =
                DisassemblyDirections.Directions.First(d => Math.Abs(d.dotProduct(normalGuess) - 1) < 0.05);

            return(DisassemblyDirections.Directions.IndexOf(equInDirections));
        }
        private static double[] FaceCenterFinder(PolygonalFace side)
        {
            var longestEdge = new Vertex[2];
            var maxLength   = double.NegativeInfinity;

            for (var i = 0; i < side.Vertices.Count - 1; i++)
            {
                for (var j = i + 1; j < side.Vertices.Count; j++)
                {
                    var dis = GeometryFunctions.DistanceBetweenTwoVertices(side.Vertices[i].Position,
                                                                           side.Vertices[j].Position);
                    if (dis > maxLength)
                    {
                        maxLength   = dis;
                        longestEdge = new[] { side.Vertices[i], side.Vertices[j] };
                    }
                }
            }
            return((longestEdge[0].Position.add(longestEdge[1].Position)).divide(2.0));
        }
        private static double[] ShortestEdgeMidPointOfTriangle(PolygonalFace triangle)
        {
            var shortestEdge = new Vertex[2];
            var shortestDist = double.PositiveInfinity;

            for (var i = 0; i < triangle.Vertices.Count - 1; i++)
            {
                for (var j = i + 1; j < triangle.Vertices.Count; j++)
                {
                    var dis = GeometryFunctions.DistanceBetweenTwoVertices(triangle.Vertices[i].Position,
                                                                           triangle.Vertices[j].Position);
                    if (dis >= shortestDist)
                    {
                        continue;
                    }
                    shortestDist = dis;
                    shortestEdge = new[] { triangle.Vertices[i], triangle.Vertices[j] };
                }
            }
            return((shortestEdge[0].Position.add(shortestEdge[1].Position)).divide(2.0));
        }
        private static double DiameterOfFastenerFinderUsingPolynomial(List <double> distancePointToSolid,
                                                                      int[] threadStartEndPoints, PolygonalFace longestSide, TessellatedSolid solid, double longestDist)
        {
            var newList = new List <double>();

            for (var i = threadStartEndPoints[0];
                 i < threadStartEndPoints[1];
                 i++)
            {
                newList.Add(distancePointToSolid[i]);
            }
            var obbEdgesLength =
                GeometryFunctions.SortedLengthOfObbEdges(BoundingGeometry.OrientedBoundingBoxDic[solid]);
            // one of the first two small lengths are the number that I am looking for.
            var shortestEdgeOfTriangle = GeometryFunctions.SortedEdgeLengthOfTriangle(longestSide)[0];
            var obbDepth = Math.Abs(obbEdgesLength[0] - shortestEdgeOfTriangle) < 0.01
                ? obbEdgesLength[1]
                : obbEdgesLength[0];

            return(obbDepth - 2 * (newList.Min() * longestDist));
        }
        private static Vertex[] CornerEdgeFinder(PolygonalFace polygonalFace)
        {
            // We want to find the second long edge:
            var dist0 = GeometryFunctions.DistanceBetweenTwoVertices(polygonalFace.Vertices[0].Position,
                                                                     polygonalFace.Vertices[1].Position);
            var dist1 = GeometryFunctions.DistanceBetweenTwoVertices(polygonalFace.Vertices[0].Position,
                                                                     polygonalFace.Vertices[2].Position);
            var dist2 = GeometryFunctions.DistanceBetweenTwoVertices(polygonalFace.Vertices[1].Position,
                                                                     polygonalFace.Vertices[2].Position);

            if ((dist0 > dist1 && dist0 < dist2) || (dist0 > dist2 && dist0 < dist1))
            {
                return new[] { polygonalFace.Vertices[0], polygonalFace.Vertices[1] }
            }
            ;
            if ((dist1 > dist0 && dist1 < dist2) || (dist1 > dist2 && dist1 < dist0))
            {
                return new[] { polygonalFace.Vertices[0], polygonalFace.Vertices[2] }
            }
            ;
            return(new[] { polygonalFace.Vertices[1], polygonalFace.Vertices[2] });
        }
        private static Dictionary <PolygonalFace, double> ThreeSidesOfTheObb(TessellatedSolid solid)
        {
            // This is based on my own OBB function:
            // it returns a dictionary with size of three (3 sides).
            //    Key: triangle, value: length of the potential cylinder
            var cornerVer = BoundingGeometry.OrientedBoundingBoxDic[solid].CornerVertices;
            var face1     = new PolygonalFace(new[] { new Vertex(cornerVer[0].Position), new Vertex(cornerVer[1].Position),
                                                      new Vertex(cornerVer[3].Position) }, ((cornerVer[3].Position.subtract(cornerVer[0].Position)).crossProduct(
                                                                                                cornerVer[1].Position.subtract(cornerVer[0].Position))).normalize());
            var length1 = GeometryFunctions.DistanceBetweenTwoVertices(cornerVer[0].Position, cornerVer[4].Position);
            var face2   = new PolygonalFace(new[] { new Vertex(cornerVer[1].Position), new Vertex(cornerVer[0].Position),
                                                    new Vertex(cornerVer[4].Position) }, ((cornerVer[1].Position.subtract(cornerVer[0].Position)).crossProduct(
                                                                                              cornerVer[4].Position.subtract(cornerVer[0].Position))).normalize());
            var length2 = GeometryFunctions.DistanceBetweenTwoVertices(cornerVer[0].Position, cornerVer[3].Position);
            var face3   = new PolygonalFace(new[] { new Vertex(cornerVer[0].Position), new Vertex(cornerVer[3].Position),
                                                    new Vertex(cornerVer[7].Position) }, ((cornerVer[0].Position.subtract(cornerVer[3].Position)).crossProduct(
                                                                                              cornerVer[7].Position.subtract(cornerVer[3].Position))).normalize());
            var length3 = GeometryFunctions.DistanceBetweenTwoVertices(cornerVer[0].Position, cornerVer[1].Position);

            return(new Dictionary <PolygonalFace, double> {
                { face1, length1 }, { face2, length2 }, { face3, length3 }
            });
        }
Example #28
0
 internal static void SolidTrianglesOfPartitions(List <FastenerAndNutPartition> partitions, TessellatedSolid solid, PolygonalFace faceFromLongestSide)
 {
     foreach (var vertex in solid.Vertices)
     {
         var ray = new Ray(new Vertex(vertex.Position), faceFromLongestSide.Normal);
         var intersectionPoint = GeometryFunctions.RayIntersectionPointWithFace(ray, faceFromLongestSide);
         var chosenPrtn        = PartitionOfThePoint(partitions, intersectionPoint);
         chosenPrtn.VerticesOfSolidInPartition.Add(vertex);
     }
     foreach (var face in solid.Faces)
     {
         var inds = new List <int>();
         foreach (var fV in face.Vertices)
         {
             var prt = partitions.First(p => p.VerticesOfSolidInPartition.Contains(fV));
             inds.Add(partitions.IndexOf(prt));
         }
         for (var i = inds.Min(); i <= inds.Max(); i++)
         {
             partitions[i].FacesOfSolidInPartition.Add(face);
         }
     }
 }
        private static void AddThreadedOrNonthreadedFastener(TessellatedSolid solid, List <TessellatedSolid> repeated,
                                                             List <PrimitiveSurface> prim, Tool tool, double toolSize)
        {
            var newFastener = FastenerPolynomialTrend.PolynomialTrendDetector(solid);

            if (newFastener != null)
            {
                newFastener.Tool     = tool;
                newFastener.ToolSize = toolSize;
                lock (FastenerDetector.Fasteners)
                    FastenerDetector.Fasteners.Add(newFastener);
                AutoThreadedFastenerDetection.AddRepeatedSolidstoFasteners(newFastener, repeated);
                //continue;
                return;
            }
            var lengthAndRadius =
                AutoNonthreadedFastenerDetection.FastenerEngagedLengthAndRadiusNoThread(solid, prim);
            var fastener = new Fastener
            {
                Solid            = solid,
                FastenerType     = FastenerTypeEnum.Bolt,
                Tool             = tool,
                ToolSize         = toolSize,
                RemovalDirection =
                    FastenerDetector.RemovalDirectionFinderUsingObb(solid,
                                                                    BoundingGeometry.OrientedBoundingBoxDic[solid]),
                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);
            AutoThreadedFastenerDetection.AddRepeatedSolidstoFasteners(fastener, repeated);
        }
Example #30
0
        internal static FastenerAndNutPartition PartitionOfThePoint(List <FastenerAndNutPartition> partitions, double[] point)
        {
            FastenerAndNutPartition chosenPrtn = null;
            var sumDisToEdgs = double.PositiveInfinity;

            foreach (var prtn in partitions)
            {
                var dis1 =
                    GeometryFunctions.DistanceBetweenLineAndVertex(
                        prtn.Edge1[0].Position.subtract(prtn.Edge1[1].Position), prtn.Edge1[0].Position,
                        point);
                var dis2 =
                    GeometryFunctions.DistanceBetweenLineAndVertex(
                        prtn.Edge2[0].Position.subtract(prtn.Edge2[1].Position), prtn.Edge2[0].Position,
                        point);
                var sum = dis1 + dis2;
                if (sum < sumDisToEdgs)
                {
                    sumDisToEdgs = sum;
                    chosenPrtn   = prtn;
                }
            }
            return(chosenPrtn);
        }