From 651c383925f802a49c0b63b7c2750f39373b23cd Mon Sep 17 00:00:00 2001 From: Eric Trombly Date: Thu, 26 Mar 2020 19:02:25 -0500 Subject: [PATCH] changed some for loops to list comprehensions, added openmp for area to make two loops parallel, changed a fuse to a compound --- src/Mod/Path/App/Area.cpp | 69 ++++++++++++++++++------- src/Mod/Path/App/CMakeLists.txt | 3 +- src/Mod/Path/PathScripts/PathSurface.py | 63 +++++----------------- 3 files changed, 65 insertions(+), 70 deletions(-) diff --git a/src/Mod/Path/App/Area.cpp b/src/Mod/Path/App/Area.cpp index fe552ecbd9..84d735df33 100644 --- a/src/Mod/Path/App/Area.cpp +++ b/src/Mod/Path/App/Area.cpp @@ -30,6 +30,7 @@ # include "boost_fix/intrusive/detail/memory_util.hpp" # include "boost_fix/container/detail/memory_util.hpp" # endif +# include # include # include # include @@ -1290,8 +1291,10 @@ int Area::project(TopoDS_Shape &shape_out, showShape(joiner.comp,"pre_project"); - Area area(params); + auto new_params = params; + Area area(new_params); area.myParams.SectionCount = 0; + area.myParams.Offset = 0.0; area.myParams.PocketMode = 0; area.myParams.Explode = false; @@ -1302,8 +1305,7 @@ int Area::project(TopoDS_Shape &shape_out, area.myParams.Coplanar = CoplanarNone; area.myProjecting = true; area.add(joiner.comp, OperationUnion); - const TopoDS_Shape &shape = area.getShape(); - + const TopoDS_Shape shape = area.getShape(); area.myParams.dump("project"); showShape(shape,"projected"); @@ -1478,16 +1480,29 @@ std::vector > Area::makeSections( area->setPlane(face.Moved(locInverse)); if(project) { - for(const auto &s : projectedShapes) { - gp_Trsf t; - t.SetTranslation(gp_Vec(0,0,-d)); - TopLoc_Location wloc(t); - area->add(s.shape.Moved(wloc).Moved(locInverse),s.op); + #pragma omp parallel + { + int thread_count = omp_get_num_threads(); + int thread_num = omp_get_thread_num(); + size_t chunk_size= projectedShapes.size() / thread_count; + auto begin = projectedShapes.begin(); + std::advance(begin, thread_num * chunk_size); + auto end = begin; + if(thread_num == thread_count - 1) // last thread iterates the remaining sequence + end = projectedShapes.end(); + else + std::advance(end, chunk_size); + #pragma omp barrier + for(auto s = begin; s != end; ++s) { + gp_Trsf t; + t.SetTranslation(gp_Vec(0,0,-d)); + TopLoc_Location wloc(t); + area->add(s->shape.Moved(wloc).Moved(locInverse),s->op); + } } sections.push_back(area); break; } - for(auto it=myShapes.begin();it!=myShapes.end();++it) { const auto &s = *it; BRep_Builder builder; @@ -1600,18 +1615,32 @@ std::list Area::getProjectedShapes(const gp_Trsf &trsf, bool invers TopLoc_Location loc(trsf); TopLoc_Location locInverse(loc.Inverted()); - mySkippedShapes = 0; - for(auto &s : myShapes) { - TopoDS_Shape out; - int skipped = Area::project(out,s.shape.Moved(loc),&myParams); - if(skipped < 0) { - ++mySkippedShapes; - continue; - }else - mySkippedShapes += skipped; - if(!out.IsNull()) - ret.emplace_back(s.op,inverse?out.Moved(locInverse):out); + #pragma omp parallel + { + int thread_count = omp_get_num_threads(); + int thread_num = omp_get_thread_num(); + size_t chunk_size= myShapes.size() / thread_count; + auto begin = myShapes.begin(); + std::advance(begin, thread_num * chunk_size); + auto end = begin; + if(thread_num == thread_count - 1) // last thread iterates the remaining sequence + end = myShapes.end(); + else + std::advance(end, chunk_size); + #pragma omp barrier + for(auto s = begin; s != end; ++s){ + TopoDS_Shape out; + int skipped = Area::project(out,s->shape.Moved(loc),&myParams); + if(skipped < 0) { + ++mySkippedShapes; + continue; + }else + mySkippedShapes += skipped; + if(!out.IsNull()) + ret.emplace_back(s->op,inverse?out.Moved(locInverse):out); + } } + if(mySkippedShapes) AREA_WARN("skipped " << mySkippedShapes << " sub shapes during projection"); return ret; diff --git a/src/Mod/Path/App/CMakeLists.txt b/src/Mod/Path/App/CMakeLists.txt index 2cee9a3a3a..ec50f473ab 100644 --- a/src/Mod/Path/App/CMakeLists.txt +++ b/src/Mod/Path/App/CMakeLists.txt @@ -118,8 +118,9 @@ SOURCE_GROUP("Module" FILES ${Mod_SRCS}) # SOURCE_GROUP("KDL" FILES ${KDL_SRCS} ${KDL_HPPS} ${UTIL_SRCS} ${UTIL_HPPS} ) #endif(WIN32) +find_package(OpenMP REQUIRED) add_library(Path SHARED ${Path_SRCS}) -target_link_libraries(Path ${Path_LIBS}) +target_link_libraries(Path ${Path_LIBS} OpenMP::OpenMP_CXX) if(FREECAD_USE_PCH) add_definitions(-D_PreComp_) diff --git a/src/Mod/Path/PathScripts/PathSurface.py b/src/Mod/Path/PathScripts/PathSurface.py index 792928a4ba..7514da410e 100644 --- a/src/Mod/Path/PathScripts/PathSurface.py +++ b/src/Mod/Path/PathScripts/PathSurface.py @@ -365,9 +365,9 @@ class ObjectSurface(PathOp.ObjectOp): def opExecute(self, obj): '''opExecute(obj) ... process surface operation''' PathLog.track() - import cProfile - pr = cProfile.Profile() - pr.enable() + #import cProfile + #pr = cProfile.Profile() + #pr.enable() self.modelSTLs = list() self.safeSTLs = list() @@ -606,8 +606,8 @@ class ObjectSurface(PathOp.ObjectOp): del self.deflection execTime = time.time() - startTime - pr.disable() - pr.dump_stats("/mnt/files/profile.cprof") + #pr.disable() + #pr.dump_stats("/mnt/files/profile.cprof") PathLog.info('Operation time: {} sec.'.format(execTime)) return True @@ -1492,7 +1492,6 @@ class ObjectSurface(PathOp.ObjectOp): else: PathLog.warning('Path transitions might not avoid the model. Verify paths.') #time.sleep(0.3) - else: # If boundbox is Job.Stock, add hidden pad under stock as base plate toolDiam = self.cutter.getDiameter() @@ -1511,11 +1510,7 @@ class ObjectSurface(PathOp.ObjectOp): voidEnv = PathUtils.getEnvelope(partshape=voidComp, depthparams=self.depthParams) # Produces .Shape fuseShapes.append(voidEnv) - f0 = fuseShapes.pop(0) - if len(fuseShapes) > 0: - fused = f0.fuse(fuseShapes) - else: - fused = f0 + fused = Part.makeCompound(fuseShapes) if self.showDebugObjects is True: T = FreeCAD.ActiveDocument.addObject('Part::Feature', 'safeSTLShape') @@ -2585,44 +2580,14 @@ class ObjectSurface(PathOp.ObjectOp): return GCODE def _planarSinglepassProcess(self, obj, PNTS): - output = [] - optimize = obj.OptimizeLinearPaths - lenPNTS = len(PNTS) - lstIdx = lenPNTS - 1 - lop = None - onLine = False - - # Initialize first three points - nxt = None - pnt = PNTS[0] - prev = FreeCAD.Vector(-442064564.6, 258539656553.27, 3538553425.847) - - # Add temp end point - PNTS.append(FreeCAD.Vector(-4895747464.6, -25855763553.2, 35865763425)) - - # Begin processing ocl points list into gcode - for i in range(0, lenPNTS): - # Calculate next point for consideration with current point - nxt = PNTS[i + 1] - - # Process point - if optimize is True: - iPOL = prev.isOnLine(nxt, pnt) - if iPOL is True: - onLine = True - else: - onLine = False - output.append(Path.Command('G1', {'X': pnt.x, 'Y': pnt.y, 'Z': pnt.z, 'F': self.horizFeed})) - else: - output.append(Path.Command('G1', {'X': pnt.x, 'Y': pnt.y, 'Z': pnt.z, 'F': self.horizFeed})) - - # Rotate point data - if onLine is False: - prev = pnt - pnt = nxt - # Efor - - temp = PNTS.pop() # Remove temp end point + if obj.OptimizeLinearPaths: + # first item will be compared to the last point, but I think that should work + output = [Path.Command('G1', {'X': PNTS[i].x, 'Y': PNTS[i].y, 'Z': PNTS[i].z, 'F': self.horizFeed}) + for i in range(0, len(PNTS) - 1) + if not PNTS[i].isOnLine(PNTS[i -1],PNTS[i + 1])] + output.append(Path.Command('G1', {'X': PNTS[-1].x, 'Y': PNTS[-1].y, 'Z': PNTS[-1].z, 'F': self.horizFeed})) + else: + output = [Path.Command('G1', {'X': pnt.x, 'Y': pnt.y, 'Z': pnt.z, 'F': self.horizFeed}) for pnt in PNTS] return output