private static List <string> PartsLockedByTheFastenerFinder(TessellatedSolid fastener, Dictionary <string, List <TessellatedSolid> > solidsNoFastener, Dictionary <TessellatedSolid, List <PrimitiveSurface> > solidPrimitive) { PotentialCollisionOfFastenerAndSolid = new List <string>(); PotentialCollisionOfFastenerAndSolidStep2 = new List <string>(); PotentialCollisionOfFastenerAndSolidStep3 = new List <string>(); var lockedByTheFastener = new List <string>(); foreach (var subAssem in solidsNoFastener) { foreach (var solid in subAssem.Value) { // This has a way simpler blocking determination code. Check it out: if (!BlockingDetermination.BoundingBoxOverlap(fastener, solid)) { continue; } if (!BlockingDetermination.ConvexHullOverlap(fastener, solid)) { continue; } if (!BlockingDetermination.ProximityFastener(fastener, solid)) { continue; } //if (!FastenerPrimitiveOverlap(solidPrimitive[fastener], solidPrimitives)) continue; lockedByTheFastener.Add(subAssem.Key); break; } } if (!lockedByTheFastener.Any() && PotentialCollisionOfFastenerAndSolid.Any()) { lockedByTheFastener.AddRange(PotentialCollisionOfFastenerAndSolid); } else if (!lockedByTheFastener.Any() && PotentialCollisionOfFastenerAndSolidStep2.Any()) { lockedByTheFastener.AddRange(PotentialCollisionOfFastenerAndSolidStep2); } else if (!lockedByTheFastener.Any() && PotentialCollisionOfFastenerAndSolidStep3.Any()) { lockedByTheFastener.AddRange(PotentialCollisionOfFastenerAndSolidStep3); } return(lockedByTheFastener); }
internal static Dictionary <int, List <Component[]> > NonAdjacentBlocking = new Dictionary <int, List <Component[]> >(); //Component[0] is blocked by Component[1] internal static List <int> Run(designGraph assemblyGraph, List <TessellatedSolid> solids) { Solids = new List <TessellatedSolid>(solids); Directions = IcosahedronPro.DirectionGeneration(); var globalDirPool = new List <int>(); var solidPrimitive = BlockingDetermination.PrimitiveMaker(solids); //var gears = BoltAndGearDetection.GearDetector(solidPrimitive); AddingNodesToGraph(assemblyGraph, solids);//, gears, screwsAndBolts); /*for (var i = 0; i < solids.Count - 1; i++) * { * var solid1 = solids[i]; * var solid1Primitives = solidPrimitive[solid1]; * for (var j = i + 1; j < solids.Count; j++) * { * var solid2 = solids[j]; * var solid2Primitives = solidPrimitive[solid2]; * List<int> localDirInd; * double cert; * if (BlockingDetermination.DefineBlocking(assemblyGraph, solid1, solid2, solid1Primitives, solid2Primitives, * globalDirPool, out localDirInd, out cert)) * { * // I wrote the code in a way that "solid1" is always "Reference" and "solid2" is always "Moving". * //List<int> finDirs, infDirs; * //UnconnectedBlockingDetermination.FiniteDirectionsBetweenConnectedParts(solid1, solid2, localDirInd, out finDirs, out infDirs); * var from = assemblyGraph[solid2.Name]; // Moving * var to = assemblyGraph[solid1.Name]; // Reference * assemblyGraph.addArc((Component)from, (Component)to); * var a = (Connection)assemblyGraph.arcs.Last(); * a.Certainty = cert; * AddInformationToArc(a, localDirInd); * } * } * }*/ return(globalDirPool); }
internal static void RunPerecptronLearner(bool regenerateTrainingData) { // this functions, finds the training stls, opens them, // read them and creates the csv file of the training data // which includes the features of each solid. // Here is what I need to pay attention: // 1. if the csv file exists and the user doesnt want to improve(!) the results // do nothing // 2. if the csv doesnt exist or the user has new training stls, we can run it and // improve the classifier. var path = #if NOSRC Program.state.inputDir + "src/Assembly Planner/InitialGraphMaker/BoltAndGearDetector"; #else "bin/training"; #endif //Path to write the csv to: #if NOSRC var trainingDataPath = path + "/TrainingData.csv"; var weightsAndVotesPath = path + "/WeightsAndVotes.csv"; #else var trainingDataPath = path + "/ClassifierFiles/TrainingData.csv"; var weightsAndVotesPath = path + "/ClassifierFiles/WeightsAndVotes.csv"; #endif if (!regenerateTrainingData && File.Exists(weightsAndVotesPath)) { return; } if (!regenerateTrainingData && !File.Exists(weightsAndVotesPath) && File.Exists(trainingDataPath)) { // CSV of the training data exists, but weights and votes, dont exist, therefore: run the Learner Learner(); // this will automatically create the csv containing weights and votes return; } if (!regenerateTrainingData && !File.Exists(weightsAndVotesPath) && !File.Exists(trainingDataPath)) { Console.WriteLine("Sorry!! csv files don't exist. We need to generate the training data"); } //statusReporter.PrintMessage("BOUNDING GEOMETRIES ARE SUCCESSFULLY CREATED.", 1f); //Path to read STLs from: #if NOSRC var stlFastenerPath = path + "/Fastener"; var stlNotFastenerPath = path + "/notFastener"; #else var stlFastenerPath = path + "/TrainingSTLs/Fastener"; var stlNotFastenerPath = path + "/TrainingSTLs/notFastener"; #endif var fastenersTraining = StlToSolid(stlFastenerPath); var fastenerPrimitive = BlockingDetermination.PrimitiveMaker(fastenersTraining); var ntFastenersTraining = StlToSolid(stlNotFastenerPath); var notFastenerPrimitive = BlockingDetermination.PrimitiveMaker(ntFastenersTraining); if (!File.Exists(trainingDataPath)) { File.Create(trainingDataPath).Close(); } // now fill the csv: TrainingDataCsvFiller(trainingDataPath, fastenerPrimitive, notFastenerPrimitive); Learner(); }
internal static void Run(designGraph graph, List <TessellatedSolid> solids, List <int> gDir) { //Parallel.ForEach(gDir, dir => foreach (var dir in gDir) { var direction = DisassemblyDirections.Directions[dir]; var blockingsForDirection = new List <NonAdjacentBlockings>(); //Parallel.ForEach(solids.Where(s => graph.nodes.Any(n => n.name == s.Name)), solid => foreach (var solid in solids.Where(s => graph.nodes.Any(n => n.name == s.Name))) { // now find the blocking parts var rays = new List <Ray>(); foreach (var vertex in solid.ConvexHull.Vertices) { rays.Add( new Ray( new Vertex(new[] { vertex.Position[0], vertex.Position[1], vertex.Position[2] }), new[] { direction[0], direction[1], direction[2] })); } // add more vertices to the ray rays.AddRange( AddingMoreRays(solid.ConvexHull.Edges.Where(e => e != null && e.Length > 2).ToArray(), direction)); foreach (var solidBlocking in solids.Where(s => graph.nodes.Any(n => n.name == s.Name) && // it is not fastener s != solid // it is not the same as current solid && !graph.arcs.Any(a => // there is no arc between the current and the candidate (a.From.name == solid.Name && a.To.name == s.Name) || (a.From.name == s.Name && a.To.name == solid.Name)))) { if (!BoundingBoxBlocking(direction, solidBlocking, solid)) { continue; } var distanceToTheClosestFace = double.PositiveInfinity; var overlap = false; if (BlockingDetermination.ConvexHullOverlap(solid, solidBlocking)) { overlap = ConvexHullOverlappNonAdjacent(rays, solid, solidBlocking, direction); continue; } else { overlap = DontConcexHullsOverlapNonAdjacent(rays, solidBlocking); } if (overlap) { blockingsForDirection.Add(new NonAdjacentBlockings { blockingSolids = new[] { solid, solidBlocking }, blockingDistance = distanceToTheClosestFace }); } } } //); // lock (NonAdjacentBlocking) NonAdjacentBlocking.Add(dir, blockingsForDirection); } // ); // To be fixed later: // This ConvertToSecondary can be later added directly after generation. //ConvertToSecondaryArc(graph, NonAdjacentBlocking); }
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); }
private static void CheckToHaveConnectedGraph(designGraph assemblyGraph) { // The code will crash if the graph is not connected // let's take a look: var batches = new List <HashSet <Component> >(); var stack = new Stack <Component>(); var visited = new HashSet <Component>(); var globalVisited = new HashSet <Component>(); foreach (Component Component in assemblyGraph.nodes.Where(n => !globalVisited.Contains(n))) { stack.Clear(); visited.Clear(); stack.Push(Component); while (stack.Count > 0) { var pNode = stack.Pop(); visited.Add(pNode); globalVisited.Add(pNode); List <Connection> a2; lock (pNode.arcs) a2 = pNode.arcs.Where(a => a is Connection).Cast <Connection>().ToList(); foreach (Connection arc in a2) { if (!assemblyGraph.nodes.Contains(arc.From) || !assemblyGraph.nodes.Contains(arc.To)) { continue; } var otherNode = (Component)(arc.From == pNode ? arc.To : arc.From); if (visited.Contains(otherNode)) { continue; } stack.Push(otherNode); } } if (visited.Count == assemblyGraph.nodes.Count) { return; } batches.Add(new HashSet <Component>(visited)); } Console.WriteLine("\nSome of the assembly parts are not connected to the rest of the model."); var referenceBatch = batches[0]; var c = false; var visits = 0; var loop = 0; while (referenceBatch.Count < assemblyGraph.nodes.Count) { loop++; if (loop >= 15) { break; } foreach (var rb in referenceBatch) { for (var j = 1; j < batches.Count; j++) { foreach (var b in batches[j]) { foreach (var p1 in Program.Solids[rb.name]) { foreach (var p2 in Program.Solids[b.name]) { if (BlockingDetermination.BoundingBoxOverlap(p1, p2)) { if (BlockingDetermination.ConvexHullOverlap(p1, p2)) { visits++; if (visits == 1) { Console.WriteLine( "\n * Since the graph needs to be connected, the following connections are added by the software:"); } // add a connection with low cetainty between them var lastAdded = (Connection)assemblyGraph.addArc(rb, b, "", typeof(Connection)); lastAdded.Certainty = 0.1; referenceBatch.UnionWith(batches[j]); batches.RemoveAt(j); c = true; Console.WriteLine("\n - " + lastAdded.XmlFrom + lastAdded.XmlTo); } } if (c) { break; } } if (c) { break; } } if (c) { break; } } if (c) { break; } } if (c) { break; } } } if (loop < 15) { Console.WriteLine( "\n * When you are reviewing the connections, please pay a closer attention to the connections above"); } else { Console.WriteLine("\n * Some connections must be added manually between the following batches"); } for (int i = 0; i < batches.Count; i++) { var batch = batches[i]; Console.WriteLine("\n - Batch " + i + ":"); foreach (var component in batch) { Console.WriteLine(" + " + component.name); } } }