예제 #1
0
 internal static void AddRepeatedSolidstoNuts(Nut lastAddedNut, List <TessellatedSolid> repeatedSolid)
 {
     foreach (var solid in repeatedSolid)
     {
         if (solid == lastAddedNut.Solid)
         {
             continue;
         }
         FastenerDetector.Nuts.Add(new Nut
         {
             Solid            = solid,
             NumberOfThreads  = lastAddedNut.NumberOfThreads,
             RemovalDirection = lastAddedNut.RemovalDirection,
             OverallLength    = lastAddedNut.OverallLength,
             Diameter         = lastAddedNut.Diameter,
             Certainty        = lastAddedNut.Certainty,
             Tool             = lastAddedNut.Tool,
             ToolSize         = lastAddedNut.ToolSize,
             NutType          = lastAddedNut.NutType
         });
     }
 }
        internal static void ConnectFastenersNutsAndWashers(List <List <TessellatedSolid> > groupedPotentialFasteners)
        {
            // Possible cases:
            //  1. Fastener
            //  2. Fastener-Nut
            //  3. Fastener-Nut-Washer
            //  4. Fastener-Washer
            //  5. Nut
            //  6. Nut-Washer
            var counter1 = 0;

            foreach (var fastener in FastenerDetector.Fasteners)
            {
                counter1++;
                // if there is a fastener, find its nuts and washers
                var groupList = groupedPotentialFasteners.Where(g => g.Contains(fastener.Solid)).ToList();

                //------------------------------------- Case 1 ------------------------------------
                if (groupList.Count == 0)
                {
                    continue;
                }
                var group        = groupList.ToList()[0];
                var numFasteners = group.Count(s => FastenerDetector.Fasteners.Any(f => f.Solid == s));
                if (numFasteners > 1)
                {
                    continue;
                }
                //group.Add(fastener.Solid);
                //if (group.Count == 1) continue;

                //----------------------------------- Cases 2,3,4 ---------------------------------
                var nutAndWasherRemovalDirection = DisassemblyDirections.DirectionsAndOpposits[fastener.RemovalDirection];
                var nuts    = FastenerDetector.Nuts.Where(n => group.Contains(n.Solid)).ToList();
                var nutList = new List <Nut>();
                if (nuts.Any())
                {
                    foreach (var nut in nuts)
                    {
                        nut.RemovalDirection = nutAndWasherRemovalDirection;
                        nut.Diameter         = fastener.Diameter;
                        nut.Certainty        = 1.0;
                        nutList.Add(nut);
                    }
                }
                var potentialWasher = group.Where(s => s != fastener.Solid && nuts.All(n => s != n.Solid)).ToList();
                // if there is a solid which is very very small comparing the bolt, it is a washer?
                // the possible washer can still be a nut that has not been detected before
                // take its obb. if the smallest edge to the longest edge is less than 0.2, it's a washer,
                // otherwise it can be a nut with low certainty
                var washers = new List <Washer>();
                foreach (var pWasher in potentialWasher)
                {
                    if (Math.Abs(pWasher.Volume) > Math.Abs(fastener.Solid.Volume))
                    {
                        continue;
                    }
                    var edgesOfObb =
                        GeometryFunctions.SortedLengthOfObbEdges(BoundingGeometry.OrientedBoundingBoxDic[pWasher]);
                    if ((edgesOfObb[0] / edgesOfObb[2]) < 0.2)
                    // shortest/ longest // this can be fuzzified to define ceratinty
                    {
                        washers.Add(new Washer
                        {
                            Solid            = pWasher,
                            Certainty        = 0.7,
                            RemovalDirection = nutAndWasherRemovalDirection
                        });
                    }
                    else
                    {
                        // it can be a nut
                        var uncertainNut = new Nut
                        {
                            Solid            = pWasher,
                            Certainty        = 0.4,
                            RemovalDirection = nutAndWasherRemovalDirection
                        };
                        nutList.Add(uncertainNut);
                        FastenerDetector.Nuts.Add(uncertainNut);
                    }
                }
                fastener.Nuts   = nutList;
                fastener.Washer = washers;
                FastenerDetector.Washers.UnionWith(washers);
            }
            // if there is a detected nut, but its fastener was not detected:
            // fastener is unknown
            var counter2 = 0;

            foreach (var nut in FastenerDetector.Nuts)
            {
                counter2++;
                if (FastenerDetector.Fasteners.All(f => f.Nuts == null || !f.Nuts.Contains(nut)))
                {
                    // this a nut that doesnt have any fastener.
                    var groupList = groupedPotentialFasteners.Where(g => g.Contains(nut.Solid)).ToList();

                    //------------------------------------- Case 5 ------------------------------------
                    if (groupList.Count == 0)
                    {
                        continue;
                    }
                    var group = groupList.ToList()[0];
                    group.Add(nut.Solid);
                    //if (group.Count == 1) continue;

                    //---------------------------------- Cases 2,6 --------------------------------
                    var           potentialFastener            = group.Where(s => s != nut.Solid).ToList();
                    Fastener      fastener                     = null;
                    var           nutAndWasherRemovalDirection = 0;
                    List <Washer> washers = new List <Washer>();
                    foreach (var pF in potentialFastener)
                    {
                        if (pF.Volume > nut.Solid.Volume && fastener == null)
                        {
                            // can be a fastener
                            fastener = new Fastener
                            {
                                Solid            = pF,
                                RemovalDirection =
                                    FastenerDetector.RemovalDirectionFinderUsingObb(pF,
                                                                                    BoundingGeometry.OrientedBoundingBoxDic[pF]),
                                OverallLength =
                                    GeometryFunctions.SortedLengthOfObbEdges(
                                        BoundingGeometry.OrientedBoundingBoxDic[pF])[2],
                                EngagedLength = GeometryFunctions.SortedLengthOfObbEdges( // TBD
                                    BoundingGeometry.OrientedBoundingBoxDic[pF])[2],
                                Diameter  = nut.Diameter,
                                Certainty = 0.3
                            };
                            nutAndWasherRemovalDirection = DisassemblyDirections.Directions.IndexOf(
                                DisassemblyDirections.Directions[fastener.RemovalDirection].multiply(-1.0));
                        }
                        if (pF.Volume < nut.Solid.Volume)
                        {
                            // can be a washer
                            washers.Add(new Washer
                            {
                                Solid     = pF,
                                Certainty = 0.2
                            });
                        }
                    }
                    // by this point these things can have happened:
                    // A nut that its unknown fastener is found
                    // or a nut that its washer is found without fastener
                    // a nut, with its fastener and washer
                    FastenerDetector.Washers.UnionWith(washers);
                    if (fastener != null)
                    {
                        FastenerDetector.Fasteners.Add(fastener);
                        nut.RemovalDirection = nutAndWasherRemovalDirection;
                        fastener.Nuts        = new List <Nut> {
                            nut
                        };
                        fastener.Washer = washers;
                    }
                    // but if the fastener is null, if any washer exists,
                    //  it is a washer for the nut. Example: there is a
                    //  rod with some threads on one of its ends.
                    //  I cannot find the rod, but I can possibly find the
                    //  nut and the washer. So I will also define washer as
                    //  a property for nut.
                    nut.Washer = washers;
                    // removal direction? I can say along a line, and
                    // the see if any of those directions are infinite.
                    // but this doesnt work for threaded nuts and rods
                }
            }
        }
        internal static void Run(
            Dictionary <TessellatedSolid, List <PrimitiveSurface> > solidPrimitive,
            Dictionary <TessellatedSolid, List <TessellatedSolid> > multipleRefs)
        {
            var width = 55;
            var check = 0;

            LoadingBar.start(width, 0);

            var smallParts = FastenerDetector.SmallObjectsDetector(DisassemblyDirectionsWithFastener.PartsWithOneGeom);

            PreSelectedFastenerToFastenerClass(solidPrimitive, multipleRefs);
            foreach (
                var preSelected in
                FastenerDetector.PreSelectedFasteners.Where(preSelected => !smallParts.Contains(preSelected)))
            {
                smallParts.Add(preSelected);
            }

            FastenerDetector.PotentialFastener = new Dictionary <TessellatedSolid, double>();
            foreach (var p in smallParts)
            {
                FastenerDetector.PotentialFastener.Add(p, 0.1);
            }
            var groupedPotentialFasteners = FastenerDetector.GroupingSmallParts(smallParts);
            var uniqueParts = new HashSet <TessellatedSolid>();

            foreach (var s in multipleRefs.Keys.Where(FastenerDetector.PotentialFastener.Keys.Contains))
            {
                uniqueParts.Add(s);
            }
            foreach (
                var preFastener in
                FastenerDetector.Fasteners.Where(preFastener => uniqueParts.Contains(preFastener.Solid)))
            {
                uniqueParts.Remove(preFastener.Solid);
            }

            var equalPrimitivesForEveryUniqueSolid = FastenerDetector.EqualFlatPrimitiveAreaFinder(uniqueParts,
                                                                                                   solidPrimitive);
            List <int> learnerVotes;
            var        learnerWeights = FastenerPerceptronLearner.ReadingLearnerWeightsAndVotesFromCsv(out learnerVotes);


            List <string> nameList = new List <string>();

            foreach (var part in uniqueParts)
            {
                nameList.Add(part.Name);
            }
            int preCutoff  = 0;
            int postCutoff = 0;

            PartNameAnalysis.findCommonPreSuffixes(nameList, ref preCutoff, ref postCutoff);



            var refresh = (int)Math.Ceiling((float)uniqueParts.Count / (float)(width * 4));

            Parallel.ForEach(uniqueParts, solid =>
                             //foreach (var solid in uniqueParts)
            {
                if (check % refresh == 0)
                {
                    LoadingBar.refresh(width, ((float)check) / ((float)uniqueParts.Count));
                }
                check++;

                double toolSize;
                var commonHead = AutoThreadedFastenerDetection.CommonHeadCheck(solid, solidPrimitive[solid],
                                                                               equalPrimitivesForEveryUniqueSolid[solid], out toolSize);
                if (commonHead == 1)
                {
                    // can be a threaded hex fastener, threaded hex nut, nonthreaded hex fastener, nonthreaded hex nut
                    var newFastener = FastenerPolynomialTrend.PolynomialTrendDetector(solid);
                    if (newFastener != null)
                    {
                        // threaded hex fastener
                        newFastener.Tool     = Tool.HexWrench;
                        newFastener.ToolSize = toolSize;
                        lock (FastenerDetector.Fasteners)
                            FastenerDetector.Fasteners.Add(newFastener);
                        AutoThreadedFastenerDetection.AddRepeatedSolidstoFasteners(newFastener, multipleRefs[solid]);
                        //continue;
                        return;
                    }
                    var lengthAndRadius =
                        AutoNonthreadedFastenerDetection.FastenerEngagedLengthAndRadiusNoThread(solid, solidPrimitive[solid]);
                    if (AutoNonthreadedFastenerDetection.IsItNut(
                            solidPrimitive[solid].Where(p => p is Cylinder).Cast <Cylinder>().ToList(), solid))
                    {
                        var nut = new Nut
                        {
                            NutType       = NutType.Hex,
                            Solid         = solid,
                            ToolSize      = toolSize,
                            OverallLength = lengthAndRadius[0],
                            Diameter      = lengthAndRadius[1] * 2.0
                        };
                        lock (FastenerDetector.Nuts)
                            FastenerDetector.Nuts.Add(nut);
                        AutoThreadedFastenerDetection.AddRepeatedSolidstoNuts(nut, multipleRefs[solid]);
                    }
                    // nonthreaded hex fastener
                    var fas = new Fastener
                    {
                        Solid            = solid,
                        FastenerType     = FastenerTypeEnum.Bolt,
                        Tool             = Tool.HexWrench,
                        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(fas);
                    AutoThreadedFastenerDetection.AddRepeatedSolidstoFasteners(fas, multipleRefs[solid]);
                    return;
                }
                if (commonHead == 2)
                {
                    // can be a threaded allen, nonthreaded allen
                    AddThreadedOrNonthreadedFastener(solid, multipleRefs[solid], solidPrimitive[solid], Tool.Allen,
                                                     toolSize);
                    return;
                }
                if (commonHead == 3 || commonHead == 5)
                {
                    // can be a threaded philips fastener, nonthreaded philips fastener
                    AddThreadedOrNonthreadedFastener(solid, multipleRefs[solid], solidPrimitive[solid], Tool.PhillipsBlade,
                                                     toolSize);
                    return;
                }
                if (commonHead == 4)
                {
                    // can be a threaded flat fastener, nonthreaded flat fastener
                    AddThreadedOrNonthreadedFastener(solid, multipleRefs[solid], solidPrimitive[solid], Tool.FlatBlade,
                                                     toolSize);
                    return;
                }

                // if it's not a common head and not threaded, I cannot detect it.
                // so the rest will be similar to threaded fastener detector
                if (FastenerPerceptronLearner.FastenerPerceptronClassifier(solidPrimitive[solid], solid, learnerWeights, learnerVotes))
                {
                    var newFastener = FastenerPolynomialTrend.PolynomialTrendDetector(solid);
                    if (newFastener != null)
                    {
                        lock (FastenerDetector.Fasteners)
                            FastenerDetector.Fasteners.Add(newFastener);
                        AutoThreadedFastenerDetection.AddRepeatedSolidstoFasteners(newFastener, multipleRefs[solid]);
                        //continue;
                        return;
                    }
                    // can be a nut
                    // use bounding cylinder to detect nuts.
                    // Since the nuts are small, the OBB function doesnt work accurately for them.
                    //  So, I cannot really trust this.
                    var newNut = NutPolynomialTrend.PolynomialTrendDetector(solid);
                    if (newNut != null)
                    // It is a nut with certainty == 1
                    {
                        lock (FastenerDetector.Nuts)
                            FastenerDetector.Nuts.Add(newNut);
                        AutoThreadedFastenerDetection.AddRepeatedSolidstoNuts(newNut, multipleRefs[solid]);
                        //continue;
                        return;
                    }
                    // still can be a nut since the upper approach is not really accurate
                    // this 50 percent certainty can go up if the nut is mated with a
                    // detected fastener
                    foreach (var repeatedSolid in multipleRefs[solid])
                    {
                        lock (FastenerDetector.Nuts)
                            FastenerDetector.Nuts.Add(new Nut
                            {
                                Solid    = repeatedSolid,
                                Diameter = BoundingGeometry.BoundingCylinderDic[solid].Radius * 2.0,
                                // this is approximate
                                OverallLength = BoundingGeometry.BoundingCylinderDic[solid].Length,
                                Certainty     = 0.5
                            });
                    }
                    //continue;
                    return;
                }
                // if it is not captured by any of the upper methods, give it another chance:
                if (AutoThreadedFastenerDetection.ThreadDetector(solid, solidPrimitive[solid]))
                {
                    var newFastener = FastenerPolynomialTrend.PolynomialTrendDetector(solid);
                    if (newFastener != null)
                    {
                        newFastener.FastenerType = FastenerTypeEnum.Bolt;
                        lock (FastenerDetector.Fasteners)
                            FastenerDetector.Fasteners.Add(newFastener);
                        AutoThreadedFastenerDetection.AddRepeatedSolidstoFasteners(newFastener, multipleRefs[solid]);
                        //continue;
                        return;
                    }
                    //if not, it is a nut:
                    foreach (var repeatedSolid in multipleRefs[solid])
                    {
                        lock (FastenerDetector.Nuts)
                            FastenerDetector.Nuts.Add(new Nut
                            {
                                Solid    = repeatedSolid,
                                Diameter = BoundingGeometry.BoundingCylinderDic[solid].Radius * 2.0,
                                // this is approximate
                                OverallLength = BoundingGeometry.BoundingCylinderDic[solid].Length * 2.0,
                                Certainty     = 0.5
                            });
                    }
                }
            }
                             );
            // now use groupped small objects:
            AutoNonthreadedFastenerDetection.ConnectFastenersNutsAndWashers(groupedPotentialFasteners);
            LoadingBar.refresh(width, 1);
        }