internal static Dictionary <TessellatedSolid, List <PrimitiveSurface> > PrimitiveMaker(List <TessellatedSolid> parts)
        {
            Console.WriteLine();
            Console.WriteLine("Classifying Primitives for " + parts.Count + " unique parts ....");
            var partPrimitive = new Dictionary <TessellatedSolid, List <PrimitiveSurface> >();


            int width   = 55;
            int refresh = (int)Math.Ceiling(((float)parts.Count) / ((float)(width)));
            int check   = 0;

            LoadingBar.start(width, 0);

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

                var solidPrim = solid.ClassifyPrimitiveSurfaces(true);
                lock (partPrimitive)
                    partPrimitive.Add(solid, solidPrim);
            }
                             );//
            LoadingBar.refresh(width, 1);
            return(partPrimitive);
        }
Example #2
0
        internal static void Run(
            Dictionary <TessellatedSolid, List <PrimitiveSurface> > solidPrimitive,
            Dictionary <TessellatedSolid, List <TessellatedSolid> > multipleRefs)
        {
            // This is mostly similar to the auto fastener detection with no thread, but instead of learning
            // from the area of the cylinder and for example flat, we will learn from the number of faces.
            // why? because if we have thread, we will have too many triangles. And this can be useful.
            // I can also detect helix and use this to detect the threaded fasteners

            // Important: if the fasteners are threaded using solidworks Fastener toolbox, it will not
            //            have helix. The threads will be small cones with the same axis and equal area.
            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);

            FastenerGaussianNaiveBayes.GNB();


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

            foreach (var part in uniqueParts)
            {
                nameList.Add(part.Name);
            }
            float nameRating;

            float ratingAverage = 0;
            float ratingMax     = -1;
            float ratingMin     = 100000000000;
            int   preCutoff     = 0;
            int   postCutoff    = 0;

            PartNameAnalysis.findCommonPreSuffixes(nameList, ref preCutoff, ref postCutoff);
            foreach (var part in uniqueParts)
            {
                nameRating     = PartNameAnalysis.SolidHasFastenerKeyword(part, preCutoff, postCutoff);
                ratingAverage += nameRating;
                ratingMax      = Math.Max(ratingMax, nameRating);
                ratingMin      = Math.Min(ratingMin, nameRating);
            }
            float proportion = 1 - (ratingMax - ratingMin) / 3;

            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++;

                var initialCertainty = FastenerGaussianNaiveBayes.GaussianNaiveBayesClassifier(solidPrimitive[solid], solid);

                nameRating = (PartNameAnalysis.SolidHasFastenerKeyword(solid, preCutoff, postCutoff) - ratingMin) / (0.001f + ratingMax - ratingMin);

                FastenerDetector.PotentialFastener[solid] = (0.1 + initialCertainty) * proportion + (1 - nameRating) * (1 - proportion);
                foreach (var up in multipleRefs[solid])
                {
                    FastenerDetector.PotentialFastener[up] = (0.1 + initialCertainty) * proportion + (1 - nameRating) * (1 - proportion);
                }

                // if a fastener is detected using polynomial trend approach, it is definitely a fastener but not a nut.
                // if it is detected using any other approach, but not polynomial trend, it is a possible nut.
                double toolSize;
                var commonHead = CommonHeadCheck(solid, solidPrimitive[solid], equalPrimitivesForEveryUniqueSolid[solid],
                                                 out toolSize);
                if (commonHead != 0)
                {
                    var newFastener = FastenerPolynomialTrend.PolynomialTrendDetector(solid);
                    if (newFastener != null)
                    {
                        newFastener.ToolSize = toolSize;
                        if (commonHead == 1)
                        {
                            newFastener.Tool = Tool.HexWrench;
                            lock (FastenerDetector.Fasteners)
                                FastenerDetector.Fasteners.Add(newFastener);
                            AddRepeatedSolidstoFasteners(newFastener, multipleRefs[solid]);
                            //continue;
                            return;
                        }
                        if (commonHead == 2)
                        {
                            newFastener.Tool = Tool.Allen;
                            lock (FastenerDetector.Fasteners)
                                FastenerDetector.Fasteners.Add(newFastener);
                            AddRepeatedSolidstoFasteners(newFastener, multipleRefs[solid]);
                            //continue;
                            return;
                        }
                        if (commonHead == 3)
                        {
                            newFastener.Tool = Tool.PhillipsBlade;
                            lock (FastenerDetector.Fasteners)
                                FastenerDetector.Fasteners.Add(newFastener);
                            AddRepeatedSolidstoFasteners(newFastener, multipleRefs[solid]);
                            //continue;
                            return;
                        }
                        if (commonHead == 4)
                        {
                            newFastener.Tool = Tool.FlatBlade;
                            lock (FastenerDetector.Fasteners)
                                FastenerDetector.Fasteners.Add(newFastener);
                            AddRepeatedSolidstoFasteners(newFastener, multipleRefs[solid]);
                            //continue;
                            return;
                        }
                        if (commonHead == 5)
                        {
                            newFastener.Tool = Tool.PhillipsBlade;
                            lock (FastenerDetector.Fasteners)
                                FastenerDetector.Fasteners.Add(newFastener);
                            AddRepeatedSolidstoFasteners(newFastener, multipleRefs[solid]);
                            //continue;
                            return;
                        }
                    }
                    else // can be a nut
                    {
                        if (commonHead == 1)
                        {
                            FastenerDetector.Nuts.Add(new Nut
                            {
                                Solid         = solid,
                                NutType       = NutType.Hex,
                                Tool          = Tool.HexWrench,
                                ToolSize      = toolSize,
                                OverallLength = BoundingGeometry.BoundingCylinderDic[solid].Length,
                                Certainty     = initialCertainty // 0.9
                            });
                            foreach (var repeatedSolid in multipleRefs[solid])
                            {
                                lock (FastenerDetector.Nuts)
                                    FastenerDetector.Nuts.Add(new Nut
                                    {
                                        Solid         = repeatedSolid,
                                        NutType       = NutType.Hex,
                                        Tool          = Tool.HexWrench,
                                        ToolSize      = toolSize,
                                        OverallLength = BoundingGeometry.BoundingCylinderDic[solid].Length,
                                        Certainty     = initialCertainty // 0.9
                                    });
                            }
                            //continue;
                            return;
                        }
                    }
                }
                if (FastenerPerceptronLearner.FastenerPerceptronClassifier(solidPrimitive[solid], solid, learnerWeights,
                                                                           learnerVotes))
                {
                    var newFastener = FastenerPolynomialTrend.PolynomialTrendDetector(solid);
                    if (newFastener != null)
                    {
                        lock (FastenerDetector.Fasteners)
                            FastenerDetector.Fasteners.Add(newFastener);
                        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);
                        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     = initialCertainty // 0.5
                            });
                    }
                    //continue;
                    return;
                }
                // if it is not captured by any of the upper methods, give it another chance:
                if (ThreadDetector(solid, solidPrimitive[solid]))
                {
                    var newFastener = FastenerPolynomialTrend.PolynomialTrendDetector(solid);
                    if (newFastener != null)
                    {
                        newFastener.FastenerType = FastenerTypeEnum.Bolt;
                        lock (FastenerDetector.Fasteners)
                            FastenerDetector.Fasteners.Add(newFastener);
                        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     = initialCertainty // 0.5
                            });
                    }
                }
            }
                             ); //
            // now use groupped small objects:
            AutoNonthreadedFastenerDetection.ConnectFastenersNutsAndWashers(groupedPotentialFasteners);
            LoadingBar.refresh(width, 1);
        }
        internal static void Run(
            Dictionary <TessellatedSolid, List <PrimitiveSurface> > solidPrimitive,
            Dictionary <TessellatedSolid, List <TessellatedSolid> > multipleRefs)
        {
            // This approach will use the symmetric shape of the fasteners' heads. If there is no thread,
            // we willl consider the area of the positive culinders for bolts and negative cylinder for
            // nuts.
            // This is an important point:
            //      1. Find the small objects using all of the solids
            //      2. Group them using small objects
            //      3. Detect the fasteners using multiple references. (for each similar object, detect one of them)
            var width = 55;
            var check = 0;

            LoadingBar.start(width, 0);

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

            //new List<TessellatedSolid>(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);
            var checkedSolids = new HashSet <TessellatedSolid>();

            FastenerGaussianNaiveBayes.GNB();



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

            foreach (var part in uniqueParts)
            {
                nameList.Add(part.Name);
            }
            float nameRating;

            float ratingAverage = 0;
            float ratingMax     = -1;
            float ratingMin     = 100000000000;
            int   preCutoff     = 0;
            int   postCutoff    = 0;

            PartNameAnalysis.findCommonPreSuffixes(nameList, ref preCutoff, ref postCutoff);
            foreach (var part in uniqueParts)
            {
                nameRating     = PartNameAnalysis.SolidHasFastenerKeyword(part, preCutoff, postCutoff);
                ratingAverage += nameRating;
                ratingMax      = Math.Max(ratingMax, nameRating);
                ratingMin      = Math.Min(ratingMin, nameRating);
            }
            float proportion = 1 - (ratingMax - ratingMin) / 3;



            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++;

                var initialCertainty = FastenerGaussianNaiveBayes.GaussianNaiveBayesClassifier(solidPrimitive[solid],
                                                                                               solid);

                nameRating = (PartNameAnalysis.SolidHasFastenerKeyword(solid, preCutoff, postCutoff) - ratingMin) / (0.001f + ratingMax - ratingMin);

                FastenerDetector.PotentialFastener[solid] = (0.1 + initialCertainty) * proportion + (1 - nameRating) * (1 - proportion);
                foreach (var up in multipleRefs[solid])
                {
                    FastenerDetector.PotentialFastener[up] = (0.1 + initialCertainty) * proportion + (1 - nameRating) * (1 - proportion);
                }


                if (solidPrimitive[solid].Count == 0)
                {
                    return;
                }
                if (HexBoltNutAllen(solid, solidPrimitive[solid], equalPrimitivesForEveryUniqueSolid[solid],
                                    multipleRefs[solid]))
                {
                    //continue;
                    lock (checkedSolids)
                    {
                        checkedSolids.Add(solid);
                    }
                    return;
                }
                if (PhillipsHeadBolt(solid, solidPrimitive[solid], equalPrimitivesForEveryUniqueSolid[solid],
                                     multipleRefs[solid]))
                {
                    //continue;
                    lock (checkedSolids)
                    {
                        checkedSolids.Add(solid);
                    }
                    return;
                }
                if (SlotHeadBolt(solid, solidPrimitive[solid], equalPrimitivesForEveryUniqueSolid[solid],
                                 multipleRefs[solid]))
                {
                    //continue;
                    lock (checkedSolids)
                    {
                        checkedSolids.Add(solid);
                    }
                    return;
                }
                if (PhillipsSlotComboHeadBolt(solid, solidPrimitive[solid], equalPrimitivesForEveryUniqueSolid[solid],
                                              multipleRefs[solid]))
                {
                    //continue;
                    lock (checkedSolids)
                    {
                        checkedSolids.Add(solid);
                    }
                    return;
                }
                lock (checkedSolids)
                {
                    checkedSolids.Add(solid);
                }
            }
                             );//
            // when all of the fasteners are recognized, it's time to check the third level filter:
            // something is not acceptable: nut without fastener. If there is a nut without fastener,
            // I will try to look for that.
            // Is there anyway to detect more?
            ConnectFastenersNutsAndWashers(groupedPotentialFasteners);
            LoadingBar.refresh(width, 1);
        }
        // This class is added as an alternative for current Nonadjacent blocking determination approach.
        // The overal approach is the same as before (ray shooting), but number of both rays and blocking
        // triangles are droped to speedup the function.
        // Rays: Instead of checking blockings for every direction, for every two parts, their possible
        //       blocking directions are found based upon the planes that can seperate the two CVHs linearlly.
        //       (If the CVHs are not linearly seperable we cannot apply this.)
        // Triangles: Number of triangles (of the blocking solid) is the most affecting factor in blocking
        //       determination. Code gets really really slow when it goes to check intersection of the ray
        //       and all the triangles of the solid. We are avoiding this problem here by partitionaning
        //       our search space into k number of sections obtained originally from OBB of the solid.
        internal static void Run(designGraph graph, Dictionary <string, List <TessellatedSolid> > subAssems, List <int> gDir)
        {
            Console.WriteLine("\n\nNonadjacent Blocking Determination is running ....");
            long totalCases      = 0;
            var  subAssemsToList = subAssems.ToList();

            for (var i = 0; i < subAssems.Count - 1; i++)
            {
                var subAssem1 = subAssemsToList[i];
                for (var j = i + 1; j < subAssems.Count; j++)
                {
                    var subAssem2 = subAssemsToList[j];
                    var tri2Sub1  = subAssem1.Value.Sum(s => s.Faces.Length);
                    var tri2Sub2  = subAssem2.Value.Sum(s => s.Faces.Length);
                    totalCases += tri2Sub1 * tri2Sub2;
                }
            }
            ObbFacesHashSet = new Dictionary <TessellatedSolid, HashSet <PolygonalFace> >();
            CombinedCVHForMultipleGeometries = new Dictionary <string, TVGLConvexHull>();

            long counter = 0;

            foreach (var subAssem in subAssems)
            {
                List <BoundingBox> pairList = new List <BoundingBox>();
                foreach (var s in subAssem.Value)
                {
                    //CvhHashSet.Add(s, new HashSet<PolygonalFace>(s.ConvexHull.Faces));


                    //$ What was used previously

                    /*
                     * ObbFacesHashSet.Add(s,
                     *  new HashSet<PolygonalFace>(
                     *      PartitioningSolid.TwelveFaceGenerator(
                     *          BoundingGeometry.OrientedBoundingBoxDic.First(b=> b.Key.Name == s.Name).Value.CornerVertices.Select(
                     *              cv => new Vertex(cv.Position)).ToArray())));
                     */
                    KeyValuePair <TessellatedSolid, BoundingBox> pair = BoundingGeometry.OrientedBoundingBoxDic.FirstOrDefault(b => b.Key.Name == s.Name);
                    if (!pair.Equals(default(KeyValuePair <TessellatedSolid, BoundingBox>)))
                    {
                        ObbFacesHashSet.Add(s, new HashSet <PolygonalFace>(PartitioningSolid.TwelveFaceGenerator(pair.Value.CornerVertices.Select(cv => new Vertex(cv.Position)).ToArray())));
                    }
                }
            }

            CreateCombinedCVHs(subAssems);



            var solidsL = subAssems.ToList();


            int width   = 55;
            int total   = (solidsL.Count + 1) * (solidsL.Count / 2);
            int refresh = (int)Math.Ceiling(((float)total) / ((float)(width)));
            int check   = 0;

            LoadingBar.start(width, 0);


            for (var i = 0; i < solidsL.Count; i++)
            {
                var solidMoving = solidsL[i].Value;
                for (var j = i + 1; j < solidsL.Count; j++)
                {
                    if (check % refresh == 0)
                    {
                        LoadingBar.refresh(width, ((float)check) / ((float)total));
                    }
                    check++;

                    var blocked = false;
                    // check the convex hull of these two solids to find the planes tha can linearly seperate them
                    // solid1 is moving and solid2 is blocking
                    var solidBlocking = solidsL[j].Value;
                    counter += solidMoving.Sum(s => s.Faces.Length) * solidBlocking.Sum(s => s.Faces.Length);
                    if (
                        graph.arcs.Any(
                            a => a is Connection &&
                            ((a.From.name == solidsL[i].Key && a.To.name == solidsL[j].Key) ||
                             (a.From.name == solidsL[j].Key && a.To.name == solidsL[i].Key))))
                    {
                        continue;
                    }
                    // Add a secondary arc to the
                    var from = GetNode(graph, solidsL[i].Key);
                    var to   = GetNode(graph, solidsL[j].Key);
                    graph.addArc(from, to, from.name + to.name, typeof(SecondaryConnection));
                    var lastAddedSecArc    = (SecondaryConnection)graph.arcs.Last();
                    var filteredDirections = FilterGlobalDirections(solidMoving, solidBlocking, gDir);
                    var oppositeFiltrdDirs = filteredDirections.Select(d => DisassemblyDirections.DirectionsAndOppositsForGlobalpool[d]).ToList();
                    // remember this: if solid2 is not blocking solid1, we need to check if solid1 is blocking 2 in the opposite direction.
                    // if filteredDirections.Count == gDir.Count then the CVHs overlap
                    // Only directions need to be checked which the moving part can move along them:
                    var scndFilteredDirectionsMoving   = FinalSetOfDirectionsFinder(graph, solidMoving, filteredDirections);
                    var scndFilteredDirectionsBlocking = new List <int>();
                    scndFilteredDirectionsBlocking = FinalSetOfDirectionsFinder(graph, solidBlocking,
                                                                                filteredDirections.Count == gDir.Count ? filteredDirections : oppositeFiltrdDirs);
                    foreach (
                        var d in
                        scndFilteredDirectionsMoving.Where(
                            d =>
                            !scndFilteredDirectionsBlocking.Contains(
                                DisassemblyDirections.DirectionsAndOppositsForGlobalpool[d])))
                    {
                        scndFilteredDirectionsBlocking.Add(DisassemblyDirections.DirectionsAndOppositsForGlobalpool[d]);
                    }
                    foreach (
                        var d in
                        scndFilteredDirectionsBlocking.Where(
                            d =>
                            !scndFilteredDirectionsMoving.Contains(
                                DisassemblyDirections.DirectionsAndOppositsForGlobalpool[d])))
                    {
                        scndFilteredDirectionsMoving.Add(DisassemblyDirections.DirectionsAndOppositsForGlobalpool[d]);
                    }
                    if (filteredDirections.Count == gDir.Count)
                    {
                        //continue;
                        Parallel.ForEach(scndFilteredDirectionsMoving, filtDir =>
                                         //foreach (var filtDir in filteredDirections)
                        {
                            var direction = DisassemblyDirections.Directions[filtDir];
                            blocked       = BlockingDeterminationWithCvhOverlapping(direction, solidMoving, solidBlocking);
                            if (blocked)
                            {
                                lock (lastAddedSecArc.Directions)
                                    lastAddedSecArc.Directions.Add(filtDir);
                                if (
                                    scndFilteredDirectionsBlocking.Contains(
                                        DisassemblyDirections.DirectionsAndOppositsForGlobalpool[filtDir]))
                                {
                                    scndFilteredDirectionsBlocking.Remove(
                                        DisassemblyDirections.DirectionsAndOppositsForGlobalpool[filtDir]);
                                }
                            }
                        });
                        Parallel.ForEach(scndFilteredDirectionsBlocking, filtDir =>
                                         //foreach (var filtDir in filteredDirections)
                        {
                            var direction = DisassemblyDirections.Directions[filtDir];
                            blocked       = BlockingDeterminationWithCvhOverlapping(direction, solidBlocking, solidMoving);
                            if (blocked)
                            {
                                lock (lastAddedSecArc.Directions)
                                    lastAddedSecArc.Directions.Add(DisassemblyDirections.DirectionsAndOppositsForGlobalpool[filtDir]);
                            }
                        });
                        if (lastAddedSecArc.Directions.Count == 0)
                        {
                            graph.removeArc(lastAddedSecArc);
                        }
                    }
                    else
                    {
                        //continue;
                        // If CVHs dont overlap:

                        //$ Made this non-parallel for debugging purposes - switch back later
                        Parallel.ForEach(scndFilteredDirectionsMoving, filtDir =>
                                         //foreach (var filtDir in filteredDirections)
                        {
                            var direction = DisassemblyDirections.Directions[filtDir];
                            blocked       = BlockingDeterminationNoCvhOverlapping(direction, solidMoving, solidBlocking);
                            if (blocked)
                            {
                                lock (lastAddedSecArc.Directions)
                                    lastAddedSecArc.Directions.Add(filtDir);
                                if (
                                    scndFilteredDirectionsBlocking.Contains(
                                        DisassemblyDirections.DirectionsAndOppositsForGlobalpool[filtDir]))
                                {
                                    scndFilteredDirectionsBlocking.Remove(
                                        DisassemblyDirections.DirectionsAndOppositsForGlobalpool[filtDir]);
                                }
                            }
                        });

                        Parallel.ForEach(scndFilteredDirectionsBlocking, filtDir =>
                                         //foreach (var filtDir in filteredDirections)
                        {
                            var direction = DisassemblyDirections.Directions[filtDir];
                            blocked       = BlockingDeterminationNoCvhOverlapping(direction, solidBlocking, solidMoving);
                            if (blocked)
                            {
                                lock (lastAddedSecArc.Directions)
                                    lastAddedSecArc.Directions.Add(DisassemblyDirections.DirectionsAndOppositsForGlobalpool[filtDir]);
                            }
                        });
                        if (lastAddedSecArc.Directions.Count == 0)
                        {
                            graph.removeArc(lastAddedSecArc);
                        }
                    }
                }
            }
            LoadingBar.refresh(width, 1);
            CreateSameDirectionDictionary(gDir);
        }
        internal static void CreatePartitions(Dictionary <string, List <TessellatedSolid> > solids)
        {
            Console.WriteLine("\nUpdating Bounding Geometries ....");
            int width   = 55;
            int refresh = (int)Math.Ceiling(((float)solids.Count) / ((float)(width * 4)));
            int check   = 0;

            LoadingBar.start(width, 0);
            var solidGeometries  = solids.SelectMany(s => s.Value).ToList();
            var solidGeometries2 = Program.Solids.SelectMany(s => s.Value).ToList();
            var totalVerts       = solidGeometries.Sum(s => s.Vertices.Count());

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

                /*Partition[] prtn;
                 *
                 * for ()
                 * {
                 *
                 * }*/

                BoundingBox bad  = new BoundingBox();
                BoundingBox val  = bad;
                Partition[] prtn = new Partition[0];
                foreach (KeyValuePair <TessellatedSolid, BoundingBox> b
                         in BoundingGeometry.OrientedBoundingBoxDic)
                {
                    if (b.Key.Name == solid.Name)
                    {
                        val = b.Value;
                    }
                }
                if (!val.Equals(bad))
                {
                    prtn = Run(new HashSet <Vertex>(solid.Vertices), new HashSet <PolygonalFace>(solid.Faces),
                               val.CornerVertices.Select(cv => new Vertex(cv.Position)).ToArray());
                }
                else
                {
                    //$ Removing this check for now
                    //string err = "A bounding box was not found";
                    //throw new SystemException(err);
                }

                /*
                 * prtn = Run(new HashSet<Vertex>(solid.Vertices), new HashSet<PolygonalFace>(solid.Faces),
                 *  BoundingGeometry.OrientedBoundingBoxDic.First(b=>b.Key.Name == solid.Name).Value.CornerVertices.Select(
                 *      cv => new Vertex(cv.Position)).ToArray());*/
                //lock (Partitions)
                //{
                Partitions.Add(solid, prtn);
                //}
            }//);

            // partition of AABB:
            Parallel.ForEach(solidGeometries2, solid =>
            {
                var cornerVer = new[]
                {
                    new Vertex(new [] { solid.XMin, solid.YMin, solid.ZMin }),
                    new Vertex(new [] { solid.XMin, solid.YMin, solid.ZMax }),
                    new Vertex(new [] { solid.XMin, solid.YMax, solid.ZMin }),
                    new Vertex(new [] { solid.XMin, solid.YMax, solid.ZMax }),
                    new Vertex(new [] { solid.XMax, solid.YMin, solid.ZMin }),
                    new Vertex(new [] { solid.XMax, solid.YMin, solid.ZMax }),
                    new Vertex(new [] { solid.XMax, solid.YMax, solid.ZMin }),
                    new Vertex(new [] { solid.XMax, solid.YMax, solid.ZMax }),
                };
                var prtn = RunForAABB(new HashSet <Vertex>(solid.Vertices), new HashSet <PolygonalFace>(solid.Faces), cornerVer);
                lock (PartitionsAABB)
                {
                    PartitionsAABB.Add(solid, prtn);
                }
            });//
            LoadingBar.refresh(width, 1);
        }
        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);
        }
