public static void doAssemblyPlanning(string dir)
        {
            state = new ProgramState();
            if (dir == "")
            {
                dir = ".";
            }
            if (serverMode)
            {
                ProgramState.Load(dir + slash + "intermediate" + slash + "ProgramState.xml", ref state);
            }
            else
            {
                ProgramState.Load(dir + slash + "bin" + slash + "intermediate" + slash + "ProgramState.xml", ref state);
            }
            LoadState();

            checkDirs();
            AssemblyGraph.RepairGraphConnections();


            //$ Adding this so that bounding box related functionalities still work
            BoundingGeometry.OrientedBoundingBoxDic = new Dictionary <TessellatedSolid, BoundingBox>();
            BoundingGeometry.BoundingCylinderDic    = new Dictionary <TessellatedSolid, BoundingCylinder>();
            BoundingGeometry.CreateOBB2(Solids);
            BoundingGeometry.CreateBoundingCylinder(Solids);

            PartitioningSolid.Partitions     = new Dictionary <TessellatedSolid, Partition[]>();
            PartitioningSolid.PartitionsAABB = new Dictionary <TessellatedSolid, PartitionAABB[]>();
            PartitioningSolid.CreatePartitions(Program.SimplifiedSolids);

            NonadjacentBlockingWithPartitioning.Run(AssemblyGraph, SolidsNoFastenerSimplified, globalDirPool);
            GraphSaving.SaveTheGraph(AssemblyGraph);
            Stabilityfunctions.GenerateReactionForceInfo(AssemblyGraph);
            var leapSearch = new LeapSearch();
            var solutions  = leapSearch.Run(AssemblyGraph, Solids, globalDirPool);

            OptimalOrientation.Run(solutions);
            var cand = new AssemblyCandidate()
            {
                Sequence = solutions
            };

            cand.SaveToDisk(state.inputDir + slash + "XML" + slash + "solution.xml");
            WorkerAllocation.Run(solutions);

            SaveState();
            if (serverMode)
            {
                state.Save(state.inputDir + slash + "intermediate" + slash + "ProgramState.xml");
            }
            else
            {
                state.Save(state.inputDir + slash + "bin" + slash + "intermediate" + slash + "ProgramState.xml");
            }
            Console.WriteLine("\n\nDone");
        }
        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);
        }
        // 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);
        }
Esempio n. 4
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);
        }