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); }
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); }