Example #7
0
        internal static List <int> RunGraphGeneration(designGraph assemblyGraph, Dictionary <string, List <TessellatedSolid> > solidsNoFastener)
        {
            Solids           = Program.Solids;
            solidsNoFastener = Program.SolidsNoFastener;

            //$ Added because it seems that primitive surfaces are populated in step one
            //  Extracting primitives from the list of solids
            foreach (KeyValuePair <string, List <TessellatedSolid> > p in Solids)
            {
                foreach (TessellatedSolid t in p.Value)
                {
                    SolidPrimitive[t] = t.Primitives;
                }
            }
            //

            //PrintOutSomeInitialStats();
            var globalDirPool = new List <int>();
            // Detect gear mates
            //------------------------------------------------------------------------------------------
            var gears = GearDetector.Run(PartsWithOneGeom, SolidPrimitive);
            var sw    = new Stopwatch();

            sw.Start();

            // Add the solids as nodes to the graph. Exclude the fasteners
            //------------------------------------------------------------------------------------------
            //DisassemblyDirections.Solids = new List<TessellatedSolid>(solidsNoFastener);
            AddingNodesToGraph(assemblyGraph, solidsNoFastener); //, gears, screwsAndBolts);

            // Implementing region octree for every solid
            //------------------------------------------------------------------------------------------
            PartitioningSolid.Partitions     = new Dictionary <TessellatedSolid, Partition[]>();
            PartitioningSolid.PartitionsAABB = new Dictionary <TessellatedSolid, PartitionAABB[]>();
            PartitioningSolid.CreatePartitions(solidsNoFastener);

            // Part to part interaction to obtain removal directions between every connected pair
            //------------------------------------------------------------------------------------------

            Console.WriteLine(" \n\nAdjacent Blocking Determination ...");
            var width = 55;

            LoadingBar.start(width, 0);

            BlockingDetermination.OverlappingSurfaces = new List <OverlappedSurfaces>();
            var  solidNofastenerList = solidsNoFastener.ToList();
            long totalTriTobeChecked = 0;
            var  overlapCheck        = new HashSet <KeyValuePair <string, List <TessellatedSolid> >[]>();

            for (var i = 0; i < solidsNoFastener.Count - 1; i++)
            {
                var subAssem1 = solidNofastenerList[i];
                for (var j = i + 1; j < solidsNoFastener.Count; j++)
                {
                    var subAssem2 = solidNofastenerList[j];
                    overlapCheck.Add(new[] { subAssem1, subAssem2 });
                    var tri2Sub1 = subAssem1.Value.Sum(s => s.Faces.Length);
                    var tri2Sub2 = subAssem2.Value.Sum(s => s.Faces.Length);
                    totalTriTobeChecked += tri2Sub1 * tri2Sub2;
                }
            }
            var  total   = overlapCheck.Count;
            var  refresh = (int)Math.Ceiling(((float)total) / ((float)(width * 4)));
            var  check   = 0;
            long counter = 0;


            //$ Need to convert back to parallel after debug
            //foreach (var each in overlapCheck)
            Parallel.ForEach(overlapCheck, each =>
            {
                if (check % refresh == 0)
                {
                    LoadingBar.refresh(width, ((float)check) / ((float)total));
                }
                check++;
                var localDirInd = new List <int>();
                for (var t = 0; t < DisassemblyDirections.Directions.Count; t++)
                {
                    localDirInd.Add(t);
                }
                var connected = false;
                var certainty = 0.0;
                foreach (var solid1 in each[0].Value)
                {
                    foreach (var solid2 in each[1].Value)
                    {
                        counter += solid1.Faces.Length * solid2.Faces.Length;
                        double localCertainty;
                        var blocked = BlockingDetermination.DefineBlocking(solid1, solid2, globalDirPool,
                                                                           localDirInd, out localCertainty);
                        if (connected == false)
                        {
                            connected = blocked;
                        }
                        if (localCertainty > certainty)
                        {
                            certainty = localCertainty;
                        }
                    }
                }
                if (connected)
                {
                    // I wrote the code in a way that "solid1" is always "Reference" and "solid2" is always "Moving".
                    // Update the romoval direction if it is a gear mate:
                    localDirInd = GearDetector.UpdateRemovalDirectionsIfGearMate(each[0].Value,
                                                                                 each[1].Value, gears, localDirInd);
                    List <int> finDirs, infDirs;
                    NonadjacentBlockingDetermination.FiniteDirectionsBetweenConnectedPartsWithPartitioning(
                        each[0].Value, each[1].Value, localDirInd, out finDirs, out infDirs);
                    lock (assemblyGraph)
                    {
                        var from = assemblyGraph[each[1].Key]; // Moving
                        var to   = assemblyGraph[each[0].Key]; // Reference
                        assemblyGraph.addArc((node)from, (node)to, "", typeof(Connection));
                        var a       = (Connection)assemblyGraph.arcs.Last();
                        a.Certainty = certainty;
                        AddInformationToArc(a, finDirs, infDirs);
                    }
                }
            });
            LoadingBar.refresh(width, 1);
            Fastener.AddFastenersInformation(assemblyGraph, solidsNoFastener, SolidPrimitive);
            // create oppositeDirections for global direction pool.
            FindingOppositeDirectionsForGlobalPool(globalDirPool);

            // Simplify the solids, before doing anything
            //------------------------------------------------------------------------------------------
            foreach (var solid in solidsNoFastener)
            {
                Program.SolidsNoFastenerSimplified.Add(solid.Key, Program.SimplifiedSolids[solid.Key]);
            }
            SimplifySolids(Program.SimplifiedSolids, 0.7);

            // Implementing region octree for every solid
            //------------------------------------------------------------------------------------------
            PartitioningSolid.Partitions     = new Dictionary <TessellatedSolid, Partition[]>();
            PartitioningSolid.PartitionsAABB = new Dictionary <TessellatedSolid, PartitionAABB[]>();
            PartitioningSolid.CreatePartitions(Program.SimplifiedSolids);

            CheckToHaveConnectedGraph(assemblyGraph);


            return(globalDirPool);
        }