From a17a3cf6d79ad135ea05e4e3d2385e427a9400b2 Mon Sep 17 00:00:00 2001 From: Adrian Insaurralde Avalos Date: Tue, 3 Sep 2024 14:54:36 -0400 Subject: [PATCH] CAM: apply precommit --- src/Mod/CAM/App/AppPath.cpp | 57 +- src/Mod/CAM/App/AppPathPy.cpp | 804 +- src/Mod/CAM/App/Area.cpp | 2542 +++--- src/Mod/CAM/App/Area.h | 124 +- src/Mod/CAM/App/AreaParams.h | 565 +- src/Mod/CAM/App/AreaPyImp.cpp | 687 +- src/Mod/CAM/App/Command.cpp | 186 +- src/Mod/CAM/App/Command.h | 77 +- src/Mod/CAM/App/CommandPyImp.cpp | 120 +- src/Mod/CAM/App/FeatureArea.cpp | 178 +- src/Mod/CAM/App/FeatureArea.h | 35 +- src/Mod/CAM/App/FeatureAreaPy.xml | 1 - src/Mod/CAM/App/FeatureAreaPyImp.cpp | 57 +- src/Mod/CAM/App/FeaturePath.cpp | 24 +- src/Mod/CAM/App/FeaturePath.h | 19 +- src/Mod/CAM/App/FeaturePathCompound.cpp | 49 +- src/Mod/CAM/App/FeaturePathCompound.h | 18 +- src/Mod/CAM/App/FeaturePathCompoundPyImp.cpp | 35 +- src/Mod/CAM/App/FeaturePathShape.cpp | 55 +- src/Mod/CAM/App/FeaturePathShape.h | 14 +- src/Mod/CAM/App/ParamsHelper.h | 488 +- src/Mod/CAM/App/Path.cpp | 251 +- src/Mod/CAM/App/Path.h | 133 +- src/Mod/CAM/App/PathPyImp.cpp | 57 +- src/Mod/CAM/App/PathSegmentWalker.cpp | 212 +- src/Mod/CAM/App/PathSegmentWalker.h | 46 +- src/Mod/CAM/App/PreCompiled.h | 20 +- src/Mod/CAM/App/PropertyPath.cpp | 43 +- src/Mod/CAM/App/PropertyPath.h | 24 +- src/Mod/CAM/App/Voronoi.cpp | 443 +- src/Mod/CAM/App/Voronoi.h | 98 +- src/Mod/CAM/App/VoronoiCell.cpp | 89 +- src/Mod/CAM/App/VoronoiCell.h | 27 +- src/Mod/CAM/App/VoronoiCellPyImp.cpp | 248 +- src/Mod/CAM/App/VoronoiEdge.cpp | 61 +- src/Mod/CAM/App/VoronoiEdge.h | 23 +- src/Mod/CAM/App/VoronoiEdgePyImp.cpp | 957 ++- src/Mod/CAM/App/VoronoiPyImp.cpp | 512 +- src/Mod/CAM/App/VoronoiVertex.cpp | 61 +- src/Mod/CAM/App/VoronoiVertex.h | 23 +- src/Mod/CAM/App/VoronoiVertexPyImp.cpp | 193 +- src/Mod/CAM/Gui/AppPathGui.cpp | 27 +- src/Mod/CAM/Gui/AppPathGuiPy.cpp | 148 +- src/Mod/CAM/Gui/Command.cpp | 246 +- src/Mod/CAM/Gui/DlgProcessorChooser.cpp | 20 +- src/Mod/CAM/Gui/DlgProcessorChooser.h | 11 +- src/Mod/CAM/Gui/DlgSettingsPathColor.cpp | 3 +- src/Mod/CAM/Gui/DlgSettingsPathColor.h | 23 +- src/Mod/CAM/Gui/PreCompiled.h | 24 +- src/Mod/CAM/Gui/Resources/translations/CAM.ts | 18 +- .../CAM/Gui/Resources/translations/CAM_be.ts | 20 +- .../CAM/Gui/Resources/translations/CAM_ca.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_cs.ts | 34 +- .../CAM/Gui/Resources/translations/CAM_da.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_de.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_el.ts | 36 +- .../Gui/Resources/translations/CAM_es-AR.ts | 38 +- .../Gui/Resources/translations/CAM_es-ES.ts | 38 +- .../CAM/Gui/Resources/translations/CAM_eu.ts | 38 +- .../CAM/Gui/Resources/translations/CAM_fi.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_fr.ts | 22 +- .../CAM/Gui/Resources/translations/CAM_gl.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_hr.ts | 64 +- .../CAM/Gui/Resources/translations/CAM_hu.ts | 40 +- .../CAM/Gui/Resources/translations/CAM_id.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_it.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_ja.ts | 26 +- .../CAM/Gui/Resources/translations/CAM_ka.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_ko.ts | 40 +- .../CAM/Gui/Resources/translations/CAM_lt.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_nl.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_pl.ts | 110 +- .../Gui/Resources/translations/CAM_pt-BR.ts | 36 +- .../Gui/Resources/translations/CAM_pt-PT.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_ro.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_ru.ts | 30 +- .../CAM/Gui/Resources/translations/CAM_sl.ts | 36 +- .../Gui/Resources/translations/CAM_sr-CS.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_sr.ts | 36 +- .../Gui/Resources/translations/CAM_sv-SE.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_tr.ts | 36 +- .../CAM/Gui/Resources/translations/CAM_uk.ts | 36 +- .../Gui/Resources/translations/CAM_val-ES.ts | 36 +- .../Gui/Resources/translations/CAM_zh-CN.ts | 34 +- .../Gui/Resources/translations/CAM_zh-TW.ts | 36 +- src/Mod/CAM/Gui/TaskDlgPathCompound.cpp | 50 +- src/Mod/CAM/Gui/TaskDlgPathCompound.h | 27 +- src/Mod/CAM/Gui/ViewProviderArea.cpp | 48 +- src/Mod/CAM/Gui/ViewProviderArea.h | 12 +- src/Mod/CAM/Gui/ViewProviderPath.cpp | 567 +- src/Mod/CAM/Gui/ViewProviderPath.h | 58 +- src/Mod/CAM/Gui/ViewProviderPathCompound.cpp | 14 +- src/Mod/CAM/Gui/ViewProviderPathCompound.h | 6 +- src/Mod/CAM/Gui/ViewProviderPathShape.cpp | 30 +- src/Mod/CAM/Gui/ViewProviderPathShape.h | 7 +- src/Mod/CAM/Path/Base/Drillable.py | 37 +- src/Mod/CAM/Path/Base/FeedRate.py | 18 +- src/Mod/CAM/Path/Base/Generator/dogboneII.py | 19 +- src/Mod/CAM/Path/Base/Generator/drill.py | 8 +- src/Mod/CAM/Path/Base/Generator/helix.py | 4 +- src/Mod/CAM/Path/Base/Generator/rotation.py | 8 +- .../CAM/Path/Base/Generator/threadmilling.py | 12 +- src/Mod/CAM/Path/Base/Generator/toolchange.py | 8 +- src/Mod/CAM/Path/Base/Gui/GetPoint.py | 24 +- .../CAM/Path/Base/Gui/PreferencesAdvanced.py | 12 +- src/Mod/CAM/Path/Base/Gui/PropertyBag.py | 44 +- src/Mod/CAM/Path/Base/Gui/SetupSheet.py | 17 +- src/Mod/CAM/Path/Base/Gui/Util.py | 16 +- src/Mod/CAM/Path/Base/Language.py | 8 +- src/Mod/CAM/Path/Base/SetupSheet.py | 56 +- .../CAM/Path/Base/SetupSheetOpPrototype.py | 12 +- src/Mod/CAM/Path/Base/Util.py | 11 +- src/Mod/CAM/Path/Dressup/Boundary.py | 29 +- src/Mod/CAM/Path/Dressup/DogboneII.py | 17 +- src/Mod/CAM/Path/Dressup/Gui/AxisMap.py | 32 +- src/Mod/CAM/Path/Dressup/Gui/Boundary.py | 18 +- src/Mod/CAM/Path/Dressup/Gui/Dogbone.py | 87 +- src/Mod/CAM/Path/Dressup/Gui/DogboneII.py | 18 +- src/Mod/CAM/Path/Dressup/Gui/Dragknife.py | 54 +- src/Mod/CAM/Path/Dressup/Gui/LeadInOut.py | 56 +- src/Mod/CAM/Path/Dressup/Gui/RampEntry.py | 76 +- .../CAM/Path/Dressup/Gui/TagPreferences.py | 36 +- src/Mod/CAM/Path/Dressup/Gui/Tags.py | 36 +- src/Mod/CAM/Path/Dressup/Gui/ZCorrect.py | 37 +- src/Mod/CAM/Path/Dressup/Tags.py | 118 +- src/Mod/CAM/Path/Dressup/Utils.py | 6 +- src/Mod/CAM/Path/Geom.py | 50 +- src/Mod/CAM/Path/Main/Gui/Camotics.py | 8 +- src/Mod/CAM/Path/Main/Gui/Fixture.py | 4 +- src/Mod/CAM/Path/Main/Gui/Inspect.py | 35 +- src/Mod/CAM/Path/Main/Gui/Job.py | 232 +- src/Mod/CAM/Path/Main/Gui/JobDlg.py | 28 +- src/Mod/CAM/Path/Main/Gui/PreferencesJob.py | 92 +- src/Mod/CAM/Path/Main/Gui/SanityCmd.py | 15 +- src/Mod/CAM/Path/Main/Gui/Simulator.py | 40 +- src/Mod/CAM/Path/Main/Gui/SimulatorGL.py | 86 +- src/Mod/CAM/Path/Main/Job.py | 92 +- src/Mod/CAM/Path/Main/Sanity/HTMLTemplate.py | 1 + src/Mod/CAM/Path/Main/Sanity/Sanity.py | 68 +- src/Mod/CAM/Path/Main/Stock.py | 41 +- src/Mod/CAM/Path/Op/Adaptive.py | 80 +- src/Mod/CAM/Path/Op/Area.py | 71 +- src/Mod/CAM/Path/Op/Base.py | 93 +- src/Mod/CAM/Path/Op/CircularHoleBase.py | 14 +- src/Mod/CAM/Path/Op/Custom.py | 7 +- src/Mod/CAM/Path/Op/Deburr.py | 52 +- src/Mod/CAM/Path/Op/Drilling.py | 52 +- src/Mod/CAM/Path/Op/Engrave.py | 20 +- src/Mod/CAM/Path/Op/EngraveBase.py | 20 +- src/Mod/CAM/Path/Op/FeatureExtension.py | 30 +- src/Mod/CAM/Path/Op/Gui/Adaptive.py | 32 +- src/Mod/CAM/Path/Op/Gui/Array.py | 49 +- src/Mod/CAM/Path/Op/Gui/Base.py | 113 +- src/Mod/CAM/Path/Op/Gui/CircularHoleBase.py | 6 +- src/Mod/CAM/Path/Op/Gui/Comment.py | 4 +- src/Mod/CAM/Path/Op/Gui/Copy.py | 4 +- src/Mod/CAM/Path/Op/Gui/Deburr.py | 12 +- src/Mod/CAM/Path/Op/Gui/Drilling.py | 21 +- src/Mod/CAM/Path/Op/Gui/Engrave.py | 9 +- src/Mod/CAM/Path/Op/Gui/FeatureExtension.py | 27 +- src/Mod/CAM/Path/Op/Gui/Helix.py | 8 +- src/Mod/CAM/Path/Op/Gui/MillFace.py | 8 +- src/Mod/CAM/Path/Op/Gui/Pocket.py | 4 +- src/Mod/CAM/Path/Op/Gui/PocketBase.py | 5 +- src/Mod/CAM/Path/Op/Gui/PocketShape.py | 14 +- src/Mod/CAM/Path/Op/Gui/Profile.py | 10 +- src/Mod/CAM/Path/Op/Gui/SimpleCopy.py | 18 +- src/Mod/CAM/Path/Op/Gui/Slot.py | 12 +- src/Mod/CAM/Path/Op/Gui/Stop.py | 8 +- src/Mod/CAM/Path/Op/Gui/Surface.py | 29 +- src/Mod/CAM/Path/Op/Gui/ThreadMilling.py | 28 +- src/Mod/CAM/Path/Op/Gui/Vcarve.py | 13 +- src/Mod/CAM/Path/Op/Gui/Waterline.py | 12 +- src/Mod/CAM/Path/Op/Helix.py | 20 +- src/Mod/CAM/Path/Op/MillFace.py | 55 +- src/Mod/CAM/Path/Op/Pocket.py | 77 +- src/Mod/CAM/Path/Op/PocketBase.py | 10 +- src/Mod/CAM/Path/Op/PocketShape.py | 41 +- src/Mod/CAM/Path/Op/Probe.py | 9 +- src/Mod/CAM/Path/Op/Profile.py | 119 +- src/Mod/CAM/Path/Op/Slot.py | 130 +- src/Mod/CAM/Path/Op/Surface.py | 245 +- src/Mod/CAM/Path/Op/SurfaceSupport.py | 197 +- src/Mod/CAM/Path/Op/ThreadMilling.py | 20 +- src/Mod/CAM/Path/Op/Util.py | 27 +- src/Mod/CAM/Path/Op/Vcarve.py | 46 +- src/Mod/CAM/Path/Op/Waterline.py | 220 +- src/Mod/CAM/Path/Post/Command.py | 18 +- src/Mod/CAM/Path/Post/Processor.py | 19 +- src/Mod/CAM/Path/Post/Utils.py | 29 +- src/Mod/CAM/Path/Post/UtilsArguments.py | 8 +- src/Mod/CAM/Path/Post/UtilsExport.py | 30 +- src/Mod/CAM/Path/Post/UtilsParse.py | 45 +- .../Post/scripts/KineticNCBeamicon2_post.py | 39 +- .../CAM/Path/Post/scripts/centroid_post.py | 10 +- .../CAM/Path/Post/scripts/comparams_post.py | 4 +- src/Mod/CAM/Path/Post/scripts/dumper_post.py | 10 +- src/Mod/CAM/Path/Post/scripts/dxf_post.py | 3 - .../Path/Post/scripts/dynapath_4060_post.py | 109 +- .../CAM/Path/Post/scripts/dynapath_post.py | 40 +- src/Mod/CAM/Path/Post/scripts/estlcam_post.py | 72 +- src/Mod/CAM/Path/Post/scripts/example_post.py | 2 - src/Mod/CAM/Path/Post/scripts/example_pre.py | 3 - src/Mod/CAM/Path/Post/scripts/fablin_post.py | 11 +- .../CAM/Path/Post/scripts/fangling_post.py | 209 +- src/Mod/CAM/Path/Post/scripts/fanuc_post.py | 53 +- src/Mod/CAM/Path/Post/scripts/gcode_pre.py | 6 +- src/Mod/CAM/Path/Post/scripts/generic_post.py | 2 +- src/Mod/CAM/Path/Post/scripts/grbl_post.py | 82 +- .../CAM/Path/Post/scripts/heidenhain_post.py | 88 +- src/Mod/CAM/Path/Post/scripts/jtech_post.py | 43 +- .../CAM/Path/Post/scripts/linuxcnc_post.py | 50 +- .../CAM/Path/Post/scripts/mach3_mach4_post.py | 45 +- src/Mod/CAM/Path/Post/scripts/marlin_post.py | 51 +- src/Mod/CAM/Path/Post/scripts/opensbp_post.py | 1 - src/Mod/CAM/Path/Post/scripts/opensbp_pre.py | 2 - src/Mod/CAM/Path/Post/scripts/philips_post.py | 71 +- .../Path/Post/scripts/refactored_test_post.py | 4 +- src/Mod/CAM/Path/Post/scripts/rml_post.py | 2 - src/Mod/CAM/Path/Post/scripts/rrf_post.py | 47 +- src/Mod/CAM/Path/Post/scripts/slic3r_pre.py | 2 - .../CAM/Path/Post/scripts/smoothie_post.py | 23 +- src/Mod/CAM/Path/Post/scripts/uccnc_post.py | 29 +- src/Mod/CAM/Path/Post/scripts/wedm_post.py | 144 +- src/Mod/CAM/Path/Preferences.py | 12 +- src/Mod/CAM/Path/Tool/Bit.py | 32 +- src/Mod/CAM/Path/Tool/Controller.py | 22 +- src/Mod/CAM/Path/Tool/Gui/Bit.py | 7 +- src/Mod/CAM/Path/Tool/Gui/BitCmd.py | 4 +- src/Mod/CAM/Path/Tool/Gui/BitEdit.py | 8 +- src/Mod/CAM/Path/Tool/Gui/BitLibrary.py | 96 +- src/Mod/CAM/Path/Tool/Gui/BitLibraryCmd.py | 4 +- src/Mod/CAM/Path/Tool/Gui/Controller.py | 20 +- src/Mod/CAM/PathCommands.py | 16 +- src/Mod/CAM/PathGlobal.h | 10 +- .../CAM/PathPythonGui/simple_edit_panel.py | 8 +- src/Mod/CAM/PathScripts/PathUtils.py | 54 +- src/Mod/CAM/PathScripts/PathUtilsGui.py | 4 +- .../PathSimulator/App/AppPathSimulator.cpp | 51 +- src/Mod/CAM/PathSimulator/App/PathSim.cpp | 78 +- src/Mod/CAM/PathSimulator/App/PathSim.h | 32 +- .../CAM/PathSimulator/App/PathSimPyImp.cpp | 191 +- src/Mod/CAM/PathSimulator/App/PreCompiled.h | 3 +- src/Mod/CAM/PathSimulator/App/VolSim.cpp | 1306 +-- src/Mod/CAM/PathSimulator/App/VolSim.h | 324 +- src/Mod/CAM/PathSimulator/AppGL/CAMSim.cpp | 3 +- src/Mod/CAM/PathSimulator/AppGL/CAMSim.h | 2 +- .../CAM/PathSimulator/AppGL/CAMSimPyImp.cpp | 35 +- .../PathSimulator/AppGL/DlgCAMSimulator.cpp | 82 +- .../CAM/PathSimulator/AppGL/DlgCAMSimulator.h | 4 +- src/Mod/CAM/PathSimulator/AppGL/EndMill.h | 2 +- src/Mod/CAM/PathSimulator/AppGL/GlUtils.h | 8 +- .../CAM/PathSimulator/AppGL/GuiDisplay.cpp | 31 +- src/Mod/CAM/PathSimulator/AppGL/GuiDisplay.h | 14 +- src/Mod/CAM/PathSimulator/AppGL/MillMotion.h | 2 +- .../CAM/PathSimulator/AppGL/MillPathLine.cpp | 20 +- .../CAM/PathSimulator/AppGL/MillPathLine.h | 3 +- .../PathSimulator/AppGL/MillPathSegment.cpp | 6 +- .../PathSimulator/AppGL/MillSimulation.cpp | 3 +- .../CAM/PathSimulator/AppGL/MillSimulation.h | 8 +- src/Mod/CAM/PathSimulator/AppGL/PreCompiled.h | 3 +- src/Mod/CAM/PathSimulator/AppGL/Shader.cpp | 30 +- src/Mod/CAM/PathSimulator/AppGL/Shader.h | 2 +- .../CAM/PathSimulator/AppGL/SimDisplay.cpp | 33 +- src/Mod/CAM/PathSimulator/AppGL/SimShapes.cpp | 2 +- src/Mod/CAM/PathSimulator/AppGL/SimShapes.h | 1 - .../CAM/PathSimulator/AppGL/SolidObject.cpp | 3 +- src/Mod/CAM/PathSimulator/AppGL/SolidObject.h | 2 +- .../CAM/PathSimulator/AppGL/StockObject.cpp | 3 +- src/Mod/CAM/PathSimulator/AppGL/StockObject.h | 2 +- .../CAM/PathSimulator/AppGL/TextureLoader.cpp | 12 +- .../CAM/PathSimulator/AppGL/TextureLoader.h | 4 +- src/Mod/CAM/PathSimulator/PathSimulator.dox | 1 - src/Mod/CAM/TestCAMApp.py | 5 +- src/Mod/CAM/Tests/FilePathTestUtils.py | 2 - src/Mod/CAM/Tests/PathTestUtils.py | 20 +- src/Mod/CAM/Tests/TestCAMSanity.py | 1 + src/Mod/CAM/Tests/TestLinuxCNCPost.py | 91 +- src/Mod/CAM/Tests/TestPathAdaptive.py | 46 +- src/Mod/CAM/Tests/TestPathCore.py | 8 +- src/Mod/CAM/Tests/TestPathDepthParams.py | 12 +- src/Mod/CAM/Tests/TestPathDressupDogbone.py | 4 +- src/Mod/CAM/Tests/TestPathDrillable.py | 36 +- .../CAM/Tests/TestPathGeneratorDogboneII.py | 13 +- src/Mod/CAM/Tests/TestPathGeom.py | 208 +- src/Mod/CAM/Tests/TestPathHelix.py | 16 +- src/Mod/CAM/Tests/TestPathHelixGenerator.py | 4 +- src/Mod/CAM/Tests/TestPathHelpers.py | 4 +- src/Mod/CAM/Tests/TestPathLanguage.py | 8 +- src/Mod/CAM/Tests/TestPathOpDeburr.py | 16 +- src/Mod/CAM/Tests/TestPathOpUtil.py | 66 +- src/Mod/CAM/Tests/TestPathPost.py | 44 +- src/Mod/CAM/Tests/TestPathPreferences.py | 20 +- src/Mod/CAM/Tests/TestPathProfile.py | 109 +- src/Mod/CAM/Tests/TestPathPropertyBag.py | 12 +- src/Mod/CAM/Tests/TestPathSetupSheet.py | 48 +- src/Mod/CAM/Tests/TestPathStock.py | 48 +- src/Mod/CAM/Tests/TestPathThreadMilling.py | 24 +- src/Mod/CAM/Tests/TestPathVoronoi.py | 36 +- src/Mod/CAM/Tests/TestRefactoredTestPost.py | 8 +- .../CAM/Tests/TestRefactoredTestPostGCodes.py | 46 +- src/Mod/CAM/Tools/Bit/5mm_Drill.fctb | 2 +- src/Mod/CAM/Tools/Bit/6mm_Ball_End.fctb | 2 +- src/Mod/CAM/Tools/Bit/6mm_Bullnose.fctb | 2 +- src/Mod/CAM/Tools/README.md | 1 - src/Mod/CAM/Tools/toolbit-attributes.py | 10 +- src/Mod/CAM/libarea/Adaptive.cpp | 5616 +++++++------ src/Mod/CAM/libarea/Adaptive.hpp | 241 +- src/Mod/CAM/libarea/Arc.cpp | 174 +- src/Mod/CAM/libarea/Arc.h | 39 +- src/Mod/CAM/libarea/Area.cpp | 1407 ++-- src/Mod/CAM/libarea/Area.h | 177 +- src/Mod/CAM/libarea/AreaClipper.cpp | 856 +- src/Mod/CAM/libarea/AreaDxf.cpp | 29 +- src/Mod/CAM/libarea/AreaDxf.h | 18 +- src/Mod/CAM/libarea/AreaOrderer.cpp | 181 +- src/Mod/CAM/libarea/AreaOrderer.h | 27 +- src/Mod/CAM/libarea/AreaPocket.cpp | 855 +- src/Mod/CAM/libarea/Box2D.h | 174 +- src/Mod/CAM/libarea/CMakeLists.txt | 2 +- src/Mod/CAM/libarea/Circle.cpp | 107 +- src/Mod/CAM/libarea/Circle.h | 22 +- src/Mod/CAM/libarea/Curve.cpp | 2159 ++--- src/Mod/CAM/libarea/Curve.h | 151 +- src/Mod/CAM/libarea/Point.h | 120 +- src/Mod/CAM/libarea/PythonStuff.cpp | 683 +- src/Mod/CAM/libarea/PythonStuff.h | 1 - src/Mod/CAM/libarea/clipper.cpp | 7330 +++++++++-------- src/Mod/CAM/libarea/clipper.hpp | 611 +- src/Mod/CAM/libarea/kurve/Construction.cpp | 1877 +++-- src/Mod/CAM/libarea/kurve/Finite.cpp | 1213 +-- src/Mod/CAM/libarea/kurve/Matrix.cpp | 1088 +-- src/Mod/CAM/libarea/kurve/README | 21 +- src/Mod/CAM/libarea/kurve/geometry.h | 2685 +++--- src/Mod/CAM/libarea/kurve/kurve.cpp | 2475 +++--- src/Mod/CAM/libarea/kurve/offset.cpp | 704 +- src/Mod/CAM/libarea/pyarea.cpp | 255 +- 337 files changed, 26842 insertions(+), 25585 deletions(-) diff --git a/src/Mod/CAM/App/AppPath.cpp b/src/Mod/CAM/App/AppPath.cpp index fe05bece15..15001275db 100644 --- a/src/Mod/CAM/App/AppPath.cpp +++ b/src/Mod/CAM/App/AppPath.cpp @@ -45,8 +45,9 @@ #include "VoronoiVertexPy.h" -namespace PathApp { - extern PyObject* initModule(); +namespace PathApp +{ +extern PyObject* initModule(); } /* Python entry */ @@ -56,7 +57,7 @@ PyMOD_INIT_FUNC(PathApp) try { Base::Interpreter().runString("import Part"); } - catch(const Base::Exception& e) { + catch (const Base::Exception& e) { PyErr_SetString(PyExc_ImportError, e.what()); PyMOD_Return(nullptr); } @@ -67,37 +68,37 @@ PyMOD_INIT_FUNC(PathApp) Py::Object module(pathModule); // Add Types to module - Base::Interpreter().addType(&Path::CommandPy ::Type, pathModule, "Command"); - Base::Interpreter().addType(&Path::PathPy ::Type, pathModule, "Path"); - Base::Interpreter().addType(&Path::AreaPy ::Type, pathModule, "Area"); + Base::Interpreter().addType(&Path::CommandPy ::Type, pathModule, "Command"); + Base::Interpreter().addType(&Path::PathPy ::Type, pathModule, "Path"); + Base::Interpreter().addType(&Path::AreaPy ::Type, pathModule, "Area"); PyObject* voronoiModule(module.getAttr("Voronoi").ptr()); - Base::Interpreter().addType(&Path::VoronoiPy ::Type, voronoiModule, "Diagram"); - Base::Interpreter().addType(&Path::VoronoiCellPy ::Type, voronoiModule, "Cell"); - Base::Interpreter().addType(&Path::VoronoiEdgePy ::Type, voronoiModule, "Edge"); - Base::Interpreter().addType(&Path::VoronoiVertexPy ::Type, voronoiModule, "Vertex"); + Base::Interpreter().addType(&Path::VoronoiPy ::Type, voronoiModule, "Diagram"); + Base::Interpreter().addType(&Path::VoronoiCellPy ::Type, voronoiModule, "Cell"); + Base::Interpreter().addType(&Path::VoronoiEdgePy ::Type, voronoiModule, "Edge"); + Base::Interpreter().addType(&Path::VoronoiVertexPy ::Type, voronoiModule, "Vertex"); // NOTE: To finish the initialization of our own type objects we must // call PyType_Ready, otherwise we run into a segmentation fault, later on. // This function is responsible for adding inherited slots from a type's base class. - Path::Command ::init(); - Path::Toolpath ::init(); - Path::PropertyPath ::init(); - Path::Feature ::init(); - Path::FeaturePython ::init(); - Path::FeatureCompound ::init(); - Path::FeatureCompoundPython ::init(); - Path::FeatureShape ::init(); - Path::FeatureShapePython ::init(); - Path::Area ::init(); - Path::FeatureArea ::init(); - Path::FeatureAreaPython ::init(); - Path::FeatureAreaView ::init(); - Path::FeatureAreaViewPython ::init(); - Path::Voronoi ::init(); - Path::VoronoiCell ::init(); - Path::VoronoiEdge ::init(); - Path::VoronoiVertex ::init(); + Path::Command ::init(); + Path::Toolpath ::init(); + Path::PropertyPath ::init(); + Path::Feature ::init(); + Path::FeaturePython ::init(); + Path::FeatureCompound ::init(); + Path::FeatureCompoundPython ::init(); + Path::FeatureShape ::init(); + Path::FeatureShapePython ::init(); + Path::Area ::init(); + Path::FeatureArea ::init(); + Path::FeatureAreaPython ::init(); + Path::FeatureAreaView ::init(); + Path::FeatureAreaViewPython ::init(); + Path::Voronoi ::init(); + Path::VoronoiCell ::init(); + Path::VoronoiEdge ::init(); + Path::VoronoiVertex ::init(); PyMOD_Return(pathModule); } diff --git a/src/Mod/CAM/App/AppPathPy.cpp b/src/Mod/CAM/App/AppPathPy.cpp index a89fc3b31e..8eb6e2db88 100644 --- a/src/Mod/CAM/App/AppPathPy.cpp +++ b/src/Mod/CAM/App/AppPathPy.cpp @@ -22,15 +22,15 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include -# include -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include +#include +#include +#include +#include #endif #include @@ -50,392 +50,470 @@ #include "FeaturePath.h" -#define PATH_CATCH catch (Standard_Failure &e) \ - { \ - std::string str; \ - Standard_CString msg = e.GetMessageString(); \ - str += typeid(e).name(); \ - str += " "; \ - if (msg) {str += msg;} \ - else {str += "No OCCT Exception Message";} \ - Base::Console().Error(str.c_str()); \ - PyErr_SetString(Part::PartExceptionOCCError,str.c_str()); \ - } \ - catch(Base::Exception &e) \ - { \ - std::string str; \ - str += "FreeCAD exception thrown ("; \ - str += e.what(); \ - str += ")"; \ - e.ReportException(); \ - PyErr_SetString(Base::PyExc_FC_GeneralError,str.c_str());\ - } \ - catch(std::exception &e) \ - { \ - std::string str; \ - str += "STL exception thrown ("; \ - str += e.what(); \ - str += ")"; \ - Base::Console().Error(str.c_str()); \ - PyErr_SetString(Base::PyExc_FC_GeneralError,str.c_str());\ - } \ - catch(const char *e) \ - { \ - PyErr_SetString(Base::PyExc_FC_GeneralError,e); \ - } throw Py::Exception(); +#define PATH_CATCH \ + catch (Standard_Failure & e) \ + { \ + std::string str; \ + Standard_CString msg = e.GetMessageString(); \ + str += typeid(e).name(); \ + str += " "; \ + if (msg) { \ + str += msg; \ + } \ + else { \ + str += "No OCCT Exception Message"; \ + } \ + Base::Console().Error(str.c_str()); \ + PyErr_SetString(Part::PartExceptionOCCError, str.c_str()); \ + } \ + catch (Base::Exception & e) \ + { \ + std::string str; \ + str += "FreeCAD exception thrown ("; \ + str += e.what(); \ + str += ")"; \ + e.ReportException(); \ + PyErr_SetString(Base::PyExc_FC_GeneralError, str.c_str()); \ + } \ + catch (std::exception & e) \ + { \ + std::string str; \ + str += "STL exception thrown ("; \ + str += e.what(); \ + str += ")"; \ + Base::Console().Error(str.c_str()); \ + PyErr_SetString(Base::PyExc_FC_GeneralError, str.c_str()); \ + } \ + catch (const char* e) \ + { \ + PyErr_SetString(Base::PyExc_FC_GeneralError, e); \ + } \ + throw Py::Exception(); -namespace PathApp { - class VoronoiModule : public Py::ExtensionModule - { - public: - VoronoiModule() : Py::ExtensionModule("Voronoi") - { - initialize("Working with Voronoi diagrams and data structures"); - } - ~VoronoiModule() override {} - }; +namespace PathApp +{ +class VoronoiModule: public Py::ExtensionModule +{ +public: + VoronoiModule() + : Py::ExtensionModule("Voronoi") + { + initialize("Working with Voronoi diagrams and data structures"); + } + ~VoronoiModule() override + {} +}; - class Module : public Py::ExtensionModule - { - VoronoiModule voronoi; - public: +class Module: public Py::ExtensionModule +{ + VoronoiModule voronoi; - Module() : Py::ExtensionModule("PathApp") - { - add_varargs_method("write",&Module::write, - "write(object,filename): Exports a given path object to a GCode file" - ); - add_varargs_method("read",&Module::read, - "read(filename,[document]): Imports a GCode file into the given document" - ); - add_varargs_method("show",&Module::show, - "show(path,[string]): Add the path to the active document or create one if no document exists" - ); - add_varargs_method("fromShape",&Module::fromShape, - "fromShape(Shape): Returns a Path object from a Part Shape (deprecated - use fromShapes() instead)" - ); - add_keyword_method("fromShapes",&Module::fromShapes, - "fromShapes(shapes, start=Vector(), return_end=False" PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_PATH) ")\n" - "\nReturns a Path object from a list of shapes\n" - "\n* shapes: input list of shapes.\n" - "\n* start (Vector()): feed start position, and also serves as a hint of path entry.\n" - "\n* return_end (False): if True, returns tuple (path, endPosition).\n" - PARAM_PY_DOC(ARG, AREA_PARAMS_PATH) - ); - add_keyword_method("sortWires",&Module::sortWires, - "sortWires(shapes, start=Vector(), " - PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_ARC_PLANE) - PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_SORT) ")\n" - "\nReturns (wires,end), where 'wires' is sorted across Z value and with optimized travel distance,\n" - "and 'end' is the ending position of the whole wires. If arc_plane==1, it returns (wires,end,arc_plane),\n" - "where arc_plane is the found plane if any, or unchanged.\n" - "\n* shapes: input shape list\n" - "\n* start (Vector()): optional start position.\n" - PARAM_PY_DOC(ARG, AREA_PARAMS_ARC_PLANE) - PARAM_PY_DOC(ARG, AREA_PARAMS_SORT) - ); - initialize("This module is the Path module."); // register with Python +public: + Module() + : Py::ExtensionModule("PathApp") + { + add_varargs_method("write", + &Module::write, + "write(object,filename): Exports a given path object to a GCode file"); + add_varargs_method( + "read", + &Module::read, + "read(filename,[document]): Imports a GCode file into the given document"); + add_varargs_method("show", + &Module::show, + "show(path,[string]): Add the path to the active document or create one " + "if no document exists"); + add_varargs_method("fromShape", + &Module::fromShape, + "fromShape(Shape): Returns a Path object from a Part Shape (deprecated " + "- use fromShapes() instead)"); + add_keyword_method( + "fromShapes", + &Module::fromShapes, + "fromShapes(shapes, start=Vector(), return_end=False" PARAM_PY_ARGS_DOC( + ARG, + AREA_PARAMS_PATH) ")\n" + "\nReturns a Path object from a list of shapes\n" + "\n* shapes: input list of shapes.\n" + "\n* start (Vector()): feed start position, and also serves as a " + "hint of path entry.\n" + "\n* return_end (False): if True, returns tuple (path, " + "endPosition).\n" PARAM_PY_DOC(ARG, AREA_PARAMS_PATH)); + add_keyword_method( + "sortWires", + &Module::sortWires, + "sortWires(shapes, start=Vector(), " PARAM_PY_ARGS_DOC(ARG, AREA_PARAMS_ARC_PLANE) + PARAM_PY_ARGS_DOC( + ARG, + AREA_PARAMS_SORT) ")\n" + "\nReturns (wires,end), where 'wires' is sorted across Z " + "value and with optimized travel distance,\n" + "and 'end' is the ending position of the whole wires. If " + "arc_plane==1, it returns (wires,end,arc_plane),\n" + "where arc_plane is the found plane if any, or unchanged.\n" + "\n* shapes: input shape list\n" + "\n* start (Vector()): optional start " + "position.\n" PARAM_PY_DOC(ARG, AREA_PARAMS_ARC_PLANE) + PARAM_PY_DOC(ARG, AREA_PARAMS_SORT)); + initialize("This module is the Path module."); // register with Python - PyModule_AddObject(m_module, "Voronoi", voronoi.module().ptr()); - } + PyModule_AddObject(m_module, "Voronoi", voronoi.module().ptr()); + } - ~Module() override {} + ~Module() override + {} - private: +private: + Py::Object write(const Py::Tuple& args) + { + char* Name; + PyObject* pObj; + if (!PyArg_ParseTuple(args.ptr(), "Oet", &pObj, "utf-8", &Name)) { + throw Py::Exception(); + } + std::string EncodedName = std::string(Name); + PyMem_Free(Name); + Base::FileInfo file(EncodedName.c_str()); - Py::Object write(const Py::Tuple& args) - { - char* Name; - PyObject* pObj; - if (!PyArg_ParseTuple(args.ptr(), "Oet",&pObj,"utf-8",&Name)) - throw Py::Exception(); - std::string EncodedName = std::string(Name); - PyMem_Free(Name); - Base::FileInfo file(EncodedName.c_str()); + if (PyObject_TypeCheck(pObj, &(App::DocumentObjectPy::Type))) { + App::DocumentObject* obj = + static_cast(pObj)->getDocumentObjectPtr(); + if (obj->getTypeId().isDerivedFrom(Base::Type::fromName("Path::Feature"))) { + const Path::Toolpath& path = static_cast(obj)->Path.getValue(); + std::string gcode = path.toGCode(); + Base::ofstream ofile(file); + ofile << gcode; + ofile.close(); + } + else { + throw Py::RuntimeError("The given file is not a path"); + } + } - if (PyObject_TypeCheck(pObj, &(App::DocumentObjectPy::Type))) { - App::DocumentObject* obj = static_cast(pObj)->getDocumentObjectPtr(); - if (obj->getTypeId().isDerivedFrom(Base::Type::fromName("Path::Feature"))) { - const Path::Toolpath& path = static_cast(obj)->Path.getValue(); - std::string gcode = path.toGCode(); - Base::ofstream ofile(file); - ofile << gcode; - ofile.close(); - } - else { - throw Py::RuntimeError("The given file is not a path"); - } - } - - return Py::None(); - } + return Py::None(); + } - Py::Object read(const Py::Tuple& args) - { - char* Name; - const char* DocName=nullptr; - if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&DocName)) - throw Py::Exception(); - std::string EncodedName = std::string(Name); - PyMem_Free(Name); + Py::Object read(const Py::Tuple& args) + { + char* Name; + const char* DocName = nullptr; + if (!PyArg_ParseTuple(args.ptr(), "et|s", "utf-8", &Name, &DocName)) { + throw Py::Exception(); + } + std::string EncodedName = std::string(Name); + PyMem_Free(Name); - Base::FileInfo file(EncodedName.c_str()); - if (!file.exists()) - throw Py::RuntimeError("File doesn't exist"); + Base::FileInfo file(EncodedName.c_str()); + if (!file.exists()) { + throw Py::RuntimeError("File doesn't exist"); + } - App::Document *pcDoc; - if (DocName) - pcDoc = App::GetApplication().getDocument(DocName); - else - pcDoc = App::GetApplication().getActiveDocument(); - if (!pcDoc) - pcDoc = App::GetApplication().newDocument(DocName); + App::Document* pcDoc; + if (DocName) { + pcDoc = App::GetApplication().getDocument(DocName); + } + else { + pcDoc = App::GetApplication().getActiveDocument(); + } + if (!pcDoc) { + pcDoc = App::GetApplication().newDocument(DocName); + } - try { - // read the gcode file - Base::ifstream filestr(file); - std::stringstream buffer; - buffer << filestr.rdbuf(); - std::string gcode = buffer.str(); - Path::Toolpath path; - path.setFromGCode(gcode); - Path::Feature *object = static_cast(pcDoc->addObject("Path::Feature",file.fileNamePure().c_str())); - object->Path.setValue(path); - pcDoc->recompute(); - } - catch (const Base::Exception& e) { - throw Py::RuntimeError(e.what()); - } + try { + // read the gcode file + Base::ifstream filestr(file); + std::stringstream buffer; + buffer << filestr.rdbuf(); + std::string gcode = buffer.str(); + Path::Toolpath path; + path.setFromGCode(gcode); + Path::Feature* object = static_cast( + pcDoc->addObject("Path::Feature", file.fileNamePure().c_str())); + object->Path.setValue(path); + pcDoc->recompute(); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } - return Py::None(); - } + return Py::None(); + } - Py::Object show(const Py::Tuple& args) - { - PyObject *pcObj; - const char *name = "Path"; - if (!PyArg_ParseTuple(args.ptr(), "O!|s", &(Path::PathPy::Type), &pcObj, &name)) - throw Py::Exception(); + Py::Object show(const Py::Tuple& args) + { + PyObject* pcObj; + const char* name = "Path"; + if (!PyArg_ParseTuple(args.ptr(), "O!|s", &(Path::PathPy::Type), &pcObj, &name)) { + throw Py::Exception(); + } - try { - App::Document *pcDoc = App::GetApplication().getActiveDocument(); - if (!pcDoc) - pcDoc = App::GetApplication().newDocument(); - Path::PathPy* pPath = static_cast(pcObj); - Path::Feature *pcFeature = static_cast(pcDoc->addObject("Path::Feature", name)); - Path::Toolpath* pa = pPath->getToolpathPtr(); - if (!pa) { - throw Py::Exception(PyExc_ReferenceError, "object doesn't reference a valid path"); - } + try { + App::Document* pcDoc = App::GetApplication().getActiveDocument(); + if (!pcDoc) { + pcDoc = App::GetApplication().newDocument(); + } + Path::PathPy* pPath = static_cast(pcObj); + Path::Feature* pcFeature = + static_cast(pcDoc->addObject("Path::Feature", name)); + Path::Toolpath* pa = pPath->getToolpathPtr(); + if (!pa) { + throw Py::Exception(PyExc_ReferenceError, "object doesn't reference a valid path"); + } - // copy the data - pcFeature->Path.setValue(*pa); - } - catch (const Base::Exception& e) { - throw Py::RuntimeError(e.what()); - } + // copy the data + pcFeature->Path.setValue(*pa); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } - return Py::None(); - } + return Py::None(); + } - Py::Object fromShape(const Py::Tuple& args) - { - PyObject *pcObj; - if (!PyArg_ParseTuple(args.ptr(), "O", &pcObj)) - throw Py::Exception(); - TopoDS_Shape shape; - try { - if (PyObject_TypeCheck(pcObj, &(Part::TopoShapePy::Type))) { - shape = static_cast(pcObj)->getTopoShapePtr()->getShape(); - } else { - throw Py::TypeError("the given object is not a shape"); - } - if (!shape.IsNull()) { - if (shape.ShapeType() == TopAbs_WIRE) { - Path::Toolpath result; - bool first = true; - Base::Placement last; + Py::Object fromShape(const Py::Tuple& args) + { + PyObject* pcObj; + if (!PyArg_ParseTuple(args.ptr(), "O", &pcObj)) { + throw Py::Exception(); + } + TopoDS_Shape shape; + try { + if (PyObject_TypeCheck(pcObj, &(Part::TopoShapePy::Type))) { + shape = static_cast(pcObj)->getTopoShapePtr()->getShape(); + } + else { + throw Py::TypeError("the given object is not a shape"); + } + if (!shape.IsNull()) { + if (shape.ShapeType() == TopAbs_WIRE) { + Path::Toolpath result; + bool first = true; + Base::Placement last; - TopExp_Explorer ExpEdges (shape,TopAbs_EDGE); - while (ExpEdges.More()) { - const TopoDS_Edge& edge = TopoDS::Edge(ExpEdges.Current()); - TopExp_Explorer ExpVerts(edge,TopAbs_VERTEX); - bool vfirst = true; - while (ExpVerts.More()) { - const TopoDS_Vertex& vert = TopoDS::Vertex(ExpVerts.Current()); - gp_Pnt pnt = BRep_Tool::Pnt(vert); - Base::Placement tpl; - tpl.setPosition(Base::Vector3d(pnt.X(),pnt.Y(),pnt.Z())); - if (first) { - // add first point as a G0 move - Path::Command cmd; - std::ostringstream ctxt; - ctxt << "G0 X" << tpl.getPosition().x << " Y" << tpl.getPosition().y << " Z" << tpl.getPosition().z; - cmd.setFromGCode(ctxt.str()); - result.addCommand(cmd); - first = false; - vfirst = false; - } else { - if (vfirst) - vfirst = false; - else { - Path::Command cmd; - cmd.setFromPlacement(tpl); + TopExp_Explorer ExpEdges(shape, TopAbs_EDGE); + while (ExpEdges.More()) { + const TopoDS_Edge& edge = TopoDS::Edge(ExpEdges.Current()); + TopExp_Explorer ExpVerts(edge, TopAbs_VERTEX); + bool vfirst = true; + while (ExpVerts.More()) { + const TopoDS_Vertex& vert = TopoDS::Vertex(ExpVerts.Current()); + gp_Pnt pnt = BRep_Tool::Pnt(vert); + Base::Placement tpl; + tpl.setPosition(Base::Vector3d(pnt.X(), pnt.Y(), pnt.Z())); + if (first) { + // add first point as a G0 move + Path::Command cmd; + std::ostringstream ctxt; + ctxt << "G0 X" << tpl.getPosition().x << " Y" << tpl.getPosition().y + << " Z" << tpl.getPosition().z; + cmd.setFromGCode(ctxt.str()); + result.addCommand(cmd); + first = false; + vfirst = false; + } + else { + if (vfirst) { + vfirst = false; + } + else { + Path::Command cmd; + cmd.setFromPlacement(tpl); - // write arc data if needed - BRepAdaptor_Curve adapt(edge); - if (adapt.GetType() == GeomAbs_Circle) { - gp_Circ circ = adapt.Circle(); - gp_Pnt c = circ.Location(); - bool clockwise = false; - gp_Dir n = circ.Axis().Direction(); - if (n.Z() < 0) - clockwise = true; - Base::Vector3d center = Base::Vector3d(c.X(),c.Y(),c.Z()); - // center coords must be relative to last point - center -= last.getPosition(); - cmd.setCenter(center,clockwise); - } - result.addCommand(cmd); - } - } - ExpVerts.Next(); - last = tpl; - } - ExpEdges.Next(); - } - return Py::asObject(new Path::PathPy(new Path::Toolpath(result))); - } else { - throw Py::TypeError("the given shape must be a wire"); - } - } else { - throw Py::TypeError("the given shape is empty"); - } - } - catch (const Base::Exception& e) { - throw Py::RuntimeError(e.what()); - } - } + // write arc data if needed + BRepAdaptor_Curve adapt(edge); + if (adapt.GetType() == GeomAbs_Circle) { + gp_Circ circ = adapt.Circle(); + gp_Pnt c = circ.Location(); + bool clockwise = false; + gp_Dir n = circ.Axis().Direction(); + if (n.Z() < 0) { + clockwise = true; + } + Base::Vector3d center = Base::Vector3d(c.X(), c.Y(), c.Z()); + // center coords must be relative to last point + center -= last.getPosition(); + cmd.setCenter(center, clockwise); + } + result.addCommand(cmd); + } + } + ExpVerts.Next(); + last = tpl; + } + ExpEdges.Next(); + } + return Py::asObject(new Path::PathPy(new Path::Toolpath(result))); + } + else { + throw Py::TypeError("the given shape must be a wire"); + } + } + else { + throw Py::TypeError("the given shape is empty"); + } + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } + } - Py::Object fromShapes(const Py::Tuple& args, const Py::Dict &kwds) - { - PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_PATH) - PyObject *pShapes=nullptr; - PyObject *start=nullptr; - PyObject *return_end=Py_False; - static const std::array kwd_list {"shapes", "start", "return_end", - PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_PATH), nullptr}; - if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), - "O|O!O!" PARAM_PY_KWDS(AREA_PARAMS_PATH), - kwd_list, &pShapes, &(Base::VectorPy::Type), &start, &PyBool_Type, &return_end, - PARAM_REF(PARAM_FARG,AREA_PARAMS_PATH))) { - throw Py::Exception(); - } + Py::Object fromShapes(const Py::Tuple& args, const Py::Dict& kwds) + { + PARAM_PY_DECLARE_INIT(PARAM_FARG, AREA_PARAMS_PATH) + PyObject* pShapes = nullptr; + PyObject* start = nullptr; + PyObject* return_end = Py_False; + static const std::array kwd_list { + "shapes", + "start", + "return_end", + PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_PATH), + nullptr}; + if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(), + kwds.ptr(), + "O|O!O!" PARAM_PY_KWDS(AREA_PARAMS_PATH), + kwd_list, + &pShapes, + &(Base::VectorPy::Type), + &start, + &PyBool_Type, + &return_end, + PARAM_REF(PARAM_FARG, AREA_PARAMS_PATH))) { + throw Py::Exception(); + } - std::list shapes; - if (PyObject_TypeCheck(pShapes, &(Part::TopoShapePy::Type))) - shapes.push_back(static_cast(pShapes)->getTopoShapePtr()->getShape()); - else if (PyObject_TypeCheck(pShapes, &(PyList_Type)) || - PyObject_TypeCheck(pShapes, &(PyTuple_Type))) - { - Py::Sequence shapeSeq(pShapes); - for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) { - PyObject* item = (*it).ptr(); - if(!PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) { - PyErr_SetString(PyExc_TypeError, "non-shape object in sequence"); - throw Py::Exception(); - } - shapes.push_back(static_cast(item)->getTopoShapePtr()->getShape()); - } - } + std::list shapes; + if (PyObject_TypeCheck(pShapes, &(Part::TopoShapePy::Type))) { + shapes.push_back( + static_cast(pShapes)->getTopoShapePtr()->getShape()); + } + else if (PyObject_TypeCheck(pShapes, &(PyList_Type)) + || PyObject_TypeCheck(pShapes, &(PyTuple_Type))) { + Py::Sequence shapeSeq(pShapes); + for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) { + PyObject* item = (*it).ptr(); + if (!PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) { + PyErr_SetString(PyExc_TypeError, "non-shape object in sequence"); + throw Py::Exception(); + } + shapes.push_back( + static_cast(item)->getTopoShapePtr()->getShape()); + } + } - gp_Pnt pstart; - if(start) { - Base::Vector3d vec = static_cast(start)->value(); - pstart.SetCoord(vec.x, vec.y, vec.z); - } + gp_Pnt pstart; + if (start) { + Base::Vector3d vec = static_cast(start)->value(); + pstart.SetCoord(vec.x, vec.y, vec.z); + } - try { - gp_Pnt pend; - std::unique_ptr path(new Path::Toolpath); - Path::Area::toPath(*path,shapes,start?&pstart:nullptr, &pend, - PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_PATH)); - if (!Base::asBoolean(return_end)) - return Py::asObject(new Path::PathPy(path.release())); - Py::Tuple tuple(2); - tuple.setItem(0, Py::asObject(new Path::PathPy(path.release()))); - tuple.setItem(1, Py::asObject(new Base::VectorPy(Base::Vector3d(pend.X(),pend.Y(),pend.Z())))); - return tuple; - } PATH_CATCH - } + try { + gp_Pnt pend; + std::unique_ptr path(new Path::Toolpath); + Path::Area::toPath(*path, + shapes, + start ? &pstart : nullptr, + &pend, + PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_PATH)); + if (!Base::asBoolean(return_end)) { + return Py::asObject(new Path::PathPy(path.release())); + } + Py::Tuple tuple(2); + tuple.setItem(0, Py::asObject(new Path::PathPy(path.release()))); + tuple.setItem( + 1, + Py::asObject(new Base::VectorPy(Base::Vector3d(pend.X(), pend.Y(), pend.Z())))); + return tuple; + } + PATH_CATCH + } - Py::Object sortWires(const Py::Tuple& args, const Py::Dict &kwds) - { - PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_ARC_PLANE) - PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_SORT) - PyObject *pShapes=nullptr; - PyObject *start=nullptr; - static const std::array kwd_list {"shapes", "start", - PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_ARC_PLANE), - PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_SORT), nullptr}; - if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), - "O|O!" - PARAM_PY_KWDS(AREA_PARAMS_ARC_PLANE) - PARAM_PY_KWDS(AREA_PARAMS_SORT), - kwd_list, &pShapes, &(Base::VectorPy::Type), &start, - PARAM_REF(PARAM_FARG,AREA_PARAMS_ARC_PLANE), - PARAM_REF(PARAM_FARG,AREA_PARAMS_SORT))) - throw Py::Exception(); + Py::Object sortWires(const Py::Tuple& args, const Py::Dict& kwds) + { + PARAM_PY_DECLARE_INIT(PARAM_FARG, AREA_PARAMS_ARC_PLANE) + PARAM_PY_DECLARE_INIT(PARAM_FARG, AREA_PARAMS_SORT) + PyObject* pShapes = nullptr; + PyObject* start = nullptr; + static const std::array kwd_list { + "shapes", + "start", + PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_ARC_PLANE), + PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_SORT), + nullptr}; + if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(), + kwds.ptr(), + "O|O!" PARAM_PY_KWDS(AREA_PARAMS_ARC_PLANE) + PARAM_PY_KWDS(AREA_PARAMS_SORT), + kwd_list, + &pShapes, + &(Base::VectorPy::Type), + &start, + PARAM_REF(PARAM_FARG, AREA_PARAMS_ARC_PLANE), + PARAM_REF(PARAM_FARG, AREA_PARAMS_SORT))) { + throw Py::Exception(); + } - std::list shapes; - if (PyObject_TypeCheck(pShapes, &(Part::TopoShapePy::Type))) { - shapes.push_back(static_cast(pShapes)->getTopoShapePtr()->getShape()); - } - else if (PyObject_TypeCheck(pShapes, &(PyList_Type)) || - PyObject_TypeCheck(pShapes, &(PyTuple_Type))) { - Py::Sequence shapeSeq(pShapes); - for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) { - PyObject* item = (*it).ptr(); - if(!PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) { - PyErr_SetString(PyExc_TypeError, "non-shape object in sequence"); - throw Py::Exception(); - } - shapes.push_back(static_cast(item)->getTopoShapePtr()->getShape()); - } - } + std::list shapes; + if (PyObject_TypeCheck(pShapes, &(Part::TopoShapePy::Type))) { + shapes.push_back( + static_cast(pShapes)->getTopoShapePtr()->getShape()); + } + else if (PyObject_TypeCheck(pShapes, &(PyList_Type)) + || PyObject_TypeCheck(pShapes, &(PyTuple_Type))) { + Py::Sequence shapeSeq(pShapes); + for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) { + PyObject* item = (*it).ptr(); + if (!PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) { + PyErr_SetString(PyExc_TypeError, "non-shape object in sequence"); + throw Py::Exception(); + } + shapes.push_back( + static_cast(item)->getTopoShapePtr()->getShape()); + } + } - gp_Pnt pstart,pend; - if(start) { - Base::Vector3d vec = static_cast(start)->value(); - pstart.SetCoord(vec.x, vec.y, vec.z); - } + gp_Pnt pstart, pend; + if (start) { + Base::Vector3d vec = static_cast(start)->value(); + pstart.SetCoord(vec.x, vec.y, vec.z); + } - try { - bool need_arc_plane = arc_plane == Path::Area::ArcPlaneAuto; - std::list wires = Path::Area::sortWires(shapes, start != nullptr, &pstart, - &pend, nullptr, &arc_plane, PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_SORT)); - Py::List list; - for(auto &wire : wires) { - list.append(Part::shape2pyshape(TopoDS::Wire(wire))); - } + try { + bool need_arc_plane = arc_plane == Path::Area::ArcPlaneAuto; + std::list wires = + Path::Area::sortWires(shapes, + start != nullptr, + &pstart, + &pend, + nullptr, + &arc_plane, + PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_SORT)); + Py::List list; + for (auto& wire : wires) { + list.append(Part::shape2pyshape(TopoDS::Wire(wire))); + } - Py::Tuple ret(need_arc_plane ? 3 : 2); - ret.setItem(0, list); - ret.setItem(1, Py::asObject(new Base::VectorPy(Base::Vector3d(pend.X(),pend.Y(),pend.Z())))); - if (need_arc_plane) - ret.setItem(2, Py::Long(arc_plane)); + Py::Tuple ret(need_arc_plane ? 3 : 2); + ret.setItem(0, list); + ret.setItem( + 1, + Py::asObject(new Base::VectorPy(Base::Vector3d(pend.X(), pend.Y(), pend.Z())))); + if (need_arc_plane) { + ret.setItem(2, Py::Long(arc_plane)); + } - return ret; - } PATH_CATCH - } - }; + return ret; + } + PATH_CATCH + } +}; - PyObject* initModule() - { - return Base::Interpreter().addModule(new Module); - } +PyObject* initModule() +{ + return Base::Interpreter().addModule(new Module); +} -} // namespace Path +} // namespace PathApp diff --git a/src/Mod/CAM/App/Area.cpp b/src/Mod/CAM/App/Area.cpp index a639af19e5..6d94ea27c4 100644 --- a/src/Mod/CAM/App/Area.cpp +++ b/src/Mod/CAM/App/Area.cpp @@ -26,47 +26,47 @@ #define BOOST_GEOMETRY_DISABLE_DEPRECATED_03_WARNING #ifndef _PreComp_ -# include +#include -# include -# include -# include -# include +#include +#include +#include +#include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #endif #include @@ -81,10 +81,10 @@ #include "Area.h" -//FIXME: ISO C++11 requires at least one argument for the "..." in a variadic macro +// FIXME: ISO C++11 requires at least one argument for the "..." in a variadic macro #if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" #endif @@ -93,8 +93,15 @@ namespace bgi = boost::geometry::index; using RParameters = bgi::linear<16>; -BOOST_GEOMETRY_REGISTER_POINT_3D_GET_SET( - gp_Pnt, double, bg::cs::cartesian, X, Y, Z, SetX, SetY, SetZ) +BOOST_GEOMETRY_REGISTER_POINT_3D_GET_SET(gp_Pnt, + double, + bg::cs::cartesian, + X, + Y, + Z, + SetX, + SetY, + SetZ) #define AREA_LOG FC_LOG #define AREA_WARN FC_WARN @@ -104,9 +111,11 @@ BOOST_GEOMETRY_REGISTER_POINT_3D_GET_SET( #define AREA_XY AREA_XY #ifdef FC_DEBUG -# define AREA_DBG FC_WARN +#define AREA_DBG FC_WARN #else -# define AREA_DBG(...) do{}while(0) +#define AREA_DBG(...) \ + do { \ + } while (0) #endif FC_LOG_LEVEL_INIT("Path.Area", true, true) @@ -114,16 +123,17 @@ FC_LOG_LEVEL_INIT("Path.Area", true, true) using namespace Path; CAreaParams::CAreaParams() - :PARAM_INIT(PARAM_FNAME, AREA_PARAMS_CAREA) + : PARAM_INIT(PARAM_FNAME, AREA_PARAMS_CAREA) {} AreaParams::AreaParams() : PARAM_INIT(PARAM_FNAME, AREA_PARAMS_AREA) {} -void AreaParams::dump(const char* msg) const { +void AreaParams::dump(const char* msg) const +{ -#define AREA_PARAM_PRINT(_param) \ +#define AREA_PARAM_PRINT(_param) \ ss << PARAM_FNAME_STR(_param) << " = " << PARAM_FNAME(_param) << '\n'; if (FC_LOG_INSTANCE.level() > FC_LOGLEVEL_TRACE) { @@ -136,22 +146,23 @@ void AreaParams::dump(const char* msg) const { CAreaConfig::CAreaConfig(const CAreaParams& p, bool noFitArcs) { -#define AREA_CONF_SAVE_AND_APPLY(_param) \ - PARAM_FNAME(_param) = BOOST_PP_CAT(CArea::get_,PARAM_FARG(_param))();\ - BOOST_PP_CAT(CArea::set_,PARAM_FARG(_param))(p.PARAM_FNAME(_param)); +#define AREA_CONF_SAVE_AND_APPLY(_param) \ + PARAM_FNAME(_param) = BOOST_PP_CAT(CArea::get_, PARAM_FARG(_param))(); \ + BOOST_PP_CAT(CArea::set_, PARAM_FARG(_param))(p.PARAM_FNAME(_param)); PARAM_FOREACH(AREA_CONF_SAVE_AND_APPLY, AREA_PARAMS_CAREA); // Arc fitting is lossy. We shall reduce the number of unnecessary fit - if (noFitArcs) + if (noFitArcs) { CArea::set_fit_arcs(false); - + } } -CAreaConfig::~CAreaConfig() { +CAreaConfig::~CAreaConfig() +{ -#define AREA_CONF_RESTORE(_param) \ - BOOST_PP_CAT(CArea::set_,PARAM_FARG(_param))(PARAM_FNAME(_param)); +#define AREA_CONF_RESTORE(_param) \ + BOOST_PP_CAT(CArea::set_, PARAM_FARG(_param))(PARAM_FNAME(_param)); PARAM_FOREACH(AREA_CONF_RESTORE, AREA_PARAMS_CAREA); } @@ -163,19 +174,20 @@ TYPESYSTEM_SOURCE(Path::Area, Base::BaseClass) bool Area::s_aborting; Area::Area(const AreaParams* params) - :myParams(s_params) + : myParams(s_params) , myHaveFace(false) , myHaveSolid(false) , myShapeDone(false) , myProjecting(false) , mySkippedShapes(0) { - if (params) + if (params) { setParams(*params); + } } Area::Area(const Area& other, bool deep_copy) - :Base::BaseClass(other) + : Base::BaseClass(other) , myShapes(other.myShapes) , myTrsf(other.myTrsf) , myParams(other.myParams) @@ -186,23 +198,28 @@ Area::Area(const Area& other, bool deep_copy) , myProjecting(false) , mySkippedShapes(0) { - if (!deep_copy || !other.isBuilt()) + if (!deep_copy || !other.isBuilt()) { return; - if (other.myArea) + } + if (other.myArea) { myArea = std::make_unique(*other.myArea); + } myShapePlane = other.myShapePlane; myShape = other.myShape; myShapeDone = other.myShapeDone; mySections.reserve(other.mySections.size()); - for (const shared_ptr& area : other.mySections) + for (const shared_ptr& area : other.mySections) { mySections.push_back(make_shared(*area, true)); + } } -Area::~Area() { +Area::~Area() +{ clean(); } -void Area::setPlane(const TopoDS_Shape& shape) { +void Area::setPlane(const TopoDS_Shape& shape) +{ clean(); if (shape.IsNull()) { myWorkPlane.Nullify(); @@ -210,25 +227,30 @@ void Area::setPlane(const TopoDS_Shape& shape) { } gp_Trsf trsf; TopoDS_Shape plane = findPlane(shape, trsf); - if (plane.IsNull()) + if (plane.IsNull()) { throw Base::ValueError("shape is not planar"); + } myWorkPlane = plane; myTrsf = trsf; } -static bool getShapePlane(const TopoDS_Shape& shape, gp_Pln& pln) { - if (shape.IsNull()) +static bool getShapePlane(const TopoDS_Shape& shape, gp_Pln& pln) +{ + if (shape.IsNull()) { return false; + } if (shape.ShapeType() == TopAbs_FACE) { BRepAdaptor_Surface adapt(TopoDS::Face(shape)); - if (adapt.GetType() != GeomAbs_Plane) + if (adapt.GetType() != GeomAbs_Plane) { return false; + } pln = adapt.Plane(); return true; } BRepLib_FindSurface finder(shape.Located(TopLoc_Location()), -1, Standard_True); - if (!finder.Found()) + if (!finder.Found()) { return false; + } // TODO: It seemed that FindSurface disregard shape's // transformation SOMETIME, so we have to transformed the found @@ -244,20 +266,32 @@ static bool getShapePlane(const TopoDS_Shape& shape, gp_Pln& pln) { return true; } -bool Area::isCoplanar(const TopoDS_Shape& s1, const TopoDS_Shape& s2) { - if (s1.IsNull() || s2.IsNull()) +bool Area::isCoplanar(const TopoDS_Shape& s1, const TopoDS_Shape& s2) +{ + if (s1.IsNull() || s2.IsNull()) { return false; - if (s1.IsSame(s2)) + } + if (s1.IsSame(s2)) { return true; + } gp_Pln pln1, pln2; - if (!getShapePlane(s1, pln1) || !getShapePlane(s2, pln2)) + if (!getShapePlane(s1, pln1) || !getShapePlane(s2, pln2)) { return false; - return pln1.Position().IsCoplanar(pln2.Position(), Precision::Confusion(), Precision::Confusion()); + } + return pln1.Position().IsCoplanar(pln2.Position(), + Precision::Confusion(), + Precision::Confusion()); } -int Area::addShape(CArea& area, const TopoDS_Shape& shape, const gp_Trsf* trsf, - double deflection, const TopoDS_Shape* plane, bool force_coplanar, - CArea* areaOpen, bool to_edges, bool reorient) +int Area::addShape(CArea& area, + const TopoDS_Shape& shape, + const gp_Trsf* trsf, + double deflection, + const TopoDS_Shape* plane, + bool force_coplanar, + CArea* areaOpen, + bool to_edges, + bool reorient) { bool haveShape = false; int skipped = 0; @@ -266,14 +300,18 @@ int Area::addShape(CArea& area, const TopoDS_Shape& shape, const gp_Trsf* trsf, const TopoDS_Face& face = TopoDS::Face(it.Current()); if (plane && !isCoplanar(face, *plane)) { ++skipped; - if (force_coplanar) continue; + if (force_coplanar) { + continue; + } } - for (TopExp_Explorer it(face, TopAbs_WIRE); it.More(); it.Next()) + for (TopExp_Explorer it(face, TopAbs_WIRE); it.More(); it.Next()) { addWire(area, TopoDS::Wire(it.Current()), trsf, deflection); + } } - if (haveShape) + if (haveShape) { return skipped; + } CArea _area; CArea _areaOpen; @@ -283,42 +321,55 @@ int Area::addShape(CArea& area, const TopoDS_Shape& shape, const gp_Trsf* trsf, const TopoDS_Wire& wire = TopoDS::Wire(it.Current()); if (plane && !isCoplanar(wire, *plane)) { ++skipped; - if (force_coplanar) continue; + if (force_coplanar) { + continue; + } } - if (BRep_Tool::IsClosed(wire)) + if (BRep_Tool::IsClosed(wire)) { addWire(_area, wire, trsf, deflection); - else if (to_edges) { - for (TopExp_Explorer it(wire, TopAbs_EDGE); it.More(); it.Next()) - addWire(_areaOpen, BRepBuilderAPI_MakeWire( - TopoDS::Edge(it.Current())).Wire(), trsf, deflection, true); } - else + else if (to_edges) { + for (TopExp_Explorer it(wire, TopAbs_EDGE); it.More(); it.Next()) { + addWire(_areaOpen, + BRepBuilderAPI_MakeWire(TopoDS::Edge(it.Current())).Wire(), + trsf, + deflection, + true); + } + } + else { addWire(_areaOpen, wire, trsf, deflection); + } } if (!haveShape) { for (TopExp_Explorer it(shape, TopAbs_EDGE); it.More(); it.Next()) { if (plane && !isCoplanar(it.Current(), *plane)) { ++skipped; - if (force_coplanar) continue; + if (force_coplanar) { + continue; + } } - TopoDS_Wire wire = BRepBuilderAPI_MakeWire( - TopoDS::Edge(it.Current())).Wire(); + TopoDS_Wire wire = BRepBuilderAPI_MakeWire(TopoDS::Edge(it.Current())).Wire(); addWire(BRep_Tool::IsClosed(wire) ? _area : _areaOpen, wire, trsf, deflection); } } - if (reorient) + if (reorient) { _area.Reorder(); + } area.m_curves.splice(area.m_curves.end(), _area.m_curves); - if (areaOpen) + if (areaOpen) { areaOpen->m_curves.splice(areaOpen->m_curves.end(), _areaOpen.m_curves); - else + } + else { area.m_curves.splice(area.m_curves.end(), _areaOpen.m_curves); + } return skipped; } -static std::vector discretize(const TopoDS_Edge& edge, double deflection) { +static std::vector discretize(const TopoDS_Edge& edge, double deflection) +{ std::vector ret; BRepAdaptor_Curve curve(edge); Standard_Real efirst, elast; @@ -335,11 +386,12 @@ static std::vector discretize(const TopoDS_Edge& edge, double deflection // GCPnts_QuasiUniformDeflection discretizer(curve, deflection, first, last); // GCPnts_UniformDeflection discretizer(curve, deflection, efirst, elast); - if (!discretizer.IsDone()) + if (!discretizer.IsDone()) { Standard_Failure::Raise("Curve discretization failed"); + } if (discretizer.NbPoints() > 1) { int nbPoints = discretizer.NbPoints(); - //strangely OCC discretizer points are one-based, not zero-based, why? + // strangely OCC discretizer points are one-based, not zero-based, why? if (reversed) { for (int i = nbPoints - 1; i >= 1; --i) { ret.push_back(discretizer.Value(i)); @@ -356,12 +408,14 @@ static std::vector discretize(const TopoDS_Edge& edge, double deflection return ret; } -void Area::addWire(CArea& area, const TopoDS_Wire& wire, - const gp_Trsf* trsf, double deflection, bool to_edges) +void Area::addWire(CArea& area, + const TopoDS_Wire& wire, + const gp_Trsf* trsf, + double deflection, + bool to_edges) { CCurve ccurve; - BRepTools_WireExplorer xp(trsf ? TopoDS::Wire( - wire.Moved(TopLoc_Location(*trsf))) : wire); + BRepTools_WireExplorer xp(trsf ? TopoDS::Wire(wire.Moved(TopLoc_Location(*trsf))) : wire); if (!xp.More()) { AREA_TRACE("empty wire"); @@ -379,56 +433,59 @@ void Area::addWire(CArea& area, const TopoDS_Wire& wire, p = curve.Value(reversed ? curve.FirstParameter() : curve.LastParameter()); switch (curve.GetType()) { - case GeomAbs_Line: { - ccurve.append(CVertex(Point(p.X(), p.Y()))); - if (to_edges) { - area.append(ccurve); - ccurve.m_vertices.pop_front(); - } - break; - } case GeomAbs_Circle: { - double first = curve.FirstParameter(); - double last = curve.LastParameter(); - gp_Circ circle = curve.Circle(); - gp_Dir dir = circle.Axis().Direction(); - gp_Pnt center = circle.Location(); - int type = dir.Z() < 0 ? -1 : 1; - if (reversed) type = -type; - if (fabs(first - last) > M_PI) { - // Split arc(circle) larger than half circle. Because gcode - // can't handle full circle? - gp_Pnt mid = curve.Value((last - first) * 0.5 + first); - ccurve.append(CVertex(type, Point(mid.X(), mid.Y()), - Point(center.X(), center.Y()))); - } - ccurve.append(CVertex(type, Point(p.X(), p.Y()), - Point(center.X(), center.Y()))); - if (to_edges) { - ccurve.UnFitArcs(); - CCurve c; - c.append(ccurve.m_vertices.front()); - auto it = ccurve.m_vertices.begin(); - for (++it; it != ccurve.m_vertices.end(); ++it) { - c.append(*it); - area.append(c); - c.m_vertices.pop_front(); - } - ccurve.m_vertices.clear(); - ccurve.append(c.m_vertices.front()); - } - break; - } default: { - // Discretize all other type of curves - const auto& pts = discretize(edge, deflection); - for (size_t i = 1; i < pts.size(); ++i) { - auto& pt = pts[i]; - ccurve.append(CVertex(Point(pt.X(), pt.Y()))); + case GeomAbs_Line: { + ccurve.append(CVertex(Point(p.X(), p.Y()))); if (to_edges) { area.append(ccurve); ccurve.m_vertices.pop_front(); } + break; + } + case GeomAbs_Circle: { + double first = curve.FirstParameter(); + double last = curve.LastParameter(); + gp_Circ circle = curve.Circle(); + gp_Dir dir = circle.Axis().Direction(); + gp_Pnt center = circle.Location(); + int type = dir.Z() < 0 ? -1 : 1; + if (reversed) { + type = -type; + } + if (fabs(first - last) > M_PI) { + // Split arc(circle) larger than half circle. Because gcode + // can't handle full circle? + gp_Pnt mid = curve.Value((last - first) * 0.5 + first); + ccurve.append( + CVertex(type, Point(mid.X(), mid.Y()), Point(center.X(), center.Y()))); + } + ccurve.append(CVertex(type, Point(p.X(), p.Y()), Point(center.X(), center.Y()))); + if (to_edges) { + ccurve.UnFitArcs(); + CCurve c; + c.append(ccurve.m_vertices.front()); + auto it = ccurve.m_vertices.begin(); + for (++it; it != ccurve.m_vertices.end(); ++it) { + c.append(*it); + area.append(c); + c.m_vertices.pop_front(); + } + ccurve.m_vertices.clear(); + ccurve.append(c.m_vertices.front()); + } + break; + } + default: { + // Discretize all other type of curves + const auto& pts = discretize(edge, deflection); + for (size_t i = 1; i < pts.size(); ++i) { + auto& pt = pts[i]; + ccurve.append(CVertex(Point(pt.X(), pt.Y()))); + if (to_edges) { + area.append(ccurve); + ccurve.m_vertices.pop_front(); + } + } } - } } } if (!to_edges) { @@ -441,7 +498,8 @@ void Area::addWire(CArea& area, const TopoDS_Wire& wire, } -void Area::clean(bool deleteShapes) { +void Area::clean(bool deleteShapes) +{ myShapeDone = false; mySections.clear(); myShape.Nullify(); @@ -455,49 +513,54 @@ void Area::clean(bool deleteShapes) { } } -static inline ClipperLib::ClipType toClipperOp(short op) { +static inline ClipperLib::ClipType toClipperOp(short op) +{ switch (op) { - case Area::OperationUnion: - return ClipperLib::ctUnion; - break; - case Area::OperationDifference: - return ClipperLib::ctDifference; - break; - case Area::OperationIntersection: - return ClipperLib::ctIntersection; - break; - case Area::OperationXor: - return ClipperLib::ctXor; - break; - default: - throw Base::ValueError("invalid Operation"); + case Area::OperationUnion: + return ClipperLib::ctUnion; + break; + case Area::OperationDifference: + return ClipperLib::ctDifference; + break; + case Area::OperationIntersection: + return ClipperLib::ctIntersection; + break; + case Area::OperationXor: + return ClipperLib::ctXor; + break; + default: + throw Base::ValueError("invalid Operation"); } } -void Area::add(const TopoDS_Shape& shape, short op) { +void Area::add(const TopoDS_Shape& shape, short op) +{ - if (shape.IsNull()) + if (shape.IsNull()) { throw Base::ValueError("null shape"); + } - if (op != OperationCompound) + if (op != OperationCompound) { toClipperOp(op); + } bool haveSolid = TopExp_Explorer(shape, TopAbs_SOLID).More(); - //TODO: shall we support Shells? - if ((!haveSolid && myHaveSolid) || - (haveSolid && !myHaveSolid && !myShapes.empty())) + // TODO: shall we support Shells? + if ((!haveSolid && myHaveSolid) || (haveSolid && !myHaveSolid && !myShapes.empty())) { throw Base::ValueError("mixing solid and planar shapes is not allowed"); + } myHaveSolid = haveSolid; clean(); - if (op != OperationCompound && myShapes.empty()) + if (op != OperationCompound && myShapes.empty()) { op = OperationUnion; + } myShapes.emplace_back(op, shape); } -class ClearedAreaSegmentVisitor : public PathSegmentVisitor +class ClearedAreaSegmentVisitor: public PathSegmentVisitor { private: CArea pathSegments; @@ -506,20 +569,20 @@ private: double radius; Base::BoundBox3d bbox; - void point(const Base::Vector3d &p) + void point(const Base::Vector3d& p) { if (p.z <= maxZ) { if (bbox.MinX <= p.x && p.x <= bbox.MaxX && bbox.MinY <= p.y && p.y <= bbox.MaxY) { CCurve curve; - curve.append(CVertex{{p.x + radius, p.y}}); - curve.append(CVertex{1, {p.x - radius, p.y}, {p.x, p.y}}); - curve.append(CVertex{1, {p.x + radius, p.y}, {p.x, p.y}}); + curve.append(CVertex {{p.x + radius, p.y}}); + curve.append(CVertex {1, {p.x - radius, p.y}, {p.x, p.y}}); + curve.append(CVertex {1, {p.x + radius, p.y}, {p.x, p.y}}); holes.append(curve); } } } - void line(const Base::Vector3d &last, const Base::Vector3d &next) + void line(const Base::Vector3d& last, const Base::Vector3d& next) { if (last.z <= maxZ && next.z <= maxZ) { Base::BoundBox2d segBox = {}; @@ -527,41 +590,55 @@ private: segBox.Add({next.x, next.y}); if (bbox.Intersect(segBox)) { CCurve curve; - curve.append(CVertex{{last.x, last.y}}); - curve.append(CVertex{{next.x, next.y}}); + curve.append(CVertex {{last.x, last.y}}); + curve.append(CVertex {{next.x, next.y}}); pathSegments.append(curve); } } } + public: - ClearedAreaSegmentVisitor(double maxZ, double radius, Base::BoundBox3d bbox) : maxZ(maxZ), radius(radius), bbox(bbox) + ClearedAreaSegmentVisitor(double maxZ, double radius, Base::BoundBox3d bbox) + : maxZ(maxZ) + , radius(radius) + , bbox(bbox) { bbox.Enlarge(radius); } CArea getClearedArea() { - CArea result{pathSegments}; + CArea result {pathSegments}; result.Thicken(radius); result.Union(holes); return result; } - void g0(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts) override + void g0(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts) override { (void)id; (void)pts; line(last, next); } - void g1(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts) override + void g1(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts) override { (void)id; (void)pts; line(last, next); } - void g23(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, const Base::Vector3d ¢er) override + void g23(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts, + const Base::Vector3d& center) override { (void)id; (void)center; @@ -573,17 +650,21 @@ public: // Add an arc CCurve curve; - curve.append(CVertex{{last.x, last.y}}); - curve.append(CVertex{ccw ? 1 : -1, {next.x, next.y}, {center.x, center.y}}); + curve.append(CVertex {{last.x, last.y}}); + curve.append(CVertex {ccw ? 1 : -1, {next.x, next.y}, {center.x, center.y}}); pathSegments.append(curve); } - void g8x(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, - const std::deque &plist, const std::deque &qlist) override + void g8x(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts, + const std::deque& plist, + const std::deque& qlist) override { // (peck) drilling (void)id; - (void)qlist; // pecks are always within the bounds of plist + (void)qlist; // pecks are always within the bounds of plist point(last); for (const auto p : pts) { @@ -594,7 +675,7 @@ public: } point(next); } - void g38(int id, const Base::Vector3d &last, const Base::Vector3d &next) override + void g38(int id, const Base::Vector3d& last, const Base::Vector3d& next) override { // probe operation; clears nothing (void)id; @@ -603,26 +684,29 @@ public: } }; -std::shared_ptr Area::getClearedArea(const Toolpath *path, double diameter, double zmax, Base::BoundBox3d bbox) { +std::shared_ptr +Area::getClearedArea(const Toolpath* path, double diameter, double zmax, Base::BoundBox3d bbox) +{ build(); // Precision losses in arc/segment conversions (multiples of Accuracy): - // 2.3 in generation of gcode (see documentation in the implementation of CCurve::CheckForArc (libarea/Curve.cpp) - // 1 in gcode arc to segment - // 1 in Thicken() cleared area - // 2 in getRestArea target area offset in and back out - // Oversize cleared areas by buffer to smooth out imprecision in arc/segment conversion. getRestArea() will compensate for this + // 2.3 in generation of gcode (see documentation in the implementation of CCurve::CheckForArc + // (libarea/Curve.cpp) 1 in gcode arc to segment 1 in Thicken() cleared area 2 in getRestArea + // target area offset in and back out Oversize cleared areas by buffer to smooth out imprecision + // in arc/segment conversion. getRestArea() will compensate for this AreaParams params = myParams; - params.Accuracy = myParams.Accuracy * .7/4; // 2.3 already encoded in gcode; 4 * .7/4 = 3 total + params.Accuracy = + myParams.Accuracy * .7 / 4; // 2.3 already encoded in gcode; 4 * .7/4 = 3 total params.SubjectFill = ClipperLib::pftNonZero; params.ClipFill = ClipperLib::pftNonZero; const double buffer = myParams.Accuracy * 3; - // Do not fit arcs after these offsets; it introduces unnecessary approximation error, and all off - // those arcs will be converted back to segments again for clipper differencing in getRestArea anyway + // Do not fit arcs after these offsets; it introduces unnecessary approximation error, and all + // off those arcs will be converted back to segments again for clipper differencing in + // getRestArea anyway CAreaConfig conf(params, /*no_fit_arcs*/ true); - ClearedAreaSegmentVisitor visitor(zmax, diameter/2 + buffer, bbox); + ClearedAreaSegmentVisitor visitor(zmax, diameter / 2 + buffer, bbox); PathSegmentWalker walker(*path); walker.walk(visitor, Base::Vector3d(0, 0, zmax + 1)); @@ -633,7 +717,8 @@ std::shared_ptr Area::getClearedArea(const Toolpath *path, double diameter TopoDS_Shape clearedAreaShape = Area::toShape(ca, false); clearedArea->add(clearedAreaShape, OperationCompound); clearedArea->build(); - } else { + } + else { clearedArea->myArea = std::make_unique(); clearedArea->myAreaOpen = std::make_unique(); } @@ -641,20 +726,22 @@ std::shared_ptr Area::getClearedArea(const Toolpath *path, double diameter return clearedArea; } -std::shared_ptr Area::getRestArea(std::vector> clearedAreas, double diameter) { +std::shared_ptr Area::getRestArea(std::vector> clearedAreas, + double diameter) +{ build(); #define AREA_MY(_param) myParams.PARAM_FNAME(_param) PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_OFFSET_CONF); PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_CLIPPER_FILL); // Precision losses in arc/segment conversions (multiples of Accuracy): - // 2.3 in generation of gcode (see documentation in the implementation of CCurve::CheckForArc (libarea/Curve.cpp) - // 1 in gcode arc to segment - // 1 in Thicken() cleared area - // 2 in getRestArea target area offset in and back out - // Cleared area representations are oversized by buffer to smooth out imprecision in arc/segment conversion. getRestArea() will compensate for this + // 2.3 in generation of gcode (see documentation in the implementation of CCurve::CheckForArc + // (libarea/Curve.cpp) 1 in gcode arc to segment 1 in Thicken() cleared area 2 in getRestArea + // target area offset in and back out Cleared area representations are oversized by buffer to + // smooth out imprecision in arc/segment conversion. getRestArea() will compensate for this AreaParams params = myParams; - params.Accuracy = myParams.Accuracy * .7/4; // 2.3 already encoded in gcode; 4 * .7/4 = 3 total + params.Accuracy = + myParams.Accuracy * .7 / 4; // 2.3 already encoded in gcode; 4 * .7/4 = 3 total const double buffer = myParams.Accuracy * 3; const double roundPrecision = params.Accuracy; @@ -662,29 +749,47 @@ std::shared_ptr Area::getRestArea(std::vector> clear Area clearedAreasInPlane(¶ms); clearedAreasInPlane.myArea.reset(new CArea()); for (std::shared_ptr clearedArea : clearedAreas) { - gp_Trsf trsf = clearedArea->myTrsf; - trsf.Invert(); - trsf.SetTranslationPart(gp_Vec{trsf.TranslationPart().X(), trsf.TranslationPart().Y(), -myTrsf.TranslationPart().Z()}); // discard z-height of cleared workplane, set to myWorkPlane's height - TopoDS_Shape clearedShape = Area::toShape(*clearedArea->myArea, false, &trsf); - Area::addShape(*(clearedAreasInPlane.myArea), clearedShape, &myTrsf, .01 /*default value*/, - &myWorkPlane); + gp_Trsf trsf = clearedArea->myTrsf; + trsf.Invert(); + trsf.SetTranslationPart(gp_Vec { + trsf.TranslationPart().X(), + trsf.TranslationPart().Y(), + -myTrsf.TranslationPart() + .Z()}); // discard z-height of cleared workplane, set to myWorkPlane's height + TopoDS_Shape clearedShape = Area::toShape(*clearedArea->myArea, false, &trsf); + Area::addShape(*(clearedAreasInPlane.myArea), + clearedShape, + &myTrsf, + .01 /*default value*/, + &myWorkPlane); } CArea clearable(*myArea); - clearable.OffsetWithClipper(-diameter/2, JoinType, EndType, params.MiterLimit, roundPrecision); - clearable.OffsetWithClipper(diameter/2, JoinType, EndType, params.MiterLimit, roundPrecision); + clearable.OffsetWithClipper(-diameter / 2, + JoinType, + EndType, + params.MiterLimit, + roundPrecision); + clearable.OffsetWithClipper(diameter / 2, JoinType, EndType, params.MiterLimit, roundPrecision); // remaining = clearable - prevCleared CArea remaining(clearable); - remaining.Clip(toClipperOp(Area::OperationDifference), &*(clearedAreasInPlane.myArea), SubjectFill, ClipFill); + remaining.Clip(toClipperOp(Area::OperationDifference), + &*(clearedAreasInPlane.myArea), + SubjectFill, + ClipFill); // rest = intersect(clearable, offset(remaining, dTool)) // add buffer to dTool to compensate for oversizing in getClearedArea CArea restCArea(remaining); - restCArea.OffsetWithClipper(diameter + buffer, JoinType, EndType, params.MiterLimit, roundPrecision); + restCArea.OffsetWithClipper(diameter + buffer, + JoinType, + EndType, + params.MiterLimit, + roundPrecision); restCArea.Clip(toClipperOp(Area::OperationIntersection), &clearable, SubjectFill, ClipFill); - if(restCArea.m_curves.size() == 0) { + if (restCArea.m_curves.size() == 0) { return {}; } @@ -704,7 +809,8 @@ TopoDS_Shape Area::toTopoShape() } -void Area::setParams(const AreaParams& params) { +void Area::setParams(const AreaParams& params) +{ #define AREA_SRC(_param) params.PARAM_FNAME(_param) // Validate all enum type of parameters PARAM_ENUM_CHECK(AREA_SRC, PARAM_ENUM_EXCEPT, AREA_PARAMS_CONF); @@ -714,44 +820,56 @@ void Area::setParams(const AreaParams& params) { } } -void Area::addToBuild(CArea& area, const TopoDS_Shape& shape) { +void Area::addToBuild(CArea& area, const TopoDS_Shape& shape) +{ if (myParams.Fill == FillAuto && !myHaveFace) { TopExp_Explorer it(shape, TopAbs_FACE); myHaveFace = it.More(); } TopoDS_Shape plane = getPlane(); CArea areaOpen; - mySkippedShapes += addShape(area, shape, &myTrsf, myParams.Deflection, - myParams.Coplanar == CoplanarNone ? nullptr : &plane, - myHaveSolid || myParams.Coplanar == CoplanarForce, &areaOpen, - myParams.OpenMode == OpenModeEdges, myParams.Reorient); + mySkippedShapes += addShape(area, + shape, + &myTrsf, + myParams.Deflection, + myParams.Coplanar == CoplanarNone ? nullptr : &plane, + myHaveSolid || myParams.Coplanar == CoplanarForce, + &areaOpen, + myParams.OpenMode == OpenModeEdges, + myParams.Reorient); if (myProjecting) { // when projecting, we force all wires to be CCW in order to remove // inner holes for (auto& c : area.m_curves) { - if (c.IsClosed() && c.IsClockwise()) + if (c.IsClosed() && c.IsClockwise()) { c.Reverse(); + } } } if (!areaOpen.m_curves.empty()) { - if (&area == myArea.get() || myParams.OpenMode == OpenModeNone) + if (&area == myArea.get() || myParams.OpenMode == OpenModeNone) { myAreaOpen->m_curves.splice(myAreaOpen->m_curves.end(), areaOpen.m_curves); - else + } + else { AREA_WARN("open wires discarded in clipping shapes"); + } } } -static inline void getEndPoints(const TopoDS_Edge& e, gp_Pnt& p1, gp_Pnt& p2) { +static inline void getEndPoints(const TopoDS_Edge& e, gp_Pnt& p1, gp_Pnt& p2) +{ p1 = BRep_Tool::Pnt(TopExp::FirstVertex(e)); p2 = BRep_Tool::Pnt(TopExp::LastVertex(e)); } -static inline void getEndPoints(const TopoDS_Wire& wire, gp_Pnt& p1, gp_Pnt& p2) { +static inline void getEndPoints(const TopoDS_Wire& wire, gp_Pnt& p1, gp_Pnt& p2) +{ BRepTools_WireExplorer xp(wire); p1 = BRep_Tool::Pnt(TopoDS::Vertex(xp.CurrentVertex())); - for (; xp.More(); xp.Next()); + for (; xp.More(); xp.Next()) + ; p2 = BRep_Tool::Pnt(TopoDS::Vertex(xp.CurrentVertex())); } @@ -761,17 +879,20 @@ static inline void getEndPoints(const TopoDS_Wire& wire, gp_Pnt& p1, gp_Pnt& p2) // See https://github.com/realthunder/FreeCAD/blob/LinkStable/src/Mod/Part/App/WireJoiner.h for the // original implementation of the class and https://github.com/FreeCAD/FreeCAD/pull/12535 for the // import conversation. -struct WireJoiner { +struct WireJoiner +{ using Box = bg::model::box; - static bool getBBox(const TopoDS_Edge& e, Box& box) { + static bool getBBox(const TopoDS_Edge& e, Box& box) + { Bnd_Box bound; BRepBndLib::Add(e, bound); bound.SetGap(0.1); if (bound.IsVoid()) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { AREA_WARN("failed to get bound of edge"); + } return false; } Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; @@ -780,31 +901,40 @@ struct WireJoiner { return true; } - struct EdgeInfo { + struct EdgeInfo + { TopoDS_Edge edge; gp_Pnt p1; gp_Pnt p2; Box box; int iteration; - int iStart[2]; // adjacent list index start for p1 and p2 - int iEnd[2]; // adjacent list index end + int iStart[2]; // adjacent list index start for p1 and p2 + int iEnd[2]; // adjacent list index end bool used; bool hasBox; EdgeInfo(const TopoDS_Edge& e, bool bbox) - :edge(e), hasBox(false) + : edge(e) + , hasBox(false) { getEndPoints(e, p1, p2); - if (bbox) hasBox = getBBox(e, box); + if (bbox) { + hasBox = getBBox(e, box); + } reset(); } - EdgeInfo(const TopoDS_Edge& e, const gp_Pnt& pt1, - const gp_Pnt& pt2, bool bbox) - :edge(e), p1(pt1), p2(pt2), hasBox(false) + EdgeInfo(const TopoDS_Edge& e, const gp_Pnt& pt1, const gp_Pnt& pt2, bool bbox) + : edge(e) + , p1(pt1) + , p2(pt2) + , hasBox(false) { - if (bbox) hasBox = getBBox(e, box); + if (bbox) { + hasBox = getBBox(e, box); + } reset(); } - void reset() { + void reset() + { iteration = 0; used = false; iStart[0] = iStart[1] = iEnd[0] = iEnd[1] = -1; @@ -814,19 +944,24 @@ struct WireJoiner { using Edges = std::list; Edges edges; - struct VertexInfo { + struct VertexInfo + { Edges::iterator it; bool start; VertexInfo(Edges::iterator it, bool start) - :it(it), start(start) + : it(it) + , start(start) {} - bool operator==(const VertexInfo& other) const { + bool operator==(const VertexInfo& other) const + { return it == other.it && start == other.start; } - const gp_Pnt& pt() const { + const gp_Pnt& pt() const + { return start ? it->p1 : it->p2; } - const gp_Pnt& ptOther() const { + const gp_Pnt& ptOther() const + { return start ? it->p2 : it->p1; } }; @@ -834,7 +969,8 @@ struct WireJoiner { struct PntGetter { using result_type = const gp_Pnt&; - result_type operator()(const VertexInfo& v) const { + result_type operator()(const VertexInfo& v) const + { return v.pt(); } }; @@ -844,7 +980,8 @@ struct WireJoiner { struct BoxGetter { using result_type = const Box&; - result_type operator()(Edges::iterator it) const { + result_type operator()(Edges::iterator it) const + { return it->box; } }; @@ -853,44 +990,53 @@ struct WireJoiner { BRep_Builder builder; TopoDS_Compound comp; - WireJoiner() { + WireJoiner() + { builder.MakeCompound(comp); } - void remove(Edges::iterator it) { - if (it->hasBox) + void remove(Edges::iterator it) + { + if (it->hasBox) { boxMap.remove(it); + } vmap.remove(VertexInfo(it, true)); vmap.remove(VertexInfo(it, false)); edges.erase(it); } - void add(Edges::iterator it) { + void add(Edges::iterator it) + { vmap.insert(VertexInfo(it, true)); vmap.insert(VertexInfo(it, false)); - if (it->hasBox) + if (it->hasBox) { boxMap.insert(it); + } } - void add(const TopoDS_Edge& e, bool bbox = false) { + void add(const TopoDS_Edge& e, bool bbox = false) + { gp_Pnt p1, p2; getEndPoints(e, p1, p2); edges.emplace_front(e, p1, p2, bbox); add(edges.begin()); } - void add(const TopoDS_Shape& shape, bool bbox = false) { - for (TopExp_Explorer xp(shape, TopAbs_EDGE); xp.More(); xp.Next()) + void add(const TopoDS_Shape& shape, bool bbox = false) + { + for (TopExp_Explorer xp(shape, TopAbs_EDGE); xp.More(); xp.Next()) { add(TopoDS::Edge(xp.Current()), bbox); + } } - //This algorithm tries to join connected edges into wires + // This algorithm tries to join connected edges into wires // - //tol*tol>Precision::SquareConfusion() can be used to join points that are - //close but do not coincide with a line segment. The close points may be - //the results of rounding issue. + // tol*tol>Precision::SquareConfusion() can be used to join points that are + // close but do not coincide with a line segment. The close points may be + // the results of rounding issue. // - void join(double tol) { + void join(double tol) + { tol = tol * tol; while (!edges.empty()) { auto it = edges.begin(); @@ -908,17 +1054,21 @@ struct WireJoiner { vmap.query(bgi::nearest(pt, 1), std::back_inserter(ret)); assert(ret.size() == 1); double d = ret[0].pt().SquareDistance(pt); - if (d > tol) break; + if (d > tol) { + break; + } const auto& info = *ret[0].it; bool start = ret[0].start; if (d > Precision::SquareConfusion()) { // insert a filling edge to solve the tolerance problem const gp_Pnt& pt = ret[idx].pt(); - if (idx) + if (idx) { mkWire.Add(BRepBuilderAPI_MakeEdge(pend, pt).Edge()); - else + } + else { mkWire.Add(BRepBuilderAPI_MakeEdge(pt, pstart).Edge()); + } } if (idx == 1 && start) { @@ -949,7 +1099,8 @@ struct WireJoiner { } // split any edges that are intersected by other edge's end point in the middle - void splitEdges() { + void splitEdges() + { for (auto it = edges.begin(); it != edges.end();) { const auto& info = *it; if (!info.hasBox) { @@ -963,20 +1114,21 @@ struct WireJoiner { bool intersects = false; for (auto vit = boxMap.qbegin(bgi::intersects(info.box)); - !intersects && vit != boxMap.qend(); - ++vit) - { + !intersects && vit != boxMap.qend(); + ++vit) { const auto& other = *(*vit); - if (info.edge.IsSame(other.edge)) continue; + if (info.edge.IsSame(other.edge)) { + continue; + } for (int i = 0; i < 2; ++i) { const gp_Pnt& p = i ? other.p1 : other.p2; - if (pstart.SquareDistance(p) <= Precision::SquareConfusion() || - pend.SquareDistance(p) <= Precision::SquareConfusion()) + if (pstart.SquareDistance(p) <= Precision::SquareConfusion() + || pend.SquareDistance(p) <= Precision::SquareConfusion()) { continue; + } - BRepExtrema_DistShapeShape extss( - BRepBuilderAPI_MakeVertex(p), info.edge); + BRepExtrema_DistShapeShape extss(BRepBuilderAPI_MakeVertex(p), info.edge); if (extss.IsDone() && extss.NbSolution()) { const gp_Pnt& pp = extss.PointOnShape2(1); if (pp.SquareDistance(p) <= Precision::SquareConfusion()) { @@ -985,8 +1137,9 @@ struct WireJoiner { break; } } - else if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + else if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { AREA_WARN("BRepExtrema_DistShapeShape failed"); + } } } @@ -997,8 +1150,8 @@ struct WireJoiner { Standard_Real first, last; Handle_Geom_Curve curve = BRep_Tool::Curve(it->edge, first, last); - bool reversed = pstart.SquareDistance(curve->Value(last)) <= - Precision::SquareConfusion(); + bool reversed = + pstart.SquareDistance(curve->Value(last)) <= Precision::SquareConfusion(); BRepBuilderAPI_MakeEdge mkEdge1, mkEdge2; if (reversed) { @@ -1010,10 +1163,12 @@ struct WireJoiner { mkEdge2.Init(curve, pt, pend); } if (!mkEdge1.IsDone() || !mkEdge2.IsDone()) { - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) - AREA_WARN((reversed ? "reversed " : "") << "edge split failed " << - AREA_XYZ(pstart) << ", " << AREA_XYZ(pt) << ", " << AREA_XYZ(pend) << - ", " << ", err: " << mkEdge1.Error() << ", " << mkEdge2.Error()); + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { + AREA_WARN((reversed ? "reversed " : "") + << "edge split failed " << AREA_XYZ(pstart) << ", " << AREA_XYZ(pt) + << ", " << AREA_XYZ(pend) << ", " << ", err: " << mkEdge1.Error() + << ", " << mkEdge2.Error()); + } ++it; continue; } @@ -1029,7 +1184,8 @@ struct WireJoiner { // This algorithm tries to find a set of closed wires that includes as many // edges (added by calling add() ) as possible. One edge may be included // in more than one closed wires if it connects to more than one edges. - int findClosedWires(double tol = Precision::Confusion()) { + int findClosedWires(double tol = Precision::Confusion()) + { // Note on tolerance: It seems OCC projector sometimes mess up the // tolerance of edges which are supposed to be connected. So use a // lesser precision below, and call makeCleanWire to fix the tolerance @@ -1039,15 +1195,15 @@ struct WireJoiner { int count = 0; int skips = 0; - for (auto& info : edges) + for (auto& info : edges) { info.reset(); + } FC_TIME_INIT(t); int rcount = 0; for (auto& info : edges) { - if (BRep_Tool::IsClosed(info.edge)) - { + if (BRep_Tool::IsClosed(info.edge)) { auto wire = BRepBuilderAPI_MakeWire(info.edge).Wire(); Area::showShape(wire, "closed"); builder.Add(comp, wire); @@ -1058,15 +1214,18 @@ struct WireJoiner { pt[0] = info.p1; pt[1] = info.p2; for (int i = 0; i < 2; ++i) { - if (info.iStart[i] >= 0) + if (info.iStart[i] >= 0) { continue; + } info.iEnd[i] = info.iStart[i] = (int)adjacentList.size(); // populate adjacent list - for (auto vit = vmap.qbegin(bgi::nearest(pt[i], INT_MAX)); vit != vmap.qend(); ++vit) { + for (auto vit = vmap.qbegin(bgi::nearest(pt[i], INT_MAX)); vit != vmap.qend(); + ++vit) { ++rcount; - if (vit->pt().SquareDistance(pt[i]) > tol) + if (vit->pt().SquareDistance(pt[i]) > tol) { break; + } auto& vinfo = *vit; // yes, we push ourself too, because other edges require // this info in the adjacent list. We'll do filtering later. @@ -1089,24 +1248,31 @@ struct WireJoiner { // both ends edgesToVisit.insert(&info); } - else + else { ++skips; + } } FC_TIME_LOG(t, "rtree::nearest (" << rcount << ')'); - struct StackInfo { + struct StackInfo + { size_t iStart; size_t iEnd; size_t iCurrent; - explicit StackInfo(size_t idx) :iStart(idx), iEnd(idx), iCurrent(idx) {} + explicit StackInfo(size_t idx) + : iStart(idx) + , iEnd(idx) + , iCurrent(idx) + {} }; std::vector stack; std::vector vertexStack; for (int iteration = 1; !edgesToVisit.empty(); ++iteration) { EdgeInfo* currentInfo = *edgesToVisit.begin(); - int currentIdx = 1; // used to tell whether search connection from the start(0) or end(1) + int currentIdx = + 1; // used to tell whether search connection from the start(0) or end(1) TopoDS_Edge& e = currentInfo->edge; edgesToVisit.erase(edgesToVisit.begin()); gp_Pnt pstart = currentInfo->p1; @@ -1123,7 +1289,8 @@ struct WireJoiner { auto& r = stack.back(); // this loop is to find all edges connected to pend, and save them into stack.back() - for (int i = currentInfo->iStart[currentIdx]; i < currentInfo->iEnd[currentIdx]; ++i) { + for (int i = currentInfo->iStart[currentIdx]; i < currentInfo->iEnd[currentIdx]; + ++i) { auto& info = *adjacentList[i].it; if (info.iteration != iteration) { info.iteration = iteration; @@ -1146,8 +1313,9 @@ struct WireJoiner { // if no edge left in stack.back(), then pop it, and try again vertexStack.erase(vertexStack.begin() + r.iStart, vertexStack.end()); stack.pop_back(); - if (stack.empty()) + if (stack.empty()) { break; + } ++stack.back().iCurrent; } if (stack.empty()) { @@ -1167,10 +1335,12 @@ struct WireJoiner { for (auto& r : stack) { const auto& v = vertexStack[r.iCurrent]; auto& info = *v.it; - if (v.start) + if (v.start) { wireData->Add(info.edge); - else + } + else { wireData->Add(TopoDS::Edge(info.edge.Reversed())); + } } // TechDraw even uses 0.1 as tolerance. Really? Why? TopoDS_Wire wire = makeCleanWire(wireData, 0.01); @@ -1201,7 +1371,8 @@ struct WireJoiner { //! make a clean wire with sorted, oriented, connected, etc edges // Copied from TechDraw::EdgeWalker - static TopoDS_Wire makeCleanWire(Handle(ShapeExtend_WireData) wireData, double tol) { + static TopoDS_Wire makeCleanWire(Handle(ShapeExtend_WireData) wireData, double tol) + { TopoDS_Wire result; BRepBuilderAPI_MakeWire mkWire; ShapeFix_ShapeTolerance sTol; @@ -1224,43 +1395,55 @@ struct WireJoiner { result = mkWire.Wire(); return result; } - }; -void Area::explode(const TopoDS_Shape& shape) { +void Area::explode(const TopoDS_Shape& shape) +{ const TopoDS_Shape& plane = getPlane(); bool haveShape = false; for (TopExp_Explorer it(shape, TopAbs_FACE); it.More(); it.Next()) { haveShape = true; if (myParams.Coplanar != CoplanarNone && !isCoplanar(it.Current(), plane)) { ++mySkippedShapes; - if (myParams.Coplanar == CoplanarForce) + if (myParams.Coplanar == CoplanarForce) { continue; + } } for (TopExp_Explorer itw(it.Current(), TopAbs_WIRE); itw.More(); itw.Next()) { - for (BRepTools_WireExplorer xp(TopoDS::Wire(itw.Current())); xp.More(); xp.Next()) - addWire(*myArea, BRepBuilderAPI_MakeWire( - TopoDS::Edge(xp.Current())).Wire(), &myTrsf, myParams.Deflection, true); + for (BRepTools_WireExplorer xp(TopoDS::Wire(itw.Current())); xp.More(); xp.Next()) { + addWire(*myArea, + BRepBuilderAPI_MakeWire(TopoDS::Edge(xp.Current())).Wire(), + &myTrsf, + myParams.Deflection, + true); + } } } - if (haveShape) + if (haveShape) { return; + } for (TopExp_Explorer it(shape, TopAbs_EDGE); it.More(); it.Next()) { if (myParams.Coplanar != CoplanarNone && !isCoplanar(it.Current(), plane)) { ++mySkippedShapes; - if (myParams.Coplanar == CoplanarForce) + if (myParams.Coplanar == CoplanarForce) { continue; + } } - addWire(*myArea, BRepBuilderAPI_MakeWire( - TopoDS::Edge(it.Current())).Wire(), &myTrsf, myParams.Deflection, true); + addWire(*myArea, + BRepBuilderAPI_MakeWire(TopoDS::Edge(it.Current())).Wire(), + &myTrsf, + myParams.Deflection, + true); } } -void Area::showShape(const TopoDS_Shape& shape, const char* name, const char* fmt, ...) { +void Area::showShape(const TopoDS_Shape& shape, const char* name, const char* fmt, ...) +{ if (FC_LOG_INSTANCE.level() > FC_LOGLEVEL_TRACE) { App::Document* pcDoc = App::GetApplication().getActiveDocument(); - if (!pcDoc) + if (!pcDoc) { pcDoc = App::GetApplication().newDocument(); + } char buf[256]; if (!name && fmt) { va_list args; @@ -1269,19 +1452,23 @@ void Area::showShape(const TopoDS_Shape& shape, const char* name, const char* fm va_end(args); name = buf; } - Part::Feature* pcFeature = static_cast(pcDoc->addObject("Part::Feature", name)); + Part::Feature* pcFeature = + static_cast(pcDoc->addObject("Part::Feature", name)); pcFeature->Shape.setValue(shape); } } template -static void showShapes(const T& shapes, const char* name, const char* fmt = nullptr, ...) { +static void showShapes(const T& shapes, const char* name, const char* fmt = nullptr, ...) +{ if (FC_LOG_INSTANCE.level() > FC_LOGLEVEL_TRACE) { BRep_Builder builder; TopoDS_Compound comp; builder.MakeCompound(comp); for (auto& s : shapes) { - if (s.IsNull()) continue; + if (s.IsNull()) { + continue; + } builder.Add(comp, s); } char buf[256]; @@ -1298,75 +1485,92 @@ static void showShapes(const T& shapes, const char* name, const char* fmt = null template static int foreachSubshape(const TopoDS_Shape& shape, - Func func, int type = TopAbs_FACE, bool groupOpenEdges = false) + Func func, + int type = TopAbs_FACE, + bool groupOpenEdges = false) { int res = -1; std::vector openShapes; switch (type) { - case TopAbs_SOLID: - for (TopExp_Explorer it(shape, TopAbs_SOLID); it.More(); it.Next()) { - res = TopAbs_SOLID; - func(it.Current(), TopAbs_SOLID); - } - if (res >= 0) break; - //fall through - case TopAbs_FACE: - for (TopExp_Explorer it(shape, TopAbs_FACE); it.More(); it.Next()) { - res = TopAbs_FACE; - func(it.Current(), TopAbs_FACE); - } - if (res >= 0) break; - //fall through - case TopAbs_WIRE: - for (TopExp_Explorer it(shape, TopAbs_WIRE); it.More(); it.Next()) { - res = TopAbs_WIRE; - if (groupOpenEdges && !BRep_Tool::IsClosed(TopoDS::Wire(it.Current()))) - openShapes.push_back(it.Current()); - else - func(it.Current(), TopAbs_WIRE); - } - if (res >= 0) break; - //fall through - default: - for (TopExp_Explorer it(shape, TopAbs_EDGE); it.More(); it.Next()) { - res = TopAbs_EDGE; - if (groupOpenEdges) { - TopoDS_Edge e = TopoDS::Edge(it.Current()); - gp_Pnt p1, p2; - getEndPoints(e, p1, p2); - if (p1.SquareDistance(p2) > Precision::SquareConfusion()) { + case TopAbs_SOLID: + for (TopExp_Explorer it(shape, TopAbs_SOLID); it.More(); it.Next()) { + res = TopAbs_SOLID; + func(it.Current(), TopAbs_SOLID); + } + if (res >= 0) { + break; + } + // fall through + case TopAbs_FACE: + for (TopExp_Explorer it(shape, TopAbs_FACE); it.More(); it.Next()) { + res = TopAbs_FACE; + func(it.Current(), TopAbs_FACE); + } + if (res >= 0) { + break; + } + // fall through + case TopAbs_WIRE: + for (TopExp_Explorer it(shape, TopAbs_WIRE); it.More(); it.Next()) { + res = TopAbs_WIRE; + if (groupOpenEdges && !BRep_Tool::IsClosed(TopoDS::Wire(it.Current()))) { openShapes.push_back(it.Current()); - continue; + } + else { + func(it.Current(), TopAbs_WIRE); } } - func(it.Current(), TopAbs_EDGE); - } + if (res >= 0) { + break; + } + // fall through + default: + for (TopExp_Explorer it(shape, TopAbs_EDGE); it.More(); it.Next()) { + res = TopAbs_EDGE; + if (groupOpenEdges) { + TopoDS_Edge e = TopoDS::Edge(it.Current()); + gp_Pnt p1, p2; + getEndPoints(e, p1, p2); + if (p1.SquareDistance(p2) > Precision::SquareConfusion()) { + openShapes.push_back(it.Current()); + continue; + } + } + func(it.Current(), TopAbs_EDGE); + } } - if (openShapes.empty()) + if (openShapes.empty()) { return res; + } BRep_Builder builder; TopoDS_Compound comp; builder.MakeCompound(comp); - for (auto& s : openShapes) + for (auto& s : openShapes) { builder.Add(comp, s); + } func(comp, TopAbs_COMPOUND); return TopAbs_COMPOUND; } -struct FindPlane { +struct FindPlane +{ TopoDS_Shape& myPlaneShape; gp_Trsf& myTrsf; double& myZ; FindPlane(TopoDS_Shape& s, gp_Trsf& t, double& z) - :myPlaneShape(s), myTrsf(t), myZ(z) + : myPlaneShape(s) + , myTrsf(t) + , myZ(z) {} - void operator()(const TopoDS_Shape& shape, int) { + void operator()(const TopoDS_Shape& shape, int) + { gp_Trsf trsf; gp_Pln pln; - if (!getShapePlane(shape, pln)) + if (!getShapePlane(shape, pln)) { return; + } gp_Ax3 pos = pln.Position(); AREA_TRACE("plane pos " << AREA_XYZ(pos.Location()) << ", " << AREA_XYZ(pos.Direction())); @@ -1383,12 +1587,15 @@ struct FindPlane { bool x0 = fabs(dir.X()) < Precision::Confusion(); bool y0 = fabs(dir.Y()) < Precision::Confusion(); bool z0 = fabs(dir.Z()) < Precision::Confusion(); - if (x0 && y0) + if (x0 && y0) { dir.SetZ(fabs(dir.Z())); - else if (x0 && z0) + } + else if (x0 && z0) { dir.SetY(fabs(dir.Y())); - else if (y0 && z0) + } + else if (y0 && z0) { dir.SetX(fabs(dir.X())); + } pos.SetDirection(dir); trsf.SetTransformation(pos); @@ -1396,16 +1603,17 @@ struct FindPlane { if (x0 && y0) { TopExp_Explorer it(shape, TopAbs_VERTEX); const auto& pt = BRep_Tool::Pnt(TopoDS::Vertex(it.Current())); - if (!myPlaneShape.IsNull() && myZ > pt.Z()) + if (!myPlaneShape.IsNull() && myZ > pt.Z()) { return; + } myZ = pt.Z(); } - else if (!myPlaneShape.IsNull()) + else if (!myPlaneShape.IsNull()) { return; + } myPlaneShape = shape; myTrsf = trsf; - AREA_TRACE("plane pos " << AREA_XYZ(pos.Location()) << - ", " << AREA_XYZ(pos.Direction())); + AREA_TRACE("plane pos " << AREA_XYZ(pos.Location()) << ", " << AREA_XYZ(pos.Direction())); } }; @@ -1418,9 +1626,9 @@ TopoDS_Shape Area::findPlane(const TopoDS_Shape& shape, gp_Trsf& trsf) } int Area::project(TopoDS_Shape& shape_out, - const TopoDS_Shape& shape_in, - const AreaParams* params, - const TopoDS_Shape* work_plane) + const TopoDS_Shape& shape_in, + const AreaParams* params, + const TopoDS_Shape* work_plane) { FC_TIME_INIT2(t, t1); Handle_HLRBRep_Algo brep_hlr; @@ -1440,13 +1648,13 @@ int Area::project(TopoDS_Shape& shape_out, FC_TIME_LOG(t1, "HLRBrep_Algo"); WireJoiner joiner; try { -#define ADD_HLR_SHAPE(_name) \ - shape = hlrToShape._name##Compound();\ - if(!shape.IsNull()){\ - BRepLib::BuildCurves3d(shape);\ - joiner.add(shape,true);\ - showShape(shape,"raw_" #_name);\ - } +#define ADD_HLR_SHAPE(_name) \ + shape = hlrToShape._name##Compound(); \ + if (!shape.IsNull()) { \ + BRepLib::BuildCurves3d(shape); \ + joiner.add(shape, true); \ + showShape(shape, "raw_" #_name); \ + } TopoDS_Shape shape; HLRBRep_HLRToShape hlrToShape(brep_hlr); ADD_HLR_SHAPE(V); @@ -1501,21 +1709,23 @@ int Area::project(TopoDS_Shape& shape_out, return skips; } -std::vector > Area::makeSections( - PARAM_ARGS(PARAM_FARG, AREA_PARAMS_SECTION_EXTRA), - const std::vector& _heights, - const TopoDS_Shape& section_plane) +std::vector> Area::makeSections(PARAM_ARGS(PARAM_FARG, AREA_PARAMS_SECTION_EXTRA), + const std::vector& _heights, + const TopoDS_Shape& section_plane) { TopoDS_Shape plane; gp_Trsf trsf; - if (!section_plane.IsNull()) + if (!section_plane.IsNull()) { plane = findPlane(section_plane, trsf); - else + } + else { plane = getPlane(&trsf); + } - if (plane.IsNull()) + if (plane.IsNull()) { throw Base::ValueError("failed to obtain section plane"); + } FC_TIME_INIT2(t, t1); @@ -1529,41 +1739,48 @@ std::vector > Area::makeSections( bounds.SetGap(0.0); Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); - AREA_TRACE("section bounds X(" << xMin << ',' << xMax << "), Y(" << - yMin << ',' << yMax << "), Z(" << zMin << ',' << zMax << ')'); + AREA_TRACE("section bounds X(" << xMin << ',' << xMax << "), Y(" << yMin << ',' << yMax + << "), Z(" << zMin << ',' << zMax << ')'); std::vector heights; double tolerance = 0.0; if (_heights.empty()) { double z; double d = fabs(myParams.Stepdown); - if (myParams.SectionCount > 1 && d < Precision::Confusion()) + if (myParams.SectionCount > 1 && d < Precision::Confusion()) { throw Base::ValueError("invalid stepdown"); + } if (mode == SectionModeBoundBox) { - if (myParams.Stepdown > 0.0) + if (myParams.Stepdown > 0.0) { z = zMax - myParams.SectionOffset; - else + } + else { z = zMin + myParams.SectionOffset; + } } else if (mode == SectionModeWorkplane) { // Because we've transformed the shapes using the work plane so // that the work plane is aligned with xy0 plane, the starting Z // value shall be 0 minus the given section offset. Note the // section offset is relative to the starting Z - if (myParams.Stepdown > 0.0) + if (myParams.Stepdown > 0.0) { z = -myParams.SectionOffset; - else + } + else { z = myParams.SectionOffset; + } } else { gp_Pnt pt(0, 0, myParams.SectionOffset); z = pt.Transformed(loc).Z(); } - if (z > zMax) + if (z > zMax) { z = zMax; - else if (z < zMin) + } + else if (z < zMin) { z = zMin; + } double dz; if (myParams.Stepdown > 0.0) { dz = z - zMin; @@ -1574,27 +1791,35 @@ std::vector > Area::makeSections( tolerance = -myParams.SectionTolerance; } int count = myParams.SectionCount; - if (count<0 || count * d > dz) + if (count < 0 || count * d > dz) { count = floor(dz / d) + 1; + } heights.reserve(count); for (int i = 0; i < count; ++i, z -= myParams.Stepdown) { double height = z - tolerance; if (z - zMin < myParams.SectionTolerance) { height = zMin + myParams.SectionTolerance; - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { AREA_WARN("hit bottom " << z << ',' << zMin << ',' << height); + } heights.push_back(height); - if (myParams.Stepdown > 0.0) break; + if (myParams.Stepdown > 0.0) { + break; + } } else if (zMax - z < myParams.SectionTolerance) { height = zMax - myParams.SectionTolerance; - if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { AREA_WARN("hit top " << z << ',' << zMax << ',' << height); + } heights.push_back(height); - if (myParams.Stepdown < 0.0) break; + if (myParams.Stepdown < 0.0) { + break; + } } - else + else { heights.push_back(height); + } } } else { @@ -1603,30 +1828,36 @@ std::vector > Area::makeSections( bool hitMax = false, hitMin = false; for (double z : _heights) { switch (mode) { - case SectionModeAbsolute: { - gp_Pnt pt(0, 0, z); - z = pt.Transformed(loc).Z(); - break; - }case SectionModeBoundBox: - z = zMax - z; - break; - case SectionModeWorkplane: - z = -z; - break; - default: - throw Base::ValueError("invalid section mode"); + case SectionModeAbsolute: { + gp_Pnt pt(0, 0, z); + z = pt.Transformed(loc).Z(); + break; + } + case SectionModeBoundBox: + z = zMax - z; + break; + case SectionModeWorkplane: + z = -z; + break; + default: + throw Base::ValueError("invalid section mode"); } if (z - zMin < myParams.SectionTolerance) { - if (hitMin) continue; + if (hitMin) { + continue; + } hitMin = true; double zNew = zMin + myParams.SectionTolerance; - //Silence the warning if _heights is not empty - if (_heights.empty() && FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) + // Silence the warning if _heights is not empty + if (_heights.empty() && FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { AREA_WARN("hit bottom " << z << ',' << zMin << ',' << zNew); + } z = zNew; } else if (zMax - z < myParams.SectionTolerance) { - if (hitMax) continue; + if (hitMax) { + continue; + } double zNew = zMax - myParams.SectionTolerance; AREA_WARN("hit top " << z << ',' << zMax << ',' << zNew); z = zNew; @@ -1635,10 +1866,11 @@ std::vector > Area::makeSections( } } - if (heights.empty()) + if (heights.empty()) { throw Base::ValueError("no sections"); + } - std::vector > sections; + std::vector> sections; sections.reserve(heights.size()); std::list projectedShapes; @@ -1700,24 +1932,30 @@ std::vector > Area::makeSections( Part::FaceMakerBullseye mkFace; mkFace.setPlane(pln); for (const TopoDS_Wire& wire : wires) { - if (BRep_Tool::IsClosed(wire)) + if (BRep_Tool::IsClosed(wire)) { mkFace.addWire(wire); + } } try { mkFace.Build(); const TopoDS_Shape& shape = mkFace.Shape(); - if (shape.IsNull()) + if (shape.IsNull()) { AREA_WARN("FaceMakerBullseye return null shape on section"); + } else { showShape(shape, nullptr, "section_%u_face", i); - for (auto it = wires.begin(), itNext = it; it != wires.end(); it = itNext) { + for (auto it = wires.begin(), itNext = it; it != wires.end(); + it = itNext) { ++itNext; - if (BRep_Tool::IsClosed(*it)) + if (BRep_Tool::IsClosed(*it)) { wires.erase(it); + } } - for (TopExp_Explorer xp(shape, myParams.Fill == FillNone ? TopAbs_WIRE : TopAbs_FACE); - xp.More(); xp.Next()) - { + for (TopExp_Explorer xp(shape, + myParams.Fill == FillNone ? TopAbs_WIRE + : TopAbs_FACE); + xp.More(); + xp.Next()) { builder.Add(comp, xp.Current()); } } @@ -1725,8 +1963,9 @@ std::vector > Area::makeSections( catch (Base::Exception& e) { AREA_WARN("FaceMakerBullseye failed on section: " << e.what()); } - for (const TopoDS_Wire& wire : wires) + for (const TopoDS_Wire& wire : wires) { builder.Add(comp, wire); + } } // Make sure the compound has at least one edge @@ -1737,10 +1976,9 @@ std::vector > Area::makeSections( } else if (area->myShapes.empty()) { auto itNext = it; - if (++itNext != myShapes.end() && - (itNext->op == OperationIntersection || - itNext->op == OperationDifference)) - { + if (++itNext != myShapes.end() + && (itNext->op == OperationIntersection + || itNext->op == OperationDifference)) { break; } } @@ -1766,25 +2004,34 @@ std::vector > Area::makeSections( return sections; } -TopoDS_Shape Area::getPlane(gp_Trsf* trsf) { +TopoDS_Shape Area::getPlane(gp_Trsf* trsf) +{ if (!myWorkPlane.IsNull()) { - if (trsf) *trsf = myTrsf; + if (trsf) { + *trsf = myTrsf; + } return myWorkPlane; } if (myShapePlane.IsNull()) { - if (myShapes.empty()) + if (myShapes.empty()) { throw Base::ValueError("no shape added"); + } double top_z; - for (auto& s : myShapes) + for (auto& s : myShapes) { foreachSubshape(s.shape, FindPlane(myShapePlane, myTrsf, top_z)); - if (myShapePlane.IsNull()) + } + if (myShapePlane.IsNull()) { throw Base::ValueError("shapes are not planar"); + } + } + if (trsf) { + *trsf = myTrsf; } - if (trsf) *trsf = myTrsf; return myShapePlane; } -bool Area::isBuilt() const { +bool Area::isBuilt() const +{ return (myArea || !mySections.empty()); } @@ -1797,28 +2044,33 @@ std::list Area::getProjectedShapes(const gp_Trsf& trsf, bool invers mySkippedShapes = 0; for (auto& s : myShapes) { TopoDS_Shape out; - int skipped = - Area::project(out, s.shape.Moved(loc), &myParams, &myWorkPlane); + int skipped = Area::project(out, s.shape.Moved(loc), &myParams, &myWorkPlane); if (skipped < 0) { ++mySkippedShapes; continue; } - else + else { mySkippedShapes += skipped; - if (!out.IsNull()) + } + if (!out.IsNull()) { ret.emplace_back(s.op, inverse ? out.Moved(locInverse) : out); + } } - if (mySkippedShapes) + if (mySkippedShapes) { AREA_WARN("skipped " << mySkippedShapes << " sub shapes during projection"); + } return ret; } -void Area::build() { - if (isBuilt()) +void Area::build() +{ + if (isBuilt()) { return; + } - if (myShapes.empty()) + if (myShapes.empty()) { throw Base::ValueError("no shape added"); + } PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_CLIPPER_FILL); @@ -1842,7 +2094,8 @@ void Area::build() { short op = OperationUnion; bool pending = false; bool exploding = myParams.Explode; - const auto& shapes = (myParams.Outline && !myProjecting) ? getProjectedShapes(trsf) : myShapes; + const auto& shapes = + (myParams.Outline && !myProjecting) ? getProjectedShapes(trsf) : myShapes; for (const Shape& s : shapes) { if (exploding) { exploding = false; @@ -1850,12 +2103,14 @@ void Area::build() { continue; } else if (op != s.op) { - if (myParams.OpenMode != OpenModeNone) + if (myParams.OpenMode != OpenModeNone) { myArea->m_curves.splice(myArea->m_curves.end(), myAreaOpen->m_curves); + } pending = false; if (!areaClip.m_curves.empty()) { - if (op == OperationCompound) + if (op == OperationCompound) { myArea->m_curves.splice(myArea->m_curves.end(), areaClip.m_curves); + } else { myArea->Clip(toClipperOp(op), &areaClip, SubjectFill, ClipFill); areaClip.m_curves.clear(); @@ -1866,29 +2121,33 @@ void Area::build() { addToBuild(op == OperationUnion ? *myArea : areaClip, s.shape); pending = true; } - if (mySkippedShapes && !myHaveSolid) - AREA_WARN((myParams.Coplanar == CoplanarForce ? "Skipped " : "Found ") << - mySkippedShapes << " non coplanar shapes"); + if (mySkippedShapes && !myHaveSolid) { + AREA_WARN((myParams.Coplanar == CoplanarForce ? "Skipped " : "Found ") + << mySkippedShapes << " non coplanar shapes"); + } if (pending) { - if (myParams.OpenMode != OpenModeNone) + if (myParams.OpenMode != OpenModeNone) { myArea->m_curves.splice(myArea->m_curves.end(), myAreaOpen->m_curves); - if (op == OperationCompound) + } + if (op == OperationCompound) { myArea->m_curves.splice(myArea->m_curves.end(), areaClip.m_curves); + } else { myArea->Clip(toClipperOp(op), &areaClip, SubjectFill, ClipFill); } } myArea->m_curves.splice(myArea->m_curves.end(), myAreaOpen->m_curves); - //Reassemble wires after explode + // Reassemble wires after explode if (myParams.Explode) { WireJoiner joiner; gp_Trsf trsf(myTrsf.Inverted()); for (const auto& c : myArea->m_curves) { auto wire = toShape(c, &trsf); - if (!wire.IsNull()) + if (!wire.IsNull()) { joiner.add(wire); + } } joiner.join(Precision::Confusion()); @@ -1903,19 +2162,17 @@ void Area::build() { if (myParams.Outline) { myArea->Reorder(); - for (auto it = myArea->m_curves.begin(), itNext = it; - it != myArea->m_curves.end(); - it = itNext) - { + for (auto it = myArea->m_curves.begin(), itNext = it; it != myArea->m_curves.end(); + it = itNext) { ++itNext; auto& curve = *it; - if (curve.IsClosed() && curve.IsClockwise()) + if (curve.IsClosed() && curve.IsClockwise()) { myArea->m_curves.erase(it); + } } } FC_TIME_TRACE(t, "prepare"); - } catch (...) { clean(); @@ -1923,18 +2180,19 @@ void Area::build() { } } -TopoDS_Shape Area::toShape(CArea& area, short fill, int reorient) { +TopoDS_Shape Area::toShape(CArea& area, short fill, int reorient) +{ gp_Trsf trsf(myTrsf.Inverted()); bool bFill; switch (fill) { - case Area::FillAuto: - bFill = myHaveFace; - break; - case Area::FillFace: - bFill = true; - break; - default: - bFill = false; + case Area::FillAuto: + bFill = myHaveFace; + break; + case Area::FillFace: + bFill = true; + break; + default: + bFill = false; } if (myParams.FitArcs) { if (&area == myArea.get()) { @@ -1948,36 +2206,41 @@ TopoDS_Shape Area::toShape(CArea& area, short fill, int reorient) { } -#define AREA_SECTION(_op,_index,...) do {\ - if(mySections.size()) {\ - if(_index>=(int)mySections.size())\ - return TopoDS_Shape();\ - if(_index<0) {\ - BRep_Builder builder;\ - TopoDS_Compound compound;\ - builder.MakeCompound(compound);\ - for(shared_ptr area : mySections){\ - const TopoDS_Shape &s = area->_op(_index, ## __VA_ARGS__);\ - if(s.IsNull()) continue;\ - builder.Add(compound,s);\ - }\ - if(TopExp_Explorer(compound,TopAbs_EDGE).More())\ - return TopoDS_Shape(std::move(compound));\ - return TopoDS_Shape();\ - }\ - return mySections[_index]->_op(_index, ## __VA_ARGS__);\ - }\ -}while(0) +#define AREA_SECTION(_op, _index, ...) \ + do { \ + if (mySections.size()) { \ + if (_index >= (int)mySections.size()) \ + return TopoDS_Shape(); \ + if (_index < 0) { \ + BRep_Builder builder; \ + TopoDS_Compound compound; \ + builder.MakeCompound(compound); \ + for (shared_ptr area : mySections) { \ + const TopoDS_Shape& s = area->_op(_index, ##__VA_ARGS__); \ + if (s.IsNull()) \ + continue; \ + builder.Add(compound, s); \ + } \ + if (TopExp_Explorer(compound, TopAbs_EDGE).More()) \ + return TopoDS_Shape(std::move(compound)); \ + return TopoDS_Shape(); \ + } \ + return mySections[_index]->_op(_index, ##__VA_ARGS__); \ + } \ + } while (0) -TopoDS_Shape Area::getShape(int index) { +TopoDS_Shape Area::getShape(int index) +{ build(); AREA_SECTION(getShape, index); - if (myShapeDone) + if (myShapeDone) { return myShape; + } - if (!myArea) + if (!myArea) { return TopoDS_Shape(); + } CAreaConfig conf(myParams); @@ -2003,18 +2266,20 @@ TopoDS_Shape Area::getShape(int index) { FC_TIME_INIT(t); // do offset first, then pocket the inner most offset shape - std::list > areas; + std::list> areas; makeOffset(areas, PARAM_FIELDS(AREA_MY, AREA_PARAMS_OFFSET)); - if (areas.empty()) + if (areas.empty()) { areas.push_back(make_shared(*myArea)); + } Area areaPocket(&myParams); bool front = true; if (areas.size() > 1) { double step = myParams.Stepover; - if (fabs(step) < Precision::Confusion()) + if (fabs(step) < Precision::Confusion()) { step = myParams.Offset; + } front = step > 0; } @@ -2043,16 +2308,18 @@ TopoDS_Shape Area::getShape(int index) { FC_DURATION_PLUS(d, t2); } const TopoDS_Shape& shape = toShape(*area, fill); - if (shape.IsNull()) continue; + if (shape.IsNull()) { + continue; + } builder.Add(compound, shape); } - if (myParams.Thicken) + if (myParams.Thicken) { FC_DURATION_LOG(d, "Thicken"); + } // make sure the compound has at least one edge if (TopExp_Explorer(compound, TopAbs_EDGE).More()) { - builder.Add(compound, areaPocket.makePocket( - -1, PARAM_FIELDS(AREA_MY, AREA_PARAMS_POCKET))); + builder.Add(compound, areaPocket.makePocket(-1, PARAM_FIELDS(AREA_MY, AREA_PARAMS_POCKET))); myShape = compound; } myShapeDone = true; @@ -2060,13 +2327,19 @@ TopoDS_Shape Area::getShape(int index) { return myShape; } -TopoDS_Shape Area::makeOffset(int index, PARAM_ARGS(PARAM_FARG, AREA_PARAMS_OFFSET), - int reorient, bool from_center) +TopoDS_Shape Area::makeOffset(int index, + PARAM_ARGS(PARAM_FARG, AREA_PARAMS_OFFSET), + int reorient, + bool from_center) { build(); - AREA_SECTION(makeOffset, index, PARAM_FIELDS(PARAM_FARG, AREA_PARAMS_OFFSET), reorient, from_center); + AREA_SECTION(makeOffset, + index, + PARAM_FIELDS(PARAM_FARG, AREA_PARAMS_OFFSET), + reorient, + from_center); - std::list > areas; + std::list> areas; makeOffset(areas, PARAM_FIELDS(PARAM_FARG, AREA_PARAMS_OFFSET), from_center); if (areas.empty()) { if (myParams.Thicken && myParams.ToolRadius > Precision::Confusion()) { @@ -2093,40 +2366,49 @@ TopoDS_Shape Area::makeOffset(int index, PARAM_ARGS(PARAM_FARG, AREA_PARAMS_OFFS FC_DURATION_PLUS(d, t); fill = FillFace; } - else if (areas.size() == 1) + else if (areas.size() == 1) { fill = myParams.Fill; - else + } + else { fill = FillNone; + } const TopoDS_Shape& shape = toShape(*area, fill, reorient); - if (shape.IsNull()) continue; + if (shape.IsNull()) { + continue; + } builder.Add(compound, shape); } - if (thicken) + if (thicken) { FC_DURATION_LOG(d, "Thicken"); + } if (TopExp_Explorer(compound, TopAbs_EDGE).More()) { return TopoDS_Shape(std::move(compound)); } return TopoDS_Shape(); } -void Area::makeOffset(list >& areas, - PARAM_ARGS(PARAM_FARG, AREA_PARAMS_OFFSET), bool from_center) +void Area::makeOffset(list>& areas, + PARAM_ARGS(PARAM_FARG, AREA_PARAMS_OFFSET), + bool from_center) { - if (fabs(offset) < Precision::Confusion()) + if (fabs(offset) < Precision::Confusion()) { return; + } FC_TIME_INIT2(t, t1); long count = 1; if (extra_pass) { - if (fabs(stepover) < Precision::Confusion()) + if (fabs(stepover) < Precision::Confusion()) { stepover = offset; + } if (extra_pass > 0) { count += extra_pass; } else { - if (stepover > 0 || offset > 0) + if (stepover > 0 || offset > 0) { throw Base::ValueError("invalid extra count"); + } // In this case, we loop until no outputs from clipper count = -1; } @@ -2140,28 +2422,35 @@ void Area::makeOffset(list >& areas, if (offset < 0) { stepover = -fabs(stepover); if (count < 0) { - if (!last_stepover) + if (!last_stepover) { last_stepover = offset * 0.5; - else + } + else { last_stepover = -fabs(last_stepover); + } } - else + else { last_stepover = 0; + } } for (int i = 0; count < 0 || i < count; ++i, offset += stepover) { - if (from_center) + if (from_center) { areas.push_front(make_shared()); - else + } + else { areas.push_back(make_shared()); + } CArea& area = from_center ? (*areas.front()) : (*areas.back()); CArea areaOpen; #ifdef AREA_OFFSET_ALGO if (myParams.Algo == Area::Algolibarea) { for (const CCurve& c : myArea->m_curves) { - if (c.IsClosed()) + if (c.IsClosed()) { area.append(c); - else + } + else { areaOpen.append(c); + } } } else @@ -2170,33 +2459,40 @@ void Area::makeOffset(list >& areas, #ifdef AREA_OFFSET_ALGO switch (myParams.Algo) { - case Area::Algolibarea: - // libarea somehow fails offset without Reorder, but ClipperOffset - // works okay. Don't know why - area.Reorder(); - area.Offset(-offset); - if (areaOpen.m_curves.size()) { - areaOpen.Thicken(offset); - area.Clip(ClipperLib::ctUnion, &areaOpen, SubjectFill, ClipFill); - } - break; - case Area::AlgoClipperOffset: + case Area::Algolibarea: + // libarea somehow fails offset without Reorder, but ClipperOffset + // works okay. Don't know why + area.Reorder(); + area.Offset(-offset); + if (areaOpen.m_curves.size()) { + areaOpen.Thicken(offset); + area.Clip(ClipperLib::ctUnion, &areaOpen, SubjectFill, ClipFill); + } + break; + case Area::AlgoClipperOffset: #endif - area.OffsetWithClipper(offset, JoinType, EndType, - myParams.MiterLimit, myParams.RoundPrecision); + area.OffsetWithClipper(offset, + JoinType, + EndType, + myParams.MiterLimit, + myParams.RoundPrecision); #ifdef AREA_OFFSET_ALGO - break; + break; } #endif - if (count > 1) + if (count > 1) { FC_TIME_LOG(t1, "makeOffset " << i << '/' << count); + } if (area.m_curves.empty()) { - if (from_center) + if (from_center) { areas.pop_front(); - else + } + else { areas.pop_back(); - if (areas.empty()) + } + if (areas.empty()) { break; + } if (last_stepover && last_stepover > stepover) { offset -= stepover; stepover = last_stepover; @@ -2209,18 +2505,23 @@ void Area::makeOffset(list >& areas, FC_TIME_LOG(t, "makeOffset count: " << count); } -TopoDS_Shape Area::makePocket(int index, PARAM_ARGS(PARAM_FARG, AREA_PARAMS_POCKET)) { - if (tool_radius < Precision::Confusion()) +TopoDS_Shape Area::makePocket(int index, PARAM_ARGS(PARAM_FARG, AREA_PARAMS_POCKET)) +{ + if (tool_radius < Precision::Confusion()) { throw Base::ValueError("tool radius too small"); + } - if (stepover == 0.0) + if (stepover == 0.0) { stepover = tool_radius; + } - if (stepover < Precision::Confusion()) + if (stepover < Precision::Confusion()) { throw Base::ValueError("stepover too small"); + } - if (mode == Area::PocketModeNone) + if (mode == Area::PocketModeNone) { return TopoDS_Shape(); + } build(); AREA_SECTION(makePocket, index, PARAM_FIELDS(PARAM_FARG, AREA_PARAMS_POCKET)); @@ -2229,26 +2530,34 @@ TopoDS_Shape Area::makePocket(int index, PARAM_ARGS(PARAM_FARG, AREA_PARAMS_POCK bool done = false; if (index >= 0) { - if (fabs(angle_shift) >= Precision::Confusion()) + if (fabs(angle_shift) >= Precision::Confusion()) { angle += index * angle_shift; + } - if (fabs(shift) >= Precision::Confusion()) + if (fabs(shift) >= Precision::Confusion()) { shift *= index; + } } - if (angle < -360.0) + if (angle < -360.0) { angle += ceil(fabs(angle) / 360.0) * 360.0; - else if (angle > 360.0) + } + else if (angle > 360.0) { angle -= floor(angle / 360.0) * 360.0; - else if (angle < 0.0) + } + else if (angle < 0.0) { angle += 360.0; + } - if (shift < -stepover) + if (shift < -stepover) { shift += ceil(fabs(shift) / stepover) * stepover; - else if (shift > stepover) + } + else if (shift > stepover) { shift -= floor(shift / stepover) * stepover; - else if (shift < 0.0) + } + else if (shift < 0.0) { shift += stepover; + } CAreaConfig conf(myParams); @@ -2256,86 +2565,98 @@ TopoDS_Shape Area::makePocket(int index, PARAM_ARGS(PARAM_FARG, AREA_PARAMS_POCK PocketMode pm; switch (mode) { - case Area::PocketModeZigZag: - pm = ZigZagPocketMode; - break; - case Area::PocketModeSpiral: - pm = SpiralPocketMode; - break; - case Area::PocketModeOffset: { - PARAM_DECLARE_INIT(PARAM_FNAME, AREA_PARAMS_OFFSET); - Offset = -tool_radius - extra_offset - shift; - ExtraPass = -1; - Stepover = -stepover; - LastStepover = -last_stepover; - // make offset and make sure the loop is CW (i.e. inner wires) - return makeOffset(index, PARAM_FIELDS(PARAM_FNAME, AREA_PARAMS_OFFSET), -1, from_center); - }case Area::PocketModeZigZagOffset: - pm = ZigZagThenSingleOffsetPocketMode; - break; - case Area::PocketModeLine: - case Area::PocketModeGrid: - case Area::PocketModeTriangle: { - CBox2D box; - myArea->GetBox(box); - if (!box.m_valid) - throw Base::ValueError("failed to get bound box"); - double angles[4]; - int count = 1; - angles[0] = 0.0; - if (mode == Area::PocketModeGrid) { - angles[1] = 90.0; - count = 2; - if (shift < Precision::Confusion()) { - count = 4; - angles[2] = 180.0; - angles[3] = 270.0; + case Area::PocketModeZigZag: + pm = ZigZagPocketMode; + break; + case Area::PocketModeSpiral: + pm = SpiralPocketMode; + break; + case Area::PocketModeOffset: { + PARAM_DECLARE_INIT(PARAM_FNAME, AREA_PARAMS_OFFSET); + Offset = -tool_radius - extra_offset - shift; + ExtraPass = -1; + Stepover = -stepover; + LastStepover = -last_stepover; + // make offset and make sure the loop is CW (i.e. inner wires) + return makeOffset(index, + PARAM_FIELDS(PARAM_FNAME, AREA_PARAMS_OFFSET), + -1, + from_center); + } + case Area::PocketModeZigZagOffset: + pm = ZigZagThenSingleOffsetPocketMode; + break; + case Area::PocketModeLine: + case Area::PocketModeGrid: + case Area::PocketModeTriangle: { + CBox2D box; + myArea->GetBox(box); + if (!box.m_valid) { + throw Base::ValueError("failed to get bound box"); } - } - else if (mode == Area::PocketModeTriangle) { - count = 3; - angles[1] = 120; - angles[2] = 240; - } - else - shift = 0.0; //Line pattern does not support shift - Point center(box.Centre()); - double r = box.Radius() + stepover; - if (extra_offset > 0) - r += extra_offset; - int steps = (int)ceil(r * 2.0 / stepover); - for (int i = 0; i < count; ++i) { - double a = angle + angles[i]; - if (a > 360.0) a -= 360.0; - double offset = -r + shift; - for (int j = 0; j < steps; ++j, offset += stepover) { - Point p1(-r, offset), p2(r, offset); - if (a > Precision::Confusion()) { - double r = a * M_PI / 180.0; - p1.Rotate(r); - p2.Rotate(r); + double angles[4]; + int count = 1; + angles[0] = 0.0; + if (mode == Area::PocketModeGrid) { + angles[1] = 90.0; + count = 2; + if (shift < Precision::Confusion()) { + count = 4; + angles[2] = 180.0; + angles[3] = 270.0; } - out.m_curves.emplace_back(); - CCurve& curve = out.m_curves.back(); - curve.m_vertices.emplace_back(p1 + center); - curve.m_vertices.emplace_back(p2 + center); } + else if (mode == Area::PocketModeTriangle) { + count = 3; + angles[1] = 120; + angles[2] = 240; + } + else { + shift = 0.0; // Line pattern does not support shift + } + Point center(box.Centre()); + double r = box.Radius() + stepover; + if (extra_offset > 0) { + r += extra_offset; + } + int steps = (int)ceil(r * 2.0 / stepover); + for (int i = 0; i < count; ++i) { + double a = angle + angles[i]; + if (a > 360.0) { + a -= 360.0; + } + double offset = -r + shift; + for (int j = 0; j < steps; ++j, offset += stepover) { + Point p1(-r, offset), p2(r, offset); + if (a > Precision::Confusion()) { + double r = a * M_PI / 180.0; + p1.Rotate(r); + p2.Rotate(r); + } + out.m_curves.emplace_back(); + CCurve& curve = out.m_curves.back(); + curve.m_vertices.emplace_back(p1 + center); + curve.m_vertices.emplace_back(p2 + center); + } + } + PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_CLIPPER_FILL); + PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_OFFSET_CONF); + auto area = *myArea; + area.OffsetWithClipper(-tool_radius - extra_offset, + JoinType, + EndType, + myParams.MiterLimit, + myParams.RoundPrecision); + out.Clip(toClipperOp(OperationIntersection), &area, SubjectFill, ClipFill); + done = true; + break; } - PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_CLIPPER_FILL); - PARAM_ENUM_CONVERT(AREA_MY, PARAM_FNAME, PARAM_ENUM_EXCEPT, AREA_PARAMS_OFFSET_CONF); - auto area = *myArea; - area.OffsetWithClipper(-tool_radius - extra_offset, JoinType, EndType, - myParams.MiterLimit, myParams.RoundPrecision); - out.Clip(toClipperOp(OperationIntersection), &area, SubjectFill, ClipFill); - done = true; - break; - }default: - throw Base::ValueError("unknown pocket mode"); + default: + throw Base::ValueError("unknown pocket mode"); } if (!done) { - CAreaPocketParams params( - tool_radius, extra_offset, stepover, from_center, pm, angle); + CAreaPocketParams params(tool_radius, extra_offset, stepover, from_center, pm, angle); CArea in(*myArea); // MakePocketToolPath internally uses libarea Offset which somehow demands // reorder before input, otherwise nothing is shown. @@ -2351,29 +2672,31 @@ TopoDS_Shape Area::makePocket(int index, PARAM_ARGS(PARAM_FARG, AREA_PARAMS_POCK FC_TIME_LOG(t, "thicken"); return toShape(out, FillFace); } - else + else { return toShape(out, FillNone); + } } -static inline bool IsLeft(const gp_Pnt& a, const gp_Pnt& b, const gp_Pnt& c) { +static inline bool IsLeft(const gp_Pnt& a, const gp_Pnt& b, const gp_Pnt& c) +{ return ((b.X() - a.X()) * (c.Y() - a.Y()) - (b.Y() - a.Y()) * (c.X() - a.X())) > 0; } -TopoDS_Shape Area::toShape(const CCurve& _c, const gp_Trsf* trsf, int reorient) { +TopoDS_Shape Area::toShape(const CCurve& _c, const gp_Trsf* trsf, int reorient) +{ Handle(TopTools_HSequenceOfShape) hEdges = new TopTools_HSequenceOfShape(); Handle(TopTools_HSequenceOfShape) hWires = new TopTools_HSequenceOfShape(); CCurve cReversed; if (reorient) { - if (_c.IsClosed() && - ((reorient > 0 && _c.IsClockwise()) || - (reorient < 0 && !_c.IsClockwise()))) - { + if (_c.IsClosed() + && ((reorient > 0 && _c.IsClockwise()) || (reorient < 0 && !_c.IsClockwise()))) { cReversed = _c; cReversed.Reverse(); } - else + else { reorient = 0; + } } const CCurve& c = reorient ? cReversed : _c; @@ -2387,8 +2710,9 @@ TopoDS_Shape Area::toShape(const CCurve& _c, const gp_Trsf* trsf, int reorient) continue; } gp_Pnt pnext(v.m_p.x, v.m_p.y, 0); - if (pnext.SquareDistance(pt) <= Precision::SquareConfusion()) + if (pnext.SquareDistance(pt) <= Precision::SquareConfusion()) { continue; + } if (v.m_type == 0) { auto edge = BRepBuilderAPI_MakeEdge(pt, pnext).Edge(); hEdges->Append(edge); @@ -2413,8 +2737,9 @@ TopoDS_Shape Area::toShape(const CCurve& _c, const gp_Trsf* trsf, int reorient) newCenter.SetX(x - dx); newCenter.SetY(y - dy); } - AREA_WARN("Arc correction: " << r << ", " << r2 << ", center" << - AREA_XYZ(center) << "->" << AREA_XYZ(newCenter)); + AREA_WARN("Arc correction: " << r << ", " << r2 << ", center" + << AREA_XYZ(center) << "->" + << AREA_XYZ(newCenter)); center = newCenter; } gp_Ax2 axis(center, gp_Dir(0, 0, v.m_type)); @@ -2438,50 +2763,62 @@ TopoDS_Shape Area::toShape(const CCurve& _c, const gp_Trsf* trsf, int reorient) pt = pnext; } - ShapeAnalysis_FreeBounds::ConnectEdgesToWires( - hEdges, Precision::Confusion(), Standard_False, hWires); - if (!hWires->Length()) + ShapeAnalysis_FreeBounds::ConnectEdgesToWires(hEdges, + Precision::Confusion(), + Standard_False, + hWires); + if (!hWires->Length()) { return shape; - if (hWires->Length() == 1) + } + if (hWires->Length() == 1) { shape = hWires->Value(1); + } else { BRep_Builder builder; TopoDS_Compound compound; builder.MakeCompound(compound); - for (int i = 1; i <= hWires->Length(); ++i) + for (int i = 1; i <= hWires->Length(); ++i) { builder.Add(compound, hWires->Value(i)); + } shape = compound; } - if (trsf) + if (trsf) { shape.Move(TopLoc_Location(*trsf)); + } return shape; } -TopoDS_Shape Area::toShape(const CArea& area, bool fill, const gp_Trsf* trsf, int reorient) { +TopoDS_Shape Area::toShape(const CArea& area, bool fill, const gp_Trsf* trsf, int reorient) +{ BRep_Builder builder; TopoDS_Compound compound; builder.MakeCompound(compound); for (const CCurve& c : area.m_curves) { const auto& wire = toShape(c, trsf, reorient); - if (!wire.IsNull()) + if (!wire.IsNull()) { builder.Add(compound, wire); + } } TopExp_Explorer xp(compound, TopAbs_EDGE); - if (!xp.More()) + if (!xp.More()) { return TopoDS_Shape(); + } if (fill) { try { FC_TIME_INIT(t); Part::FaceMakerBullseye mkFace; - if (trsf) + if (trsf) { mkFace.setPlane(gp_Pln().Transformed(*trsf)); - for (TopExp_Explorer it(compound, TopAbs_WIRE); it.More(); it.Next()) + } + for (TopExp_Explorer it(compound, TopAbs_WIRE); it.More(); it.Next()) { mkFace.addWire(TopoDS::Wire(it.Current())); + } mkFace.Build(); - if (mkFace.Shape().IsNull()) + if (mkFace.Shape().IsNull()) { AREA_WARN("FaceMakerBullseye returns null shape"); + } FC_TIME_LOG(t, "makeFace"); return mkFace.Shape(); } @@ -2492,16 +2829,19 @@ TopoDS_Shape Area::toShape(const CArea& area, bool fill, const gp_Trsf* trsf, in return TopoDS_Shape(std::move(compound)); } -struct WireInfo { +struct WireInfo +{ TopoDS_Wire wire; std::deque points; gp_Pnt pt_end; bool isClosed; - inline const gp_Pnt& pstart() const { + inline const gp_Pnt& pstart() const + { return points.front(); } - inline const gp_Pnt& pend() const { + inline const gp_Pnt& pend() const + { return isClosed ? pstart() : pt_end; } }; @@ -2512,51 +2852,66 @@ using RValue = std::pair; struct RGetter { using result_type = const gp_Pnt&; - result_type operator()(const RValue& v) const { return v.first->points[v.second]; } + result_type operator()(const RValue& v) const + { + return v.first->points[v.second]; + } }; using RTree = bgi::rtree; -struct ShapeParams { +struct ShapeParams +{ double abscissa; int k; short orientation; short direction; - FC_DURATION_DECLARE(qd); //rtree query duration - FC_DURATION_DECLARE(bd); //rtree build duration - FC_DURATION_DECLARE(rd); //rtree remove duration - FC_DURATION_DECLARE(xd); //BRepExtrema_DistShapeShape duration + FC_DURATION_DECLARE(qd); // rtree query duration + FC_DURATION_DECLARE(bd); // rtree build duration + FC_DURATION_DECLARE(rd); // rtree remove duration + FC_DURATION_DECLARE(xd); // BRepExtrema_DistShapeShape duration ShapeParams(double _a, int _k, short o, short d) - :abscissa(_a), k(_k), orientation(o), direction(d) + : abscissa(_a) + , k(_k) + , orientation(o) + , direction(d) { FC_DURATION_INIT3(qd, bd, rd); FC_DURATION_INIT(xd); } }; -bool operator<(const Wires::iterator& a, const Wires::iterator& b) { +bool operator<(const Wires::iterator& a, const Wires::iterator& b) +{ return &(*a) < &(*b); } using RResults = std::map; -struct GetWires { +struct GetWires +{ Wires& wires; RTree& rtree; ShapeParams& params; GetWires(std::list& ws, RTree& rt, ShapeParams& rp) - :wires(ws), rtree(rt), params(rp) + : wires(ws) + , rtree(rt) + , params(rp) {} - void operator()(const TopoDS_Shape& shape, int type) { + void operator()(const TopoDS_Shape& shape, int type) + { wires.emplace_back(); WireInfo& info = wires.back(); - if (type == TopAbs_WIRE) + if (type == TopAbs_WIRE) { info.wire = TopoDS::Wire(shape); - else + } + else { info.wire = BRepBuilderAPI_MakeWire(TopoDS::Edge(shape)).Wire(); + } info.isClosed = BRep_Tool::IsClosed(info.wire); - if (info.isClosed && params.orientation == Area::OrientationReversed) + if (info.isClosed && params.orientation == Area::OrientationReversed) { info.wire.Reverse(); + } FC_TIME_INIT(t); if (params.abscissa < Precision::Confusion() || !info.isClosed) { @@ -2565,24 +2920,24 @@ struct GetWires { if (!info.isClosed && params.direction != Area::DirectionNone) { bool reverse = false; switch (params.direction) { - case Area::DirectionXPositive: - reverse = p1.X() > p2.X(); - break; - case Area::DirectionXNegative: - reverse = p1.X() < p2.X(); - break; - case Area::DirectionYPositive: - reverse = p1.Y() > p2.Y(); - break; - case Area::DirectionYNegative: - reverse = p1.Y() < p2.Y(); - break; - case Area::DirectionZPositive: - reverse = p1.Z() > p2.Z(); - break; - case Area::DirectionZNegative: - reverse = p1.Z() < p2.Z(); - break; + case Area::DirectionXPositive: + reverse = p1.X() > p2.X(); + break; + case Area::DirectionXNegative: + reverse = p1.X() < p2.X(); + break; + case Area::DirectionYPositive: + reverse = p1.Y() > p2.Y(); + break; + case Area::DirectionYNegative: + reverse = p1.Y() < p2.Y(); + break; + case Area::DirectionZPositive: + reverse = p1.Z() > p2.Z(); + break; + case Area::DirectionZNegative: + reverse = p1.Z() < p2.Z(); + break; } if (reverse) { info.wire.Reverse(); @@ -2592,8 +2947,9 @@ struct GetWires { // We don't add in-between vertices of an open wire, because we // haven't implemented open wire breaking yet. info.points.push_back(p1); - if (!info.isClosed && params.direction == Area::DirectionNone) + if (!info.isClosed && params.direction == Area::DirectionNone) { info.points.push_back(p2); + } info.pt_end = p2; } else { @@ -2606,8 +2962,10 @@ struct GetWires { info.points.push_back(BRep_Tool::Pnt(xp.CurrentVertex())); BRepAdaptor_Curve curve(xp.Current()); - GCPnts_UniformAbscissa discretizer(curve, params.abscissa, - curve.FirstParameter(), curve.LastParameter()); + GCPnts_UniformAbscissa discretizer(curve, + params.abscissa, + curve.FirstParameter(), + curve.LastParameter()); if (discretizer.IsDone()) { int nbPoints = discretizer.NbPoints(); // OCC discretizer uses one-based index, so index one is @@ -2616,24 +2974,28 @@ struct GetWires { // exclude the head and tail points, which is convenient // since we don't need to check the orientation of the // edge. - for (int i = 2; i < nbPoints; i++) + for (int i = 2; i < nbPoints; i++) { info.points.push_back(curve.Value(discretizer.Parameter(i))); + } } - else + else { AREA_WARN("discretizer failed"); + } } // no need to push the final tail point, since it's a closed wire // info.points.push_back(BRep_Tool::Pnt(xp.CurrentVertex())); } auto it = wires.end(); --it; - for (size_t i = 0, count = it->points.size(); i < count; ++i) + for (size_t i = 0, count = it->points.size(); i < count; ++i) { rtree.insert(RValue(it, i)); + } FC_DURATION_PLUS(params.bd, t); } }; -struct ShapeInfo { +struct ShapeInfo +{ gp_Pln myPln; Wires myWires; RTree myRTree; @@ -2671,11 +3033,13 @@ struct ShapeInfo { , myRebase(false) , myStart(false) {} - double nearest(const gp_Pnt& pt) { + double nearest(const gp_Pnt& pt) + { myStartPt = pt; - if (myWires.empty()) + if (myWires.empty()) { foreachSubshape(myShape, GetWires(myWires, myRTree, myParams), TopAbs_WIRE); + } // Now find the true nearest point among the wires returned. Currently // only closed wire has a true nearest point, using OCC's @@ -2712,12 +3076,14 @@ struct ShapeInfo { p = extss.PointOnShape2(1); support = extss.SupportOnShape2(1); support_edge = extss.SupportTypeShape2(1) == BRepExtrema_IsOnEdge; - if (support_edge) + if (support_edge) { extss.ParOnEdgeS2(1, myBestParameter); + } done = true; } - else + else { AREA_WARN("BRepExtrema_DistShapeShape failed"); + } FC_DURATION_PLUS(myParams.xd, t); } if (!done) { @@ -2741,7 +3107,9 @@ struct ShapeInfo { } } } - if (!first && d >= best_d) continue; + if (!first && d >= best_d) { + continue; + } first = false; myBestPt = p; myBestWire = it; @@ -2756,9 +3124,10 @@ struct ShapeInfo { return best_d; } - //Assumes nearest() has been called. Rebased the best wire - //to begin with the best point. Currently only works with closed wire - TopoDS_Shape rebaseWire(gp_Pnt& pend, double min_dist) { + // Assumes nearest() has been called. Rebased the best wire + // to begin with the best point. Currently only works with closed wire + TopoDS_Shape rebaseWire(gp_Pnt& pend, double min_dist) + { min_dist *= min_dist; BRepBuilderAPI_MakeWire mkWire; TopoDS_Shape estart; @@ -2768,9 +3137,9 @@ struct ShapeInfo { BRepTools_WireExplorer xp(TopoDS::Wire(myBestWire->wire)); gp_Pnt pprev(BRep_Tool::Pnt(xp.CurrentVertex())); - //checking the case of bestpoint == wire start - if (state == 0 && !mySupportEdge && - pprev.SquareDistance(myBestPt) <= Precision::SquareConfusion()) { + // checking the case of bestpoint == wire start + if (state == 0 && !mySupportEdge + && pprev.SquareDistance(myBestPt) <= Precision::SquareConfusion()) { pend = myBestWire->pend(); return myBestWire->wire; } @@ -2779,10 +3148,11 @@ struct ShapeInfo { for (; xp.More(); xp.Next(), pprev = pt) { const auto& edge = xp.Current(); - //state==2 means we are in second pass. estart marks the new - //start of the wire. so seeing estart means we're done - if (state == 2 && estart.IsEqual(edge)) + // state==2 means we are in second pass. estart marks the new + // start of the wire. so seeing estart means we're done + if (state == 2 && estart.IsEqual(edge)) { break; + } // Edge split not working if using BRepAdaptor_Curve. // BRepBuilderAPI_MakeEdge always fails with @@ -2796,20 +3166,21 @@ struct ShapeInfo { reversed = true; pt = curve->Value(first); } - else + else { reversed = false; + } - //state!=0 means we've found the new start of wire, now just - //keep adding new edges + // state!=0 means we've found the new start of wire, now just + // keep adding new edges if (state) { mkWire.Add(edge); continue; } - //state==0 means we are looking for the new start + // state==0 means we are looking for the new start if (mySupportEdge) { - //if best point is on some edge, split the edge in half + // if best point is on some edge, split the edge in half if (edge.IsEqual(mySupport)) { - //to fix PointProjectionFailed. + // to fix PointProjectionFailed. GeomAPI_ProjectPointOnCurve gpp; gpp.Init(myBestPt, curve); gpp.Perform(myBestPt); @@ -2834,7 +3205,7 @@ struct ShapeInfo { mkEdge1.Init(curve, pprev, myBestPt); mkEdge2.Init(curve, myBestPt, pt); } - + if (mkEdge1.IsDone() && mkEdge2.IsDone()) { if (reversed) { eend = TopoDS::Edge(mkEdge1.Edge().Reversed()); @@ -2849,9 +3220,11 @@ struct ShapeInfo { state = 1; continue; } - AREA_WARN((reversed ? "reversed " : "") << "edge split failed " << AREA_XYZ(pprev) << ", " << - AREA_XYZ(myBestPt) << ", " << AREA_XYZ(pt) << ", " << d1 << ", " << d2 << ", err: " << - mkEdge1.Error() << ", " << mkEdge2.Error()); + AREA_WARN((reversed ? "reversed " : "") + << "edge split failed " << AREA_XYZ(pprev) << ", " + << AREA_XYZ(myBestPt) << ", " << AREA_XYZ(pt) << ", " << d1 + << ", " << d2 << ", err: " << mkEdge1.Error() << ", " + << mkEdge2.Error()); } if (d1 < d2) { @@ -2881,32 +3254,37 @@ struct ShapeInfo { return myBestWire->wire; } } - if (!eend.IsNull()) + if (!eend.IsNull()) { mkWire.Add(eend); - if (mkWire.IsDone()) + } + if (mkWire.IsDone()) { return mkWire.Wire(); + } AREA_WARN("wire rebase failed"); pend = myBestWire->pend(); return myBestWire->wire; } - std::list sortWires(const gp_Pnt& pstart, gp_Pnt& pend, - double min_dist, double max_dist, gp_Pnt* pentry) { + std::list + sortWires(const gp_Pnt& pstart, gp_Pnt& pend, double min_dist, double max_dist, gp_Pnt* pentry) + { std::list wires; - if (myWires.empty() || - pstart.SquareDistance(myStartPt) > Precision::SquareConfusion()) - { + if (myWires.empty() || pstart.SquareDistance(myStartPt) > Precision::SquareConfusion()) { nearest(pstart); - if (myWires.empty()) + if (myWires.empty()) { return wires; + } } - if (pentry) *pentry = myBestPt; + if (pentry) { + *pentry = myBestPt; + } - if (min_dist < 0.01) + if (min_dist < 0.01) { min_dist = 0.01; + } while (true) { if (myRebase) { pend = myBestPt; @@ -2921,48 +3299,61 @@ struct ShapeInfo { pend = myBestWire->pend(); } FC_TIME_INIT(t); - for (size_t i = 0, count = myBestWire->points.size(); i < count; ++i) + for (size_t i = 0, count = myBestWire->points.size(); i < count; ++i) { myRTree.remove(RValue(myBestWire, i)); + } FC_DURATION_PLUS(myParams.rd, t); myWires.erase(myBestWire); - if (myWires.empty()) break; - double d = nearest(pend); - if (max_dist > 0 && d > max_dist) + if (myWires.empty()) { break; + } + double d = nearest(pend); + if (max_dist > 0 && d > max_dist) { + break; + } } return wires; } }; -struct ShapeInfoBuilder { +struct ShapeInfoBuilder +{ std::list& myList; gp_Trsf& myTrsf; short& myArcPlane; bool& myArcPlaneFound; ShapeParams& myParams; - ShapeInfoBuilder(bool& plane_found, short& arc_plane, gp_Trsf& trsf, - std::list& list, ShapeParams& params) - :myList(list), myTrsf(trsf), myArcPlane(arc_plane) - , myArcPlaneFound(plane_found), myParams(params) + ShapeInfoBuilder(bool& plane_found, + short& arc_plane, + gp_Trsf& trsf, + std::list& list, + ShapeParams& params) + : myList(list) + , myTrsf(trsf) + , myArcPlane(arc_plane) + , myArcPlaneFound(plane_found) + , myParams(params) {} - void operator()(const TopoDS_Shape& shape, int type) { + void operator()(const TopoDS_Shape& shape, int type) + { gp_Pln pln; if (!getShapePlane(shape, pln)) { myList.emplace_back(shape, myParams); return; } myList.emplace_back(pln, shape, myParams); - if (myArcPlaneFound || - myArcPlane == Area::ArcPlaneNone || - myArcPlane == Area::ArcPlaneVariable) + if (myArcPlaneFound || myArcPlane == Area::ArcPlaneNone + || myArcPlane == Area::ArcPlaneVariable) { return; + } if (type == TopAbs_EDGE) { BRepAdaptor_Curve curve(TopoDS::Edge(shape)); - if (curve.GetType() != GeomAbs_Circle) + if (curve.GetType() != GeomAbs_Circle) { return; + } } else { bool found = false; @@ -2973,63 +3364,66 @@ struct ShapeInfoBuilder { break; } } - if (!found) + if (!found) { return; + } } gp_Ax3 pos = myList.back().myPln.Position(); - if (!pos.Direct()) pos = gp_Ax3(pos.Ax2()); + if (!pos.Direct()) { + pos = gp_Ax3(pos.Ax2()); + } const gp_Dir& dir = pos.Direction(); gp_Ax3 dstPos; bool x0 = fabs(dir.X()) <= Precision::Confusion(); bool y0 = fabs(dir.Y()) <= Precision::Confusion(); bool z0 = fabs(dir.Z()) <= Precision::Confusion(); switch (myArcPlane) { - case Area::ArcPlaneAuto: { - if (x0 && y0) { - AREA_TRACE("found arc plane XY"); - myArcPlane = Area::ArcPlaneXY; + case Area::ArcPlaneAuto: { + if (x0 && y0) { + AREA_TRACE("found arc plane XY"); + myArcPlane = Area::ArcPlaneXY; + } + else if (x0 && z0) { + AREA_TRACE("found arc plane ZX"); + myArcPlane = Area::ArcPlaneZX; + } + else if (z0 && y0) { + AREA_TRACE("found arc plane YZ"); + myArcPlane = Area::ArcPlaneYZ; + } + else { + myArcPlane = Area::ArcPlaneXY; + dstPos = gp_Ax3(pos.Location(), gp_Dir(0, 0, 1)); + break; + } + myArcPlaneFound = true; + return; } - else if (x0 && z0) { - AREA_TRACE("found arc plane ZX"); - myArcPlane = Area::ArcPlaneZX; - } - else if (z0 && y0) { - AREA_TRACE("found arc plane YZ"); - myArcPlane = Area::ArcPlaneYZ; - } - else { - myArcPlane = Area::ArcPlaneXY; + case Area::ArcPlaneXY: + if (x0 && y0) { + myArcPlaneFound = true; + return; + } dstPos = gp_Ax3(pos.Location(), gp_Dir(0, 0, 1)); break; - } - myArcPlaneFound = true; - return; - }case Area::ArcPlaneXY: - if (x0 && y0) { - myArcPlaneFound = true; + case Area::ArcPlaneZX: + if (x0 && z0) { + myArcPlaneFound = true; + return; + } + dstPos = gp_Ax3(pos.Location(), gp_Dir(0, 1, 0)); + break; + case Area::ArcPlaneYZ: + if (z0 && y0) { + myArcPlaneFound = true; + return; + } + dstPos = gp_Ax3(pos.Location(), gp_Dir(1, 0, 0)); + break; + default: return; - } - dstPos = gp_Ax3(pos.Location(), gp_Dir(0, 0, 1)); - break; - case Area::ArcPlaneZX: - if (x0 && z0) { - myArcPlaneFound = true; - return; - } - dstPos = gp_Ax3(pos.Location(), gp_Dir(0, 1, 0)); - break; - case Area::ArcPlaneYZ: - if (z0 && y0) { - myArcPlaneFound = true; - return; - } - dstPos = gp_Ax3(pos.Location(), gp_Dir(1, 0, 0)); - break; - default: - return; } - AREA_WARN("force arc plane " << AREA_XYZ(dir) << - " to " << AREA_XYZ(dstPos.Direction())); + AREA_WARN("force arc plane " << AREA_XYZ(dir) << " to " << AREA_XYZ(dstPos.Direction())); myTrsf.SetTransformation(pos); gp_Trsf trsf; trsf.SetTransformation(dstPos); @@ -3038,89 +3432,103 @@ struct ShapeInfoBuilder { } }; -struct WireOrienter { +struct WireOrienter +{ std::list& wires; const gp_Dir& dir; short orientation; short direction; WireOrienter(std::list& ws, const gp_Dir& dir, short o, short d) - :wires(ws), dir(dir), orientation(o), direction(d) + : wires(ws) + , dir(dir) + , orientation(o) + , direction(d) {} - void operator()(const TopoDS_Shape& shape, int type) { - if (type == TopAbs_WIRE) + void operator()(const TopoDS_Shape& shape, int type) + { + if (type == TopAbs_WIRE) { wires.push_back(shape); - else + } + else { wires.push_back(BRepBuilderAPI_MakeWire(TopoDS::Edge(shape)).Wire()); + } TopoDS_Shape& wire = wires.back(); if (BRep_Tool::IsClosed(wire)) { - if (orientation == Area::OrientationReversed) + if (orientation == Area::OrientationReversed) { wire.Reverse(); + } } else if (direction != Area::DirectionNone) { gp_Pnt p1, p2; getEndPoints(TopoDS::Wire(wire), p1, p2); bool reverse = false; switch (direction) { - case Area::DirectionXPositive: - reverse = p1.X() > p2.X(); - break; - case Area::DirectionXNegative: - reverse = p1.X() < p2.X(); - break; - case Area::DirectionYPositive: - reverse = p1.Y() > p2.Y(); - break; - case Area::DirectionYNegative: - reverse = p1.Y() < p2.Y(); - break; - case Area::DirectionZPositive: - reverse = p1.Z() > p2.Z(); - break; - case Area::DirectionZNegative: - reverse = p1.Z() < p2.Z(); - break; + case Area::DirectionXPositive: + reverse = p1.X() > p2.X(); + break; + case Area::DirectionXNegative: + reverse = p1.X() < p2.X(); + break; + case Area::DirectionYPositive: + reverse = p1.Y() > p2.Y(); + break; + case Area::DirectionYNegative: + reverse = p1.Y() < p2.Y(); + break; + case Area::DirectionZPositive: + reverse = p1.Z() > p2.Z(); + break; + case Area::DirectionZNegative: + reverse = p1.Z() < p2.Z(); + break; } - if (reverse) + if (reverse) { wire.Reverse(); + } } } }; -typedef Standard_Real(gp_Pnt::* AxisGetter)() const; -typedef void (gp_Pnt::* AxisSetter)(Standard_Real); +typedef Standard_Real (gp_Pnt::*AxisGetter)() const; +typedef void (gp_Pnt::*AxisSetter)(Standard_Real); std::list Area::sortWires(const std::list& shapes, - bool has_start, gp_Pnt* _pstart, gp_Pnt* _pend, - double* stepdown_hint, short* _parc_plane, - PARAM_ARGS(PARAM_FARG, AREA_PARAMS_SORT)) + bool has_start, + gp_Pnt* _pstart, + gp_Pnt* _pend, + double* stepdown_hint, + short* _parc_plane, + PARAM_ARGS(PARAM_FARG, AREA_PARAMS_SORT)) { std::list wires; - if (shapes.empty()) + if (shapes.empty()) { return wires; + } AxisGetter getter; AxisSetter setter; switch (retract_axis) { - case RetractAxisX: - getter = &gp_Pnt::X; - setter = &gp_Pnt::SetX; - break; - case RetractAxisY: - getter = &gp_Pnt::Y; - setter = &gp_Pnt::SetY; - break; - default: - getter = &gp_Pnt::Z; - setter = &gp_Pnt::SetZ; + case RetractAxisX: + getter = &gp_Pnt::X; + setter = &gp_Pnt::SetX; + break; + case RetractAxisY: + getter = &gp_Pnt::Y; + setter = &gp_Pnt::SetY; + break; + default: + getter = &gp_Pnt::Z; + setter = &gp_Pnt::SetZ; } if (sort_mode == SortModeGreedy && threshold < Precision::Confusion()) { - AREA_WARN("Sort mode 'Greedy' requires a threshold value (suggestion: use the tool diameter)"); + AREA_WARN( + "Sort mode 'Greedy' requires a threshold value (suggestion: use the tool diameter)"); sort_mode = SortMode2D5; } @@ -3130,23 +3538,26 @@ std::list Area::sortWires(const std::list& shapes, if (sort_mode == SortModeNone) { gp_Dir dir; switch (arc_plane) { - case ArcPlaneYZ: - dir = gp_Dir(1, 0, 0); - break; - case ArcPlaneZX: - dir = gp_Dir(0, 1, 0); - break; - default: - if (arc_plane != ArcPlaneXY) - AREA_WARN("Sort mode 'None' without a given arc plane, using XY plane"); - arc_plane = ArcPlaneXY; - dir = gp_Dir(0, 0, 1); - break; + case ArcPlaneYZ: + dir = gp_Dir(1, 0, 0); + break; + case ArcPlaneZX: + dir = gp_Dir(0, 1, 0); + break; + default: + if (arc_plane != ArcPlaneXY) { + AREA_WARN("Sort mode 'None' without a given arc plane, using XY plane"); + } + arc_plane = ArcPlaneXY; + dir = gp_Dir(0, 0, 1); + break; } for (auto& shape : shapes) { - if (!shape.IsNull()) + if (!shape.IsNull()) { foreachSubshape(shape, - WireOrienter(wires, dir, orientation, direction), TopAbs_WIRE); + WireOrienter(wires, dir, orientation, direction), + TopAbs_WIRE); + } } return wires; } @@ -3164,40 +3575,49 @@ std::list Area::sortWires(const std::list& shapes, TopoDS_Compound comp; builder.MakeCompound(comp); for (auto& shape : shapes) { - if (!shape.IsNull()) + if (!shape.IsNull()) { builder.Add(comp, shape); + } } TopExp_Explorer xp(comp, TopAbs_EDGE); - if (xp.More()) + if (xp.More()) { shape_list.emplace_back(comp, rparams); + } } else { - //first pass, find plane of each shape + // first pass, find plane of each shape for (auto& shape : shapes) { - //explode the shape + // explode the shape if (!shape.IsNull()) { - foreachSubshape(shape, ShapeInfoBuilder( - arcPlaneFound, arc_plane, trsf, shape_list, rparams), TopAbs_FACE, true); + foreachSubshape( + shape, + ShapeInfoBuilder(arcPlaneFound, arc_plane, trsf, shape_list, rparams), + TopAbs_FACE, + true); } } FC_TIME_LOG(t1, "plane finding"); } - if (shape_list.empty()) + if (shape_list.empty()) { return wires; + } Bnd_Box bounds; gp_Pnt pstart, pend; - if (_pstart) + if (_pstart) { pstart = *_pstart; + } bool use_bound = !has_start || !_pstart; - //Second stage, group shape by its plane, and find overall boundary + // Second stage, group shape by its plane, and find overall boundary for (auto& info : shape_list) { if (arcPlaneFound) { info.myShape.Move(trsf); - if (info.myPlanar) info.myPln.Transform(trsf); + if (info.myPlanar) { + info.myPln.Transform(trsf); + } } BRepBndLib::Add(info.myShape, bounds, Standard_False); @@ -3207,18 +3627,25 @@ std::list Area::sortWires(const std::list& shapes, for (auto itNext = shape_list.begin(), it = itNext; it != shape_list.end(); it = itNext) { ++itNext; - if (!it->myPlanar) continue; + if (!it->myPlanar) { + continue; + } TopoDS_Builder builder; TopoDS_Compound comp; builder.MakeCompound(comp); bool empty = true; - for (auto itNext3 = itNext, itNext2 = itNext; itNext2 != shape_list.end(); itNext2 = itNext3) { + for (auto itNext3 = itNext, itNext2 = itNext; itNext2 != shape_list.end(); + itNext2 = itNext3) { ++itNext3; - if (!itNext2->myPlanar || - !it->myPln.Position().IsCoplanar(itNext2->myPln.Position(), - Precision::Confusion(), Precision::Confusion())) + if (!itNext2->myPlanar + || !it->myPln.Position().IsCoplanar(itNext2->myPln.Position(), + Precision::Confusion(), + Precision::Confusion())) { continue; - if (itNext == itNext2) ++itNext; + } + if (itNext == itNext2) { + ++itNext; + } builder.Add(comp, itNext2->myShape); shape_list.erase(itNext2); empty = false; @@ -3234,31 +3661,35 @@ std::list Area::sortWires(const std::list& shapes, bounds.SetGap(0.0); Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); - AREA_TRACE("bound (" << xMin << ", " << xMax << "), (" << - yMin << ", " << yMax << "), (" << zMin << ", " << zMax << ')'); + AREA_TRACE("bound (" << xMin << ", " << xMax << "), (" << yMin << ", " << yMax << "), (" << zMin + << ", " << zMax << ')'); if (use_bound) { pstart.SetCoord(xMax, yMax, zMax); - if (_pstart) *_pstart = pstart; + if (_pstart) { + *_pstart = pstart; + } } else { switch (retract_axis) { - case RetractAxisX: - if (pstart.X() < xMax) { - pstart.SetX(xMax); - } - break; - case RetractAxisY: - if (pstart.Y() < yMax) { - pstart.SetY(yMax); - } - break; - default: - if (pstart.Z() < zMax) { - pstart.SetZ(zMax); - } + case RetractAxisX: + if (pstart.X() < xMax) { + pstart.SetX(xMax); + } + break; + case RetractAxisY: + if (pstart.Y() < yMax) { + pstart.SetY(yMax); + } + break; + default: + if (pstart.Z() < zMax) { + pstart.SetZ(zMax); + } + } + if (_pstart) { + *_pstart = pstart; } - if (_pstart) *_pstart = pstart; } @@ -3275,10 +3706,12 @@ std::list Area::sortWires(const std::list& shapes, for (auto it = best_it; it != shape_list.end(); ++it) { double d; gp_Pnt pt; - if (it->myPlanar && current_it == shape_list.end()) + if (it->myPlanar && current_it == shape_list.end()) { d = it->myPln.SquareDistance(pstart); - else + } + else { d = it->nearest(pstart); + } if (d < best_d) { best_it = it; best_d = d; @@ -3302,18 +3735,19 @@ std::list Area::sortWires(const std::list& shapes, } } - wires.splice(wires.end(), - best_it->sortWires(pstart, pend, min_dist, max_dist, &pentry)); + wires.splice(wires.end(), best_it->sortWires(pstart, pend, min_dist, max_dist, &pentry)); if (use_bound && _pstart) { use_bound = false; *_pstart = pentry; } if ((sort_mode == SortMode2D5 || sort_mode == SortMode3D) && stepdown_hint) { - if (!best_it->myPlanar) + if (!best_it->myPlanar) { hint_first = true; - else if (hint_first) + } + else if (hint_first) { hint_first = false; + } else { // Calculate distance of two gp_pln. // @@ -3325,26 +3759,32 @@ std::list Area::sortWires(const std::list& shapes, const gp_Pnt& P = pln.Position().Location(); const gp_Pnt& loc = best_it->myPln.Position().Location(); const gp_Dir& dir = best_it->myPln.Position().Direction(); - double d = (dir.X() * (P.X() - loc.X()) + - dir.Y() * (P.Y() - loc.Y()) + - dir.Z() * (P.Z() - loc.Z())); - if (d < 0) d = -d; - if (d > hint) + double d = (dir.X() * (P.X() - loc.X()) + dir.Y() * (P.Y() - loc.Y()) + + dir.Z() * (P.Z() - loc.Z())); + if (d < 0) { + d = -d; + } + if (d > hint) { hint = d; + } } pln = best_it->myPln; } pstart = pend; if (best_it->myWires.empty()) { - if (current_it == best_it) + if (current_it == best_it) { current_it = shape_list.end(); + } shape_list.erase(best_it); } } - if (stepdown_hint && hint != 0.0) + if (stepdown_hint && hint != 0.0) { *stepdown_hint = hint; - if (_pend) *_pend = pend; + } + if (_pend) { + *_pend = pend; + } FC_DURATION_LOG(rparams.bd, "rtree build"); FC_DURATION_LOG(rparams.qd, "rtree query"); FC_DURATION_LOG(rparams.rd, "rtree clean"); @@ -3353,16 +3793,21 @@ std::list Area::sortWires(const std::list& shapes, return wires; } -static inline void addParameter(bool verbose, Command& cmd, const char* name, - double last, double next, bool relative = false) +static inline void addParameter(bool verbose, + Command& cmd, + const char* name, + double last, + double next, + bool relative = false) { double d = next - last; - if (verbose || fabs(d) > Precision::Confusion()) + if (verbose || fabs(d) > Precision::Confusion()) { cmd.Parameters[name] = relative ? d : next; + } } -static inline void addGCode(bool verbose, Toolpath& path, const gp_Pnt& last, - const gp_Pnt& next, const char* name) +static inline void +addGCode(bool verbose, Toolpath& path, const gp_Pnt& last, const gp_Pnt& next, const char* name) { Command cmd; cmd.Name = name; @@ -3373,8 +3818,12 @@ static inline void addGCode(bool verbose, Toolpath& path, const gp_Pnt& last, return; } -static inline void addG1(bool verbose, Toolpath& path, const gp_Pnt& last, - const gp_Pnt& next, double f, double& last_f) +static inline void addG1(bool verbose, + Toolpath& path, + const gp_Pnt& last, + const gp_Pnt& next, + double f, + double& last_f) { addGCode(verbose, path, last, next, "G1"); if (f > Precision::Confusion()) { @@ -3385,9 +3834,12 @@ static inline void addG1(bool verbose, Toolpath& path, const gp_Pnt& last, return; } -static void addG0(bool verbose, Toolpath& path, - gp_Pnt last, const gp_Pnt& next, - AxisSetter setter, double height) +static void addG0(bool verbose, + Toolpath& path, + gp_Pnt last, + const gp_Pnt& next, + AxisSetter setter, + double height) { gp_Pnt pt(next); (pt.*setter)(height); @@ -3396,9 +3848,15 @@ static void addG0(bool verbose, Toolpath& path, } } -static void addGArc(bool verbose, bool abs_center, Toolpath& path, - const gp_Pnt& pstart, const gp_Pnt& pend, const gp_Pnt& center, - bool clockwise, double f, double& last_f) +static void addGArc(bool verbose, + bool abs_center, + Toolpath& path, + const gp_Pnt& pstart, + const gp_Pnt& pend, + const gp_Pnt& center, + bool clockwise, + double f, + double& last_f) { Command cmd; cmd.Name = clockwise ? "G2" : "G3"; @@ -3422,59 +3880,76 @@ static void addGArc(bool verbose, bool abs_center, Toolpath& path, path.addCommand(cmd); } -static inline void addGCode(Toolpath& path, const char* name) { +static inline void addGCode(Toolpath& path, const char* name) +{ Command cmd; cmd.Name = name; path.addCommand(cmd); } -void Area::setWireOrientation(TopoDS_Wire& wire, const gp_Dir& dir, bool wire_ccw) { - //make a test face +void Area::setWireOrientation(TopoDS_Wire& wire, const gp_Dir& dir, bool wire_ccw) +{ + // make a test face BRepBuilderAPI_MakeFace mkFace(wire, /*onlyplane=*/Standard_True); if (!mkFace.IsDone()) { AREA_WARN("setWireOrientation: failed to make test face"); return; } TopoDS_Face tmpFace = mkFace.Face(); - //compare face surface normal with our plane's one + // compare face surface normal with our plane's one BRepAdaptor_Surface surf(tmpFace); bool ccw = surf.Plane().Axis().Direction().Dot(dir) > 0; - //unlikely, but just in case OCC decided to reverse our wire for the face... take that into account! + // unlikely, but just in case OCC decided to reverse our wire for the face... take that into + // account! TopoDS_Iterator it(tmpFace, /*CumOri=*/Standard_False); ccw ^= it.Value().Orientation() != wire.Orientation(); - if (ccw != wire_ccw) + if (ccw != wire_ccw) { wire.Reverse(); + } } -void Area::toPath(Toolpath& path, const std::list& shapes, - const gp_Pnt* _pstart, gp_Pnt* pend, PARAM_ARGS(PARAM_FARG, AREA_PARAMS_PATH)) +void Area::toPath(Toolpath& path, + const std::list& shapes, + const gp_Pnt* _pstart, + gp_Pnt* pend, + PARAM_ARGS(PARAM_FARG, AREA_PARAMS_PATH)) { std::list wires; gp_Pnt pstart; - if (_pstart) pstart = *_pstart; + if (_pstart) { + pstart = *_pstart; + } double stepdown_hint = 1.0; - wires = sortWires(shapes, _pstart != nullptr, &pstart, pend, &stepdown_hint, - PARAM_REF(PARAM_FARG, AREA_PARAMS_ARC_PLANE), - PARAM_FIELDS(PARAM_FARG, AREA_PARAMS_SORT)); + wires = sortWires(shapes, + _pstart != nullptr, + &pstart, + pend, + &stepdown_hint, + PARAM_REF(PARAM_FARG, AREA_PARAMS_ARC_PLANE), + PARAM_FIELDS(PARAM_FARG, AREA_PARAMS_SORT)); - if (wires.empty()) + if (wires.empty()) { return; + } short currentArcPlane = arc_plane; if (preamble) { // absolute mode addGCode(path, "G90"); - if (abs_center) - addGCode(path, "G90.1"); // absolute center for arc move + if (abs_center) { + addGCode(path, "G90.1"); // absolute center for arc move + } - if (arc_plane == ArcPlaneZX) + if (arc_plane == ArcPlaneZX) { addGCode(path, "G18"); - else if (arc_plane == ArcPlaneYZ) + } + else if (arc_plane == ArcPlaneYZ) { addGCode(path, "G19"); + } else { currentArcPlane = ArcPlaneXY; addGCode(path, "G17"); @@ -3484,28 +3959,30 @@ void Area::toPath(Toolpath& path, const std::list& shapes, AxisGetter getter; AxisSetter setter; switch (retract_axis) { - case RetractAxisX: - getter = &gp_Pnt::X; - setter = &gp_Pnt::SetX; - break; - case RetractAxisY: - getter = &gp_Pnt::Y; - setter = &gp_Pnt::SetY; - break; - default: - getter = &gp_Pnt::Z; - setter = &gp_Pnt::SetZ; + case RetractAxisX: + getter = &gp_Pnt::X; + setter = &gp_Pnt::SetX; + break; + case RetractAxisY: + getter = &gp_Pnt::Y; + setter = &gp_Pnt::SetY; + break; + default: + getter = &gp_Pnt::Z; + setter = &gp_Pnt::SetZ; } threshold = fabs(threshold); - if (threshold < Precision::Confusion()) + if (threshold < Precision::Confusion()) { threshold = Precision::Confusion(); + } threshold *= threshold; // in case the user didn't specify feed start, sortWire() will choose one // based on the bound. We'll further adjust that according to resume height - if (!_pstart || pstart.SquareDistance(*_pstart) > Precision::SquareConfusion()) + if (!_pstart || pstart.SquareDistance(*_pstart) > Precision::SquareConfusion()) { (pstart.*setter)(resume_height); + } gp_Pnt plast, p; // initial vertical rapid pull up to retraction (or start Z height if higher) @@ -3528,10 +4005,12 @@ void Area::toPath(Toolpath& path, const std::list& shapes, plast = p; bool first = true; bool arcWarned = false; - double cur_f = 0.0; // current feed rate - double nf = fabs(feedrate); // user specified normal move feed rate - double vf = fabs(feedrate_v); // user specified vertical move feed rate - if (vf < Precision::Confusion()) vf = nf; + double cur_f = 0.0; // current feed rate + double nf = fabs(feedrate); // user specified normal move feed rate + double vf = fabs(feedrate_v); // user specified vertical move feed rate + if (vf < Precision::Confusion()) { + vf = nf; + } for (const TopoDS_Shape& wire : wires) { @@ -3570,124 +4049,155 @@ void Area::toPath(Toolpath& path, const std::list& shapes, p = curve.Value(reversed ? curve.FirstParameter() : curve.LastParameter()); switch (curve.GetType()) { - case GeomAbs_Line: { - if (segmentation > Precision::Confusion()) { - GCPnts_UniformAbscissa discretizer(curve, segmentation, - curve.FirstParameter(), curve.LastParameter()); - if (discretizer.IsDone() && discretizer.NbPoints() > 2) { - int nbPoints = discretizer.NbPoints(); - if (reversed) { - for (int i = nbPoints - 1; i >= 1; --i) { - gp_Pnt pt = curve.Value(discretizer.Parameter(i)); - addG1(verbose, path, plast, pt, nf, cur_f); - plast = pt; - } - } - else { - for (int i = 2; i <= nbPoints; i++) { - gp_Pnt pt = curve.Value(discretizer.Parameter(i)); - addG1(verbose, path, plast, pt, nf, cur_f); - plast = pt; - } - } - break; - } - } - addG1(verbose, path, plast, p, nf, cur_f); - break; - } case GeomAbs_Circle: { - const gp_Circ& circle = curve.Circle(); - const gp_Dir& dir = circle.Axis().Direction(); - short arcPlane = ArcPlaneNone; - bool clockwise; - const char* cmd; - if (fabs(dir.X()) < Precision::Confusion() && - fabs(dir.Y()) < Precision::Confusion()) { - clockwise = dir.Z() < 0; - arcPlane = ArcPlaneXY; - cmd = "G17"; - } - else if (fabs(dir.Z()) < Precision::Confusion() && - fabs(dir.X()) < Precision::Confusion()) { - clockwise = dir.Y() < 0; - arcPlane = ArcPlaneZX; - cmd = "G18"; - } - else if (fabs(dir.Y()) < Precision::Confusion() && - fabs(dir.Z()) < Precision::Confusion()) { - clockwise = dir.X() < 0; - arcPlane = ArcPlaneYZ; - cmd = "G19"; - } - - if (arcPlane != ArcPlaneNone && - (arcPlane == currentArcPlane || arc_plane == ArcPlaneVariable)) - { - if (arcPlane != currentArcPlane) - addGCode(path, cmd); - - if (reversed) clockwise = !clockwise; - gp_Pnt center = circle.Location(); - - double first = curve.FirstParameter(); - double last = curve.LastParameter(); + case GeomAbs_Line: { if (segmentation > Precision::Confusion()) { - GCPnts_UniformAbscissa discretizer(curve, segmentation, first, last); + GCPnts_UniformAbscissa discretizer(curve, + segmentation, + curve.FirstParameter(), + curve.LastParameter()); if (discretizer.IsDone() && discretizer.NbPoints() > 2) { int nbPoints = discretizer.NbPoints(); if (reversed) { for (int i = nbPoints - 1; i >= 1; --i) { gp_Pnt pt = curve.Value(discretizer.Parameter(i)); - addGArc(verbose, abs_center, path, plast, pt, center, clockwise, nf, cur_f); + addG1(verbose, path, plast, pt, nf, cur_f); plast = pt; } } else { for (int i = 2; i <= nbPoints; i++) { gp_Pnt pt = curve.Value(discretizer.Parameter(i)); - addGArc(verbose, abs_center, path, plast, pt, center, clockwise, nf, cur_f); + addG1(verbose, path, plast, pt, nf, cur_f); plast = pt; } } break; } } - - if (fabs(first - last) > M_PI) { - // Split arc(circle) larger than half circle. - gp_Pnt mid = curve.Value((last - first) * 0.5 + first); - addGArc(verbose, abs_center, path, plast, mid, center, clockwise, nf, cur_f); - plast = mid; - } - addGArc(verbose, abs_center, path, plast, p, center, clockwise, nf, cur_f); + addG1(verbose, path, plast, p, nf, cur_f); break; } + case GeomAbs_Circle: { + const gp_Circ& circle = curve.Circle(); + const gp_Dir& dir = circle.Axis().Direction(); + short arcPlane = ArcPlaneNone; + bool clockwise; + const char* cmd; + if (fabs(dir.X()) < Precision::Confusion() + && fabs(dir.Y()) < Precision::Confusion()) { + clockwise = dir.Z() < 0; + arcPlane = ArcPlaneXY; + cmd = "G17"; + } + else if (fabs(dir.Z()) < Precision::Confusion() + && fabs(dir.X()) < Precision::Confusion()) { + clockwise = dir.Y() < 0; + arcPlane = ArcPlaneZX; + cmd = "G18"; + } + else if (fabs(dir.Y()) < Precision::Confusion() + && fabs(dir.Z()) < Precision::Confusion()) { + clockwise = dir.X() < 0; + arcPlane = ArcPlaneYZ; + cmd = "G19"; + } - if (!arcWarned) { - arcWarned = true; - AREA_WARN("arc plane not aligned, force discretization"); + if (arcPlane != ArcPlaneNone + && (arcPlane == currentArcPlane || arc_plane == ArcPlaneVariable)) { + if (arcPlane != currentArcPlane) { + addGCode(path, cmd); + } + + if (reversed) { + clockwise = !clockwise; + } + gp_Pnt center = circle.Location(); + + double first = curve.FirstParameter(); + double last = curve.LastParameter(); + if (segmentation > Precision::Confusion()) { + GCPnts_UniformAbscissa discretizer(curve, segmentation, first, last); + if (discretizer.IsDone() && discretizer.NbPoints() > 2) { + int nbPoints = discretizer.NbPoints(); + if (reversed) { + for (int i = nbPoints - 1; i >= 1; --i) { + gp_Pnt pt = curve.Value(discretizer.Parameter(i)); + addGArc(verbose, + abs_center, + path, + plast, + pt, + center, + clockwise, + nf, + cur_f); + plast = pt; + } + } + else { + for (int i = 2; i <= nbPoints; i++) { + gp_Pnt pt = curve.Value(discretizer.Parameter(i)); + addGArc(verbose, + abs_center, + path, + plast, + pt, + center, + clockwise, + nf, + cur_f); + plast = pt; + } + } + break; + } + } + + if (fabs(first - last) > M_PI) { + // Split arc(circle) larger than half circle. + gp_Pnt mid = curve.Value((last - first) * 0.5 + first); + addGArc(verbose, + abs_center, + path, + plast, + mid, + center, + clockwise, + nf, + cur_f); + plast = mid; + } + addGArc(verbose, abs_center, path, plast, p, center, clockwise, nf, cur_f); + break; + } + + if (!arcWarned) { + arcWarned = true; + AREA_WARN("arc plane not aligned, force discretization"); + } + AREA_TRACE("arc discretize " << AREA_XYZ(dir)); } - AREA_TRACE("arc discretize " << AREA_XYZ(dir)); - } - /* FALLTHRU */ - default: { - const auto& pts = discretize(edge, deflection); - for (size_t i = 1; i < pts.size(); ++i) { - auto& pt = pts[i]; - addG1(verbose, path, plast, pt, nf, cur_f); - plast = pt; + /* FALLTHRU */ + default: { + const auto& pts = discretize(edge, deflection); + for (size_t i = 1; i < pts.size(); ++i) { + auto& pt = pts[i]; + addG1(verbose, path, plast, pt, nf, cur_f); + plast = pt; + } } } - } } } } -void Area::abort(bool aborting) { +void Area::abort(bool aborting) +{ s_aborting = aborting; } -bool Area::aborting() { +bool Area::aborting() +{ return s_aborting; } @@ -3696,14 +4206,16 @@ AreaStaticParams::AreaStaticParams() AreaStaticParams Area::s_params; -void Area::setDefaultParams(const AreaStaticParams& params) { +void Area::setDefaultParams(const AreaStaticParams& params) +{ s_params = params; } -const AreaStaticParams& Area::getDefaultParams() { +const AreaStaticParams& Area::getDefaultParams() +{ return s_params; } #if defined(__clang__) -# pragma clang diagnostic pop +#pragma clang diagnostic pop #endif diff --git a/src/Mod/CAM/App/Area.h b/src/Mod/CAM/App/Area.h index 89c397d40e..0a8e16d8c9 100644 --- a/src/Mod/CAM/App/Area.h +++ b/src/Mod/CAM/App/Area.h @@ -46,24 +46,29 @@ namespace Path { /** Store libarea algorithm configuration */ -struct PathExport CAreaParams { +struct PathExport CAreaParams +{ PARAM_DECLARE(PARAM_FNAME, AREA_PARAMS_CAREA) CAreaParams(); }; /** Store all Area configurations */ -struct PathExport AreaParams: CAreaParams { +struct PathExport AreaParams: CAreaParams +{ PARAM_DECLARE(PARAM_FNAME, AREA_PARAMS_AREA) - bool operator==(const AreaParams& other) const { -#define AREA_COMPARE(_param) \ - if(PARAM_FIELD(NAME,_param)!=other.PARAM_FIELD(NAME,_param)) return false; + bool operator==(const AreaParams& other) const + { +#define AREA_COMPARE(_param) \ + if (PARAM_FIELD(NAME, _param) != other.PARAM_FIELD(NAME, _param)) \ + return false; PARAM_FOREACH(AREA_COMPARE, AREA_PARAMS_CAREA); PARAM_FOREACH(AREA_COMPARE, AREA_PARAMS_AREA); return true; } - bool operator!=(const AreaParams& other) const { + bool operator!=(const AreaParams& other) const + { return !(*this == other); } @@ -72,7 +77,8 @@ struct PathExport AreaParams: CAreaParams { AreaParams(); }; -struct PathExport AreaStaticParams: AreaParams { +struct PathExport AreaStaticParams: AreaParams +{ AreaStaticParams(); }; @@ -81,7 +87,8 @@ struct PathExport AreaStaticParams: AreaParams { * It is kind of troublesome with the fact that libarea uses static variables to * config its algorithm. CAreaConfig makes it easy to safely customize libarea. */ -struct PathExport CAreaConfig { +struct PathExport CAreaConfig +{ /** For saving current libarea settings */ PARAM_DECLARE(PARAM_FNAME, AREA_PARAMS_CAREA) @@ -101,17 +108,19 @@ struct PathExport CAreaConfig { /** Base class for FreeCAD wrapping of libarea */ -class PathExport Area: public Base::BaseClass { +class PathExport Area: public Base::BaseClass +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: - struct Shape { + struct Shape + { short op; TopoDS_Shape shape; Shape(short opCode, const TopoDS_Shape& s) - :op(opCode) + : op(opCode) , shape(s) {} }; @@ -125,7 +134,7 @@ protected: TopoDS_Shape myShapePlane; TopoDS_Shape myWorkPlane; TopoDS_Shape myShape; - std::vector > mySections; + std::vector> mySections; bool myHaveFace; bool myHaveSolid; bool myShapeDone; @@ -150,8 +159,9 @@ protected: * * See #AREA_PARAMS_OFFSET for description of the arguments. */ - void makeOffset(std::list >& areas, - PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_OFFSET), bool from_center = false); + void makeOffset(std::list>& areas, + PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_OFFSET), + bool from_center = false); /** Make a pocket of the combined shape * @@ -216,8 +226,10 @@ public: * If more than one offset is requested, a compound shape is return * containing all offset shapes as wires regardless of \c Fill setting. */ - TopoDS_Shape makeOffset(int index = -1, PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_OFFSET), - int reoirent = 0, bool from_center = false); + TopoDS_Shape makeOffset(int index = -1, + PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_OFFSET), + int reoirent = 0, + bool from_center = false); /** Make a pocket of the combined shape * @@ -237,25 +249,29 @@ public: * See #AREA_PARAMS_EXTRA for description of the arguments. Currently, there * is only one argument, namely \c mode for section mode. */ - std::vector > makeSections( - PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_SECTION_EXTRA), - const std::vector& heights = std::vector(), - const TopoDS_Shape& plane = TopoDS_Shape()); + std::vector> + makeSections(PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_SECTION_EXTRA), + const std::vector& heights = std::vector(), + const TopoDS_Shape& plane = TopoDS_Shape()); - std::shared_ptr getClearedArea(const Toolpath *path, double diameter, double zmax, Base::BoundBox3d bbox); - std::shared_ptr getRestArea(std::vector> clearedAreas, double diameter); + std::shared_ptr + getClearedArea(const Toolpath* path, double diameter, double zmax, Base::BoundBox3d bbox); + std::shared_ptr getRestArea(std::vector> clearedAreas, + double diameter); TopoDS_Shape toTopoShape(); /** Config this Area object */ void setParams(const AreaParams& params); - const std::list getChildren() const { + const std::list getChildren() const + { return myShapes; } /** Get the current configuration */ - const AreaParams& getParams() const { + const AreaParams& getParams() const + { return myParams; } @@ -275,7 +291,8 @@ public: TopoDS_Shape getShape(int index = -1); /** Return the number of sections */ - std::size_t getSectionCount() { + std::size_t getSectionCount() + { build(); return mySections.size(); } @@ -290,8 +307,11 @@ public: * \arg \c to_edges: if true, discretize all curves, and insert as open * line segments * */ - static void addWire(CArea& area, const TopoDS_Wire& wire, const gp_Trsf* trsf = nullptr, - double deflection = 0.01, bool to_edges = false); + static void addWire(CArea& area, + const TopoDS_Wire& wire, + const gp_Trsf* trsf = nullptr, + double deflection = 0.01, + bool to_edges = false); /** Add a OCC generic shape to CArea * @@ -310,10 +330,15 @@ public: * \return Returns the number of non coplaner. Planar testing only happens * if \c plane is supplied * */ - static int addShape(CArea& area, const TopoDS_Shape& shape, const gp_Trsf* trsf = nullptr, - double deflection = 0.01, const TopoDS_Shape* plane = nullptr, - bool force_coplanar = true, CArea* areaOpen = nullptr, bool to_edges = false, - bool reorient = true); + static int addShape(CArea& area, + const TopoDS_Shape& shape, + const gp_Trsf* trsf = nullptr, + double deflection = 0.01, + const TopoDS_Shape* plane = nullptr, + bool force_coplanar = true, + CArea* areaOpen = nullptr, + bool to_edges = false, + bool reorient = true); /** Convert curves in CArea into an OCC shape * @@ -322,8 +347,8 @@ public: * \arg \c trsf: optional transform matrix to transform the shape back into * its original position. * */ - static TopoDS_Shape toShape(const CArea& area, bool fill, - const gp_Trsf* trsf = nullptr, int reoirent = 0); + static TopoDS_Shape + toShape(const CArea& area, bool fill, const gp_Trsf* trsf = nullptr, int reoirent = 0); /** Convert a single curve into an OCC wire * @@ -331,7 +356,8 @@ public: * \arg \c trsf: optional transform matrix to transform the shape back into * its original position. * */ - static TopoDS_Shape toShape(const CCurve& curve, const gp_Trsf* trsf = nullptr, int reorient = 0); + static TopoDS_Shape + toShape(const CCurve& curve, const gp_Trsf* trsf = nullptr, int reorient = 0); /** Check if two OCC shape is coplanar */ static bool isCoplanar(const TopoDS_Shape& s1, const TopoDS_Shape& s2); @@ -357,8 +383,12 @@ public: * \return sorted wires */ static std::list sortWires(const std::list& shapes, - bool has_start = false, gp_Pnt* pstart = nullptr, gp_Pnt* pend = nullptr, double* stepdown_hint = nullptr, - short* arc_plane = nullptr, PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_SORT)); + bool has_start = false, + gp_Pnt* pstart = nullptr, + gp_Pnt* pend = nullptr, + double* stepdown_hint = nullptr, + short* arc_plane = nullptr, + PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_SORT)); /** Convert a list of wires to gcode * @@ -369,13 +399,16 @@ public: * * See #AREA_PARAMS_PATH for other arguments */ - static void toPath(Toolpath& path, const std::list& shapes, - const gp_Pnt* pstart = nullptr, gp_Pnt* pend = nullptr, - PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_PATH)); + static void toPath(Toolpath& path, + const std::list& shapes, + const gp_Pnt* pstart = nullptr, + gp_Pnt* pend = nullptr, + PARAM_ARGS_DEF(PARAM_FARG, AREA_PARAMS_PATH)); - static int project(TopoDS_Shape& out, const TopoDS_Shape& in, - const AreaParams* params = nullptr, - const TopoDS_Shape* work_plane = nullptr); + static int project(TopoDS_Shape& out, + const TopoDS_Shape& in, + const AreaParams* params = nullptr, + const TopoDS_Shape* work_plane = nullptr); static void setWireOrientation(TopoDS_Wire& wire, const gp_Dir& dir, bool ccw); @@ -387,9 +420,10 @@ public: static void setDefaultParams(const AreaStaticParams& params); static const AreaStaticParams& getDefaultParams(); - static void showShape(const TopoDS_Shape& shape, const char* name, const char* fmt = nullptr, ...); + static void + showShape(const TopoDS_Shape& shape, const char* name, const char* fmt = nullptr, ...); }; -} //namespace Path +} // namespace Path -#endif //PATH_AREA_H +#endif // PATH_AREA_H diff --git a/src/Mod/CAM/App/AreaParams.h b/src/Mod/CAM/App/AreaParams.h index 6740e6efb5..02c90bb622 100644 --- a/src/Mod/CAM/App/AreaParams.h +++ b/src/Mod/CAM/App/AreaParams.h @@ -34,238 +34,427 @@ #include "ParamsHelper.h" /** clipper fill type */ -#define AREA_CLIPPER_FILL_TYPE \ - (NonZero)(EvenOdd)(Positive)(Negative),(ClipperLib::PolyFillType,ClipperLib::pft) +#define AREA_CLIPPER_FILL_TYPE \ + (NonZero)(EvenOdd)(Positive)(Negative), (ClipperLib::PolyFillType, ClipperLib::pft) /** Parameters of clipper fill types */ -#define AREA_PARAMS_CLIPPER_FILL \ - ((enum2,subject_fill,SubjectFill,0,\ - "ClipperLib subject fill type. \nSee https://goo.gl/5pYQQP",AREA_CLIPPER_FILL_TYPE))\ - ((enum2,clip_fill,ClipFill,0,\ - "ClipperLib clip fill type. \nSee https://goo.gl/5pYQQP",AREA_CLIPPER_FILL_TYPE)) +#define AREA_PARAMS_CLIPPER_FILL \ + ((enum2, \ + subject_fill, \ + SubjectFill, \ + 0, \ + "ClipperLib subject fill type. \nSee https://goo.gl/5pYQQP", \ + AREA_CLIPPER_FILL_TYPE))((enum2, \ + clip_fill, \ + ClipFill, \ + 0, \ + "ClipperLib clip fill type. \nSee https://goo.gl/5pYQQP", \ + AREA_CLIPPER_FILL_TYPE)) /** Deflection parameter */ -#define AREA_PARAMS_DEFLECTION \ - ((double,deflection,Deflection,0.01,\ - "Deflection for non circular curve discretization. It also also used for\n"\ - "discretizing circular wires when you 'Explode' the shape for wire operations",\ - App::PropertyPrecision)) +#define AREA_PARAMS_DEFLECTION \ + ((double, \ + deflection, \ + Deflection, \ + 0.01, \ + "Deflection for non circular curve discretization. It also also used for\n" \ + "discretizing circular wires when you 'Explode' the shape for wire operations", \ + App::PropertyPrecision)) /** Base parameters */ -#define AREA_PARAMS_BASE \ - ((enum,fill,Fill,2,"Fill the output wires to make a face. \n"\ - "Auto means make a face if any of the children has a face.",(None)(Face)(Auto)))\ - ((enum,coplanar,Coplanar,2,\ - "Specifies the way to check coplanar. 'Force' will discard non coplaner shapes,\n"\ - "but 'Check' only gives warning.",(None)(Check)(Force)))\ - ((bool,reorient,Reorient,true,\ - "Re-orient closed wires in wire only shapes so that inner wires become holes."))\ - ((bool,outline,Outline,false,\ - "Remove all inner wires (holes) before output the final shape"))\ - ((bool,explode,Explode,false,\ - "If true, Area will explode the first shape into disconnected open edges, \n"\ - "with all curves discretized, so that later operations like 'Difference' \n"\ - "behave like wire cutting. Without exploding, 'Difference' in ClipperLib\n"\ - "behave like face cutting."))\ - ((enum,open_mode,OpenMode,0,\ - "Specify how to handle open wires. 'None' means combine without openeration.\n"\ - "'Edges' means separate to edges before Union. ClipperLib seems to have an.\n"\ - "urge to close open wires.",(None)(Union)(Edges)))\ - AREA_PARAMS_DEFLECTION \ - AREA_PARAMS_CLIPPER_FILL +#define AREA_PARAMS_BASE \ + ((enum, \ + fill, \ + Fill, \ + 2, \ + "Fill the output wires to make a face. \n" \ + "Auto means make a face if any of the children has a face.", \ + (None)(Face)(Auto)))( \ + (enum, \ + coplanar, \ + Coplanar, \ + 2, \ + "Specifies the way to check coplanar. 'Force' will discard non coplaner shapes,\n" \ + "but 'Check' only gives warning.", \ + (None)(Check)(Force)))( \ + (bool, \ + reorient, \ + Reorient, \ + true, \ + "Re-orient closed wires in wire only shapes so that inner wires become holes."))( \ + (bool, \ + outline, \ + Outline, \ + false, \ + "Remove all inner wires (holes) before output the final shape"))( \ + (bool, \ + explode, \ + Explode, \ + false, \ + "If true, Area will explode the first shape into disconnected open edges, \n" \ + "with all curves discretized, so that later operations like 'Difference' \n" \ + "behave like wire cutting. Without exploding, 'Difference' in ClipperLib\n" \ + "behave like face cutting."))( \ + (enum, \ + open_mode, \ + OpenMode, \ + 0, \ + "Specify how to handle open wires. 'None' means combine without openeration.\n" \ + "'Edges' means separate to edges before Union. ClipperLib seems to have an.\n" \ + "urge to close open wires.", \ + (None)(Union)(Edges)))AREA_PARAMS_DEFLECTION AREA_PARAMS_CLIPPER_FILL -#define AREA_PARAMS_FIT_ARCS \ - ((bool,fit_arcs,FitArcs,true,"Enable arc fitting")) +#define AREA_PARAMS_FIT_ARCS ((bool, fit_arcs, FitArcs, true, "Enable arc fitting")) /** libarea algorithm option parameters */ -#define AREA_PARAMS_CAREA \ - ((double,tolerance,Tolerance,Precision::Confusion(),\ - "Point coincidence tolerance",App::PropertyPrecision))\ - AREA_PARAMS_FIT_ARCS \ - ((bool,clipper_simple,Simplify,false,\ - "Simplify polygons after operation. See https://goo.gl/Mh9XK1"))\ - ((double,clipper_clean_distance,CleanDistance,0.0,\ - "Clean polygon smaller than this distance. See https://goo.gl/jox3JY",App::PropertyLength))\ - ((double,accuracy,Accuracy,0.01,"Arc fitting accuracy",App::PropertyPrecision))\ - ((double,units,Unit,1.0,"Scaling factor for conversion to inch",App::PropertyFloat))\ - ((short,min_arc_points,MinArcPoints,4,"Minimum segments for arc discretization"))\ - ((short,max_arc_points,MaxArcPoints,100,"Maximum segments for arc discretization (ignored currently)"))\ - ((double,clipper_scale,ClipperScale,1e7,\ - "ClipperLib operate on integers. This is the scale factor to convert\n"\ - "floating points.",App::PropertyFloat)) +#define AREA_PARAMS_CAREA \ + ((double, \ + tolerance, \ + Tolerance, \ + Precision::Confusion(), \ + "Point coincidence tolerance", \ + App::PropertyPrecision)) \ + AREA_PARAMS_FIT_ARCS((bool, \ + clipper_simple, \ + Simplify, \ + false, \ + "Simplify polygons after operation. See https://goo.gl/Mh9XK1"))( \ + (double, \ + clipper_clean_distance, \ + CleanDistance, \ + 0.0, \ + "Clean polygon smaller than this distance. See https://goo.gl/jox3JY", \ + App::PropertyLength))( \ + (double, accuracy, Accuracy, 0.01, "Arc fitting accuracy", App::PropertyPrecision))( \ + (double, \ + units, \ + Unit, \ + 1.0, \ + "Scaling factor for conversion to inch", \ + App::PropertyFloat))( \ + (short, min_arc_points, MinArcPoints, 4, "Minimum segments for arc discretization"))( \ + (short, \ + max_arc_points, \ + MaxArcPoints, \ + 100, \ + "Maximum segments for arc discretization (ignored currently)"))( \ + (double, \ + clipper_scale, \ + ClipperScale, \ + 1e7, \ + "ClipperLib operate on integers. This is the scale factor to convert\n" \ + "floating points.", \ + App::PropertyFloat)) /** Pocket parameters * * These parameters corresponds to CAreaPocketParams in libarea * */ -#define AREA_PARAMS_POCKET \ - ((enum,mode,PocketMode,0,"Selects the pocket toolpath pattern",\ - (None)(ZigZag)(Offset)(Spiral)(ZigZagOffset)(Line)(Grid)(Triangle)))\ - ((double,tool_radius,ToolRadius,1.0,"Tool radius for pocketing",App::PropertyLength))\ - ((double,extra_offset,PocketExtraOffset,0.0,"Extra offset for pocketing",App::PropertyDistance))\ - ((double,stepover,PocketStepover,0.0,\ - "Cutter diameter to step over on each pass. If =0, use ToolRadius.",App::PropertyLength))\ - ((double,last_stepover,PocketLastStepover,0.0,\ - "Cutter diameter to step over for the last loop when using offset pocket.\n"\ - "If =0, use 0.5*ToolRadius.", App::PropertyLength))\ - ((bool,from_center,FromCenter,false,"Start pocketing from center"))\ - ((double,angle,Angle,45,"Pattern angle in degree",App::PropertyAngle))\ - ((double,angle_shift,AngleShift,0.0,"Pattern angle shift for each section", App::PropertyAngle))\ - ((double,shift,Shift,0.0,"Pattern shift distance for each section.\n"\ - "The pocket pattern will be shifted in orthogonal direction by this amount for each section.\n"\ - "This gives a 3D pattern mainly for 3D printing. The shift only applies to 'Offset', 'Grid'\n"\ - "and 'Triangle'", App::PropertyDistance)) +#define AREA_PARAMS_POCKET \ + ((enum, \ + mode, \ + PocketMode, \ + 0, \ + "Selects the pocket toolpath pattern", \ + (None)(ZigZag)(Offset)(Spiral)(ZigZagOffset)(Line)(Grid)(Triangle)))( \ + (double, tool_radius, ToolRadius, 1.0, "Tool radius for pocketing", App::PropertyLength))( \ + (double, \ + extra_offset, \ + PocketExtraOffset, \ + 0.0, \ + "Extra offset for pocketing", \ + App::PropertyDistance))( \ + (double, \ + stepover, \ + PocketStepover, \ + 0.0, \ + "Cutter diameter to step over on each pass. If =0, use ToolRadius.", \ + App::PropertyLength))( \ + (double, \ + last_stepover, \ + PocketLastStepover, \ + 0.0, \ + "Cutter diameter to step over for the last loop when using offset pocket.\n" \ + "If =0, use 0.5*ToolRadius.", \ + App::PropertyLength))( \ + (bool, from_center, FromCenter, false, "Start pocketing from center"))( \ + (double, angle, Angle, 45, "Pattern angle in degree", App::PropertyAngle))( \ + (double, \ + angle_shift, \ + AngleShift, \ + 0.0, \ + "Pattern angle shift for each section", \ + App::PropertyAngle))((double, \ + shift, \ + Shift, \ + 0.0, \ + "Pattern shift distance for each section.\n" \ + "The pocket pattern will be shifted in orthogonal direction by " \ + "this amount for each section.\n" \ + "This gives a 3D pattern mainly for 3D printing. The shift only " \ + "applies to 'Offset', 'Grid'\n" \ + "and 'Triangle'", \ + App::PropertyDistance)) -#define AREA_PARAMS_POCKET_CONF \ - ((bool,thicken,Thicken,false,"Thicken the resulting wires with ToolRadius")) +#define AREA_PARAMS_POCKET_CONF \ + ((bool, thicken, Thicken, false, "Thicken the resulting wires with ToolRadius")) /** Operation code */ -#define AREA_PARAMS_OPCODE \ - ((enum,op,Operation,0,"Boolean operation.\n"\ - "For the first four operations, see https://goo.gl/Gj8RUu.\n"\ - "'Compound' means no operation, normally used to do Area.sortWires().",\ - (Union)(Difference)(Intersection)(Xor)(Compound))) +#define AREA_PARAMS_OPCODE \ + ((enum, \ + op, \ + Operation, \ + 0, \ + "Boolean operation.\n" \ + "For the first four operations, see https://goo.gl/Gj8RUu.\n" \ + "'Compound' means no operation, normally used to do Area.sortWires().", \ + (Union)(Difference)(Intersection)(Xor)(Compound))) /** Offset parameters */ -#define AREA_PARAMS_OFFSET \ - ((double,offset,Offset,0.0,\ - "Offset value, positive for expansion, negative for shrinking",App::PropertyDistance))\ - ((long,extra_pass,ExtraPass,0,"Number of extra offset pass to generate."))\ - ((double,stepover,Stepover,0.0,\ - "Cutter diameter to step over on each pass. If =0, use Offset",App::PropertyLength))\ - ((double,last_stepover,LastStepover,0.0,\ - "Cutter diameter to step over for the last loop when shrinking with ExtraPass<0, i.e. for\n"\ - "offset pocketing. If =0, use 0.5*Offset.", App::PropertyLength)) +#define AREA_PARAMS_OFFSET \ + ((double, \ + offset, \ + Offset, \ + 0.0, \ + "Offset value, positive for expansion, negative for shrinking", \ + App::PropertyDistance))( \ + (long, extra_pass, ExtraPass, 0, "Number of extra offset pass to generate."))( \ + (double, \ + stepover, \ + Stepover, \ + 0.0, \ + "Cutter diameter to step over on each pass. If =0, use Offset", \ + App::PropertyLength))((double, \ + last_stepover, \ + LastStepover, \ + 0.0, \ + "Cutter diameter to step over for the last loop when shrinking " \ + "with ExtraPass<0, i.e. for\n" \ + "offset pocketing. If =0, use 0.5*Offset.", \ + App::PropertyLength)) -#define AREA_PARAMS_SECTION_EXTRA \ - ((enum,mode,SectionMode,2,"Section offset coordinate mode.\n"\ - "'Absolute' means the absolute Z height (given in SectionOffset) to start slicing.\n"\ - "'BoundBox' means relative Z height to the bounding box of all the children shape.\n"\ - "'Workplane' means relative to workplane, minus SectionOffset.\n"\ - "Note that OCC has trouble getting the minimum bounding box of some solids, particularly\n"\ - "those with non-planar surface. It is recommended to use Workplane to specify the intended\n"\ - "starting z height.\n",(Absolute)(BoundBox)(Workplane)))\ - ((bool,project,Project,false, "The section is produced by normal projecting the outline\n"\ - "of all added shapes to the section plane, instead of slicing.")) +#define AREA_PARAMS_SECTION_EXTRA \ + ((enum, \ + mode, \ + SectionMode, \ + 2, \ + "Section offset coordinate mode.\n" \ + "'Absolute' means the absolute Z height (given in SectionOffset) to start slicing.\n" \ + "'BoundBox' means relative Z height to the bounding box of all the children shape.\n" \ + "'Workplane' means relative to workplane, minus SectionOffset.\n" \ + "Note that OCC has trouble getting the minimum bounding box of some solids, particularly\n" \ + "those with non-planar surface. It is recommended to use Workplane to specify the " \ + "intended\n" \ + "starting z height.\n", \ + (Absolute)(BoundBox)(Workplane)))( \ + (bool, \ + project, \ + Project, \ + false, \ + "The section is produced by normal projecting the outline\n" \ + "of all added shapes to the section plane, instead of slicing.")) /** Section parameters */ -#define AREA_PARAMS_SECTION \ - ((long,count,SectionCount,0,"Number of sections to generate. -1 means full sections."))\ - ((double,stepdown,Stepdown,1.0,"Step down distance for each section.\n"\ - "Positive value means going from top down, and negative the other way round",App::PropertyDistance))\ - ((double,offset,SectionOffset,0.0,"Offset for the first section. The direction of the offset is\n"\ - "determined by the section direction (i.e. the signess of Stepdown). If going from top down,\n"\ - "a positive value means offset downward, and if bottom up, it means upward",App::PropertyDistance))\ - ((double,tolerance,SectionTolerance,1e-6,"Offset value added when hitting the boundary.\n"\ - "When the section hits or over the shape boundary, a section with the height of that boundary\n"\ - "will be created. A small offset is usually required to avoid the tangential cut.",\ - App::PropertyPrecision))\ - AREA_PARAMS_SECTION_EXTRA +#define AREA_PARAMS_SECTION \ + ((long, count, SectionCount, 0, "Number of sections to generate. -1 means full sections."))( \ + (double, \ + stepdown, \ + Stepdown, \ + 1.0, \ + "Step down distance for each section.\n" \ + "Positive value means going from top down, and negative the other way round", \ + App::PropertyDistance))( \ + (double, \ + offset, \ + SectionOffset, \ + 0.0, \ + "Offset for the first section. The direction of the offset is\n" \ + "determined by the section direction (i.e. the signess of Stepdown). If going from top " \ + "down,\n" \ + "a positive value means offset downward, and if bottom up, it means upward", \ + App::PropertyDistance))( \ + (double, \ + tolerance, \ + SectionTolerance, \ + 1e-6, \ + "Offset value added when hitting the boundary.\n" \ + "When the section hits or over the shape boundary, a section with the height of that " \ + "boundary\n" \ + "will be created. A small offset is usually required to avoid the tangential cut.", \ + App::PropertyPrecision))AREA_PARAMS_SECTION_EXTRA #ifdef AREA_OFFSET_ALGO -# define AREA_PARAMS_OFFSET_ALGO \ - ((enum,algo,Algo,0,"Offset algorithm type",(Clipper)(libarea))) +#define AREA_PARAMS_OFFSET_ALGO ((enum, algo, Algo, 0, "Offset algorithm type", (Clipper)(libarea))) #else -# define AREA_PARAMS_OFFSET_ALGO +#define AREA_PARAMS_OFFSET_ALGO #endif /** Offset configuration parameters */ -#define AREA_PARAMS_OFFSET_CONF \ - AREA_PARAMS_OFFSET_ALGO \ - ((enum2,join_type,JoinType,0,"ClipperOffset join type. \nSee https://goo.gl/4odfQh",\ - (Round)(Square)(Miter),(ClipperLib::JoinType,ClipperLib::jt)))\ - ((enum2,end_type,EndType,0,"\nClipperOffset end type. See https://goo.gl/tj7gkX",\ - (OpenRound)(ClosedPolygon)(ClosedLine)(OpenSquare)(OpenButt),(ClipperLib::EndType,ClipperLib::et)))\ - ((double,miter_limit,MiterLimit,2.0,\ - "Miter limit for joint type Miter. See https://goo.gl/K8xX9h",App::PropertyFloat))\ - ((double,round_precision,RoundPrecision,0.0,\ - "Round joint precision. If =0, it defaults to Accuracy. \n"\ - "See https://goo.gl/4odfQh",App::PropertyPrecision)) +#define AREA_PARAMS_OFFSET_CONF \ + AREA_PARAMS_OFFSET_ALGO((enum2, \ + join_type, \ + JoinType, \ + 0, \ + "ClipperOffset join type. \nSee https://goo.gl/4odfQh", \ + (Round)(Square)(Miter), \ + (ClipperLib::JoinType, ClipperLib::jt))) \ + ((enum2, \ + end_type, \ + EndType, \ + 0, \ + "\nClipperOffset end type. See https://goo.gl/tj7gkX", \ + (OpenRound)(ClosedPolygon)(ClosedLine)(OpenSquare)(OpenButt), \ + (ClipperLib::EndType, ClipperLib::et)))( \ + (double, \ + miter_limit, \ + MiterLimit, \ + 2.0, \ + "Miter limit for joint type Miter. See https://goo.gl/K8xX9h", \ + App::PropertyFloat))((double, \ + round_precision, \ + RoundPrecision, \ + 0.0, \ + "Round joint precision. If =0, it defaults to Accuracy. \n" \ + "See https://goo.gl/4odfQh", \ + App::PropertyPrecision)) -#define AREA_PARAMS_MIN_DIST \ - ((double, min_dist, MinDistance, 0.0, \ - "minimum distance for the generated new wires. Wires maybe broken if the\n"\ - "algorithm see fits. Set to zero to disable wire breaking.",App::PropertyLength)) +#define AREA_PARAMS_MIN_DIST \ + ((double, \ + min_dist, \ + MinDistance, \ + 0.0, \ + "minimum distance for the generated new wires. Wires maybe broken if the\n" \ + "algorithm see fits. Set to zero to disable wire breaking.", \ + App::PropertyLength)) /** Arc plane */ -#define AREA_PARAMS_ARC_PLANE \ - ((enum, arc_plane, ArcPlane, 1, "Arc drawing plane, corresponding to G17, G18, and G19.\n"\ - "If not 'None', the output wires will be transformed to align with the selected plane,\n"\ - "and the corresponding GCode will be inserted.\n"\ - "'Auto' means the plane is determined by the first encountered arc plane. If the found\n"\ - "plane does not align to any GCode plane, XY plane is used.\n"\ - "'Variable' means the arc plane can be changed during operation to align to the\n"\ - "arc encountered.",\ - (None)(Auto)(XY)(ZX)(YZ)(Variable))) +#define AREA_PARAMS_ARC_PLANE \ + ((enum, \ + arc_plane, \ + ArcPlane, \ + 1, \ + "Arc drawing plane, corresponding to G17, G18, and G19.\n" \ + "If not 'None', the output wires will be transformed to align with the selected plane,\n" \ + "and the corresponding GCode will be inserted.\n" \ + "'Auto' means the plane is determined by the first encountered arc plane. If the found\n" \ + "plane does not align to any GCode plane, XY plane is used.\n" \ + "'Variable' means the arc plane can be changed during operation to align to the\n" \ + "arc encountered.", \ + (None)(Auto)(XY)(ZX)(YZ)(Variable))) -#define AREA_PARAMS_ORIENTATION \ - ((enum, orientation, Orientation, 0, "Enforce loop orientation\n"\ - "'Normal' means CCW for outer wires when looking against the positive axis direction, \n"\ - "and CW for inner wires. 'Reversed' means the other way round", (Normal)(Reversed))) +#define AREA_PARAMS_ORIENTATION \ + ((enum, \ + orientation, \ + Orientation, \ + 0, \ + "Enforce loop orientation\n" \ + "'Normal' means CCW for outer wires when looking against the positive axis direction, \n" \ + "and CW for inner wires. 'Reversed' means the other way round", \ + (Normal)(Reversed))) /** Area wire sorting parameters */ -#define AREA_PARAMS_SORT \ - ((enum, sort_mode, SortMode, 1, "Wire sorting mode to optimize travel distance.\n"\ - "'2D5' explode shapes into wires, and groups the shapes by its plane. The 'start' position\n"\ - "chooses the first plane to start. The algorithm will then sort within the plane and then\n"\ - "move on to the next nearest plane.\n"\ - "'3D' makes no assumption of planarity. The sorting is done across 3D space.\n"\ - "'Greedy' like '2D5' but will try to minimize travel by searching for nearest path below\n"\ - "the current milling layer. The path in lower layer is only selected if the moving distance\n"\ - "is within the value given in 'threshold'.",\ - (None)(2D5)(3D)(Greedy)))\ - AREA_PARAMS_MIN_DIST \ - ((double, abscissa, SortAbscissa, 3.0, "Controls vertex sampling on wire for nearest point searching\n"\ - "The sampling is dong using OCC GCPnts_UniformAbscissa",App::PropertyLength))\ - ((short, nearest_k, NearestK, 3, "Nearest k sampling vertices are considered during sorting"))\ - AREA_PARAMS_ORIENTATION \ - ((enum, direction, Direction, 0, "Enforce open path direction",\ - (None)(XPositive)(XNegative)(YPositive)(YNegative)(ZPositive)(ZNegative)))\ - ((double, threshold, RetractThreshold, 0.0,\ - "If two wire's end points are separated within this threshold, they are consider\n"\ - "as connected. You may want to set this to the tool diameter to keep the tool down.",\ - App::PropertyLength))\ - ((enum, retract_axis, RetractAxis, 2,"Tool retraction axis",(X)(Y)(Z))) +#define AREA_PARAMS_SORT \ + ((enum, \ + sort_mode, \ + SortMode, \ + 1, \ + "Wire sorting mode to optimize travel distance.\n" \ + "'2D5' explode shapes into wires, and groups the shapes by its plane. The 'start' " \ + "position\n" \ + "chooses the first plane to start. The algorithm will then sort within the plane and then\n" \ + "move on to the next nearest plane.\n" \ + "'3D' makes no assumption of planarity. The sorting is done across 3D space.\n" \ + "'Greedy' like '2D5' but will try to minimize travel by searching for nearest path below\n" \ + "the current milling layer. The path in lower layer is only selected if the moving " \ + "distance\n" \ + "is within the value given in 'threshold'.", \ + (None)(2D5)(3D)( \ + Greedy))) AREA_PARAMS_MIN_DIST((double, \ + abscissa, \ + SortAbscissa, \ + 3.0, \ + "Controls vertex sampling on wire for nearest point " \ + "searching\n" \ + "The sampling is dong using OCC GCPnts_UniformAbscissa", \ + App::PropertyLength))( \ + (short, \ + nearest_k, \ + NearestK, \ + 3, \ + "Nearest k sampling vertices are considered during sorting")) \ + AREA_PARAMS_ORIENTATION( \ + (enum, \ + direction, \ + Direction, \ + 0, \ + "Enforce open path direction", \ + (None)(XPositive)(XNegative)(YPositive)(YNegative)(ZPositive)(ZNegative)))( \ + (double, \ + threshold, \ + RetractThreshold, \ + 0.0, \ + "If two wire's end points are separated within this threshold, they are consider\n" \ + "as connected. You may want to set this to the tool diameter to keep the tool down.", \ + App::PropertyLength))( \ + (enum, retract_axis, RetractAxis, 2, "Tool retraction axis", (X)(Y)(Z))) /** Area path generation parameters */ -#define AREA_PARAMS_PATH \ - AREA_PARAMS_ARC_PLANE \ - AREA_PARAMS_SORT \ - ((double, retraction, Retraction, 0.0,"Tool retraction absolute coordinate along retraction axis",\ - App::PropertyLength))\ - ((double, resume_height, ResumeHeight, 0.0,\ - "When return from last retraction, this gives the pause height relative to the Z\n"\ - "value of the next move.", App::PropertyLength))\ - ((double,segmentation,Segmentation,0.0,\ - "Break long curves into segments of this length. One use case is for PCB autolevel,\n"\ - "so that more correction points can be inserted",App::PropertyLength)) \ - ((double,feedrate,FeedRate,0.0, "Normal move feed rate", App::PropertyFloat)) \ - ((double,feedrate_v,FeedRateVertical,0.0, "Vertical only (step down) move feed rate", App::PropertyFloat)) \ - ((bool,verbose,Verbose,true, "If true, each motion GCode will contain full coordinate and feedrate")) \ - ((bool,abs_center,AbsoluteArcCenter,false, "Use absolute arc center mode (G90.1)")) \ - ((bool,preamble,EmitPreamble,true,"Emit preambles")) \ - AREA_PARAMS_DEFLECTION +#define AREA_PARAMS_PATH \ + AREA_PARAMS_ARC_PLANE \ + AREA_PARAMS_SORT((double, \ + retraction, \ + Retraction, \ + 0.0, \ + "Tool retraction absolute coordinate along retraction axis", \ + App::PropertyLength)) \ + ((double, \ + resume_height, \ + ResumeHeight, \ + 0.0, \ + "When return from last retraction, this gives the pause height relative to the Z\n" \ + "value of the next move.", \ + App::PropertyLength))( \ + (double, \ + segmentation, \ + Segmentation, \ + 0.0, \ + "Break long curves into segments of this length. One use case is for PCB autolevel,\n" \ + "so that more correction points can be inserted", \ + App::PropertyLength))( \ + (double, feedrate, FeedRate, 0.0, "Normal move feed rate", App::PropertyFloat))( \ + (double, \ + feedrate_v, \ + FeedRateVertical, \ + 0.0, \ + "Vertical only (step down) move feed rate", \ + App::PropertyFloat))( \ + (bool, \ + verbose, \ + Verbose, \ + true, \ + "If true, each motion GCode will contain full coordinate and feedrate"))( \ + (bool, abs_center, AbsoluteArcCenter, false, "Use absolute arc center mode (G90.1)"))( \ + (bool, preamble, EmitPreamble, true, "Emit preambles"))AREA_PARAMS_DEFLECTION /** Group of all Area configuration parameters except CArea's*/ -#define AREA_PARAMS_AREA \ - AREA_PARAMS_BASE \ - AREA_PARAMS_OFFSET \ - AREA_PARAMS_OFFSET_CONF \ - AREA_PARAMS_POCKET \ - AREA_PARAMS_POCKET_CONF \ +#define AREA_PARAMS_AREA \ + AREA_PARAMS_BASE \ + AREA_PARAMS_OFFSET \ + AREA_PARAMS_OFFSET_CONF \ + AREA_PARAMS_POCKET \ + AREA_PARAMS_POCKET_CONF \ AREA_PARAMS_SECTION /** Group of all Area configuration parameters */ -#define AREA_PARAMS_CONF \ - AREA_PARAMS_CAREA \ +#define AREA_PARAMS_CONF \ + AREA_PARAMS_CAREA \ AREA_PARAMS_AREA /** Group of all Area parameters */ -#define AREA_PARAMS_ALL \ - AREA_PARAMS_CONF \ +#define AREA_PARAMS_ALL \ + AREA_PARAMS_CONF \ AREA_PARAMS_OPCODE -#define AREA_PARAMS_STATIC_CONF \ - AREA_PARAMS_CONF +#define AREA_PARAMS_STATIC_CONF AREA_PARAMS_CONF -#endif //PATH_AreaParam_H +#endif // PATH_AreaParam_H diff --git a/src/Mod/CAM/App/AreaPyImp.cpp b/src/Mod/CAM/App/AreaPyImp.cpp index bbfb1b5088..0775160615 100644 --- a/src/Mod/CAM/App/AreaPyImp.cpp +++ b/src/Mod/CAM/App/AreaPyImp.cpp @@ -33,10 +33,11 @@ #include "AreaPy.cpp" -static PyObject * areaAbort(PyObject *, PyObject *args, PyObject *kwd) { - static const std::array kwlist{"aborting", nullptr}; - PyObject *pObj = Py_True; - if (!Base::Wrapped_ParseTupleAndKeywords(args,kwd,"|O!",kwlist,&PyBool_Type,&pObj)) { +static PyObject* areaAbort(PyObject*, PyObject* args, PyObject* kwd) +{ + static const std::array kwlist {"aborting", nullptr}; + PyObject* pObj = Py_True; + if (!Base::Wrapped_ParseTupleAndKeywords(args, kwd, "|O!", kwlist, &PyBool_Type, &pObj)) { return nullptr; } @@ -45,161 +46,224 @@ static PyObject * areaAbort(PyObject *, PyObject *args, PyObject *kwd) { Py_Return; } -static PyObject * areaSetParams(PyObject *, PyObject *args, PyObject *kwd) { +static PyObject* areaSetParams(PyObject*, PyObject* args, PyObject* kwd) +{ - static const std::array kwlist {PARAM_FIELD_STRINGS(NAME,AREA_PARAMS_STATIC_CONF),nullptr}; + static const std::array kwlist { + PARAM_FIELD_STRINGS(NAME, AREA_PARAMS_STATIC_CONF), + nullptr}; - if(args && PySequence_Size(args)>0) - PyErr_SetString(PyExc_ValueError,"Non-keyword argument is not supported"); + if (args && PySequence_Size(args) > 0) { + PyErr_SetString(PyExc_ValueError, "Non-keyword argument is not supported"); + } - //Declare variables defined in the NAME field of the CONF parameter list - PARAM_PY_DECLARE(PARAM_FNAME,AREA_PARAMS_STATIC_CONF); + // Declare variables defined in the NAME field of the CONF parameter list + PARAM_PY_DECLARE(PARAM_FNAME, AREA_PARAMS_STATIC_CONF); AreaStaticParams params = Area::getDefaultParams(); -#define AREA_SET(_param) \ - PARAM_FNAME(_param) = \ - PARAM_TYPED(PARAM_PY_CAST_,_param)(params.PARAM_FNAME(_param)); - //populate the CONF variables with params - PARAM_FOREACH(AREA_SET,AREA_PARAMS_STATIC_CONF) +#define AREA_SET(_param) \ + PARAM_FNAME(_param) = PARAM_TYPED(PARAM_PY_CAST_, _param)(params.PARAM_FNAME(_param)); + // populate the CONF variables with params + PARAM_FOREACH(AREA_SET, AREA_PARAMS_STATIC_CONF) - //Parse arguments to overwrite CONF variables - if (!Base::Wrapped_ParseTupleAndKeywords(args, kwd, - "|" PARAM_PY_KWDS(AREA_PARAMS_STATIC_CONF), kwlist, - PARAM_REF(PARAM_FNAME,AREA_PARAMS_STATIC_CONF))) + // Parse arguments to overwrite CONF variables + if (!Base::Wrapped_ParseTupleAndKeywords(args, + kwd, + "|" PARAM_PY_KWDS(AREA_PARAMS_STATIC_CONF), + kwlist, + PARAM_REF(PARAM_FNAME, AREA_PARAMS_STATIC_CONF))) { return nullptr; + } -#define AREA_GET(_param) \ - params.PARAM_FNAME(_param) = \ - PARAM_TYPED(PARAM_CAST_PY_,_param)(PARAM_FNAME(_param)); - //populate 'params' with the CONF variables - PARAM_FOREACH(AREA_GET,AREA_PARAMS_STATIC_CONF) +#define AREA_GET(_param) \ + params.PARAM_FNAME(_param) = PARAM_TYPED(PARAM_CAST_PY_, _param)(PARAM_FNAME(_param)); + // populate 'params' with the CONF variables + PARAM_FOREACH(AREA_GET, AREA_PARAMS_STATIC_CONF) Area::setDefaultParams(params); Py_INCREF(Py_None); return Py_None; } -static PyObject* areaGetParams(PyObject *, PyObject *args) { - if (!PyArg_ParseTuple(args, "")) +static PyObject* areaGetParams(PyObject*, PyObject* args) +{ + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } - const AreaStaticParams ¶ms = Area::getDefaultParams(); + const AreaStaticParams& params = Area::getDefaultParams(); - PyObject *dict = PyDict_New(); + PyObject* dict = PyDict_New(); #define AREA_SRC(_param) params.PARAM_FNAME(_param) - PARAM_PY_DICT_SET_VALUE(dict,NAME,AREA_SRC,AREA_PARAMS_STATIC_CONF) + PARAM_PY_DICT_SET_VALUE(dict, NAME, AREA_SRC, AREA_PARAMS_STATIC_CONF) return dict; } -static PyObject * areaGetParamsDesc(PyObject *, PyObject *args, PyObject *kwd) { - PyObject *pcObj = Py_False; - static const std::array kwlist {"as_string", nullptr}; - if (!Base::Wrapped_ParseTupleAndKeywords(args, kwd, "|O!",kwlist,&PyBool_Type,&pcObj)) +static PyObject* areaGetParamsDesc(PyObject*, PyObject* args, PyObject* kwd) +{ + PyObject* pcObj = Py_False; + static const std::array kwlist {"as_string", nullptr}; + if (!Base::Wrapped_ParseTupleAndKeywords(args, kwd, "|O!", kwlist, &PyBool_Type, &pcObj)) { return nullptr; + } - if (Base::asBoolean(pcObj)) - return PyUnicode_FromString(PARAM_PY_DOC(NAME,AREA_PARAMS_STATIC_CONF)); + if (Base::asBoolean(pcObj)) { + return PyUnicode_FromString(PARAM_PY_DOC(NAME, AREA_PARAMS_STATIC_CONF)); + } - PyObject *dict = PyDict_New(); - PARAM_PY_DICT_SET_DOC(dict,NAME,AREA_PARAMS_STATIC_CONF) + PyObject* dict = PyDict_New(); + PARAM_PY_DICT_SET_DOC(dict, NAME, AREA_PARAMS_STATIC_CONF) return dict; } static const PyMethodDef areaOverrides[] = { + {"setParams", + nullptr, + 0, + "setParam(key=value...): Set algorithm parameters. You can call getParamsDesc() to \n" + "get a list of supported parameters and their descriptions.\n" PARAM_PY_DOC(NAME, + AREA_PARAMS_CONF)}, { - "setParams",nullptr,0, - "setParam(key=value...): Set algorithm parameters. You can call getParamsDesc() to \n" - "get a list of supported parameters and their descriptions.\n" - PARAM_PY_DOC(NAME,AREA_PARAMS_CONF) - }, - { - "add",nullptr,0, - "add((shape...)," PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_OPCODE) "):\n" - "Add TopoShape(s) with given operation code\n" - PARAM_PY_DOC(ARG,AREA_PARAMS_OPCODE) - "\nThe first shape's wires will be unioned together regardless of the op code given\n" - "(except for 'Compound'). Subsequent shape's wire will be combined using the op code.\n" - "All shape wires shall be coplanar, and are used to determine a working plane for face\n" - "making and offsetting. You can call setPlane() to supply a reference shape to determine\n" - "the workplane in case the added shapes are all colinear lines.\n", + "add", + nullptr, + 0, + "add((shape...)," PARAM_PY_ARGS_DOC( + ARG, + AREA_PARAMS_OPCODE) "):\n" + "Add TopoShape(s) with given operation code\n" PARAM_PY_DOC( + ARG, + AREA_PARAMS_OPCODE) "\nThe first shape's wires will be unioned " + "together regardless of the op code given\n" + "(except for 'Compound'). Subsequent " + "shape's wire will be combined using the " + "op code.\n" + "All shape wires shall be coplanar, and " + "are used to determine a working plane for " + "face\n" + "making and offsetting. You can call " + "setPlane() to supply a reference shape to " + "determine\n" + "the workplane in case the added shapes " + "are all colinear lines.\n", }, { - "makeOffset",nullptr,0, - "makeOffset(index=-1, " PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_OFFSET) "):\n" - "Make an 2D offset of the shape.\n" - "\n* index (-1): the index of the section. -1 means all sections. No effect on planar shape.\n" - PARAM_PY_DOC(ARG,AREA_PARAMS_OFFSET), + "makeOffset", + nullptr, + 0, + "makeOffset(index=-1, " PARAM_PY_ARGS_DOC( + ARG, + AREA_PARAMS_OFFSET) "):\n" + "Make an 2D offset of the shape.\n" + "\n* index (-1): the index of the section. -1 means all sections. " + "No effect on planar shape.\n" PARAM_PY_DOC(ARG, + AREA_PARAMS_OFFSET), }, { - "makePocket",nullptr,0, - "makePocket(index=-1, " PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_POCKET) "):\n" - "Generate pocket toolpath of the shape.\n" - "\n* index (-1): the index of the section. -1 means all sections. No effect on planar shape.\n" - PARAM_PY_DOC(ARG,AREA_PARAMS_POCKET), + "makePocket", + nullptr, + 0, + "makePocket(index=-1, " PARAM_PY_ARGS_DOC( + ARG, + AREA_PARAMS_POCKET) "):\n" + "Generate pocket toolpath of the shape.\n" + "\n* index (-1): the index of the section. -1 means all sections. " + "No effect on planar shape.\n" PARAM_PY_DOC(ARG, + AREA_PARAMS_POCKET), }, { - "makeSections",nullptr,0, - "makeSections(" PARAM_PY_ARGS_DOC(ARG,AREA_PARAMS_SECTION_EXTRA) ", heights=[], plane=None):\n" - "Make a list of area holding the sectioned children shapes on given heights\n" - PARAM_PY_DOC(ARG,AREA_PARAMS_SECTION_EXTRA) - "\n* heights ([]): a list of section heights, the meaning of the value is determined by 'mode'.\n" - "If not specified, the current SectionCount, and SectionOffset of this Area is used.\n" - "\n* plane (None): optional shape to specify a section plane. If not give, the current workplane\n" - "of this Area is used if section mode is 'Workplane'.", + "makeSections", + nullptr, + 0, + "makeSections(" PARAM_PY_ARGS_DOC( + ARG, + AREA_PARAMS_SECTION_EXTRA) ", heights=[], plane=None):\n" + "Make a list of area holding the sectioned children shapes " + "on given heights\n" PARAM_PY_DOC( + ARG, + AREA_PARAMS_SECTION_EXTRA) "\n* heights ([]): a list of " + "section heights, the " + "meaning of the value is " + "determined by 'mode'.\n" + "If not specified, the " + "current SectionCount, and " + "SectionOffset of this Area " + "is used.\n" + "\n* plane (None): optional " + "shape to specify a section " + "plane. If not give, the " + "current workplane\n" + "of this Area is used if " + "section mode is " + "'Workplane'.", }, { - "getClearedArea",nullptr,0, + "getClearedArea", + nullptr, + 0, "getClearedArea(path, diameter, zmax, bbox):\n" - "Gets the area cleared when a tool of the specified diameter follows the gcode represented in the path, ignoring cleared space above zmax and path segments that don't affect space within the x/y space of bbox.\n", + "Gets the area cleared when a tool of the specified diameter follows the gcode represented " + "in the path, ignoring cleared space above zmax and path segments that don't affect space " + "within the x/y space of bbox.\n", }, { - "getRestArea",nullptr,0, + "getRestArea", + nullptr, + 0, "getRestArea(clearedAreas, diameter):\n" - "Rest machining: gets the area left to be machined, assuming some of this area has already been cleared previous tool paths.\n" + "Rest machining: gets the area left to be machined, assuming some of this area has already " + "been cleared previous tool paths.\n" "clearedAreas: the regions already cleared.\n" "diameter: the tool diameter that finishes clearing this area.\n", }, + {"toTopoShape", nullptr, 0, "toTopoShape():\n"}, + {"setDefaultParams", + reinterpret_cast(reinterpret_cast(areaSetParams)), + METH_VARARGS | METH_KEYWORDS | METH_STATIC, + "setDefaultParams(key=value...):\n" + "Static method to set the default parameters of all following Path.Area, plus the following\n" + "additional parameters.\n"}, + {"getDefaultParams", + (PyCFunction)areaGetParams, + METH_VARARGS | METH_STATIC, + "getDefaultParams(): Static method to return the current default parameters."}, { - "toTopoShape",nullptr,0, - "toTopoShape():\n" - }, - { - "setDefaultParams",reinterpret_cast(reinterpret_cast(areaSetParams)), METH_VARARGS|METH_KEYWORDS|METH_STATIC, - "setDefaultParams(key=value...):\n" - "Static method to set the default parameters of all following Path.Area, plus the following\n" - "additional parameters.\n" - }, - { - "getDefaultParams",(PyCFunction)areaGetParams, METH_VARARGS|METH_STATIC, - "getDefaultParams(): Static method to return the current default parameters." - }, - { - "abort",reinterpret_cast(reinterpret_cast(areaAbort)), METH_VARARGS|METH_KEYWORDS|METH_STATIC, + "abort", + reinterpret_cast(reinterpret_cast(areaAbort)), + METH_VARARGS | METH_KEYWORDS | METH_STATIC, "abort(aborting=True): Static method to abort any ongoing operation\n" - "\nTo ensure no stray abortion is left in the previous operation, it is advised to manually clear\n" + "\nTo ensure no stray abortion is left in the previous operation, it is advised to " + "manually clear\n" "the aborting flag by calling abort(False) before starting a new operation.", }, - { - "getParamsDesc",reinterpret_cast(reinterpret_cast(areaGetParamsDesc)), METH_VARARGS|METH_KEYWORDS|METH_STATIC, - "getParamsDesc(as_string=False): Returns a list of supported parameters and their descriptions.\n" - "\n* as_string: if False, then return a dictionary of documents of all supported parameters." - }, + {"getParamsDesc", + reinterpret_cast(reinterpret_cast(areaGetParamsDesc)), + METH_VARARGS | METH_KEYWORDS | METH_STATIC, + "getParamsDesc(as_string=False): Returns a list of supported parameters and their " + "descriptions.\n" + "\n* as_string: if False, then return a dictionary of documents of all supported parameters."}, }; -struct AreaPyModifier { - AreaPyModifier() { - for(auto &method : Path::AreaPy::Methods) { - if(!method.ml_name) continue; - for(auto &entry : areaOverrides) { - if(std::strcmp(method.ml_name,entry.ml_name)==0) { - if(entry.ml_doc) +struct AreaPyModifier +{ + AreaPyModifier() + { + for (auto& method : Path::AreaPy::Methods) { + if (!method.ml_name) { + continue; + } + for (auto& entry : areaOverrides) { + if (std::strcmp(method.ml_name, entry.ml_name) == 0) { + if (entry.ml_doc) { method.ml_doc = entry.ml_doc; - if(entry.ml_meth) + } + if (entry.ml_meth) { method.ml_meth = entry.ml_meth; - if(entry.ml_flags) + } + if (entry.ml_flags) { method.ml_flags = entry.ml_flags; + } break; } } @@ -219,10 +283,10 @@ std::string AreaPy::representation() const return str.str(); } -PyObject *AreaPy::PyMake(struct _typeobject *, PyObject *args, PyObject *kwd) // Python wrapper +PyObject* AreaPy::PyMake(struct _typeobject*, PyObject* args, PyObject* kwd) // Python wrapper { AreaPy* ret = new AreaPy(new Area); - if(!ret->setParams(args,kwd)) { + if (!ret->setParams(args, kwd)) { Py_DecRef(ret); return nullptr; } @@ -234,15 +298,17 @@ PyObject *AreaPy::PyMake(struct _typeobject *, PyObject *args, PyObject *kwd) / } // constructor method -int AreaPy::PyInit(PyObject* , PyObject* ) +int AreaPy::PyInit(PyObject*, PyObject*) { return 0; } -PyObject* AreaPy::setPlane(PyObject *args) { - PyObject *pcObj; - if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapePy::Type), &pcObj)) +PyObject* AreaPy::setPlane(PyObject* args) +{ + PyObject* pcObj; + if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapePy::Type), &pcObj)) { return nullptr; + } #define GET_TOPOSHAPE(_p) static_cast(_p)->getTopoShapePtr()->getShape() getAreaPtr()->setPlane(GET_TOPOSHAPE(pcObj)); @@ -250,307 +316,368 @@ PyObject* AreaPy::setPlane(PyObject *args) { return this; } -PyObject* AreaPy::getShape(PyObject *args, PyObject *keywds) +PyObject* AreaPy::getShape(PyObject* args, PyObject* keywds) { - PyObject *pcObj = Py_False; - short index=-1; - static const std::array kwlist{"index", "rebuild", nullptr}; - if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds,"|hO!",kwlist,&index,&PyBool_Type,&pcObj)) + PyObject* pcObj = Py_False; + short index = -1; + static const std::array kwlist {"index", "rebuild", nullptr}; + if (!Base::Wrapped_ParseTupleAndKeywords(args, + keywds, + "|hO!", + kwlist, + &index, + &PyBool_Type, + &pcObj)) { return nullptr; + } - PY_TRY { - if (Base::asBoolean(pcObj)) + PY_TRY + { + if (Base::asBoolean(pcObj)) { getAreaPtr()->clean(); + } return Py::new_reference_to(Part::shape2pyshape(getAreaPtr()->getShape(index))); - } PY_CATCH_OCC + } + PY_CATCH_OCC } -PyObject* AreaPy::add(PyObject *args, PyObject *keywds) +PyObject* AreaPy::add(PyObject* args, PyObject* keywds) { - PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_OPCODE) - PyObject *pcObj; + PARAM_PY_DECLARE_INIT(PARAM_FARG, AREA_PARAMS_OPCODE) + PyObject* pcObj; - //Strangely, PyArg_ParseTupleAndKeywords requires all arguments to be keyword based, - //even non-optional ones? That doesn't make sense in python. Seems only in python 3 - //they added '$' to address that issue. - static const std::array kwlist {"shape",PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_OPCODE), nullptr}; + // Strangely, PyArg_ParseTupleAndKeywords requires all arguments to be keyword based, + // even non-optional ones? That doesn't make sense in python. Seems only in python 3 + // they added '$' to address that issue. + static const std::array kwlist {"shape", + PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_OPCODE), + nullptr}; - if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, - "O|" PARAM_PY_KWDS(AREA_PARAMS_OPCODE), - kwlist,&pcObj,PARAM_REF(PARAM_FARG,AREA_PARAMS_OPCODE))) + if (!Base::Wrapped_ParseTupleAndKeywords(args, + keywds, + "O|" PARAM_PY_KWDS(AREA_PARAMS_OPCODE), + kwlist, + &pcObj, + PARAM_REF(PARAM_FARG, AREA_PARAMS_OPCODE))) { return nullptr; + } - PY_TRY { + PY_TRY + { if (PyObject_TypeCheck(pcObj, &(Part::TopoShapePy::Type))) { - getAreaPtr()->add(GET_TOPOSHAPE(pcObj),op); + getAreaPtr()->add(GET_TOPOSHAPE(pcObj), op); Py_INCREF(this); return this; - } else if (PyObject_TypeCheck(pcObj, &(PyList_Type)) || - PyObject_TypeCheck(pcObj, &(PyTuple_Type))) { + } + else if (PyObject_TypeCheck(pcObj, &(PyList_Type)) + || PyObject_TypeCheck(pcObj, &(PyTuple_Type))) { Py::Sequence shapeSeq(pcObj); for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) { PyObject* item = (*it).ptr(); - if(!PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) { + if (!PyObject_TypeCheck(item, &(Part::TopoShapePy::Type))) { PyErr_SetString(PyExc_TypeError, "non-shape object in sequence"); return nullptr; } } - for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it){ + for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) { PyObject* item = (*it).ptr(); getAreaPtr()->add(GET_TOPOSHAPE(item), - PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_OPCODE)); + PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_OPCODE)); } Py_INCREF(this); return this; } - } PY_CATCH_OCC + } + PY_CATCH_OCC PyErr_SetString(PyExc_TypeError, "shape must be 'TopoShape' or list of 'TopoShape'"); return nullptr; } -PyObject* AreaPy::makeOffset(PyObject *args, PyObject *keywds) +PyObject* AreaPy::makeOffset(PyObject* args, PyObject* keywds) { - //Generate a keyword string defined in the ARG field of OFFSET parameter list - static const std::array kwlist {"index",PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_OFFSET), nullptr}; + // Generate a keyword string defined in the ARG field of OFFSET parameter list + static const std::array kwlist {"index", + PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_OFFSET), + nullptr}; short index = -1; - //Declare variables defined in the ARG field of the OFFSET parameter list with - //initialization to defaults - PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_OFFSET) + // Declare variables defined in the ARG field of the OFFSET parameter list with + // initialization to defaults + PARAM_PY_DECLARE_INIT(PARAM_FARG, AREA_PARAMS_OFFSET) - //Parse arguments to overwrite the defaults - if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, - "|h" PARAM_PY_KWDS(AREA_PARAMS_OFFSET), kwlist, - &index,PARAM_REF(PARAM_FARG,AREA_PARAMS_OFFSET))) + // Parse arguments to overwrite the defaults + if (!Base::Wrapped_ParseTupleAndKeywords(args, + keywds, + "|h" PARAM_PY_KWDS(AREA_PARAMS_OFFSET), + kwlist, + &index, + PARAM_REF(PARAM_FARG, AREA_PARAMS_OFFSET))) { return nullptr; + } - PY_TRY { - //Expand the variable as function call arguments - TopoDS_Shape resultShape = getAreaPtr()->makeOffset(index, - PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_OFFSET)); + PY_TRY + { + // Expand the variable as function call arguments + TopoDS_Shape resultShape = + getAreaPtr()->makeOffset(index, PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_OFFSET)); return Py::new_reference_to(Part::shape2pyshape(resultShape)); - } PY_CATCH_OCC + } + PY_CATCH_OCC } -PyObject* AreaPy::makePocket(PyObject *args, PyObject *keywds) +PyObject* AreaPy::makePocket(PyObject* args, PyObject* keywds) { - static const std::array kwlist {"index",PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_POCKET), nullptr}; + static const std::array kwlist {"index", + PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_POCKET), + nullptr}; short index = -1; - PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_POCKET) - //Override pocket mode default + PARAM_PY_DECLARE_INIT(PARAM_FARG, AREA_PARAMS_POCKET) + // Override pocket mode default mode = Area::PocketModeZigZagOffset; - if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, - "|h" PARAM_PY_KWDS(AREA_PARAMS_POCKET), kwlist, - &index,PARAM_REF(PARAM_FARG,AREA_PARAMS_POCKET))) { + if (!Base::Wrapped_ParseTupleAndKeywords(args, + keywds, + "|h" PARAM_PY_KWDS(AREA_PARAMS_POCKET), + kwlist, + &index, + PARAM_REF(PARAM_FARG, AREA_PARAMS_POCKET))) { return nullptr; } - PY_TRY { - TopoDS_Shape resultShape = getAreaPtr()->makePocket(index, - PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_POCKET)); + PY_TRY + { + TopoDS_Shape resultShape = + getAreaPtr()->makePocket(index, PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_POCKET)); return Py::new_reference_to(Part::shape2pyshape(resultShape)); - } PY_CATCH_OCC + } + PY_CATCH_OCC } -PyObject* AreaPy::makeSections(PyObject *args, PyObject *keywds) +PyObject* AreaPy::makeSections(PyObject* args, PyObject* keywds) { - static const std::array kwlist {PARAM_FIELD_STRINGS(ARG,AREA_PARAMS_SECTION_EXTRA), - "heights", "plane", nullptr}; - PyObject *heights = nullptr; - PyObject *plane = nullptr; + static const std::array kwlist { + PARAM_FIELD_STRINGS(ARG, AREA_PARAMS_SECTION_EXTRA), + "heights", + "plane", + nullptr}; + PyObject* heights = nullptr; + PyObject* plane = nullptr; - PARAM_PY_DECLARE_INIT(PARAM_FARG,AREA_PARAMS_SECTION_EXTRA) + PARAM_PY_DECLARE_INIT(PARAM_FARG, AREA_PARAMS_SECTION_EXTRA) - if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, - "|" PARAM_PY_KWDS(AREA_PARAMS_SECTION_EXTRA) "OO!", kwlist, - PARAM_REF(PARAM_FARG,AREA_PARAMS_SECTION_EXTRA), - &heights, &(Part::TopoShapePy::Type), &plane)) { + if (!Base::Wrapped_ParseTupleAndKeywords(args, + keywds, + "|" PARAM_PY_KWDS(AREA_PARAMS_SECTION_EXTRA) "OO!", + kwlist, + PARAM_REF(PARAM_FARG, AREA_PARAMS_SECTION_EXTRA), + &heights, + &(Part::TopoShapePy::Type), + &plane)) { return nullptr; } - PY_TRY { + PY_TRY + { std::vector h; - if(heights) { - if (PyObject_TypeCheck(heights, &(PyFloat_Type))) + if (heights) { + if (PyObject_TypeCheck(heights, &(PyFloat_Type))) { h.push_back(PyFloat_AsDouble(heights)); - else if (PyObject_TypeCheck(heights, &(PyList_Type)) || - PyObject_TypeCheck(heights, &(PyTuple_Type))) { + } + else if (PyObject_TypeCheck(heights, &(PyList_Type)) + || PyObject_TypeCheck(heights, &(PyTuple_Type))) { Py::Sequence shapeSeq(heights); h.reserve(shapeSeq.size()); for (Py::Sequence::iterator it = shapeSeq.begin(); it != shapeSeq.end(); ++it) { PyObject* item = (*it).ptr(); - if(!PyObject_TypeCheck(item, &(PyFloat_Type))) { + if (!PyObject_TypeCheck(item, &(PyFloat_Type))) { PyErr_SetString(PyExc_TypeError, "heights must only contain float type"); return nullptr; } h.push_back(PyFloat_AsDouble(item)); } - }else{ - PyErr_SetString(PyExc_TypeError, "heights must be of type float or list/tuple of float"); + } + else { + PyErr_SetString(PyExc_TypeError, + "heights must be of type float or list/tuple of float"); return nullptr; } } - std::vector > sections = getAreaPtr()->makeSections( - PARAM_PY_FIELDS(PARAM_FARG,AREA_PARAMS_SECTION_EXTRA), - h,plane?GET_TOPOSHAPE(plane):TopoDS_Shape()); + std::vector> sections = + getAreaPtr()->makeSections(PARAM_PY_FIELDS(PARAM_FARG, AREA_PARAMS_SECTION_EXTRA), + h, + plane ? GET_TOPOSHAPE(plane) : TopoDS_Shape()); Py::List ret; - for(auto &area : sections) - ret.append(Py::asObject(new AreaPy(new Area(*area,true)))); + for (auto& area : sections) { + ret.append(Py::asObject(new AreaPy(new Area(*area, true)))); + } return Py::new_reference_to(ret); - } PY_CATCH_OCC + } + PY_CATCH_OCC } -PyObject* AreaPy::getClearedArea(PyObject *args) -{ - PY_TRY { - PyObject *pyPath, *pyBbox; - double diameter, zmax; - if (!PyArg_ParseTuple(args, "OddO", &pyPath, &diameter, &zmax, &pyBbox)) - return nullptr; - if (!PyObject_TypeCheck(pyPath, &(PathPy::Type))) { - PyErr_SetString(PyExc_TypeError, "path must be of type PathPy"); - return nullptr; - } - if (!PyObject_TypeCheck(pyBbox, &(Base::BoundBoxPy::Type))) { - PyErr_SetString(PyExc_TypeError, "bbox must be of type BoundBoxPy"); - return nullptr; - } - const PathPy *path = static_cast(pyPath); - const Py::BoundingBox bbox(pyBbox, false); - std::shared_ptr clearedArea = getAreaPtr()->getClearedArea(path->getToolpathPtr(), diameter, zmax, bbox.getValue()); - auto pyClearedArea = Py::asObject(new AreaPy(new Area(*clearedArea, true))); - return Py::new_reference_to(pyClearedArea); - } PY_CATCH_OCC +PyObject* AreaPy::getClearedArea(PyObject* args) {PY_TRY {PyObject * pyPath, *pyBbox; +double diameter, zmax; +if (!PyArg_ParseTuple(args, "OddO", &pyPath, &diameter, &zmax, &pyBbox)) { + return nullptr; +} +if (!PyObject_TypeCheck(pyPath, &(PathPy::Type))) { + PyErr_SetString(PyExc_TypeError, "path must be of type PathPy"); + return nullptr; +} +if (!PyObject_TypeCheck(pyBbox, &(Base::BoundBoxPy::Type))) { + PyErr_SetString(PyExc_TypeError, "bbox must be of type BoundBoxPy"); + return nullptr; +} +const PathPy* path = static_cast(pyPath); +const Py::BoundingBox bbox(pyBbox, false); +std::shared_ptr clearedArea = + getAreaPtr()->getClearedArea(path->getToolpathPtr(), diameter, zmax, bbox.getValue()); +auto pyClearedArea = Py::asObject(new AreaPy(new Area(*clearedArea, true))); +return Py::new_reference_to(pyClearedArea); +} +PY_CATCH_OCC } -PyObject* AreaPy::getRestArea(PyObject *args) -{ - PY_TRY { - PyObject *pyClearedAreas; - std::vector> clearedAreas; - double diameter; - if (!PyArg_ParseTuple(args, "Od", &pyClearedAreas, &diameter)) - return nullptr; - if (pyClearedAreas && PyObject_TypeCheck(pyClearedAreas, &PyList_Type)) { - Py::Sequence clearedAreasSeq(pyClearedAreas); - clearedAreas.reserve(clearedAreasSeq.size()); - for (Py::Sequence::iterator it = clearedAreasSeq.begin(); it != clearedAreasSeq.end(); ++it) { - PyObject *item = (*it).ptr(); - if (!PyObject_TypeCheck(item, &(AreaPy::Type))) { - PyErr_SetString(PyExc_TypeError, "cleared areas must only contain AreaPy type"); - return nullptr; - } - clearedAreas.push_back(std::make_shared(*static_cast(item)->getAreaPtr(), true)); - } - } else { - PyErr_SetString(PyExc_TypeError, "clearedAreas must be of type list of AreaPy"); +PyObject* AreaPy::getRestArea(PyObject* args) {PY_TRY {PyObject * pyClearedAreas; +std::vector> clearedAreas; +double diameter; +if (!PyArg_ParseTuple(args, "Od", &pyClearedAreas, &diameter)) { + return nullptr; +} +if (pyClearedAreas && PyObject_TypeCheck(pyClearedAreas, &PyList_Type)) { + Py::Sequence clearedAreasSeq(pyClearedAreas); + clearedAreas.reserve(clearedAreasSeq.size()); + for (Py::Sequence::iterator it = clearedAreasSeq.begin(); it != clearedAreasSeq.end(); ++it) { + PyObject* item = (*it).ptr(); + if (!PyObject_TypeCheck(item, &(AreaPy::Type))) { + PyErr_SetString(PyExc_TypeError, "cleared areas must only contain AreaPy type"); return nullptr; } - - std::shared_ptr restArea = getAreaPtr()->getRestArea(clearedAreas, diameter); - if (!restArea) { - return Py_None; - } - auto pyRestArea = Py::asObject(new AreaPy(new Area(*restArea, true))); - return Py::new_reference_to(pyRestArea); - } PY_CATCH_OCC + clearedAreas.push_back( + std::make_shared(*static_cast(item)->getAreaPtr(), true)); + } +} +else { + PyErr_SetString(PyExc_TypeError, "clearedAreas must be of type list of AreaPy"); + return nullptr; } -PyObject* AreaPy::toTopoShape(PyObject *args) -{ - PY_TRY { - if (!PyArg_ParseTuple(args, "")) - return nullptr; - return Py::new_reference_to(Part::shape2pyshape(getAreaPtr()->toTopoShape())); - } PY_CATCH_OCC +std::shared_ptr restArea = getAreaPtr()->getRestArea(clearedAreas, diameter); +if (!restArea) { + return Py_None; +} +auto pyRestArea = Py::asObject(new AreaPy(new Area(*restArea, true))); +return Py::new_reference_to(pyRestArea); +} +PY_CATCH_OCC } -PyObject* AreaPy::setDefaultParams(PyObject *, PyObject *) +PyObject* AreaPy::toTopoShape(PyObject* args) { + PY_TRY {if (!PyArg_ParseTuple(args, "")) return nullptr; +return Py::new_reference_to(Part::shape2pyshape(getAreaPtr()->toTopoShape())); +} +PY_CATCH_OCC +} + +PyObject* AreaPy::setDefaultParams(PyObject*, PyObject*) { return nullptr; } -PyObject* AreaPy::setParams(PyObject *args, PyObject *keywds) +PyObject* AreaPy::setParams(PyObject* args, PyObject* keywds) { - static const std::array kwlist {PARAM_FIELD_STRINGS(NAME,AREA_PARAMS_CONF),nullptr}; + static const std::array kwlist {PARAM_FIELD_STRINGS(NAME, AREA_PARAMS_CONF), + nullptr}; - //Declare variables defined in the NAME field of the CONF parameter list - PARAM_PY_DECLARE(PARAM_FNAME,AREA_PARAMS_CONF); + // Declare variables defined in the NAME field of the CONF parameter list + PARAM_PY_DECLARE(PARAM_FNAME, AREA_PARAMS_CONF); AreaParams params = getAreaPtr()->getParams(); - //populate the CONF variables with params - PARAM_FOREACH(AREA_SET,AREA_PARAMS_CONF) + // populate the CONF variables with params + PARAM_FOREACH(AREA_SET, AREA_PARAMS_CONF) - //Parse arguments to overwrite CONF variables - if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, - "|" PARAM_PY_KWDS(AREA_PARAMS_CONF), kwlist, - PARAM_REF(PARAM_FNAME,AREA_PARAMS_CONF))) + // Parse arguments to overwrite CONF variables + if (!Base::Wrapped_ParseTupleAndKeywords(args, + keywds, + "|" PARAM_PY_KWDS(AREA_PARAMS_CONF), + kwlist, + PARAM_REF(PARAM_FNAME, AREA_PARAMS_CONF))) { return nullptr; + } - PY_TRY { - //populate 'params' with the CONF variables - PARAM_FOREACH(AREA_GET,AREA_PARAMS_CONF) + PY_TRY + { + // populate 'params' with the CONF variables + PARAM_FOREACH(AREA_GET, AREA_PARAMS_CONF) getAreaPtr()->setParams(params); Py_INCREF(this); return this; - } PY_CATCH_OCC + } + PY_CATCH_OCC } -PyObject* AreaPy::getParams(PyObject *args) +PyObject* AreaPy::getParams(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } - const AreaParams ¶ms =getAreaPtr()->getParams(); + const AreaParams& params = getAreaPtr()->getParams(); - PyObject *dict = PyDict_New(); - PARAM_PY_DICT_SET_VALUE(dict,NAME,AREA_SRC,AREA_PARAMS_CONF) + PyObject* dict = PyDict_New(); + PARAM_PY_DICT_SET_VALUE(dict, NAME, AREA_SRC, AREA_PARAMS_CONF) return dict; } -PyObject* AreaPy::getDefaultParams(PyObject *) +PyObject* AreaPy::getDefaultParams(PyObject*) { return nullptr; } -PyObject* AreaPy::abort(PyObject *, PyObject *) { - return nullptr; -} - -PyObject* AreaPy::getParamsDesc(PyObject *, PyObject *) +PyObject* AreaPy::abort(PyObject*, PyObject*) { return nullptr; } -Py::List AreaPy::getSections() const { +PyObject* AreaPy::getParamsDesc(PyObject*, PyObject*) +{ + return nullptr; +} + +Py::List AreaPy::getSections() const +{ Py::List ret; - Area *area = getAreaPtr(); - for(size_t i=0,count=area->getSectionCount(); igetSectionCount(); i < count; ++i) { ret.append(Part::shape2pyshape(getAreaPtr()->getShape(i))); + } return ret; } -Py::List AreaPy::getShapes() const { +Py::List AreaPy::getShapes() const +{ Py::List ret; - Area *area = getAreaPtr(); - const std::list &shapes = area->getChildren(); - for(auto &s : shapes) - ret.append(Py::TupleN(Part::shape2pyshape(s.shape),Py::Int(s.op))); + Area* area = getAreaPtr(); + const std::list& shapes = area->getChildren(); + for (auto& s : shapes) { + ret.append(Py::TupleN(Part::shape2pyshape(s.shape), Py::Int(s.op))); + } return ret; } -Py::Object AreaPy::getWorkplane() const { +Py::Object AreaPy::getWorkplane() const +{ return Part::shape2pyshape(getAreaPtr()->getPlane()); } -void AreaPy::setWorkplane(Py::Object obj) { +void AreaPy::setWorkplane(Py::Object obj) +{ PyObject* p = obj.ptr(); if (!PyObject_TypeCheck(p, &(Part::TopoShapePy::Type))) { std::string error = std::string("type must be 'TopoShape', not "); @@ -562,7 +689,7 @@ void AreaPy::setWorkplane(Py::Object obj) { // custom attributes get/set -PyObject *AreaPy::getCustomAttributes(const char* /*attr*/) const +PyObject* AreaPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } diff --git a/src/Mod/CAM/App/Command.cpp b/src/Mod/CAM/App/Command.cpp index 6d838688ae..ac8913b754 100644 --- a/src/Mod/CAM/App/Command.cpp +++ b/src/Mod/CAM/App/Command.cpp @@ -22,9 +22,9 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include -# include +#include +#include +#include #endif #include @@ -39,27 +39,24 @@ using namespace Base; using namespace Path; -TYPESYSTEM_SOURCE(Path::Command , Base::Persistence) +TYPESYSTEM_SOURCE(Path::Command, Base::Persistence) // Constructors & destructors -Command::Command(const char* name, - const std::map& parameters) -:Name(name),Parameters(parameters) -{ -} +Command::Command(const char* name, const std::map& parameters) + : Name(name) + , Parameters(parameters) +{} Command::Command() -{ -} +{} Command::~Command() -{ -} +{} // New methods -Placement Command::getPlacement (const Base::Vector3d pos) const +Placement Command::getPlacement(const Base::Vector3d pos) const { static const std::string x = "X"; static const std::string y = "Y"; @@ -67,19 +64,19 @@ Placement Command::getPlacement (const Base::Vector3d pos) const static const std::string a = "A"; static const std::string b = "B"; static const std::string c = "C"; - Vector3d vec(getParam(x, pos.x),getParam(y, pos.y),getParam(z, pos.z)); + Vector3d vec(getParam(x, pos.x), getParam(y, pos.y), getParam(z, pos.z)); Rotation rot; - rot.setYawPitchRoll(getParam(a),getParam(b),getParam(c)); - Placement plac(vec,rot); + rot.setYawPitchRoll(getParam(a), getParam(b), getParam(c)); + Placement plac(vec, rot); return plac; } -Vector3d Command::getCenter () const +Vector3d Command::getCenter() const { static const std::string i = "I"; static const std::string j = "J"; static const std::string k = "K"; - Vector3d vec(getParam(i),getParam(j),getParam(k)); + Vector3d vec(getParam(i), getParam(j), getParam(k)); return vec; } @@ -97,36 +94,45 @@ bool Command::has(const std::string& attr) const return Parameters.count(a) > 0; } -std::string Command::toGCode (int precision, bool padzero) const +std::string Command::toGCode(int precision, bool padzero) const { std::stringstream str; str.fill('0'); str << Name; - if(precision<0) + if (precision < 0) { precision = 0; - double scale = std::pow(10.0,precision+1); - std::int64_t iscale = static_cast(scale)/10; - for(std::map::const_iterator i = Parameters.begin(); i != Parameters.end(); ++i) { - if(i->first == "N") continue; + } + double scale = std::pow(10.0, precision + 1); + std::int64_t iscale = static_cast(scale) / 10; + for (std::map::const_iterator i = Parameters.begin(); + i != Parameters.end(); + ++i) { + if (i->first == "N") { + continue; + } str << " " << i->first; - std::int64_t v = static_cast(i->second*scale); - if(v<0) { + std::int64_t v = static_cast(i->second * scale); + if (v < 0) { v = -v; - str << '-'; //shall we allow -0 ? + str << '-'; // shall we allow -0 ? } - v+=5; + v += 5; v /= 10; - str << (v/iscale); - if(!precision) continue; + str << (v / iscale); + if (!precision) { + continue; + } int width = precision; - std::int64_t digits = v%iscale; - if(!padzero) { - if(!digits) continue; - while(digits%10 == 0) { - digits/=10; + std::int64_t digits = v % iscale; + if (!padzero) { + if (!digits) { + continue; + } + while (digits % 10 == 0) { + digits /= 10; --width; } } @@ -135,16 +141,17 @@ std::string Command::toGCode (int precision, bool padzero) const return str.str(); } -void Command::setFromGCode (const std::string& str) +void Command::setFromGCode(const std::string& str) { Parameters.clear(); std::string mode = "none"; std::string key; std::string value; - for (unsigned int i=0; i < str.size(); i++) { - if ( (isdigit(str[i])) || (str[i] == '-') || (str[i] == '.') ) { + for (unsigned int i = 0; i < str.size(); i++) { + if ((isdigit(str[i])) || (str[i] == '-') || (str[i] == '.')) { value += str[i]; - } else if (isalpha(str[i])) { + } + else if (isalpha(str[i])) { if (mode == "command") { if (!key.empty() && !value.empty()) { std::string cmd = key + value; @@ -153,32 +160,40 @@ void Command::setFromGCode (const std::string& str) key = ""; value = ""; mode = "argument"; - } else { + } + else { throw Base::BadFormatError("Badly formatted GCode command"); } mode = "argument"; - } else if (mode == "none") { + } + else if (mode == "none") { mode = "command"; - } else if (mode == "argument") { + } + else if (mode == "argument") { if (!key.empty() && !value.empty()) { double val = std::atof(value.c_str()); boost::to_upper(key); Parameters[key] = val; key = ""; value = ""; - } else { + } + else { throw Base::BadFormatError("Badly formatted GCode argument"); } - } else if (mode == "comment") { + } + else if (mode == "comment") { value += str[i]; } key = str[i]; - } else if (str[i] == '(') { + } + else if (str[i] == '(') { mode = "comment"; - } else if (str[i] == ')') { + } + else if (str[i] == ')') { key = "("; value += ")"; - } else { + } + else { // add non-ascii characters only if this is a comment if (mode == "comment") { value += str[i]; @@ -186,22 +201,25 @@ void Command::setFromGCode (const std::string& str) } } if (!key.empty() && !value.empty()) { - if ( (mode == "command") || (mode == "comment") ) { + if ((mode == "command") || (mode == "comment")) { std::string cmd = key + value; - if (mode == "command") + if (mode == "command") { boost::to_upper(cmd); + } Name = cmd; - } else { + } + else { double val = std::atof(value.c_str()); boost::to_upper(key); Parameters[key] = val; } - } else { + } + else { throw Base::BadFormatError("Badly formatted GCode argument"); } } -void Command::setFromPlacement (const Base::Placement &plac) +void Command::setFromPlacement(const Base::Placement& plac) { Name = "G1"; Parameters.clear(); @@ -215,26 +233,33 @@ void Command::setFromPlacement (const Base::Placement &plac) xval = plac.getPosition().x; yval = plac.getPosition().y; zval = plac.getPosition().z; - plac.getRotation().getYawPitchRoll(aval,bval,cval); - if (xval != 0.0) + plac.getRotation().getYawPitchRoll(aval, bval, cval); + if (xval != 0.0) { Parameters[x] = xval; - if (yval != 0.0) + } + if (yval != 0.0) { Parameters[y] = yval; - if (zval != 0.0) + } + if (zval != 0.0) { Parameters[z] = zval; - if (aval != 0.0) + } + if (aval != 0.0) { Parameters[a] = aval; - if (bval != 0.0) + } + if (bval != 0.0) { Parameters[b] = bval; - if (cval != 0.0) + } + if (cval != 0.0) { Parameters[c] = cval; + } } -void Command::setCenter(const Base::Vector3d &pos, bool clockwise) +void Command::setCenter(const Base::Vector3d& pos, bool clockwise) { if (clockwise) { Name = "G2"; - } else { + } + else { Name = "G3"; } static const std::string i = "I"; @@ -257,24 +282,32 @@ Command Command::transform(const Base::Placement& other) xval = plac.getPosition().x; yval = plac.getPosition().y; zval = plac.getPosition().z; - plac.getRotation().getYawPitchRoll(aval,bval,cval); + plac.getRotation().getYawPitchRoll(aval, bval, cval); Command c = Command(); c.Name = Name; - for(std::map::const_iterator i = Parameters.begin(); i != Parameters.end(); ++i) { + for (std::map::const_iterator i = Parameters.begin(); + i != Parameters.end(); + ++i) { std::string k = i->first; double v = i->second; - if (k == "X") + if (k == "X") { v = xval; - if (k == "Y") + } + if (k == "Y") { v = yval; - if (k == "Z") + } + if (k == "Z") { v = zval; - if (k == "A") + } + if (k == "A") { v = aval; - if (k == "B") + } + if (k == "B") { v = bval; - if (k == "C") + } + if (k == "C") { v = cval; + } c.Parameters[k] = v; } return c; @@ -282,7 +315,9 @@ Command Command::transform(const Base::Placement& other) void Command::scaleBy(double factor) { - for(std::map::const_iterator i = Parameters.begin(); i != Parameters.end(); ++i) { + for (std::map::const_iterator i = Parameters.begin(); + i != Parameters.end(); + ++i) { switch (i->first[0]) { case 'X': case 'Y': @@ -300,23 +335,22 @@ void Command::scaleBy(double factor) // Reimplemented from base class -unsigned int Command::getMemSize () const +unsigned int Command::getMemSize() const { return toGCode().size(); } -void Command::Save (Writer &writer) const +void Command::Save(Writer& writer) const { // this will only get used if saved as XML (probably never) writer.Stream() << writer.ind() << ""; - writer.Stream()<< std::endl; + writer.Stream() << std::endl; } -void Command::Restore(XMLReader &reader) +void Command::Restore(XMLReader& reader) { reader.readElement("Command"); std::string gcode = reader.getAttribute("gcode"); setFromGCode(gcode); } - diff --git a/src/Mod/CAM/App/Command.h b/src/Mod/CAM/App/Command.h index 28cc449e3d..37ef736d11 100644 --- a/src/Mod/CAM/App/Command.h +++ b/src/Mod/CAM/App/Command.h @@ -33,45 +33,52 @@ namespace Path { - /** The representation of a cnc command in a path */ - class PathExport Command : public Base::Persistence - { +/** The representation of a cnc command in a path */ +class PathExport Command: public Base::Persistence +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); - public: - //constructors - Command(); - Command(const char* name, - const std::map& parameters); - ~Command() override; - // from base class - unsigned int getMemSize () const override; - void Save (Base::Writer &/*writer*/) const override; - void Restore(Base::XMLReader &/*reader*/) override; +public: + // constructors + Command(); + Command(const char* name, const std::map& parameters); + ~Command() override; + // from base class + unsigned int getMemSize() const override; + void Save(Base::Writer& /*writer*/) const override; + void Restore(Base::XMLReader& /*reader*/) override; - // specific methods - Base::Placement getPlacement (const Base::Vector3d pos = Base::Vector3d()) const; // returns a placement from the x,y,z,a,b,c parameters - Base::Vector3d getCenter () const; // returns a 3d vector from the i,j,k parameters - void setCenter(const Base::Vector3d&, bool clockwise=true); // sets the center coordinates and the command name - std::string toGCode (int precision=6, bool padzero=true) const; // returns a GCode string representation of the command - void setFromGCode (const std::string&); // sets the parameters from the contents of the given GCode string - void setFromPlacement (const Base::Placement&); // sets the parameters from the contents of the given placement - bool has(const std::string&) const; // returns true if the given string exists in the parameters - Command transform(const Base::Placement&); // returns a transformed copy of this command - double getValue(const std::string &name) const; // returns the value of a given parameter - void scaleBy(double factor); // scales the receiver - use for imperial/metric conversions + // specific methods + Base::Placement getPlacement(const Base::Vector3d pos = Base::Vector3d()) + const; // returns a placement from the x,y,z,a,b,c parameters + Base::Vector3d getCenter() const; // returns a 3d vector from the i,j,k parameters + void setCenter(const Base::Vector3d&, + bool clockwise = true); // sets the center coordinates and the command name + std::string + toGCode(int precision = 6, + bool padzero = true) const; // returns a GCode string representation of the command + void setFromGCode( + const std::string&); // sets the parameters from the contents of the given GCode string + void setFromPlacement( + const Base::Placement&); // sets the parameters from the contents of the given placement + bool + has(const std::string&) const; // returns true if the given string exists in the parameters + Command transform(const Base::Placement&); // returns a transformed copy of this command + double getValue(const std::string& name) const; // returns the value of a given parameter + void scaleBy(double factor); // scales the receiver - use for imperial/metric conversions - // this assumes the name is upper case - inline double getParam(const std::string &name, double fallback = 0.0) const { - auto it = Parameters.find(name); - return it==Parameters.end() ? fallback : it->second; - } + // this assumes the name is upper case + inline double getParam(const std::string& name, double fallback = 0.0) const + { + auto it = Parameters.find(name); + return it == Parameters.end() ? fallback : it->second; + } - // attributes - std::string Name; - std::map Parameters; - }; + // attributes + std::string Name; + std::map Parameters; +}; -} //namespace Path +} // namespace Path -#endif // PATH_COMMAND_H +#endif // PATH_COMMAND_H diff --git a/src/Mod/CAM/App/CommandPyImp.cpp b/src/Mod/CAM/App/CommandPyImp.cpp index bb181136e9..bb0f54923c 100644 --- a/src/Mod/CAM/App/CommandPyImp.cpp +++ b/src/Mod/CAM/App/CommandPyImp.cpp @@ -22,7 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -44,7 +44,9 @@ std::string CommandPy::representation() const str << "Command "; str << getCommandPtr()->Name; str << " ["; - for(std::map::iterator i = getCommandPtr()->Parameters.begin(); i != getCommandPtr()->Parameters.end(); ++i) { + for (std::map::iterator i = getCommandPtr()->Parameters.begin(); + i != getCommandPtr()->Parameters.end(); + ++i) { std::string k = i->first; double v = i->second; str << " " << k << ":" << v; @@ -54,12 +56,13 @@ std::string CommandPy::representation() const } // -// Py::Dict parameters_copy_dict is now a class member to avoid delete/create/copy on every read access from python code -// Now the pre-filled Py::Dict is returned which is more consistent with normal python behaviour. -// It should be cleared whenever the c++ Parameters object is changed eg setParameters() or other objects invalidate its content, eg setPlacement() +// Py::Dict parameters_copy_dict is now a class member to avoid delete/create/copy on every read +// access from python code Now the pre-filled Py::Dict is returned which is more consistent with +// normal python behaviour. It should be cleared whenever the c++ Parameters object is changed eg +// setParameters() or other objects invalidate its content, eg setPlacement() // https://forum.freecad.org/viewtopic.php?f=15&t=50583 -PyObject *CommandPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +PyObject* CommandPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper { // create a new instance of CommandPy and the Twin object return new CommandPy(new Command); @@ -68,15 +71,22 @@ PyObject *CommandPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Py // constructor method int CommandPy::PyInit(PyObject* args, PyObject* kwd) { - PyObject *parameters = nullptr; - const char *name = ""; - static const std::array kwlist {"name", "parameters", nullptr}; - if (Base::Wrapped_ParseTupleAndKeywords(args, kwd, "|sO!", kwlist, &name, &PyDict_Type, ¶meters)) { + PyObject* parameters = nullptr; + const char* name = ""; + static const std::array kwlist {"name", "parameters", nullptr}; + if (Base::Wrapped_ParseTupleAndKeywords(args, + kwd, + "|sO!", + kwlist, + &name, + &PyDict_Type, + ¶meters)) { std::string sname(name); boost::to_upper(sname); try { - if (!sname.empty()) + if (!sname.empty()) { getCommandPtr()->setFromGCode(name); + } } catch (const Base::Exception& e) { PyErr_SetString(PyExc_ValueError, e.what()); @@ -97,7 +107,7 @@ int CommandPy::PyInit(PyObject* args, PyObject* kwd) boost::to_upper(ckey); double cvalue; - if (PyObject_TypeCheck(value,&(PyLong_Type))) { + if (PyObject_TypeCheck(value, &(PyLong_Type))) { cvalue = (double)PyLong_AsLong(value); } else if (PyObject_TypeCheck(value, &(PyFloat_Type))) { @@ -107,27 +117,33 @@ int CommandPy::PyInit(PyObject* args, PyObject* kwd) PyErr_SetString(PyExc_TypeError, "The dictionary can only contain number values"); return -1; } - getCommandPtr()->Parameters[ckey]=cvalue; + getCommandPtr()->Parameters[ckey] = cvalue; } - parameters_copy_dict.clear(); + parameters_copy_dict.clear(); return 0; } - PyErr_Clear(); // set by PyArg_ParseTuple() + PyErr_Clear(); // set by PyArg_ParseTuple() - if (Base::Wrapped_ParseTupleAndKeywords(args, kwd, "|sO!", kwlist, &name, &(Base::PlacementPy::Type), + if (Base::Wrapped_ParseTupleAndKeywords(args, + kwd, + "|sO!", + kwlist, + &name, + &(Base::PlacementPy::Type), ¶meters)) { std::string sname(name); boost::to_upper(sname); try { - if (!sname.empty()) + if (!sname.empty()) { getCommandPtr()->setFromGCode(name); + } } catch (const Base::Exception& e) { PyErr_SetString(PyExc_ValueError, e.what()); return -1; } - Base::PlacementPy *p = static_cast(parameters); - getCommandPtr()->setFromPlacement( *p->getPlacementPtr() ); + Base::PlacementPy* p = static_cast(parameters); + getCommandPtr()->setFromPlacement(*p->getPlacementPtr()); return 0; } return -1; @@ -152,10 +168,12 @@ void CommandPy::setName(Py::String arg) Py::Dict CommandPy::getParameters() const { // dict now a class member , https://forum.freecad.org/viewtopic.php?f=15&t=50583 - if (parameters_copy_dict.length()==0) { - for(std::map::iterator i = getCommandPtr()->Parameters.begin(); i != getCommandPtr()->Parameters.end(); ++i) { - parameters_copy_dict.setItem(i->first, Py::Float(i->second)); - } + if (parameters_copy_dict.length() == 0) { + for (std::map::iterator i = getCommandPtr()->Parameters.begin(); + i != getCommandPtr()->Parameters.end(); + ++i) { + parameters_copy_dict.setItem(i->first, Py::Float(i->second)); + } } return parameters_copy_dict; } @@ -176,7 +194,7 @@ void CommandPy::setParameters(Py::Dict arg) boost::to_upper(ckey); double cvalue; - if (PyObject_TypeCheck(value,&(PyLong_Type))) { + if (PyObject_TypeCheck(value, &(PyLong_Type))) { cvalue = (double)PyLong_AsLong(value); } else if (PyObject_TypeCheck(value, &(PyFloat_Type))) { @@ -185,14 +203,14 @@ void CommandPy::setParameters(Py::Dict arg) else { throw Py::TypeError("The dictionary can only contain number values"); } - getCommandPtr()->Parameters[ckey]=cvalue; + getCommandPtr()->Parameters[ckey] = cvalue; parameters_copy_dict.clear(); } } // GCode methods -PyObject* CommandPy::toGCode(PyObject *args) +PyObject* CommandPy::toGCode(PyObject* args) { if (PyArg_ParseTuple(args, "")) { return PyUnicode_FromString(getCommandPtr()->toGCode().c_str()); @@ -200,9 +218,9 @@ PyObject* CommandPy::toGCode(PyObject *args) throw Py::TypeError("This method accepts no argument"); } -PyObject* CommandPy::setFromGCode(PyObject *args) +PyObject* CommandPy::setFromGCode(PyObject* args) { - char *pstr=nullptr; + char* pstr = nullptr; if (PyArg_ParseTuple(args, "s", &pstr)) { std::string gcode(pstr); try { @@ -224,34 +242,40 @@ PyObject* CommandPy::setFromGCode(PyObject *args) Py::Object CommandPy::getPlacement() const { - return Py::asObject(new Base::PlacementPy(new Base::Placement(getCommandPtr()->getPlacement()))); + return Py::asObject( + new Base::PlacementPy(new Base::Placement(getCommandPtr()->getPlacement()))); } void CommandPy::setPlacement(Py::Object arg) { Py::Type PlacementType(Base::getTypeAsObject(&(Base::PlacementPy::Type))); - if(arg.isType(PlacementType)) { - getCommandPtr()->setFromPlacement( *static_cast((*arg))->getPlacementPtr() ); + if (arg.isType(PlacementType)) { + getCommandPtr()->setFromPlacement( + *static_cast((*arg))->getPlacementPtr()); parameters_copy_dict.clear(); - } else - throw Py::TypeError("Argument must be a placement"); + } + else { + throw Py::TypeError("Argument must be a placement"); + } } -PyObject* CommandPy::transform(PyObject *args) +PyObject* CommandPy::transform(PyObject* args) { - PyObject *placement; - if ( PyArg_ParseTuple(args, "O!", &(Base::PlacementPy::Type), &placement) ) { - Base::PlacementPy *p = static_cast(placement); - Path::Command trCmd = getCommandPtr()->transform( *p->getPlacementPtr() ); + PyObject* placement; + if (PyArg_ParseTuple(args, "O!", &(Base::PlacementPy::Type), &placement)) { + Base::PlacementPy* p = static_cast(placement); + Path::Command trCmd = getCommandPtr()->transform(*p->getPlacementPtr()); parameters_copy_dict.clear(); return new CommandPy(new Path::Command(trCmd)); - } else - throw Py::TypeError("Argument must be a placement"); + } + else { + throw Py::TypeError("Argument must be a placement"); + } } // custom attributes get/set -PyObject *CommandPy::getCustomAttributes(const char* attr) const +PyObject* CommandPy::getCustomAttributes(const char* attr) const { std::string satt(attr); if (satt.length() == 1) { @@ -274,21 +298,19 @@ int CommandPy::setCustomAttributes(const char* attr, PyObject* obj) if (isalpha(satt[0])) { boost::to_upper(satt); double cvalue; - if (PyObject_TypeCheck(obj,&(PyLong_Type))) { + if (PyObject_TypeCheck(obj, &(PyLong_Type))) { cvalue = (double)PyLong_AsLong(obj); - } else if (PyObject_TypeCheck(obj,&(PyFloat_Type))) { + } + else if (PyObject_TypeCheck(obj, &(PyFloat_Type))) { cvalue = PyFloat_AsDouble(obj); - } else { + } + else { return 0; } - getCommandPtr()->Parameters[satt]=cvalue; + getCommandPtr()->Parameters[satt] = cvalue; parameters_copy_dict.clear(); return 1; } } return 0; } - - - - diff --git a/src/Mod/CAM/App/FeatureArea.cpp b/src/Mod/CAM/App/FeatureArea.cpp index 03224c1769..ad0937dc8c 100644 --- a/src/Mod/CAM/App/FeatureArea.cpp +++ b/src/Mod/CAM/App/FeatureArea.cpp @@ -22,12 +22,12 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include -# include +#include +#include +#include #endif -#include // for FC_LOG_LEVEL_INIT +#include // for FC_LOG_LEVEL_INIT #include #include "FeatureArea.h" @@ -43,7 +43,7 @@ PROPERTY_SOURCE(Path::FeatureArea, Part::Feature) PARAM_ENUM_STRING_DECLARE(static const char* Enums, AREA_PARAMS_ALL) FeatureArea::FeatureArea() - :myInited(false) + : myInited(false) { ADD_PROPERTY(Sources, (nullptr)); ADD_PROPERTY(WorkPlane, (TopoDS_Shape())); @@ -62,37 +62,42 @@ FeatureArea::FeatureArea() } FeatureArea::~FeatureArea() -{ -} +{} -Area &FeatureArea::getArea() { - if(!myInited) execute(); +Area& FeatureArea::getArea() +{ + if (!myInited) { + execute(); + } return myArea; } -App::DocumentObjectExecReturn *FeatureArea::execute() +App::DocumentObjectExecReturn* FeatureArea::execute() { myInited = true; std::vector links = Sources.getValues(); - if (links.empty()) + if (links.empty()) { return new App::DocumentObjectExecReturn("No shapes linked"); + } for (std::vector::iterator it = links.begin(); it != links.end(); ++it) { - if (!(*it && (*it)->isDerivedFrom(Part::Feature::getClassTypeId()))) - return new App::DocumentObjectExecReturn("Linked object is not a Part object (has no Shape)."); + if (!(*it && (*it)->isDerivedFrom(Part::Feature::getClassTypeId()))) { + return new App::DocumentObjectExecReturn( + "Linked object is not a Part object (has no Shape)."); + } TopoDS_Shape shape = static_cast(*it)->Shape.getShape().getShape(); - if (shape.IsNull()) + if (shape.IsNull()) { return new App::DocumentObjectExecReturn("Linked shape object is empty"); + } } FC_TIME_INIT(t); AreaParams params; -#define AREA_PROP_GET(_param) \ - params.PARAM_FNAME(_param) = PARAM_FNAME(_param).getValue(); - PARAM_FOREACH(AREA_PROP_GET,AREA_PARAMS_CONF) +#define AREA_PROP_GET(_param) params.PARAM_FNAME(_param) = PARAM_FNAME(_param).getValue(); + PARAM_FOREACH(AREA_PROP_GET, AREA_PARAMS_CONF) myArea.clean(true); myArea.setParams(params); @@ -102,60 +107,68 @@ App::DocumentObjectExecReturn *FeatureArea::execute() for (std::vector::iterator it = links.begin(); it != links.end(); ++it) { myArea.add(static_cast(*it)->Shape.getShape().getShape(), - PARAM_PROP_ARGS(AREA_PARAMS_OPCODE)); + PARAM_PROP_ARGS(AREA_PARAMS_OPCODE)); } myShapes.clear(); - if(myArea.getSectionCount()==0) + if (myArea.getSectionCount() == 0) { myShapes.push_back(myArea.getShape(-1)); + } else { myShapes.reserve(myArea.getSectionCount()); - for(int i=0;i<(int)myArea.getSectionCount();++i) + for (int i = 0; i < (int)myArea.getSectionCount(); ++i) { myShapes.push_back(myArea.getShape(i)); + } } bool hasShape = false; - if(myShapes.empty()) + if (myShapes.empty()) { Shape.setValue(TopoDS_Shape()); - else{ + } + else { // compound is built even if there is only one shape to save the // trouble of messing around with placement BRep_Builder builder; TopoDS_Compound compound; builder.MakeCompound(compound); - for(auto &shape : myShapes) { - if(shape.IsNull()) continue; + for (auto& shape : myShapes) { + if (shape.IsNull()) { + continue; + } hasShape = true; - builder.Add(compound,shape); + builder.Add(compound, shape); } Shape.setValue(compound); } - FC_TIME_LOG(t,"feature execute"); + FC_TIME_LOG(t, "feature execute"); - if(!hasShape) + if (!hasShape) { return new App::DocumentObjectExecReturn("no output shape"); + } return DocumentObject::StdReturn; } -const std::vector &FeatureArea::getShapes() { +const std::vector& FeatureArea::getShapes() +{ getArea(); return myShapes; } short FeatureArea::mustExecute() const { - if(myInited && !myArea.isBuilt()) + if (myInited && !myArea.isBuilt()) { return 1; + } return Part::Feature::mustExecute(); } -PyObject *FeatureArea::getPyObject() +PyObject* FeatureArea::getPyObject() { - if (PythonObject.is(Py::_None())){ + if (PythonObject.is(Py::_None())) { // ref counter is set to 1 - PythonObject = Py::Object(new FeatureAreaPy(this),true); + PythonObject = Py::Object(new FeatureAreaPy(this), true); } return Py::new_reference_to(PythonObject); } @@ -167,93 +180,126 @@ PROPERTY_SOURCE(Path::FeatureAreaView, Part::Feature) FeatureAreaView::FeatureAreaView() { - ADD_PROPERTY(Source,(nullptr)); - ADD_PROPERTY_TYPE(SectionIndex,(0),"Section",App::Prop_None,"The start index of the section to show, negative value for reverse index from bottom"); - ADD_PROPERTY_TYPE(SectionCount,(1),"Section",App::Prop_None,"Number of sections to show, 0 to show all section starting from SectionIndex"); + ADD_PROPERTY(Source, (nullptr)); + ADD_PROPERTY_TYPE( + SectionIndex, + (0), + "Section", + App::Prop_None, + "The start index of the section to show, negative value for reverse index from bottom"); + ADD_PROPERTY_TYPE( + SectionCount, + (1), + "Section", + App::Prop_None, + "Number of sections to show, 0 to show all section starting from SectionIndex"); } -std::list FeatureAreaView::getShapes() { +std::list FeatureAreaView::getShapes() +{ std::list shapes; App::DocumentObject* pObj = Source.getValue(); - if (!pObj) + if (!pObj) { return shapes; - if(!pObj->isDerivedFrom(FeatureArea::getClassTypeId())) + } + if (!pObj->isDerivedFrom(FeatureArea::getClassTypeId())) { return shapes; + } auto all_shapes = static_cast(pObj)->getShapes(); - if(all_shapes.empty()) + if (all_shapes.empty()) { return shapes; + } - int index=SectionIndex.getValue(),count=SectionCount.getValue(); - if(index<0) { + int index = SectionIndex.getValue(), count = SectionCount.getValue(); + if (index < 0) { index += ((int)all_shapes.size()); - if(index<0) + if (index < 0) { return shapes; - if(count<=0 || index+1-count<0) { - count = index+1; + } + if (count <= 0 || index + 1 - count < 0) { + count = index + 1; index = 0; - }else - index -= count-1; - }else if(index >= (int)all_shapes.size()) + } + else { + index -= count - 1; + } + } + else if (index >= (int)all_shapes.size()) { return shapes; + } - if(count<=0) count = all_shapes.size(); - count += index; - if(count>(int)all_shapes.size()) + if (count <= 0) { count = all_shapes.size(); - for(int i=index;i (int)all_shapes.size()) { + count = all_shapes.size(); + } + for (int i = index; i < count; ++i) { shapes.push_back(all_shapes[i]); + } return shapes; } -App::DocumentObjectExecReturn *FeatureAreaView::execute() +App::DocumentObjectExecReturn* FeatureAreaView::execute() { App::DocumentObject* pObj = Source.getValue(); - if (!pObj) + if (!pObj) { return new App::DocumentObjectExecReturn("No shape linked"); + } - if(!pObj->isDerivedFrom(FeatureArea::getClassTypeId())) - return new App::DocumentObjectExecReturn("Linked object is not a FeatureArea"); + if (!pObj->isDerivedFrom(FeatureArea::getClassTypeId())) { + return new App::DocumentObjectExecReturn("Linked object is not a FeatureArea"); + } bool hasShape = false; std::list shapes = getShapes(); - if(shapes.empty()) + if (shapes.empty()) { Shape.setValue(TopoDS_Shape()); - else{ + } + else { BRep_Builder builder; TopoDS_Compound compound; builder.MakeCompound(compound); - for(auto &shape : shapes) { - if(shape.IsNull()) continue; + for (auto& shape : shapes) { + if (shape.IsNull()) { + continue; + } hasShape = true; - builder.Add(compound,shape); + builder.Add(compound, shape); } Shape.setValue(compound); } - if(!hasShape) + if (!hasShape) { return new App::DocumentObjectExecReturn("no output shape"); + } return DocumentObject::StdReturn; } // Python feature --------------------------------------------------------- -namespace App { +namespace App +{ /// @cond DOXERR PROPERTY_SOURCE_TEMPLATE(Path::FeatureAreaPython, Path::FeatureArea) PROPERTY_SOURCE_TEMPLATE(Path::FeatureAreaViewPython, Path::FeatureAreaView) -template<> const char* Path::FeatureAreaPython::getViewProviderName() const { +template<> +const char* Path::FeatureAreaPython::getViewProviderName() const +{ return "PathGui::ViewProviderAreaPython"; } -template<> const char* Path::FeatureAreaViewPython::getViewProviderName() const { +template<> +const char* Path::FeatureAreaViewPython::getViewProviderName() const +{ return "PathGui::ViewProviderAreaViewPython"; } /// @endcond // explicit template instantiation template class PathExport FeaturePythonT; -} - +} // namespace App diff --git a/src/Mod/CAM/App/FeatureArea.h b/src/Mod/CAM/App/FeatureArea.h index 9a2a83a549..938bcd592b 100644 --- a/src/Mod/CAM/App/FeatureArea.h +++ b/src/Mod/CAM/App/FeatureArea.h @@ -34,7 +34,7 @@ namespace Path { -class PathExport FeatureArea : public Part::Feature +class PathExport FeatureArea: public Part::Feature { PROPERTY_HEADER_WITH_OVERRIDE(Path::FeatureArea); @@ -43,23 +43,25 @@ public: FeatureArea(); ~FeatureArea() override; - Area &getArea(); - const std::vector &getShapes(); + Area& getArea(); + const std::vector& getShapes(); /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "PathGui::ViewProviderArea"; } - App::DocumentObjectExecReturn *execute() override; + App::DocumentObjectExecReturn* execute() override; short mustExecute() const override; - PyObject *getPyObject() override; + PyObject* getPyObject() override; - App::PropertyLinkList Sources; + App::PropertyLinkList Sources; Part::PropertyPartShape WorkPlane; PARAM_PROP_DECLARE(AREA_PARAMS_ALL) - void setWorkPlane(const TopoDS_Shape &shape) { + void setWorkPlane(const TopoDS_Shape& shape) + { WorkPlane.setValue(shape); myArea.setPlane(shape); } @@ -72,7 +74,7 @@ private: using FeatureAreaPython = App::FeaturePythonT; -class PathExport FeatureAreaView : public Part::Feature +class PathExport FeatureAreaView: public Part::Feature { PROPERTY_HEADER_WITH_OVERRIDE(Path::FeatureAreaView); @@ -82,19 +84,20 @@ public: std::list getShapes(); - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "PathGui::ViewProviderAreaView"; } - App::DocumentObjectExecReturn *execute() override; + App::DocumentObjectExecReturn* execute() override; - App::PropertyLink Source; - App::PropertyInteger SectionIndex; - App::PropertyInteger SectionCount; + App::PropertyLink Source; + App::PropertyInteger SectionIndex; + App::PropertyInteger SectionCount; }; using FeatureAreaViewPython = App::FeaturePythonT; -} //namespace Path +} // namespace Path -#endif // PATH_FeaturePath_H +#endif // PATH_FeaturePath_H diff --git a/src/Mod/CAM/App/FeatureAreaPy.xml b/src/Mod/CAM/App/FeatureAreaPy.xml index c167df2b4f..aeef6162e6 100644 --- a/src/Mod/CAM/App/FeatureAreaPy.xml +++ b/src/Mod/CAM/App/FeatureAreaPy.xml @@ -34,4 +34,3 @@ Same usage as Path.Area.setParams(). This function stores the parameters in the - diff --git a/src/Mod/CAM/App/FeatureAreaPyImp.cpp b/src/Mod/CAM/App/FeatureAreaPyImp.cpp index a4a49f3990..2ea4367722 100644 --- a/src/Mod/CAM/App/FeatureAreaPyImp.cpp +++ b/src/Mod/CAM/App/FeatureAreaPyImp.cpp @@ -41,50 +41,56 @@ std::string FeatureAreaPy::representation() const } -PyObject* FeatureAreaPy::getArea(PyObject *args) +PyObject* FeatureAreaPy::getArea(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) + if (!PyArg_ParseTuple(args, "")) { return nullptr; + } return new AreaPy(new Area(getFeatureAreaPtr()->getArea())); } -PyObject* FeatureAreaPy::setParams(PyObject *args, PyObject *keywds) +PyObject* FeatureAreaPy::setParams(PyObject* args, PyObject* keywds) { - static const std::array kwlist {PARAM_FIELD_STRINGS(NAME,AREA_PARAMS_CONF),nullptr}; + static const std::array kwlist {PARAM_FIELD_STRINGS(NAME, AREA_PARAMS_CONF), + nullptr}; - //Declare variables defined in the NAME field of the CONF parameter list - PARAM_PY_DECLARE(PARAM_FNAME,AREA_PARAMS_CONF); + // Declare variables defined in the NAME field of the CONF parameter list + PARAM_PY_DECLARE(PARAM_FNAME, AREA_PARAMS_CONF); - FeatureArea *feature = getFeatureAreaPtr(); + FeatureArea* feature = getFeatureAreaPtr(); -#define AREA_SET(_param) \ - PARAM_FNAME(_param) = \ - PARAM_TYPED(PARAM_PY_CAST_,_param)(feature->PARAM_FNAME(_param).getValue()); - //populate the CONF variables with values in properties - PARAM_FOREACH(AREA_SET,AREA_PARAMS_CONF) +#define AREA_SET(_param) \ + PARAM_FNAME(_param) = \ + PARAM_TYPED(PARAM_PY_CAST_, _param)(feature->PARAM_FNAME(_param).getValue()); + // populate the CONF variables with values in properties + PARAM_FOREACH(AREA_SET, AREA_PARAMS_CONF) - //Parse arguments to overwrite CONF variables - if (!Base::Wrapped_ParseTupleAndKeywords(args, keywds, - "|" PARAM_PY_KWDS(AREA_PARAMS_CONF), kwlist, - PARAM_REF(PARAM_FNAME,AREA_PARAMS_CONF))) + // Parse arguments to overwrite CONF variables + if (!Base::Wrapped_ParseTupleAndKeywords(args, + keywds, + "|" PARAM_PY_KWDS(AREA_PARAMS_CONF), + kwlist, + PARAM_REF(PARAM_FNAME, AREA_PARAMS_CONF))) { return nullptr; + } -#define AREA_GET(_param) \ - feature->PARAM_FNAME(_param).setValue(\ - PARAM_TYPED(PARAM_CAST_PY_,_param)(PARAM_FNAME(_param))); - //populate properties with the CONF variables - PARAM_FOREACH(AREA_GET,AREA_PARAMS_CONF) +#define AREA_GET(_param) \ + feature->PARAM_FNAME(_param).setValue(PARAM_TYPED(PARAM_CAST_PY_, _param)(PARAM_FNAME(_param))); + // populate properties with the CONF variables + PARAM_FOREACH(AREA_GET, AREA_PARAMS_CONF) Py_INCREF(Py_None); return Py_None; } -Py::Object FeatureAreaPy::getWorkPlane() const { +Py::Object FeatureAreaPy::getWorkPlane() const +{ return Part::shape2pyshape(getFeatureAreaPtr()->getArea().getPlane()); } -void FeatureAreaPy::setWorkPlane(Py::Object obj) { +void FeatureAreaPy::setWorkPlane(Py::Object obj) +{ PyObject* p = obj.ptr(); if (!PyObject_TypeCheck(p, &(Part::TopoShapePy::Type))) { std::string error = std::string("type must be 'TopoShape', not "); @@ -92,10 +98,10 @@ void FeatureAreaPy::setWorkPlane(Py::Object obj) { throw Py::TypeError(error); } getFeatureAreaPtr()->setWorkPlane( - static_cast(p)->getTopoShapePtr()->getShape()); + static_cast(p)->getTopoShapePtr()->getShape()); } -PyObject *FeatureAreaPy::getCustomAttributes(const char* /*attr*/) const +PyObject* FeatureAreaPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } @@ -105,4 +111,3 @@ int FeatureAreaPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { return 0; } - diff --git a/src/Mod/CAM/App/FeaturePath.cpp b/src/Mod/CAM/App/FeaturePath.cpp index 77e4212362..ece51e94f3 100644 --- a/src/Mod/CAM/App/FeaturePath.cpp +++ b/src/Mod/CAM/App/FeaturePath.cpp @@ -34,23 +34,26 @@ PROPERTY_SOURCE(Path::Feature, App::GeoFeature) Feature::Feature() { - ADD_PROPERTY_TYPE(Path,(Path::Toolpath()),"Base",App::Prop_None,"The path data of this feature"); + ADD_PROPERTY_TYPE(Path, + (Path::Toolpath()), + "Base", + App::Prop_None, + "The path data of this feature"); } Feature::~Feature() -{ -} +{} short Feature::mustExecute() const { return App::GeoFeature::mustExecute(); } -PyObject *Feature::getPyObject() +PyObject* Feature::getPyObject() { - if (PythonObject.is(Py::_None())){ + if (PythonObject.is(Py::_None())) { // ref counter is set to 1 - PythonObject = Py::Object(new App::DocumentObjectPy(this),true); + PythonObject = Py::Object(new App::DocumentObjectPy(this), true); } return Py::new_reference_to(PythonObject); } @@ -62,14 +65,17 @@ void Feature::onChanged(const App::Property* prop) // Python Path feature --------------------------------------------------------- -namespace App { +namespace App +{ /// @cond DOXERR PROPERTY_SOURCE_TEMPLATE(Path::FeaturePython, Path::Feature) -template<> const char* Path::FeaturePython::getViewProviderName() const { +template<> +const char* Path::FeaturePython::getViewProviderName() const +{ return "PathGui::ViewProviderPathPython"; } /// @endcond // explicit template instantiation template class PathExport FeaturePythonT; -} +} // namespace App diff --git a/src/Mod/CAM/App/FeaturePath.h b/src/Mod/CAM/App/FeaturePath.h index a82a3b2884..2f84d4d92c 100644 --- a/src/Mod/CAM/App/FeaturePath.h +++ b/src/Mod/CAM/App/FeaturePath.h @@ -33,7 +33,7 @@ namespace Path { -class PathExport Feature : public App::GeoFeature +class PathExport Feature: public App::GeoFeature { PROPERTY_HEADER_WITH_OVERRIDE(Path::Feature); @@ -43,27 +43,28 @@ public: ~Feature() override; /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "PathGui::ViewProviderPath"; } - App::DocumentObjectExecReturn *execute() override { + App::DocumentObjectExecReturn* execute() override + { return App::DocumentObject::StdReturn; } short mustExecute() const override; - PyObject *getPyObject() override; + PyObject* getPyObject() override; - PropertyPath Path; + PropertyPath Path; protected: /// get called by the container when a property has changed - void onChanged (const App::Property* prop) override; - + void onChanged(const App::Property* prop) override; }; using FeaturePython = App::FeaturePythonT; -} //namespace Path +} // namespace Path -#endif // PATH_FeaturePath_H +#endif // PATH_FeaturePath_H diff --git a/src/Mod/CAM/App/FeaturePathCompound.cpp b/src/Mod/CAM/App/FeaturePathCompound.cpp index 9b70b6f133..e4c0019f52 100644 --- a/src/Mod/CAM/App/FeaturePathCompound.cpp +++ b/src/Mod/CAM/App/FeaturePathCompound.cpp @@ -35,31 +35,38 @@ PROPERTY_SOURCE(Path::FeatureCompound, Path::Feature) FeatureCompound::FeatureCompound() { - ADD_PROPERTY_TYPE( Group, (nullptr), "Base",Prop_None,"Ordered list of paths to combine"); - ADD_PROPERTY_TYPE( UsePlacements, (false), "Base",Prop_None,"Specifies if the placements of children must be computed"); + ADD_PROPERTY_TYPE(Group, (nullptr), "Base", Prop_None, "Ordered list of paths to combine"); + ADD_PROPERTY_TYPE(UsePlacements, + (false), + "Base", + Prop_None, + "Specifies if the placements of children must be computed"); } FeatureCompound::~FeatureCompound() -{ -} +{} -App::DocumentObjectExecReturn *FeatureCompound::execute() +App::DocumentObjectExecReturn* FeatureCompound::execute() { - const std::vector &Paths = Group.getValues(); + const std::vector& Paths = Group.getValues(); Path::Toolpath result; - for (std::vector::const_iterator it= Paths.begin();it!=Paths.end();++it) { - if ((*it)->isDerivedFrom()){ - const std::vector &cmds = static_cast(*it)->Path.getValue().getCommands(); + for (std::vector::const_iterator it = Paths.begin(); it != Paths.end(); ++it) { + if ((*it)->isDerivedFrom()) { + const std::vector& cmds = + static_cast(*it)->Path.getValue().getCommands(); const Base::Placement pl = static_cast(*it)->Placement.getValue(); - for (std::vector::const_iterator it2= cmds.begin();it2!=cmds.end();++it2) { + for (std::vector::const_iterator it2 = cmds.begin(); it2 != cmds.end(); + ++it2) { if (UsePlacements.getValue()) { result.addCommand((*it2)->transform(pl)); - } else { + } + else { result.addCommand(**it2); } } - } else { + } + else { return new App::DocumentObjectExecReturn("Not all objects in group are paths!"); } } @@ -74,8 +81,9 @@ bool FeatureCompound::hasObject(const DocumentObject* obj) const { const std::vector& grp = Group.getValues(); for (std::vector::const_iterator it = grp.begin(); it != grp.end(); ++it) { - if (*it == obj) + if (*it == obj) { return true; + } } return false; @@ -102,25 +110,28 @@ void FeatureCompound::removeObject(DocumentObject* obj) } } -PyObject *FeatureCompound::getPyObject() +PyObject* FeatureCompound::getPyObject() { - if (PythonObject.is(Py::_None())){ + if (PythonObject.is(Py::_None())) { // ref counter is set to 1 - PythonObject = Py::Object(new FeaturePathCompoundPy(this),true); + PythonObject = Py::Object(new FeaturePathCompoundPy(this), true); } return Py::new_reference_to(PythonObject); } // Python Path Compound feature --------------------------------------------------------- -namespace App { +namespace App +{ /// @cond DOXERR PROPERTY_SOURCE_TEMPLATE(Path::FeatureCompoundPython, Path::FeatureCompound) -template<> const char* Path::FeatureCompoundPython::getViewProviderName() const { +template<> +const char* Path::FeatureCompoundPython::getViewProviderName() const +{ return "PathGui::ViewProviderPathCompoundPython"; } /// @endcond // explicit template instantiation template class PathExport FeaturePythonT; -} +} // namespace App diff --git a/src/Mod/CAM/App/FeaturePathCompound.h b/src/Mod/CAM/App/FeaturePathCompound.h index 5345436116..9b96cc4dea 100644 --- a/src/Mod/CAM/App/FeaturePathCompound.h +++ b/src/Mod/CAM/App/FeaturePathCompound.h @@ -31,7 +31,7 @@ namespace Path { -class PathExport FeatureCompound : public Path::Feature +class PathExport FeatureCompound: public Path::Feature { PROPERTY_HEADER_WITH_OVERRIDE(Path::Feature); @@ -40,14 +40,15 @@ public: FeatureCompound(); ~FeatureCompound() override; - App::PropertyLinkList Group; - App::PropertyBool UsePlacements; + App::PropertyLinkList Group; + App::PropertyBool UsePlacements; /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "PathGui::ViewProviderPathCompound"; } - App::DocumentObjectExecReturn *execute() override; + App::DocumentObjectExecReturn* execute() override; /// Checks whether the object \a obj is part of this group. bool hasObject(const DocumentObject* obj) const; @@ -55,13 +56,12 @@ public: void addObject(DocumentObject* obj); /// Removes an object from this group. void removeObject(DocumentObject* obj); - PyObject *getPyObject() override; - + PyObject* getPyObject() override; }; using FeatureCompoundPython = App::FeaturePythonT; -} //namespace Path +} // namespace Path -#endif // PATH_FeatureCompound_H +#endif // PATH_FeatureCompound_H diff --git a/src/Mod/CAM/App/FeaturePathCompoundPyImp.cpp b/src/Mod/CAM/App/FeaturePathCompoundPyImp.cpp index 1b7759c477..3aaa276e16 100644 --- a/src/Mod/CAM/App/FeaturePathCompoundPyImp.cpp +++ b/src/Mod/CAM/App/FeaturePathCompoundPyImp.cpp @@ -36,19 +36,23 @@ std::string FeaturePathCompoundPy::representation() const } -PyObject* FeaturePathCompoundPy::addObject(PyObject *args) +PyObject* FeaturePathCompoundPy::addObject(PyObject* args) { - PyObject *object; - if (!PyArg_ParseTuple(args, "O!", &(DocumentObjectPy::Type), &object)) + PyObject* object; + if (!PyArg_ParseTuple(args, "O!", &(DocumentObjectPy::Type), &object)) { return nullptr; + } DocumentObjectPy* docObj = static_cast(object); - if (!docObj->getDocumentObjectPtr() || !docObj->getDocumentObjectPtr()->isAttachedToDocument()) { + if (!docObj->getDocumentObjectPtr() + || !docObj->getDocumentObjectPtr()->isAttachedToDocument()) { PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot add an invalid object"); return nullptr; } - if (docObj->getDocumentObjectPtr()->getDocument() != getFeaturePathCompoundPtr()->getDocument()) { - PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot add an object from another document to this group"); + if (docObj->getDocumentObjectPtr()->getDocument() + != getFeaturePathCompoundPtr()->getDocument()) { + PyErr_SetString(Base::PyExc_FC_GeneralError, + "Cannot add an object from another document to this group"); return nullptr; } if (docObj->getDocumentObjectPtr() == this->getFeaturePathCompoundPtr()) { @@ -81,19 +85,23 @@ PyObject* FeaturePathCompoundPy::addObject(PyObject *args) } -PyObject* FeaturePathCompoundPy::removeObject(PyObject *args) +PyObject* FeaturePathCompoundPy::removeObject(PyObject* args) { - PyObject *object; - if (!PyArg_ParseTuple(args, "O!", &(DocumentObjectPy::Type), &object)) + PyObject* object; + if (!PyArg_ParseTuple(args, "O!", &(DocumentObjectPy::Type), &object)) { return nullptr; + } DocumentObjectPy* docObj = static_cast(object); - if (!docObj->getDocumentObjectPtr() || !docObj->getDocumentObjectPtr()->isAttachedToDocument()) { + if (!docObj->getDocumentObjectPtr() + || !docObj->getDocumentObjectPtr()->isAttachedToDocument()) { PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot remove an invalid object"); return nullptr; } - if (docObj->getDocumentObjectPtr()->getDocument() != getFeaturePathCompoundPtr()->getDocument()) { - PyErr_SetString(Base::PyExc_FC_GeneralError, "Cannot remove an object from another document from this group"); + if (docObj->getDocumentObjectPtr()->getDocument() + != getFeaturePathCompoundPtr()->getDocument()) { + PyErr_SetString(Base::PyExc_FC_GeneralError, + "Cannot remove an object from another document from this group"); return nullptr; } @@ -122,8 +130,7 @@ PyObject* FeaturePathCompoundPy::removeObject(PyObject *args) } - -PyObject *FeaturePathCompoundPy::getCustomAttributes(const char* /*attr*/) const +PyObject* FeaturePathCompoundPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } diff --git a/src/Mod/CAM/App/FeaturePathShape.cpp b/src/Mod/CAM/App/FeaturePathShape.cpp index 42895dc7bc..815311765e 100644 --- a/src/Mod/CAM/App/FeaturePathShape.cpp +++ b/src/Mod/CAM/App/FeaturePathShape.cpp @@ -23,8 +23,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include +#include +#include #endif #include "FeaturePathShape.h" @@ -34,22 +34,25 @@ using namespace Path; PROPERTY_SOURCE(Path::FeatureShape, Path::Feature) -PARAM_ENUM_STRING_DECLARE(static const char *Enums,AREA_PARAMS_PATH) +PARAM_ENUM_STRING_DECLARE(static const char* Enums, AREA_PARAMS_PATH) FeatureShape::FeatureShape() { - ADD_PROPERTY(Sources,(nullptr)); - ADD_PROPERTY_TYPE(StartPoint,(Base::Vector3d()),"Path",App::Prop_None,"Feed start position"); - ADD_PROPERTY_TYPE(UseStartPoint,(false),"Path",App::Prop_None,"Enable feed start position"); - PARAM_PROP_ADD("Path",AREA_PARAMS_PATH); - PARAM_PROP_SET_ENUM(Enums,AREA_PARAMS_PATH); + ADD_PROPERTY(Sources, (nullptr)); + ADD_PROPERTY_TYPE(StartPoint, + (Base::Vector3d()), + "Path", + App::Prop_None, + "Feed start position"); + ADD_PROPERTY_TYPE(UseStartPoint, (false), "Path", App::Prop_None, "Enable feed start position"); + PARAM_PROP_ADD("Path", AREA_PARAMS_PATH); + PARAM_PROP_SET_ENUM(Enums, AREA_PARAMS_PATH); } FeatureShape::~FeatureShape() -{ -} +{} -App::DocumentObjectExecReturn *FeatureShape::execute() +App::DocumentObjectExecReturn* FeatureShape::execute() { Toolpath path; std::vector links = Sources.getValues(); @@ -58,20 +61,26 @@ App::DocumentObjectExecReturn *FeatureShape::execute() return new App::DocumentObjectExecReturn("No shapes linked"); } - const Base::Vector3d &v = StartPoint.getValue(); - gp_Pnt pstart(v.x,v.y,v.z); + const Base::Vector3d& v = StartPoint.getValue(); + gp_Pnt pstart(v.x, v.y, v.z); std::list shapes; for (std::vector::iterator it = links.begin(); it != links.end(); ++it) { - if (!(*it && (*it)->isDerivedFrom(Part::Feature::getClassTypeId()))) + if (!(*it && (*it)->isDerivedFrom(Part::Feature::getClassTypeId()))) { continue; - const TopoDS_Shape &shape = static_cast(*it)->Shape.getShape().getShape(); - if (shape.IsNull()) + } + const TopoDS_Shape& shape = static_cast(*it)->Shape.getShape().getShape(); + if (shape.IsNull()) { continue; + } shapes.push_back(shape); } - Area::toPath(path,shapes,UseStartPoint.getValue()?&pstart:nullptr,nullptr,PARAM_PROP_ARGS(AREA_PARAMS_PATH)); + Area::toPath(path, + shapes, + UseStartPoint.getValue() ? &pstart : nullptr, + nullptr, + PARAM_PROP_ARGS(AREA_PARAMS_PATH)); Path.setValue(path); return App::DocumentObject::StdReturn; @@ -79,17 +88,17 @@ App::DocumentObjectExecReturn *FeatureShape::execute() // Python Path Shape feature --------------------------------------------------------- -namespace App { +namespace App +{ /// @cond DOXERR PROPERTY_SOURCE_TEMPLATE(Path::FeatureShapePython, Path::FeatureShape) -template<> const char* Path::FeatureShapePython::getViewProviderName() const { +template<> +const char* Path::FeatureShapePython::getViewProviderName() const +{ return "PathGui::ViewProviderPathShape"; } /// @endcond // explicit template instantiation template class PathExport FeaturePythonT; -} - - - +} // namespace App diff --git a/src/Mod/CAM/App/FeaturePathShape.h b/src/Mod/CAM/App/FeaturePathShape.h index 2fa1101388..49d774ed0e 100644 --- a/src/Mod/CAM/App/FeaturePathShape.h +++ b/src/Mod/CAM/App/FeaturePathShape.h @@ -35,7 +35,7 @@ namespace Path { -class PathExport FeatureShape : public Path::Feature +class PathExport FeatureShape: public Path::Feature { PROPERTY_HEADER_WITH_OVERRIDE(Path::FeatureShape); @@ -52,23 +52,23 @@ public: //@{ /// recalculate the feature - App::DocumentObjectExecReturn *execute() override; + App::DocumentObjectExecReturn* execute() override; //@} /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "PathGui::ViewProviderPathShape"; } protected: /// get called by the container when a property has changed - //void onChanged (const App::Property* prop) override; - + // void onChanged (const App::Property* prop) override; }; using FeatureShapePython = App::FeaturePythonT; -} //namespace Path +} // namespace Path -#endif // PATH_FeaturePathShape_H +#endif // PATH_FeaturePathShape_H diff --git a/src/Mod/CAM/App/ParamsHelper.h b/src/Mod/CAM/App/ParamsHelper.h index c479817531..32ecb7237b 100644 --- a/src/Mod/CAM/App/ParamsHelper.h +++ b/src/Mod/CAM/App/ParamsHelper.h @@ -189,26 +189,26 @@ * @{ */ #define PARAM_ITYPE 0 -#define PARAM_IARG 1 +#define PARAM_IARG 1 #define PARAM_INAME 2 -#define PARAM_IDEF 3 -#define PARAM_IDOC 4 -#define PARAM_ISEQ 5 -#define PARAM_IPROP 5 +#define PARAM_IDEF 3 +#define PARAM_IDOC 4 +#define PARAM_ISEQ 5 +#define PARAM_IPROP 5 #define PARAM_IINFO 6 -#define PARAM_FIELD(_idx,_param) BOOST_PP_TUPLE_ELEM(PARAM_I##_idx,_param) +#define PARAM_FIELD(_idx, _param) BOOST_PP_TUPLE_ELEM(PARAM_I##_idx, _param) -#define PARAM_FTYPE(_param) PARAM_FIELD(TYPE,_param) -#define PARAM_FARG(_param) PARAM_FIELD(ARG,_param) -#define PARAM_FNAME(_param) PARAM_FIELD(NAME,_param) -#define PARAM_FDEF(_param) PARAM_FIELD(DEF,_param) -#define PARAM_FDOC(_param) PARAM_FIELD(DOC,_param) -#define PARAM_FSEQ(_param) PARAM_FIELD(SEQ,_param) -#define PARAM_FPROP(_param) PARAM_FIELD(PROP,_param) -#define PARAM_FINFO(_param) PARAM_FIELD(INFO,_param) -#define PARAM_FENUM_TYPE(_param) BOOST_PP_TUPLE_ELEM(0,PARAM_FINFO(_param)) -#define PARAM_FENUM_PREFIX(_param) BOOST_PP_TUPLE_ELEM(1,PARAM_FINFO(_param)) +#define PARAM_FTYPE(_param) PARAM_FIELD(TYPE, _param) +#define PARAM_FARG(_param) PARAM_FIELD(ARG, _param) +#define PARAM_FNAME(_param) PARAM_FIELD(NAME, _param) +#define PARAM_FDEF(_param) PARAM_FIELD(DEF, _param) +#define PARAM_FDOC(_param) PARAM_FIELD(DOC, _param) +#define PARAM_FSEQ(_param) PARAM_FIELD(SEQ, _param) +#define PARAM_FPROP(_param) PARAM_FIELD(PROP, _param) +#define PARAM_FINFO(_param) PARAM_FIELD(INFO, _param) +#define PARAM_FENUM_TYPE(_param) BOOST_PP_TUPLE_ELEM(0, PARAM_FINFO(_param)) +#define PARAM_FENUM_PREFIX(_param) BOOST_PP_TUPLE_ELEM(1, PARAM_FINFO(_param)) /** @} */ @@ -216,18 +216,16 @@ * \defgroup ParamStringizer Field stringizers * \ingroup ParamHelper * @{ */ -#define PARAM_FIELD_STR(_idx,_param) \ - BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(PARAM_I##_idx,_param)) +#define PARAM_FIELD_STR(_idx, _param) BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(PARAM_I##_idx,_param)) -#define PARAM_FTYPE_STR(_param) PARAM_FIELD_STR(TYPE,_param) -#define PARAM_FARG_STR(_param) PARAM_FIELD_STR(ARG,_param) -#define PARAM_FNAME_STR(_param) PARAM_FIELD_STR(NAME,_param) -#define PARAM_FDEF_STR(_param) PARAM_FIELD_STR(DEF,_param) +#define PARAM_FTYPE_STR(_param) PARAM_FIELD_STR(TYPE, _param) +#define PARAM_FARG_STR(_param) PARAM_FIELD_STR(ARG, _param) +#define PARAM_FNAME_STR(_param) PARAM_FIELD_STR(NAME, _param) +#define PARAM_FDEF_STR(_param) PARAM_FIELD_STR(DEF, _param) /** @} */ /** Helper for #PARAM_FSEQ_STR */ -#define PARAM_FSEQ_STR_(_i,_elem) \ - BOOST_PP_COMMA_IF(_i) BOOST_PP_STRINGIZE(_elem) +#define PARAM_FSEQ_STR_(_i, _elem) BOOST_PP_COMMA_IF(_i) BOOST_PP_STRINGIZE(_elem) /** \c SEQ stringizer will stringify each element separately * @@ -235,8 +233,7 @@ * #seq[0], #seq[1] ... * \ingroup ParamHelper */ -#define PARAM_FSEQ_STR(_param) \ - PARAM_FOREACH_I(PARAM_FSEQ_STR_,PARAM_FSEQ(_param)) +#define PARAM_FSEQ_STR(_param) PARAM_FOREACH_I(PARAM_FSEQ_STR_, PARAM_FSEQ(_param)) /** \defgroup ParamLooper Looper macros @@ -245,7 +242,7 @@ */ /** Helper for #PARAM_FOREACH */ -#define PARAM_FOREACH_(_,_op,_param) _op(_param) +#define PARAM_FOREACH_(_, _op, _param) _op(_param) /** Apply macro \a _op to each parameter in sequence \a _seq * @@ -255,11 +252,10 @@ * \endcode * \ingroup ParamLooper */ -#define PARAM_FOREACH(_op,_seq) \ - BOOST_PP_SEQ_FOR_EACH(PARAM_FOREACH_,_op,_seq) +#define PARAM_FOREACH(_op, _seq) BOOST_PP_SEQ_FOR_EACH(PARAM_FOREACH_, _op, _seq) /** Helper for #PARAM_FOREACH_I */ -#define PARAM_FOREACH_I_(_,_op,_i,_param) _op(_i,_param) +#define PARAM_FOREACH_I_(_, _op, _i, _param) _op(_i, _param) /** Apply macro \a _op to each parameter in sequence \a _seq with additional index * @@ -269,13 +265,11 @@ * \endcode * \ingroup ParamLooper * */ -#define PARAM_FOREACH_I(_op,_seq) \ - BOOST_PP_SEQ_FOR_EACH_I(PARAM_FOREACH_I_,_op,_seq) +#define PARAM_FOREACH_I(_op, _seq) BOOST_PP_SEQ_FOR_EACH_I(PARAM_FOREACH_I_, _op, _seq) /** Helper for #PARAM_TYPED_FOREACH */ -#define PARAM_TYPED_FOREACH_(_1,_op,_param) \ - PARAM_TYPED(_op,_param)(_param) +#define PARAM_TYPED_FOREACH_(_1, _op, _param) PARAM_TYPED(_op, _param)(_param) /** Type depended macro construction * @@ -286,41 +280,37 @@ * \endcode * \ingroup ParamLooper */ -#define PARAM_TYPED(_op,_param) \ - BOOST_PP_CAT(_op,PARAM_FTYPE(_param)) +#define PARAM_TYPED(_op, _param) BOOST_PP_CAT(_op, PARAM_FTYPE(_param)) /** Apply type dependent macro call to a sequence of parameters * * \a _op will be converted to \a _op##\ for each parameter * \ingroup ParamLooper */ -#define PARAM_TYPED_FOREACH(_op,_seq) \ - BOOST_PP_SEQ_FOR_EACH(PARAM_TYPED_FOREACH_,_op,_seq) +#define PARAM_TYPED_FOREACH(_op, _seq) BOOST_PP_SEQ_FOR_EACH(PARAM_TYPED_FOREACH_, _op, _seq) /** \defgroup ParamCommon Common helpers * \ingroup ParamHelper */ -#define PARAM_TYPE_short short -#define PARAM_TYPE_long long -#define PARAM_TYPE_double double -#define PARAM_TYPE_bool bool -#define PARAM_TYPE_enum short -#define PARAM_TYPE_enum2 short +#define PARAM_TYPE_short short +#define PARAM_TYPE_long long +#define PARAM_TYPE_double double +#define PARAM_TYPE_bool bool +#define PARAM_TYPE_enum short +#define PARAM_TYPE_enum2 short /** Obtain parameter type * * The main purpose is to alias enum type to short * \ingroup ParamCommon */ -#define PARAM_TYPE(_param) \ - PARAM_TYPED(PARAM_TYPE_,_param) +#define PARAM_TYPE(_param) PARAM_TYPED(PARAM_TYPE_, _param) /** Helper for #PARAM_DECLARE */ -#define PARAM_DECLARE_(_1,_src,_param) \ - PARAM_TYPE(_param) _src(_param); +#define PARAM_DECLARE_(_1, _src, _param) PARAM_TYPE(_param) _src(_param); /** * Declares parameters using the given field as name @@ -342,13 +332,11 @@ * \endcode * \ingroup ParamCommon */ -#define PARAM_DECLARE(_src,_seq) \ - BOOST_PP_SEQ_FOR_EACH(PARAM_DECLARE_,_src,_seq) +#define PARAM_DECLARE(_src, _seq) BOOST_PP_SEQ_FOR_EACH(PARAM_DECLARE_, _src, _seq) /** Helper for #PARAM_DECLARE_INIT */ -#define PARAM_DECLARE_INIT_(_1,_src,_param) \ - PARAM_TYPE(_param) _src(_param) = PARAM_FDEF(_param); +#define PARAM_DECLARE_INIT_(_1, _src, _param) PARAM_TYPE(_param) _src(_param) = PARAM_FDEF(_param); /** * Declares parameters with initialization to default using the given field as @@ -363,15 +351,17 @@ * \endcode * \ingroup ParamCommon */ -#define PARAM_DECLARE_INIT(_src,_seq) \ - BOOST_PP_SEQ_FOR_EACH(PARAM_DECLARE_INIT_,_src,_seq) +#define PARAM_DECLARE_INIT(_src, _seq) BOOST_PP_SEQ_FOR_EACH(PARAM_DECLARE_INIT_, _src, _seq) -#define PARAM_ENUM_DECLARE_enum_(_1,_name,_i,_elem) \ - BOOST_PP_COMMA_IF(_i) BOOST_PP_CAT(_name,_elem) +#define PARAM_ENUM_DECLARE_enum_(_1, _name, _i, _elem) \ + BOOST_PP_COMMA_IF(_i) BOOST_PP_CAT(_name, _elem) -#define PARAM_ENUM_DECLARE_enum(_param) \ - enum {BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_DECLARE_enum_,PARAM_FNAME(_param),PARAM_FSEQ(_param))}; +#define PARAM_ENUM_DECLARE_enum(_param) \ + enum \ + { \ + BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_DECLARE_enum_, PARAM_FNAME(_param), PARAM_FSEQ(_param)) \ + }; #define PARAM_ENUM_DECLARE_short(_param) #define PARAM_ENUM_DECLARE_long(_param) @@ -393,8 +383,7 @@ * ... * \endcode * \ingroup ParamEnumHelper*/ -#define PARAM_ENUM_DECLARE(_seq) \ - PARAM_TYPED_FOREACH(PARAM_ENUM_DECLARE_,_seq) +#define PARAM_ENUM_DECLARE(_seq) PARAM_TYPED_FOREACH(PARAM_ENUM_DECLARE_, _seq) /** \addgroup ParamEnumHelper Enum convert helpers @@ -406,22 +395,23 @@ #define PARAM_ENUM_CONVERT_enum(...) #define PARAM_ENUM_CONVERT_enum2 PARAM_ENUM_CONVERT_SINGLE -#define PARAM_ENUM_CONVERT_enum_(_dst,_name,_prefix,_elem) \ - case BOOST_PP_CAT(_name,_elem):\ - _dst = BOOST_PP_CAT(_prefix,_elem);\ - break; +#define PARAM_ENUM_CONVERT_enum_(_dst, _name, _prefix, _elem) \ + case BOOST_PP_CAT(_name, _elem): \ + _dst = BOOST_PP_CAT(_prefix, _elem); \ + break; -#define PARAM_ENUM_CONVERT__(_1,_args,_i,_elem) \ - PARAM_ENUM_CONVERT_enum_(BOOST_PP_TUPLE_ELEM(0,_args),\ - BOOST_PP_TUPLE_ELEM(1,_args),\ - BOOST_PP_TUPLE_ELEM(2,_args),\ - _elem); +#define PARAM_ENUM_CONVERT__(_1, _args, _i, _elem) \ + PARAM_ENUM_CONVERT_enum_(BOOST_PP_TUPLE_ELEM(0, _args), \ + BOOST_PP_TUPLE_ELEM(1, _args), \ + BOOST_PP_TUPLE_ELEM(2, _args), \ + _elem); -#define PARAM_ENUM_CONVERT_(_1,_args,_param) \ - PARAM_TYPED(PARAM_ENUM_CONVERT_,_param)(BOOST_PP_TUPLE_ELEM(0,_args),\ - BOOST_PP_TUPLE_ELEM(1,_args),\ - BOOST_PP_TUPLE_ELEM(2,_args),\ - _param) +#define PARAM_ENUM_CONVERT_(_1, _args, _param) \ + PARAM_TYPED(PARAM_ENUM_CONVERT_, _param) \ + (BOOST_PP_TUPLE_ELEM(0, _args), \ + BOOST_PP_TUPLE_ELEM(1, _args), \ + BOOST_PP_TUPLE_ELEM(2, _args), \ + _param) /** Convert single enum parameter value into user defined enum type * @@ -430,17 +420,18 @@ * for more detail. Make sure the outer parenthesis of \c _param is stripped, * i.e. not double but single parenthesis */ -#define PARAM_ENUM_CONVERT_SINGLE(_src,_dst,_default,_param) \ - PARAM_FENUM_TYPE(_param) _dst(_param);\ - switch(_src(_param)) {\ - BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_CONVERT__,\ - (_dst(_param),PARAM_FNAME(_param),PARAM_FENUM_PREFIX(_param)),PARAM_FSEQ(_param))\ - default: \ - _default(_param);\ - } +#define PARAM_ENUM_CONVERT_SINGLE(_src, _dst, _default, _param) \ + PARAM_FENUM_TYPE(_param) _dst(_param); \ + switch (_src(_param)) { \ + BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_CONVERT__, \ + (_dst(_param), PARAM_FNAME(_param), PARAM_FENUM_PREFIX(_param)), \ + PARAM_FSEQ(_param)) \ + default: \ + _default(_param); \ + } /** Default handling in #PARAM_ENUM_CONVERT and #PARAM_ENUM_CHECK*/ -#define PARAM_ENUM_EXCEPT(_param) \ +#define PARAM_ENUM_EXCEPT(_param) \ throw Base::ValueError("invalid value for enum " PARAM_FNAME_STR(_param)) /** @} */ @@ -508,8 +499,8 @@ * The above code assumes you've already defined \a Test1 and \a Test2 some * where as the source variable. */ -#define PARAM_ENUM_CONVERT(_src,_dst,_default,_seq) \ - BOOST_PP_SEQ_FOR_EACH(PARAM_ENUM_CONVERT_,(_src,_dst,_default),_seq) +#define PARAM_ENUM_CONVERT(_src, _dst, _default, _seq) \ + BOOST_PP_SEQ_FOR_EACH(PARAM_ENUM_CONVERT_, (_src, _dst, _default), _seq) #define PARAM_ENUM_CHECK_short(...) @@ -519,21 +510,20 @@ #define PARAM_ENUM_CHECK_enum PARAM_ENUM_CHECK_SINGLE #define PARAM_ENUM_CHECK_enum2 PARAM_ENUM_CHECK_SINGLE -#define PARAM_ENUM_CHECK_enum_(_1,_name,_i,_elem) \ - case BOOST_PP_CAT(_name,_elem): break; +#define PARAM_ENUM_CHECK_enum_(_1, _name, _i, _elem) \ + case BOOST_PP_CAT(_name, _elem): \ + break; -#define PARAM_ENUM_CHECK_(_1,_args,_param) \ - PARAM_TYPED(PARAM_ENUM_CHECK_,_param)(BOOST_PP_TUPLE_ELEM(0,_args),\ - BOOST_PP_TUPLE_ELEM(1,_args),\ - _param) +#define PARAM_ENUM_CHECK_(_1, _args, _param) \ + PARAM_TYPED(PARAM_ENUM_CHECK_, _param) \ + (BOOST_PP_TUPLE_ELEM(0, _args), BOOST_PP_TUPLE_ELEM(1, _args), _param) -#define PARAM_ENUM_CHECK_SINGLE(_src,_default,_param) \ - switch(_src(_param)) {\ - BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_CHECK_enum_,\ - PARAM_FNAME(_param),PARAM_FSEQ(_param))\ - default: \ - _default(_param);\ - } +#define PARAM_ENUM_CHECK_SINGLE(_src, _default, _param) \ + switch (_src(_param)) { \ + BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_CHECK_enum_, PARAM_FNAME(_param), PARAM_FSEQ(_param)) \ + default: \ + _default(_param); \ + } /* Validate enum type parameters * @@ -554,8 +544,8 @@ * * \arg \c _seq: Parameter sequence */ -#define PARAM_ENUM_CHECK(_src,_default,_seq) \ - BOOST_PP_SEQ_FOR_EACH(PARAM_ENUM_CHECK_,(_src,_default),_seq) +#define PARAM_ENUM_CHECK(_src, _default, _seq) \ + BOOST_PP_SEQ_FOR_EACH(PARAM_ENUM_CHECK_, (_src, _default), _seq) #define PARAM_ENUM_STRING_DECLARE_short(...) @@ -565,12 +555,12 @@ #define PARAM_ENUM_STRING_DECLARE_enum2 PARAM_ENUM_STRING_DECLARE_enum /** Helper for #PARAM_ENUM_STRING_DECLARE */ -#define PARAM_ENUM_STRING_DECLARE_enum(_prefix,_param) \ - BOOST_PP_CAT(_prefix,PARAM_FNAME(_param))[] = {PARAM_FSEQ_STR(_param),NULL}; +#define PARAM_ENUM_STRING_DECLARE_enum(_prefix, _param) \ + BOOST_PP_CAT(_prefix, PARAM_FNAME(_param))[] = {PARAM_FSEQ_STR(_param), NULL}; /** Helper for #PARAM_ENUM_STRING_DECLARE */ -#define PARAM_ENUM_STRING_DECLARE_(_1,_prefix,_param) \ - PARAM_TYPED(PARAM_ENUM_STRING_DECLARE_,_param)(_prefix,_param) +#define PARAM_ENUM_STRING_DECLARE_(_1, _prefix, _param) \ + PARAM_TYPED(PARAM_ENUM_STRING_DECLARE_, _param)(_prefix, _param) /** Make \c enum string list * @@ -584,13 +574,12 @@ * PARAM_ENUM_STRING_DECLARE(static const char *Enum, MyParamsSeq) * \ingroup ParamEnumHelper */ -#define PARAM_ENUM_STRING_DECLARE(_prefix,_seq) \ - BOOST_PP_SEQ_FOR_EACH(PARAM_ENUM_STRING_DECLARE_,_prefix,_seq) +#define PARAM_ENUM_STRING_DECLARE(_prefix, _seq) \ + BOOST_PP_SEQ_FOR_EACH(PARAM_ENUM_STRING_DECLARE_, _prefix, _seq) /** Helper for #PARAM_INIT */ -#define PARAM_INIT_(_,_src,_i,_param) \ - BOOST_PP_COMMA_IF(_i) _src(_param)(PARAM_FDEF(_param)) +#define PARAM_INIT_(_, _src, _i, _param) BOOST_PP_COMMA_IF(_i) _src(_param)(PARAM_FDEF(_param)) /** Constructor initialization * @@ -603,14 +592,13 @@ * \endcode * \ingroup ParamCommon */ -#define PARAM_INIT(_src,_seq) \ - BOOST_PP_SEQ_FOR_EACH_I(PARAM_INIT_,_src,_seq) +#define PARAM_INIT(_src, _seq) BOOST_PP_SEQ_FOR_EACH_I(PARAM_INIT_, _src, _seq) /** Helper for #PARAM_OP */ -#define PARAM_OP_(_,_args,_param) \ - BOOST_PP_TUPLE_ELEM(0,_args)(_param) BOOST_PP_TUPLE_ELEM(1,_args) \ - BOOST_PP_TUPLE_ELEM(2,_args)(_param); +#define PARAM_OP_(_, _args, _param) \ + BOOST_PP_TUPLE_ELEM(0, _args) \ + (_param) BOOST_PP_TUPLE_ELEM(1, _args) BOOST_PP_TUPLE_ELEM(2, _args)(_param); /** Perform operation on two instance of each parameter in a sequence * @@ -629,13 +617,12 @@ * * \ingroup ParamCommon */ -#define PARAM_OP(_src,_op,_dst,_seq) \ - BOOST_PP_SEQ_FOR_EACH(PARAM_COPY_,(_src,_op,_dst),_seq) +#define PARAM_OP(_src, _op, _dst, _seq) BOOST_PP_SEQ_FOR_EACH(PARAM_COPY_, (_src, _op, _dst), _seq) /** Helper for #PARAM_ARGS_DEF */ -#define PARAM_ARGS_DEF_(_,_src,_i,_param) \ - BOOST_PP_COMMA_IF(_i) PARAM_TYPE(_param) _src(_param)=PARAM_FDEF(_param) +#define PARAM_ARGS_DEF_(_, _src, _i, _param) \ + BOOST_PP_COMMA_IF(_i) PARAM_TYPE(_param) _src(_param) = PARAM_FDEF(_param) /** Declare the parameters as function argument list with defaults. * @@ -648,13 +635,11 @@ * \endcode * \ingroup ParamCommon */ -#define PARAM_ARGS_DEF(_src,_seq) \ - BOOST_PP_SEQ_FOR_EACH_I(PARAM_ARGS_DEF_,_src,_seq) +#define PARAM_ARGS_DEF(_src, _seq) BOOST_PP_SEQ_FOR_EACH_I(PARAM_ARGS_DEF_, _src, _seq) /** Helper for #PARAM_ARGS */ -#define PARAM_ARGS_(_,_src,_i,_param) \ - BOOST_PP_COMMA_IF(_i) PARAM_TYPE(_param) _src(_param) +#define PARAM_ARGS_(_, _src, _i, _param) BOOST_PP_COMMA_IF(_i) PARAM_TYPE(_param) _src(_param) /** Declare the parameters as function argument list without defaults. * @@ -667,8 +652,7 @@ * \endcode * \ingroup ParamCommon */ -#define PARAM_ARGS(_src,_seq) \ - BOOST_PP_SEQ_FOR_EACH_I(PARAM_ARGS_,_src,_seq) +#define PARAM_ARGS(_src, _seq) BOOST_PP_SEQ_FOR_EACH_I(PARAM_ARGS_, _src, _seq) /** \defgroup ParamPy Python helper @@ -682,37 +666,33 @@ */ /** Helper for #PARAM_PY_DOC_enum */ -#define PARAM_PY_DOC_enum_(_i,_elem) \ - BOOST_PP_IF(_i,","," ") #_i "=" #_elem +#define PARAM_PY_DOC_enum_(_i, _elem) BOOST_PP_IF(_i, ",", " ") #_i "=" #_elem /** Generate doc for an enum parameter */ -#define PARAM_PY_DOC_enum(_field,_param) \ - "\n* " PARAM_FIELD_STR(_field,_param) "(" PARAM_FDEF_STR(_param)"):" \ - PARAM_FOREACH_I(PARAM_PY_DOC_enum_, PARAM_FSEQ(_param)) ". " \ - PARAM_FDOC(_param) "\n" +#define PARAM_PY_DOC_enum(_field, _param) \ + "\n* " PARAM_FIELD_STR(_field, _param) "(" PARAM_FDEF_STR(_param) "):" PARAM_FOREACH_I( \ + PARAM_PY_DOC_enum_, \ + PARAM_FSEQ(_param)) ". " PARAM_FDOC(_param) "\n" /* Generate doc for other type of parameter */ -#define PARAM_PY_DOC_short(_field,_param) \ - "\n* " PARAM_FIELD_STR(_field,_param) "(" PARAM_FDEF_STR(_param)"): " \ - PARAM_FDOC(_param) "\n" +#define PARAM_PY_DOC_short(_field, _param) \ + "\n* " PARAM_FIELD_STR(_field, _param) "(" PARAM_FDEF_STR(_param) "): " PARAM_FDOC(_param) "\n" #define PARAM_PY_DOC_long PARAM_PY_DOC_short #define PARAM_PY_DOC_double PARAM_PY_DOC_short #define PARAM_PY_DOC_bool PARAM_PY_DOC_short #define PARAM_PY_DOC_enum2 PARAM_PY_DOC_enum -#define PARAM_PY_DOC_(_,_field,_param) \ - PARAM_TYPED(PARAM_PY_DOC_,_param)(_field,_param) +#define PARAM_PY_DOC_(_, _field, _param) PARAM_TYPED(PARAM_PY_DOC_, _param)(_field, _param) /* Generate document of a sequence of parameters * \ingroup ParamDoc */ -#define PARAM_PY_DOC(_field,_seq) \ - BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DOC_,_field,_seq) +#define PARAM_PY_DOC(_field, _seq) BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DOC_, _field, _seq) /** Helper for #PARAM_PY_ARGS_DOC */ -#define PARAM_PY_ARGS_DOC_(_,_field,_i,_param) \ - BOOST_PP_IF(_i,", "," ") PARAM_FIELD_STR(_field,_param) "=" PARAM_FDEF_STR(_param) +#define PARAM_PY_ARGS_DOC_(_, _field, _i, _param) \ + BOOST_PP_IF(_i, ", ", " ") PARAM_FIELD_STR(_field, _param) "=" PARAM_FDEF_STR(_param) /** Generate argument list string * \arg \c _field: specifies the \ref ParamField "field" to use as name @@ -724,13 +704,11 @@ * * \ingroup ParamDoc */ -#define PARAM_PY_ARGS_DOC(_field,_seq) \ - BOOST_PP_SEQ_FOR_EACH_I(PARAM_PY_ARGS_DOC_,_field,_seq) +#define PARAM_PY_ARGS_DOC(_field, _seq) BOOST_PP_SEQ_FOR_EACH_I(PARAM_PY_ARGS_DOC_, _field, _seq) /** Helper for #PARAM_FIELDS */ -#define PARAM_FIELDS_(_1,_src,_i,_param) \ - BOOST_PP_COMMA_IF(_i) _src(_param) +#define PARAM_FIELDS_(_1, _src, _i, _param) BOOST_PP_COMMA_IF(_i) _src(_param) /** Expand to a list of the given field in the parameter sequence * @@ -743,28 +721,27 @@ * \endcode * \ingroup ParamCommon ParamPy */ -#define PARAM_FIELDS(_src,_seq) \ - BOOST_PP_SEQ_FOR_EACH_I(PARAM_FIELDS_,_src,_seq) +#define PARAM_FIELDS(_src, _seq) BOOST_PP_SEQ_FOR_EACH_I(PARAM_FIELDS_, _src, _seq) -#define PARAM_PY_CAST_short(_v) (_v) -#define PARAM_PY_CAST_long(_v) (_v) +#define PARAM_PY_CAST_short(_v) (_v) +#define PARAM_PY_CAST_long(_v) (_v) #define PARAM_PY_CAST_double(_v) (_v) -#define PARAM_PY_CAST_bool(_v) ((_v)?Py_True:Py_False) -#define PARAM_PY_CAST_enum(_v) (_v) -#define PARAM_PY_CAST_enum2(_v) (_v) +#define PARAM_PY_CAST_bool(_v) ((_v) ? Py_True : Py_False) +#define PARAM_PY_CAST_enum(_v) (_v) +#define PARAM_PY_CAST_enum2(_v) (_v) -#define PARAM_CAST_PY_short(_v) (_v) -#define PARAM_CAST_PY_long(_v) (_v) +#define PARAM_CAST_PY_short(_v) (_v) +#define PARAM_CAST_PY_long(_v) (_v) #define PARAM_CAST_PY_double(_v) (_v) -#define PARAM_CAST_PY_bool(_v) (PyObject_IsTrue(_v)?true:false) -#define PARAM_CAST_PY_enum(_v) (_v) -#define PARAM_CAST_PY_enum2(_v) (_v) +#define PARAM_CAST_PY_bool(_v) (PyObject_IsTrue(_v) ? true : false) +#define PARAM_CAST_PY_enum(_v) (_v) +#define PARAM_CAST_PY_enum2(_v) (_v) /** Helper for #PARAM_PY_FIELDS */ -#define PARAM_PY_FIELDS_(_1,_src,_i,_param) \ - BOOST_PP_COMMA_IF(_i) PARAM_TYPED(PARAM_CAST_PY_,_param)(_src(_param)) +#define PARAM_PY_FIELDS_(_1, _src, _i, _param) \ + BOOST_PP_COMMA_IF(_i) PARAM_TYPED(PARAM_CAST_PY_, _param)(_src(_param)) /** Expand to a comma separated list of the given field in the sequence * @@ -774,77 +751,70 @@ * The field will be casted from python C to C type * \ingroup ParamCommon ParamPy */ -#define PARAM_PY_FIELDS(_src,_seq) \ - BOOST_PP_SEQ_FOR_EACH_I(PARAM_PY_FIELDS_,_src,_seq) +#define PARAM_PY_FIELDS(_src, _seq) BOOST_PP_SEQ_FOR_EACH_I(PARAM_PY_FIELDS_, _src, _seq) /** Helper for #PARAM_FIELD_STRINGS */ -#define PARAM_FIELD_STRINGS_(_1,_field,_i,_param) \ - BOOST_PP_COMMA_IF(_i) PARAM_FIELD_STR(_field,_param) +#define PARAM_FIELD_STRINGS_(_1, _field, _i, _param) \ + BOOST_PP_COMMA_IF(_i) PARAM_FIELD_STR(_field, _param) /** Expand to a list of stringified fields * \ingroup ParamStringizer ParamPy */ -#define PARAM_FIELD_STRINGS(_field,_seq) \ - BOOST_PP_SEQ_FOR_EACH_I(PARAM_FIELD_STRINGS_,_field,_seq) +#define PARAM_FIELD_STRINGS(_field, _seq) \ + BOOST_PP_SEQ_FOR_EACH_I(PARAM_FIELD_STRINGS_, _field, _seq) -#define PARAM_PYARG_short "h" -#define PARAM_PYARG_long "l" +#define PARAM_PYARG_short "h" +#define PARAM_PYARG_long "l" #define PARAM_PYARG_double "d" -#define PARAM_PYARG_bool "O" -#define PARAM_PYARG_enum "h" -#define PARAM_PYARG_enum2 "h" +#define PARAM_PYARG_bool "O" +#define PARAM_PYARG_enum "h" +#define PARAM_PYARG_enum2 "h" /** Helper for #PARAM_PY_KWDS */ -#define PARAM_PY_KWDS_(_param) \ - PARAM_TYPED(PARAM_PYARG_,_param) +#define PARAM_PY_KWDS_(_param) PARAM_TYPED(PARAM_PYARG_, _param) /** Generate a format string for keywords based argument * \ingroup ParamPy */ -#define PARAM_PY_KWDS(_seq) \ - PARAM_FOREACH(PARAM_PY_KWDS_,_seq) +#define PARAM_PY_KWDS(_seq) PARAM_FOREACH(PARAM_PY_KWDS_, _seq) -#define PARAM_PY_TYPE_short short -#define PARAM_PY_TYPE_long long -#define PARAM_PY_TYPE_double double -#define PARAM_PY_TYPE_bool PyObject* -#define PARAM_PY_TYPE_enum short -#define PARAM_PY_TYPE_enum2 short +#define PARAM_PY_TYPE_short short +#define PARAM_PY_TYPE_long long +#define PARAM_PY_TYPE_double double +#define PARAM_PY_TYPE_bool PyObject* +#define PARAM_PY_TYPE_enum short +#define PARAM_PY_TYPE_enum2 short /** Helper for #PARAM_PY_DECLARE */ -#define PARAM_PY_DECLARE_(_1,_src,_param) \ - PARAM_TYPED(PARAM_PY_TYPE_,_param) _src(_param); +#define PARAM_PY_DECLARE_(_1, _src, _param) PARAM_TYPED(PARAM_PY_TYPE_, _param) _src(_param); /** Declare field variables for Python C type without initialization * \ingroup ParamPy */ -#define PARAM_PY_DECLARE(_src,_seq) \ - BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DECLARE_,_src,_seq) +#define PARAM_PY_DECLARE(_src, _seq) BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DECLARE_, _src, _seq) -#define PARAM_PY_INIT_short(_v) _v -#define PARAM_PY_INIT_long(_v) _v -#define PARAM_PY_INIT_double(_v) _v -#define PARAM_PY_INIT_bool(_v) ((_v)?Py_True:Py_False) -#define PARAM_PY_INIT_enum(_v) _v -#define PARAM_PY_INIT_enum2(_v) _v +#define PARAM_PY_INIT_short(_v) _v +#define PARAM_PY_INIT_long(_v) _v +#define PARAM_PY_INIT_double(_v) _v +#define PARAM_PY_INIT_bool(_v) ((_v) ? Py_True : Py_False) +#define PARAM_PY_INIT_enum(_v) _v +#define PARAM_PY_INIT_enum2(_v) _v /** Helper for #PARAM_PY_DECLARE_INIT */ -#define PARAM_PY_DECLARE_INIT_(_1,_src,_param) \ - PARAM_TYPED(PARAM_PY_TYPE_,_param) _src(_param) = \ - PARAM_TYPED(PARAM_PY_INIT_,_param)(PARAM_FDEF(_param)); +#define PARAM_PY_DECLARE_INIT_(_1, _src, _param) \ + PARAM_TYPED(PARAM_PY_TYPE_, _param) \ + _src(_param) = PARAM_TYPED(PARAM_PY_INIT_, _param)(PARAM_FDEF(_param)); /** Declare field variables of Python c type with initialization to default * \ingroup ParamPy */ -#define PARAM_PY_DECLARE_INIT(_src,_seq) \ - BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DECLARE_INIT_,_src,_seq) +#define PARAM_PY_DECLARE_INIT(_src, _seq) BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DECLARE_INIT_, _src, _seq) /** Helper for #PARAM_REF */ -#define PARAM_REF_(_1,_src,_i,_param) \ - BOOST_PP_COMMA_IF(_i) &_src(_param) +#define PARAM_REF_(_1, _src, _i, _param) BOOST_PP_COMMA_IF(_i) & _src(_param) /** Generate a list of field references * @@ -857,30 +827,27 @@ * \endcode * \ingroup ParamPy */ -#define PARAM_REF(_src,_seq) \ - BOOST_PP_SEQ_FOR_EACH_I(PARAM_REF_,_src,_seq) +#define PARAM_REF(_src, _seq) BOOST_PP_SEQ_FOR_EACH_I(PARAM_REF_, _src, _seq) -#define PARAM_CAST_PYOBJ_short(_v) PyLong_FromLong(_v) -#define PARAM_CAST_PYOBJ_long(_v) PyLong_FromLong(_v) +#define PARAM_CAST_PYOBJ_short(_v) PyLong_FromLong(_v) +#define PARAM_CAST_PYOBJ_long(_v) PyLong_FromLong(_v) -#define PARAM_CAST_PYOBJ_double(_v) PyFloat_FromDouble(_v) -#define PARAM_CAST_PYOBJ_bool(_v) ((_v)?Py_True:Py_False) -#define PARAM_CAST_PYOBJ_enum PARAM_CAST_PYOBJ_short -#define PARAM_CAST_PYOBJ_enum2 PARAM_CAST_PYOBJ_short +#define PARAM_CAST_PYOBJ_double(_v) PyFloat_FromDouble(_v) +#define PARAM_CAST_PYOBJ_bool(_v) ((_v) ? Py_True : Py_False) +#define PARAM_CAST_PYOBJ_enum PARAM_CAST_PYOBJ_short +#define PARAM_CAST_PYOBJ_enum2 PARAM_CAST_PYOBJ_short /** Stringize field to a Python string * \ingroup ParamPy ParamStringizer */ -#define PARAM_PY_STR(_field,_param) \ - PyUnicode_FromString(PARAM_FIELD_STR(_field,_param)) +#define PARAM_PY_STR(_field, _param) PyUnicode_FromString(PARAM_FIELD_STR(_field, _param)) /** Helper for #PARAM_PY_DICT_SET_VALUE */ -#define PARAM_PY_DICT_SET_VALUE_(_1,_args,_param) \ - PyDict_SetItem(BOOST_PP_TUPLE_ELEM(0,_args), \ - PARAM_PY_STR(BOOST_PP_TUPLE_ELEM(1,_args),_param),\ - PARAM_TYPED(PARAM_CAST_PYOBJ_,_param)(\ - BOOST_PP_TUPLE_ELEM(2,_args)(_param))); +#define PARAM_PY_DICT_SET_VALUE_(_1, _args, _param) \ + PyDict_SetItem(BOOST_PP_TUPLE_ELEM(0, _args), \ + PARAM_PY_STR(BOOST_PP_TUPLE_ELEM(1, _args), _param), \ + PARAM_TYPED(PARAM_CAST_PYOBJ_, _param)(BOOST_PP_TUPLE_ELEM(2, _args)(_param))); /** Populate a Python dict with a structure variable * @@ -897,22 +864,20 @@ * \endcode * \ingroup ParamPy */ -#define PARAM_PY_DICT_SET_VALUE(_dict,_field,_src,_seq) \ - BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DICT_SET_VALUE_,(_dict,_field,_src),_seq) +#define PARAM_PY_DICT_SET_VALUE(_dict, _field, _src, _seq) \ + BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DICT_SET_VALUE_, (_dict, _field, _src), _seq) -#define PARAM_PY_DICT_DOC_enum_(_i,_elem) \ - BOOST_PP_IF(_i,","," ") #_i "=" #_elem +#define PARAM_PY_DICT_DOC_enum_(_i, _elem) BOOST_PP_IF(_i, ",", " ") #_i "=" #_elem /** Generate doc for an enum parameter */ -#define PARAM_PY_DICT_DOC_enum(_param) \ - "(" PARAM_FDEF_STR(_param) ") - " \ - PARAM_FOREACH_I(PARAM_PY_DOC_enum_, PARAM_FSEQ(_param)) ".\n" \ - PARAM_FDOC(_param) "\n" +#define PARAM_PY_DICT_DOC_enum(_param) \ + "(" PARAM_FDEF_STR(_param) ") - " PARAM_FOREACH_I( \ + PARAM_PY_DOC_enum_, \ + PARAM_FSEQ(_param)) ".\n" PARAM_FDOC(_param) "\n" /* Generate doc for other type of parameter */ -#define PARAM_PY_DICT_DOC_(_param) \ - "(" PARAM_FDEF_STR(_param) ") - " PARAM_FDOC(_param) "\n" +#define PARAM_PY_DICT_DOC_(_param) "(" PARAM_FDEF_STR(_param) ") - " PARAM_FDOC(_param) "\n" #define PARAM_PY_DICT_DOC_short PARAM_PY_DICT_DOC_ @@ -922,10 +887,10 @@ #define PARAM_PY_DICT_DOC_enum2 PARAM_PY_DICT_DOC_enum /** Helper for #PARAM_PY_DICT_SET_DOC */ -#define PARAM_PY_DICT_SET_DOC_(_1,_args,_param) \ - PyDict_SetItem(BOOST_PP_TUPLE_ELEM(0,_args), \ - PARAM_PY_STR(BOOST_PP_TUPLE_ELEM(1,_args),_param),\ - PyUnicode_FromString(PARAM_TYPED(PARAM_PY_DICT_DOC_,_param)(_param))); +#define PARAM_PY_DICT_SET_DOC_(_1, _args, _param) \ + PyDict_SetItem(BOOST_PP_TUPLE_ELEM(0, _args), \ + PARAM_PY_STR(BOOST_PP_TUPLE_ELEM(1, _args), _param), \ + PyUnicode_FromString(PARAM_TYPED(PARAM_PY_DICT_DOC_, _param)(_param))); /** Populate a Python dict with the doc field of the parameter sequence * @@ -940,8 +905,8 @@ * \endcode * \ingroup ParamDoc */ -#define PARAM_PY_DICT_SET_DOC(_dict,_field,_seq) \ - BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DICT_SET_DOC_,(_dict,_field),_seq) +#define PARAM_PY_DICT_SET_DOC(_dict, _field, _seq) \ + BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DICT_SET_DOC_, (_dict, _field), _seq) /** \defgroup ParamProperty Property Macros @@ -957,27 +922,30 @@ /** @} */ /** Helper for #PARAM_PROP_DECLARE */ -#define PARAM_PROP_DECLARE_(_param) \ - PARAM_TYPED(PARAM_PROP_,_param)(_param); +#define PARAM_PROP_DECLARE_(_param) PARAM_TYPED(PARAM_PROP_, _param)(_param); /** Declare FreeCAD properties * \ingroup ParamProperty */ -#define PARAM_PROP_DECLARE(_seq) \ - PARAM_FOREACH(PARAM_PROP_DECLARE_,_seq) +#define PARAM_PROP_DECLARE(_seq) PARAM_FOREACH(PARAM_PROP_DECLARE_, _seq) /** Replace FreeCAD #ADD_PROPERTY_TYPE to fix singifying macro */ -#define PARAM_ADD_PROPERTY_TYPE(_prop_, _defaultval_, _group_,_type_,_Docu_) \ - do { \ - this->_prop_.setValue _defaultval_;\ - this->_prop_.setContainer(this); \ - propertyData.addProperty(static_cast(this), BOOST_PP_STRINGIZE(_prop_), &this->_prop_, (_group_),(_type_),(_Docu_)); \ - } while (0) +#define PARAM_ADD_PROPERTY_TYPE(_prop_, _defaultval_, _group_, _type_, _Docu_) \ + do { \ + this->_prop_.setValue _defaultval_; \ + this->_prop_.setContainer(this); \ + propertyData.addProperty( \ + static_cast(this), \ + BOOST_PP_STRINGIZE(_prop_), &this->_prop_, (_group_), (_type_), (_Docu_)); \ + } while (0) /** Generic property adding */ -#define PARAM_PROP_ADD_(_group,_param) \ - PARAM_ADD_PROPERTY_TYPE(PARAM_FNAME(_param), (PARAM_FDEF(_param)),\ - _group,App::Prop_None,PARAM_FDOC(_param)); +#define PARAM_PROP_ADD_(_group, _param) \ + PARAM_ADD_PROPERTY_TYPE(PARAM_FNAME(_param), \ + (PARAM_FDEF(_param)), \ + _group, \ + App::Prop_None, \ + PARAM_FDOC(_param)); #define PARAM_PROP_ADD_short PARAM_PROP_ADD_ #define PARAM_PROP_ADD_long PARAM_PROP_ADD_ @@ -986,19 +954,21 @@ #define PARAM_PROP_ADD_enum2 PARAM_PROP_ADD_enum /** Add \c enum type parameter as property */ -#define PARAM_PROP_ADD_enum(_group,_param) \ - PARAM_ADD_PROPERTY_TYPE(PARAM_FNAME(_param), ((long)PARAM_FDEF(_param)),\ - _group,App::Prop_None,PARAM_FDOC(_param)); +#define PARAM_PROP_ADD_enum(_group, _param) \ + PARAM_ADD_PROPERTY_TYPE(PARAM_FNAME(_param), \ + ((long)PARAM_FDEF(_param)), \ + _group, \ + App::Prop_None, \ + PARAM_FDOC(_param)); /** Helper for #PARAM_PROP_ADD */ -#define PARAM_PROP_ADD_TYPED(_1,_group,_i,_param) \ - PARAM_TYPED(PARAM_PROP_ADD_,_param)(_group,_param) +#define PARAM_PROP_ADD_TYPED(_1, _group, _i, _param) \ + PARAM_TYPED(PARAM_PROP_ADD_, _param)(_group, _param) /** Add FreeCAD properties * \ingroup ParamProperty */ -#define PARAM_PROP_ADD(_group,_seq) \ - BOOST_PP_SEQ_FOR_EACH_I(PARAM_PROP_ADD_TYPED,_group,_seq) +#define PARAM_PROP_ADD(_group, _seq) BOOST_PP_SEQ_FOR_EACH_I(PARAM_PROP_ADD_TYPED, _group, _seq) #define PARAM_PROP_SET_ENUM_short(...) #define PARAM_PROP_SET_ENUM_long(...) @@ -1007,23 +977,22 @@ #define PARAM_PROP_SET_ENUM_enum2 PARAM_PROP_SET_ENUM_enum /** Setup \c enum type parameter */ -#define PARAM_PROP_SET_ENUM_enum(_prefix,_param) \ - PARAM_FNAME(_param).setEnums(BOOST_PP_CAT(_prefix,PARAM_FNAME(_param))); +#define PARAM_PROP_SET_ENUM_enum(_prefix, _param) \ + PARAM_FNAME(_param).setEnums(BOOST_PP_CAT(_prefix, PARAM_FNAME(_param))); /** Helper for #PARAM_PROP_SET_ENUM */ -#define PARAM_PROP_SET_ENUM_TYPED(_1,_prefix,_param) \ - PARAM_TYPED(PARAM_PROP_SET_ENUM_,_param)(_prefix,_param) +#define PARAM_PROP_SET_ENUM_TYPED(_1, _prefix, _param) \ + PARAM_TYPED(PARAM_PROP_SET_ENUM_, _param)(_prefix, _param) /* Setup the \c enum string list for \c enum type properties * \ingroup ParamProperty */ -#define PARAM_PROP_SET_ENUM(_prefix,_seq) \ - BOOST_PP_SEQ_FOR_EACH(PARAM_PROP_SET_ENUM_TYPED,_prefix,_seq) +#define PARAM_PROP_SET_ENUM(_prefix, _seq) \ + BOOST_PP_SEQ_FOR_EACH(PARAM_PROP_SET_ENUM_TYPED, _prefix, _seq) /** Helper for #PARAM_PROP_ARGS */ -#define PARAM_PROP_ARGS_(_i,_param) \ - BOOST_PP_COMMA_IF(_i) PARAM_FNAME(_param).getValue() +#define PARAM_PROP_ARGS_(_i, _param) BOOST_PP_COMMA_IF(_i) PARAM_FNAME(_param).getValue() /** Expand the property list as function arguments * @@ -1033,13 +1002,13 @@ * \endcode * \ingroup ParamProperty */ -#define PARAM_PROP_ARGS(_seq) \ - PARAM_FOREACH_I(PARAM_PROP_ARGS_,_seq) +#define PARAM_PROP_ARGS(_seq) PARAM_FOREACH_I(PARAM_PROP_ARGS_, _seq) /** Helper for #PARAM_PROP_TOUCHED */ -#define PARAM_PROP_TOUCHED_(_param) \ - if(PARAM_FNAME(_param).isTouched()) return 1; +#define PARAM_PROP_TOUCHED_(_param) \ + if (PARAM_FNAME(_param).isTouched()) \ + return 1; /** Returns 1 if any properties is touched * @@ -1050,7 +1019,6 @@ * ... * \ingroup ParamProperty */ -#define PARAM_PROP_TOUCHED(_seq) \ - PARAM_FOREACH(PARAM_PROP_TOUCHED_,_seq) +#define PARAM_PROP_TOUCHED(_seq) PARAM_FOREACH(PARAM_PROP_TOUCHED_, _seq) -#endif // PARAMS_HELPER_H +#endif // PARAMS_HELPER_H diff --git a/src/Mod/CAM/App/Path.cpp b/src/Mod/CAM/App/Path.cpp index cb61089bc6..f3f4f8e7e4 100644 --- a/src/Mod/CAM/App/Path.cpp +++ b/src/Mod/CAM/App/Path.cpp @@ -35,11 +35,10 @@ using namespace Path; using namespace Base; -TYPESYSTEM_SOURCE(Path::Toolpath , Base::Persistence) +TYPESYSTEM_SOURCE(Path::Toolpath, Base::Persistence) Toolpath::Toolpath() -{ -} +{} Toolpath::Toolpath(const Toolpath& otherPath) : vpcCommands(otherPath.vpcCommands.size()) @@ -54,15 +53,18 @@ Toolpath::~Toolpath() clear(); } -Toolpath &Toolpath::operator=(const Toolpath& otherPath) +Toolpath& Toolpath::operator=(const Toolpath& otherPath) { - if (this == &otherPath) + if (this == &otherPath) { return *this; + } clear(); vpcCommands.resize(otherPath.vpcCommands.size()); int i = 0; - for (std::vector::const_iterator it=otherPath.vpcCommands.begin();it!=otherPath.vpcCommands.end();++it,i++) { + for (std::vector::const_iterator it = otherPath.vpcCommands.begin(); + it != otherPath.vpcCommands.end(); + ++it, i++) { vpcCommands[i] = new Command(**it); } center = otherPath.center; @@ -72,27 +74,30 @@ Toolpath &Toolpath::operator=(const Toolpath& otherPath) void Toolpath::clear() { - for(std::vector::iterator it = vpcCommands.begin();it!=vpcCommands.end();++it) - delete ( *it ); + for (std::vector::iterator it = vpcCommands.begin(); it != vpcCommands.end(); ++it) { + delete (*it); + } vpcCommands.clear(); recalculate(); } -void Toolpath::addCommand(const Command &Cmd) +void Toolpath::addCommand(const Command& Cmd) { - Command *tmp = new Command(Cmd); + Command* tmp = new Command(Cmd); vpcCommands.push_back(tmp); recalculate(); } -void Toolpath::insertCommand(const Command &Cmd, int pos) +void Toolpath::insertCommand(const Command& Cmd, int pos) { if (pos == -1) { addCommand(Cmd); - } else if (pos <= static_cast(vpcCommands.size())) { - Command *tmp = new Command(Cmd); - vpcCommands.insert(vpcCommands.begin()+pos,tmp); - } else { + } + else if (pos <= static_cast(vpcCommands.size())) { + Command* tmp = new Command(Cmd); + vpcCommands.insert(vpcCommands.begin() + pos, tmp); + } + else { throw Base::IndexError("Index not in range"); } recalculate(); @@ -101,11 +106,13 @@ void Toolpath::insertCommand(const Command &Cmd, int pos) void Toolpath::deleteCommand(int pos) { if (pos == -1) { - //delete(*vpcCommands.rbegin()); // causes crash + // delete(*vpcCommands.rbegin()); // causes crash vpcCommands.pop_back(); - } else if (pos <= static_cast(vpcCommands.size())) { - vpcCommands.erase (vpcCommands.begin()+pos); - } else { + } + else if (pos <= static_cast(vpcCommands.size())) { + vpcCommands.erase(vpcCommands.begin() + pos); + } + else { throw Base::IndexError("Index not in range"); } recalculate(); @@ -113,19 +120,22 @@ void Toolpath::deleteCommand(int pos) double Toolpath::getLength() { - if(vpcCommands.empty()) + if (vpcCommands.empty()) { return 0; + } double l = 0; - Vector3d last(0,0,0); + Vector3d last(0, 0, 0); Vector3d next; - for(std::vector::const_iterator it = vpcCommands.begin();it!=vpcCommands.end();++it) { + for (std::vector::const_iterator it = vpcCommands.begin(); it != vpcCommands.end(); + ++it) { std::string name = (*it)->Name; next = (*it)->getPlacement(last).getPosition(); - if ( (name == "G0") || (name == "G00") || (name == "G1") || (name == "G01") ) { + if ((name == "G0") || (name == "G00") || (name == "G1") || (name == "G01")) { // straight line l += (next - last).Length(); last = next; - } else if ( (name == "G2") || (name == "G02") || (name == "G3") || (name == "G03") ) { + } + else if ((name == "G2") || (name == "G02") || (name == "G3") || (name == "G03")) { // arc Vector3d center = (*it)->getCenter(); double radius = (last - center).Length(); @@ -141,7 +151,8 @@ double Toolpath::getCycleTime(double hFeed, double vFeed, double hRapid, double { // check the feedrates are set if ((hFeed == 0) || (vFeed == 0)) { - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/CAM"); + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/CAM"); if (!hGrp->GetBool("WarningsSuppressAllSpeeds", true)) { Base::Console().Warning("Feed Rate Error: Check Tool Controllers have Feed Rates"); } @@ -162,9 +173,10 @@ double Toolpath::getCycleTime(double hFeed, double vFeed, double hRapid, double double l = 0; double time = 0; bool verticalMove = false; - Vector3d last(0,0,0); + Vector3d last(0, 0, 0); Vector3d next; - for (std::vector::const_iterator it = vpcCommands.begin();it!=vpcCommands.end();++it) { + for (std::vector::const_iterator it = vpcCommands.begin(); it != vpcCommands.end(); + ++it) { std::string name = (*it)->Name; float feedrate = (*it)->getParam("F"); @@ -173,22 +185,24 @@ double Toolpath::getCycleTime(double hFeed, double vFeed, double hRapid, double feedrate = hFeed; next = (*it)->getPlacement(last).getPosition(); - if (last.z != next.z){ + if (last.z != next.z) { verticalMove = true; feedrate = vFeed; } - if ((name == "G0") || (name == "G00")){ + if ((name == "G0") || (name == "G00")) { // Rapid Move l += (next - last).Length(); feedrate = hRapid; - if(verticalMove){ + if (verticalMove) { feedrate = vRapid; } - }else if ((name == "G1") || (name == "G01")) { + } + else if ((name == "G1") || (name == "G01")) { // Feed Move l += (next - last).Length(); - }else if ((name == "G2") || (name == "G02") || (name == "G3") || (name == "G03") ) { + } + else if ((name == "G2") || (name == "G02") || (name == "G3") || (name == "G03")) { // Arc Move Vector3d center = (*it)->getCenter(); double radius = (last - center).Length(); @@ -202,60 +216,76 @@ double Toolpath::getCycleTime(double hFeed, double vFeed, double hRapid, double return time; } -class BoundBoxSegmentVisitor : public PathSegmentVisitor +class BoundBoxSegmentVisitor: public PathSegmentVisitor { public: BoundBoxSegmentVisitor() - { } + {} - void g0(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts) override + void g0(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts) override { - (void)id; - processPt(last); - processPts(pts); - processPt(next); + (void)id; + processPt(last); + processPts(pts); + processPt(next); } - void g1(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts) override + void g1(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts) override { - (void)id; - processPt(last); - processPts(pts); - processPt(next); + (void)id; + processPt(last); + processPts(pts); + processPt(next); } - void g23(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, const Base::Vector3d ¢er) override + void g23(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts, + const Base::Vector3d& center) override { - (void)id; - (void)center; - processPt(last); - processPts(pts); - processPt(next); + (void)id; + (void)center; + processPt(last); + processPts(pts); + processPt(next); } - void g8x(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, - const std::deque &p, const std::deque &q) override + void g8x(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts, + const std::deque& p, + const std::deque& q) override { - (void)id; - (void)q; // always within the bounds of p - processPt(last); - processPts(pts); - processPts(p); - processPt(next); + (void)id; + (void)q; // always within the bounds of p + processPt(last); + processPts(pts); + processPts(p); + processPt(next); } - void g38(int id, const Base::Vector3d &last, const Base::Vector3d &next) override + void g38(int id, const Base::Vector3d& last, const Base::Vector3d& next) override { - (void)id; - processPt(last); - processPt(next); + (void)id; + processPt(last); + processPt(next); } Base::BoundBox3d bb; private: - void processPts(const std::deque &pts) { - for (std::deque::const_iterator it=pts.begin(); pts.end() != it; ++it) { + void processPts(const std::deque& pts) + { + for (std::deque::const_iterator it = pts.begin(); pts.end() != it; ++it) { processPt(*it); } } - void processPt(const Base::Vector3d &pt) { + void processPt(const Base::Vector3d& pt) + { bb.MaxX = std::max(bb.MaxX, pt.x); bb.MinX = std::min(bb.MinX, pt.x); bb.MaxY = std::max(bb.MaxY, pt.y); @@ -274,17 +304,20 @@ Base::BoundBox3d Toolpath::getBoundBox() const return visitor.bb; } -static void bulkAddCommand(const std::string &gcodestr, std::vector &commands, bool &inches) +static void +bulkAddCommand(const std::string& gcodestr, std::vector& commands, bool& inches) { - Command *cmd = new Command(); + Command* cmd = new Command(); cmd->setFromGCode(gcodestr); if ("G20" == cmd->Name) { inches = true; delete cmd; - } else if ("G21" == cmd->Name) { + } + else if ("G21" == cmd->Name) { inches = false; delete cmd; - } else { + } + else { if (inches) { cmd->scaleBy(25.4); } @@ -297,8 +330,8 @@ void Toolpath::setFromGCode(const std::string instr) clear(); // remove comments - //boost::regex e("\\(.*?\\)"); - //std::string str = boost::regex_replace(instr, e, ""); + // boost::regex e("\\(.*?\\)"); + // std::string str = boost::regex_replace(instr, e, ""); std::string str(instr); // split input string by () or G or M commands @@ -306,39 +339,40 @@ void Toolpath::setFromGCode(const std::string instr) std::size_t found = str.find_first_of("(gGmM"); int last = -1; bool inches = false; - while (found != std::string::npos) - { + while (found != std::string::npos) { if (str[found] == '(') { // start of comment - if ( (last > -1) && (mode == "command") ) { + if ((last > -1) && (mode == "command")) { // before opening a comment, add the last found command - std::string gcodestr = str.substr(last, found-last); + std::string gcodestr = str.substr(last, found - last); bulkAddCommand(gcodestr, vpcCommands, inches); } mode = "comment"; last = found; - found = str.find_first_of(')', found+1); - } else if (str[found] == ')') { + found = str.find_first_of(')', found + 1); + } + else if (str[found] == ')') { // end of comment - std::string gcodestr = str.substr(last, found-last+1); + std::string gcodestr = str.substr(last, found - last + 1); bulkAddCommand(gcodestr, vpcCommands, inches); last = -1; - found = str.find_first_of("(gGmM", found+1); + found = str.find_first_of("(gGmM", found + 1); mode = "command"; - } else if (mode == "command") { + } + else if (mode == "command") { // command if (last > -1) { - std::string gcodestr = str.substr(last, found-last); + std::string gcodestr = str.substr(last, found - last); bulkAddCommand(gcodestr, vpcCommands, inches); } last = found; - found = str.find_first_of("(gGmM", found+1); + found = str.find_first_of("(gGmM", found + 1); } } // add the last command found, if any if (last > -1) { if (mode == "command") { - std::string gcodestr = str.substr(last,std::string::npos); + std::string gcodestr = str.substr(last, std::string::npos); bulkAddCommand(gcodestr, vpcCommands, inches); } } @@ -348,18 +382,20 @@ void Toolpath::setFromGCode(const std::string instr) std::string Toolpath::toGCode() const { std::string result; - for (std::vector::const_iterator it=vpcCommands.begin();it!=vpcCommands.end();++it) { + for (std::vector::const_iterator it = vpcCommands.begin(); it != vpcCommands.end(); + ++it) { result += (*it)->toGCode(); result += "\n"; } return result; } -void Toolpath::recalculate() // recalculates the path cache +void Toolpath::recalculate() // recalculates the path cache { - if(vpcCommands.empty()) + if (vpcCommands.empty()) { return; + } // TODO recalculate the KDL stuff. At the moment, this is unused. @@ -420,35 +456,39 @@ void Toolpath::recalculate() // recalculates the path cache // reimplemented from base class -unsigned int Toolpath::getMemSize () const +unsigned int Toolpath::getMemSize() const { return toGCode().size(); } -void Toolpath::setCenter(const Base::Vector3d &c) +void Toolpath::setCenter(const Base::Vector3d& c) { center = c; recalculate(); } -static void saveCenter(Writer &writer, const Base::Vector3d ¢er) +static void saveCenter(Writer& writer, const Base::Vector3d& center) { - writer.Stream() << writer.ind() << "
" << std::endl; + writer.Stream() << writer.ind() << "
" << std::endl; } -void Toolpath::Save (Writer &writer) const +void Toolpath::Save(Writer& writer) const { if (writer.isForceXML()) { - writer.Stream() << writer.ind() << "" << std::endl; + writer.Stream() << writer.ind() << "" << std::endl; writer.incInd(); saveCenter(writer, center); - for(unsigned int i = 0; i < getSize(); i++) { + for (unsigned int i = 0; i < getSize(); i++) { vpcCommands[i]->Save(writer); } writer.decInd(); - } else { - writer.Stream() << writer.ind() - << "" << std::endl; + } + else { + writer.Stream() << writer.ind() << "" << std::endl; writer.incInd(); saveCenter(writer, center); writer.decInd(); @@ -456,25 +496,26 @@ void Toolpath::Save (Writer &writer) const writer.Stream() << writer.ind() << "" << std::endl; } -void Toolpath::SaveDocFile (Base::Writer &writer) const +void Toolpath::SaveDocFile(Base::Writer& writer) const { - if (toGCode().empty()) + if (toGCode().empty()) { return; + } writer.Stream() << toGCode(); } -void Toolpath::Restore(XMLReader &reader) +void Toolpath::Restore(XMLReader& reader) { reader.readElement("Path"); - std::string file (reader.getAttribute("file") ); + std::string file(reader.getAttribute("file")); if (!file.empty()) { // initiate a file read - reader.addFile(file.c_str(),this); + reader.addFile(file.c_str(), this); } } -void Toolpath::RestoreDocFile(Base::Reader &reader) +void Toolpath::RestoreDocFile(Base::Reader& reader) { std::string gcode; std::string line; @@ -483,10 +524,4 @@ void Toolpath::RestoreDocFile(Base::Reader &reader) gcode += " "; } setFromGCode(gcode); - } - - - - - diff --git a/src/Mod/CAM/App/Path.h b/src/Mod/CAM/App/Path.h index e9b8264584..5866e70c61 100644 --- a/src/Mod/CAM/App/Path.h +++ b/src/Mod/CAM/App/Path.h @@ -33,72 +33,85 @@ namespace Path { - /** The representation of a CNC Toolpath */ +/** The representation of a CNC Toolpath */ - class PathExport Toolpath : public Base::Persistence +class PathExport Toolpath: public Base::Persistence +{ + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + +public: + Toolpath(); + Toolpath(const Toolpath&); + ~Toolpath() override; + + Toolpath& operator=(const Toolpath&); + + // from base class + unsigned int getMemSize() const override; + void Save(Base::Writer& /*writer*/) const override; + void Restore(Base::XMLReader& /*reader*/) override; + void SaveDocFile(Base::Writer& writer) const override; + void RestoreDocFile(Base::Reader& reader) override; + + // interface + void clear(); // clears the internal data + void addCommand(const Command& Cmd); // adds a command at the end + void insertCommand(const Command& Cmd, int); // inserts a command + void deleteCommand(int); // deletes a command + double getLength(); // return the Length (mm) of the Path + double getCycleTime(double, double, double, double); // return the Cycle Time (s) of the Path + void recalculate(); // recalculates the points + void + setFromGCode(const std::string); // sets the path from the contents of the given GCode string + std::string toGCode() const; // gets a gcode string representation from the Path + Base::BoundBox3d getBoundBox() const; + + // shortcut functions + unsigned int getSize() const { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + return vpcCommands.size(); + } + const std::vector& getCommands() const + { + return vpcCommands; + } + const Command& getCommand(unsigned int pos) const + { + return *vpcCommands[pos]; + } - public: - Toolpath(); - Toolpath(const Toolpath&); - ~Toolpath() override; + // support for rotation + const Base::Vector3d& getCenter() const + { + return center; + } + void setCenter(const Base::Vector3d& c); - Toolpath &operator=(const Toolpath&); + static const int SchemaVersion = 2; - // from base class - unsigned int getMemSize () const override; - void Save (Base::Writer &/*writer*/) const override; - void Restore(Base::XMLReader &/*reader*/) override; - void SaveDocFile (Base::Writer &writer) const override; - void RestoreDocFile(Base::Reader &reader) override; +protected: + std::vector vpcCommands; + Base::Vector3d center; + // KDL::Path_Composite *pcPath; - // interface - void clear(); // clears the internal data - void addCommand(const Command &Cmd); // adds a command at the end - void insertCommand(const Command &Cmd, int); // inserts a command - void deleteCommand(int); // deletes a command - double getLength(); // return the Length (mm) of the Path - double getCycleTime(double, double, double, double); // return the Cycle Time (s) of the Path - void recalculate(); // recalculates the points - void setFromGCode(const std::string); // sets the path from the contents of the given GCode string - std::string toGCode() const; // gets a gcode string representation from the Path - Base::BoundBox3d getBoundBox() const; + /* + inline KDL::Frame toFrame(const Base::Placement &To){ + return KDL::Frame(KDL::Rotation::Quaternion(To.getRotation()[0], + To.getRotation()[1], + To.getRotation()[2], + To.getRotation()[3]), + KDL::Vector(To.getPosition()[0], + To.getPosition()[1], + To.getPosition()[2])); + } + inline Base::Placement toPlacement(const KDL::Frame &To){ + double x,y,z,w; + To.M.GetQuaternion(x,y,z,w); + return Base::Placement(Base::Vector3d(To.p[0],To.p[1],To.p[2]),Base::Rotation(x,y,z,w)); + } */ +}; - // shortcut functions - unsigned int getSize() const { return vpcCommands.size(); } - const std::vector &getCommands() const { return vpcCommands; } - const Command &getCommand(unsigned int pos) const { return *vpcCommands[pos]; } - - // support for rotation - const Base::Vector3d& getCenter() const { return center; } - void setCenter(const Base::Vector3d &c); - - static const int SchemaVersion = 2; - - protected: - std::vector vpcCommands; - Base::Vector3d center; - //KDL::Path_Composite *pcPath; - - /* - inline KDL::Frame toFrame(const Base::Placement &To){ - return KDL::Frame(KDL::Rotation::Quaternion(To.getRotation()[0], - To.getRotation()[1], - To.getRotation()[2], - To.getRotation()[3]), - KDL::Vector(To.getPosition()[0], - To.getPosition()[1], - To.getPosition()[2])); - } - inline Base::Placement toPlacement(const KDL::Frame &To){ - double x,y,z,w; - To.M.GetQuaternion(x,y,z,w); - return Base::Placement(Base::Vector3d(To.p[0],To.p[1],To.p[2]),Base::Rotation(x,y,z,w)); - } */ - }; - -} //namespace Path +} // namespace Path -#endif // PATH_Path_H +#endif // PATH_Path_H diff --git a/src/Mod/CAM/App/PathPyImp.cpp b/src/Mod/CAM/App/PathPyImp.cpp index d118b77a1b..734b6eab66 100644 --- a/src/Mod/CAM/App/PathPyImp.cpp +++ b/src/Mod/CAM/App/PathPyImp.cpp @@ -46,7 +46,7 @@ std::string PathPy::representation() const return str.str(); } -PyObject *PathPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +PyObject* PathPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper { // create a new instance of PathPy and the Twin object return new PathPy(new Toolpath); @@ -55,16 +55,18 @@ PyObject *PathPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Pytho // constructor method int PathPy::PyInit(PyObject* args, PyObject* /*kwd*/) { - PyObject *pcObj=nullptr; - char *gcode; + PyObject* pcObj = nullptr; + char* gcode; if (PyArg_ParseTuple(args, "|O!", &(PyList_Type), &pcObj)) { if (pcObj) { Py::List list(pcObj); for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { if (PyObject_TypeCheck((*it).ptr(), &(Path::CommandPy::Type))) { - Path::Command &cmd = *static_cast((*it).ptr())->getCommandPtr(); + Path::Command& cmd = + *static_cast((*it).ptr())->getCommandPtr(); getToolpathPtr()->addCommand(cmd); - } else { + } + else { PyErr_SetString(PyExc_TypeError, "The list must contain only Path Commands"); return -1; } @@ -72,7 +74,7 @@ int PathPy::PyInit(PyObject* args, PyObject* /*kwd*/) } return 0; } - PyErr_Clear(); // set by PyArg_ParseTuple() + PyErr_Clear(); // set by PyArg_ParseTuple() if (PyArg_ParseTuple(args, "|s", &gcode)) { getToolpathPtr()->setFromGCode(gcode); return 0; @@ -87,8 +89,10 @@ int PathPy::PyInit(PyObject* args, PyObject* /*kwd*/) Py::List PathPy::getCommands() const { Py::List list; - for(unsigned int i = 0; i < getToolpathPtr()->getSize(); i++) - list.append(Py::asObject(new Path::CommandPy(new Path::Command(getToolpathPtr()->getCommand(i))))); + for (unsigned int i = 0; i < getToolpathPtr()->getSize(); i++) { + list.append( + Py::asObject(new Path::CommandPy(new Path::Command(getToolpathPtr()->getCommand(i))))); + } return list; } @@ -97,9 +101,10 @@ void PathPy::setCommands(Py::List list) getToolpathPtr()->clear(); for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { if (PyObject_TypeCheck((*it).ptr(), &(Path::CommandPy::Type))) { - Path::Command &cmd = *static_cast((*it).ptr())->getCommandPtr(); + Path::Command& cmd = *static_cast((*it).ptr())->getCommandPtr(); getToolpathPtr()->addCommand(cmd); - } else { + } + else { throw Py::TypeError("The list can only contain Path Commands"); } } @@ -134,7 +139,7 @@ Py::Object PathPy::getBoundBox() const // specific methods -PyObject* PathPy::copy(PyObject * args) +PyObject* PathPy::copy(PyObject* args) { if (PyArg_ParseTuple(args, "")) { return new PathPy(new Path::Toolpath(*getToolpathPtr())); @@ -142,21 +147,21 @@ PyObject* PathPy::copy(PyObject * args) throw Py::TypeError("This method accepts no argument"); } -PyObject* PathPy::addCommands(PyObject * args) +PyObject* PathPy::addCommands(PyObject* args) { PyObject* o; if (PyArg_ParseTuple(args, "O!", &(Path::CommandPy::Type), &o)) { - Path::Command &cmd = *static_cast(o)->getCommandPtr(); + Path::Command& cmd = *static_cast(o)->getCommandPtr(); getToolpathPtr()->addCommand(cmd); return new PathPy(new Path::Toolpath(*getToolpathPtr())); - //Py_Return; + // Py_Return; } PyErr_Clear(); if (PyArg_ParseTuple(args, "O!", &(PyList_Type), &o)) { Py::List list(o); for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { if (PyObject_TypeCheck((*it).ptr(), &(Path::CommandPy::Type))) { - Path::Command &cmd = *static_cast((*it).ptr())->getCommandPtr(); + Path::Command& cmd = *static_cast((*it).ptr())->getCommandPtr(); getToolpathPtr()->addCommand(cmd); } } @@ -165,19 +170,19 @@ PyObject* PathPy::addCommands(PyObject * args) Py_Error(PyExc_TypeError, "Wrong parameters - command or list of commands expected"); } -PyObject* PathPy::insertCommand(PyObject * args) +PyObject* PathPy::insertCommand(PyObject* args) { PyObject* o; int pos = -1; if (PyArg_ParseTuple(args, "O!|i", &(Path::CommandPy::Type), &o, &pos)) { - Path::Command &cmd = *static_cast(o)->getCommandPtr(); - getToolpathPtr()->insertCommand(cmd,pos); + Path::Command& cmd = *static_cast(o)->getCommandPtr(); + getToolpathPtr()->insertCommand(cmd, pos); return new PathPy(new Path::Toolpath(*getToolpathPtr())); } Py_Error(PyExc_TypeError, "Wrong parameters - expected command and optional integer"); } -PyObject* PathPy::deleteCommand(PyObject * args) +PyObject* PathPy::deleteCommand(PyObject* args) { int pos = -1; if (PyArg_ParseTuple(args, "|i", &pos)) { @@ -187,10 +192,10 @@ PyObject* PathPy::deleteCommand(PyObject * args) Py_Error(PyExc_TypeError, "Wrong parameters - expected an integer (optional)"); } -PyObject* PathPy::getCycleTime(PyObject * args) +PyObject* PathPy::getCycleTime(PyObject* args) { double hFeed, vFeed, hRapid, vRapid; - if (PyArg_ParseTuple(args, "dddd", &hFeed, &vFeed, &hRapid, &vRapid)){ + if (PyArg_ParseTuple(args, "dddd", &hFeed, &vFeed, &hRapid, &vRapid)) { return PyFloat_FromDouble(getToolpathPtr()->getCycleTime(hFeed, vFeed, hRapid, vRapid)); } return nullptr; @@ -198,7 +203,7 @@ PyObject* PathPy::getCycleTime(PyObject * args) // GCode methods -PyObject* PathPy::toGCode(PyObject * args) +PyObject* PathPy::toGCode(PyObject* args) { if (PyArg_ParseTuple(args, "")) { std::string result = getToolpathPtr()->toGCode(); @@ -207,9 +212,9 @@ PyObject* PathPy::toGCode(PyObject * args) throw Py::TypeError("This method accepts no argument"); } -PyObject* PathPy::setFromGCode(PyObject * args) +PyObject* PathPy::setFromGCode(PyObject* args) { - char *pstr=nullptr; + char* pstr = nullptr; if (PyArg_ParseTuple(args, "s", &pstr)) { std::string gcode(pstr); getToolpathPtr()->setFromGCode(gcode); @@ -221,7 +226,7 @@ PyObject* PathPy::setFromGCode(PyObject * args) // custom attributes get/set -PyObject *PathPy::getCustomAttributes(const char* /*attr*/) const +PyObject* PathPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } @@ -230,5 +235,3 @@ int PathPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { return 0; } - - diff --git a/src/Mod/CAM/App/PathSegmentWalker.cpp b/src/Mod/CAM/App/PathSegmentWalker.cpp index 93718ae39c..d0ebe7c5a4 100644 --- a/src/Mod/CAM/App/PathSegmentWalker.cpp +++ b/src/Mod/CAM/App/PathSegmentWalker.cpp @@ -29,21 +29,23 @@ #include "PathSegmentWalker.h" -#define ARC_MIN_SEGMENTS 20.0 // minimum # segments to interpolate an arc +#define ARC_MIN_SEGMENTS 20.0 // minimum # segments to interpolate an arc #ifndef M_PI - #define M_PI 3.14159265358979323846 /* pi */ +#define M_PI 3.14159265358979323846 /* pi */ #endif #ifndef M_PI_2 - #define M_PI_2 1.57079632679489661923 /* pi/2 */ +#define M_PI_2 1.57079632679489661923 /* pi/2 */ #endif namespace Path { -Base::Vector3d compensateRotation(const Base::Vector3d &pt, const Base::Rotation &rot, const Base::Vector3d ¢er) +Base::Vector3d compensateRotation(const Base::Vector3d& pt, + const Base::Rotation& rot, + const Base::Vector3d& center) { Base::Vector3d ptRotated; rot.multVec(pt - center, ptRotated); @@ -58,15 +60,17 @@ Base::Rotation yawPitchRoll(double a, double b, double c) } PathSegmentVisitor::~PathSegmentVisitor() -{ -} +{} -void PathSegmentVisitor::setup(const Base::Vector3d &last) +void PathSegmentVisitor::setup(const Base::Vector3d& last) { (void)last; } -void PathSegmentVisitor::g0(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts) +void PathSegmentVisitor::g0(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts) { (void)id; (void)last; @@ -74,7 +78,10 @@ void PathSegmentVisitor::g0(int id, const Base::Vector3d &last, const Base::Vect (void)pts; } -void PathSegmentVisitor::g1(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts) +void PathSegmentVisitor::g1(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts) { (void)id; (void)last; @@ -82,7 +89,11 @@ void PathSegmentVisitor::g1(int id, const Base::Vector3d &last, const Base::Vect (void)pts; } -void PathSegmentVisitor::g23(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, const Base::Vector3d ¢er) +void PathSegmentVisitor::g23(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts, + const Base::Vector3d& center) { (void)id; (void)last; @@ -91,8 +102,12 @@ void PathSegmentVisitor::g23(int id, const Base::Vector3d &last, const Base::Vec (void)center; } -void PathSegmentVisitor::g8x(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, - const std::deque &p, const std::deque &q) +void PathSegmentVisitor::g8x(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts, + const std::deque& p, + const std::deque& q) { (void)id; (void)last; @@ -102,26 +117,27 @@ void PathSegmentVisitor::g8x(int id, const Base::Vector3d &last, const Base::Vec (void)q; } -void PathSegmentVisitor::g38(int id, const Base::Vector3d &last, const Base::Vector3d &next) +void PathSegmentVisitor::g38(int id, const Base::Vector3d& last, const Base::Vector3d& next) { (void)id; (void)last; (void)next; } -PathSegmentWalker::PathSegmentWalker(const Toolpath &tp_) - :tp(tp_) +PathSegmentWalker::PathSegmentWalker(const Toolpath& tp_) + : tp(tp_) {} -void PathSegmentWalker::walk(PathSegmentVisitor &cb, const Base::Vector3d &startPosition) +void PathSegmentWalker::walk(PathSegmentVisitor& cb, const Base::Vector3d& startPosition) { - if(tp.getSize()==0) { + if (tp.getSize() == 0) { return; } - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Part"); - float deviation = hGrp->GetFloat("MeshDeviation",0.2); + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Part"); + float deviation = hGrp->GetFloat("MeshDeviation", 0.2); Base::Vector3d rotCenter = tp.getCenter(); Base::Vector3d last(startPosition); @@ -138,35 +154,49 @@ void PathSegmentWalker::walk(PathSegmentVisitor &cb, const Base::Vector3d &start cb.setup(last); - for (unsigned int i = 0; i < tp.getSize(); i++) { + for (unsigned int i = 0; i < tp.getSize(); i++) { std::deque points; - const Path::Command &cmd = tp.getCommand(i); - const std::string &name = cmd.Name; + const Path::Command& cmd = tp.getCommand(i); + const std::string& name = cmd.Name; Base::Vector3d next = cmd.getPlacement().getPosition(); double a = A; double b = B; double c = C; - if (!absolute) + if (!absolute) { next = last + next; - if (!cmd.has("X")) next.x = last.x; - if (!cmd.has("Y")) next.y = last.y; - if (!cmd.has("Z")) next.z = last.z; - if ( cmd.has("A")) a = cmd.getValue("A"); - if ( cmd.has("B")) b = cmd.getValue("B"); - if ( cmd.has("C")) c = cmd.getValue("C"); + } + if (!cmd.has("X")) { + next.x = last.x; + } + if (!cmd.has("Y")) { + next.y = last.y; + } + if (!cmd.has("Z")) { + next.z = last.z; + } + if (cmd.has("A")) { + a = cmd.getValue("A"); + } + if (cmd.has("B")) { + b = cmd.getValue("B"); + } + if (cmd.has("C")) { + c = cmd.getValue("C"); + } Base::Rotation nrot = yawPitchRoll(a, b, c); Base::Vector3d rnext = compensateRotation(next, nrot, rotCenter); - if ( (name == "G0") || (name == "G00") || (name == "G1") || (name == "G01") ) { + if ((name == "G0") || (name == "G00") || (name == "G1") || (name == "G01")) { // straight line if (nrot != lrot) { - double amax = std::max(fmod(fabs(a - A), 360), std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360))); + double amax = std::max(fmod(fabs(a - A), 360), + std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360))); double angle = amax / 180 * M_PI; - int segments = std::max(ARC_MIN_SEGMENTS, 3.0/(deviation/angle)); + int segments = std::max(ARC_MIN_SEGMENTS, 3.0 / (deviation / angle)); double da = (a - A) / segments; double db = (b - B) / segments; @@ -177,7 +207,7 @@ void PathSegmentWalker::walk(PathSegmentVisitor &cb, const Base::Vector3d &start for (int j = 1; j < segments; j++) { Base::Vector3d inter = last + dnext * j; - Base::Rotation rot = yawPitchRoll(A + da*j, B + db*j, C + dc*j); + Base::Rotation rot = yawPitchRoll(A + da * j, B + db * j, C + dc * j); Base::Vector3d rinter = compensateRotation(inter, rot, rotCenter); points.push_back(rinter); @@ -186,7 +216,8 @@ void PathSegmentWalker::walk(PathSegmentVisitor &cb, const Base::Vector3d &start if ("G0" == name || "G00" == name) { cb.g0(i, last, rnext, points); - } else { + } + else { cb.g1(i, last, rnext, points); } @@ -195,57 +226,71 @@ void PathSegmentWalker::walk(PathSegmentVisitor &cb, const Base::Vector3d &start B = b; C = c; lrot = nrot; - - } else if ( (name == "G2") || (name == "G02") || (name == "G3") || (name == "G03") ) { + } + else if ((name == "G2") || (name == "G02") || (name == "G3") || (name == "G03")) { // arc Base::Vector3d norm; Base::Vector3d center; - if ( (name == "G2") || (name == "G02") ) + if ((name == "G2") || (name == "G02")) { norm.*pz = -1.0; - else + } + else { norm.*pz = 1.0; + } - if (absolutecenter) + if (absolutecenter) { center = cmd.getCenter(); - else + } + else { center = (last + cmd.getCenter()); + } Base::Vector3d next0(next); next0.*pz = 0.0; Base::Vector3d last0(last); last0.*pz = 0.0; Base::Vector3d center0(center); center0.*pz = 0.0; - //double radius = (last - center).Length(); + // double radius = (last - center).Length(); double angle = (next0 - center0).GetAngle(last0 - center0); // GetAngle will always return the minor angle. Switch if needed Base::Vector3d anorm = (last0 - center0) % (next0 - center0); if (anorm.*pz < 0) { - if(name == "G3" || name == "G03") + if (name == "G3" || name == "G03") { angle = M_PI * 2 - angle; - } else if(anorm.*pz > 0) { - if(name == "G2" || name == "G02") + } + } + else if (anorm.*pz > 0) { + if (name == "G2" || name == "G02") { angle = M_PI * 2 - angle; - } else if (angle == 0) + } + } + else if (angle == 0) { angle = M_PI * 2; + } - double amax = std::max(fmod(fabs(a - A), 360), std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360))); + double amax = std::max(fmod(fabs(a - A), 360), + std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360))); - int segments = std::max(ARC_MIN_SEGMENTS, 3.0/(deviation/std::max(angle, amax))); //we use a rather simple rule here, provisorily - double dZ = (next.*pz - last.*pz)/segments; //How far each segment will helix in Z + int segments = std::max( + ARC_MIN_SEGMENTS, + 3.0 + / (deviation + / std::max(angle, amax))); // we use a rather simple rule here, provisorily + double dZ = (next.*pz - last.*pz) / segments; // How far each segment will helix in Z - double dangle = angle/segments; + double dangle = angle / segments; double da = (a - A) / segments; double db = (b - B) / segments; double dc = (c - C) / segments; for (int j = 1; j < segments; j++) { Base::Vector3d inter; - Base::Rotation rot(norm, dangle*j); + Base::Rotation rot(norm, dangle * j); rot.multVec((last0 - center0), inter); - inter.*pz = last.*pz + dZ * j; //Enable displaying helices + inter.*pz = last.*pz + dZ * j; // Enable displaying helices - Base::Rotation arot = yawPitchRoll(A + da*j, B + db*j, C + dc*j); + Base::Rotation arot = yawPitchRoll(A + da * j, B + db * j, C + dc * j); Base::Vector3d rinter = compensateRotation(center0 + inter, arot, rotCenter); points.push_back(rinter); @@ -258,28 +303,30 @@ void PathSegmentWalker::walk(PathSegmentVisitor &cb, const Base::Vector3d &start B = b; C = c; lrot = nrot; - - } else if (name == "G90") { + } + else if (name == "G90") { // absolute mode absolute = true; - - } else if (name == "G91") { + } + else if (name == "G91") { // relative mode absolute = false; - - } else if (name == "G90.1") { + } + else if (name == "G90.1") { // absolute mode absolutecenter = true; - - } else if (name == "G91.1") { + } + else if (name == "G91.1") { // relative mode absolutecenter = false; - - } else if ((name=="G73")||(name=="G81")||(name=="G82")||(name=="G83")||(name=="G84")||(name=="G85")||(name=="G86")||(name=="G89")){ + } + else if ((name == "G73") || (name == "G81") || (name == "G82") || (name == "G83") + || (name == "G84") || (name == "G85") || (name == "G86") || (name == "G89")) { // drill,tap,bore double r = 0; - if (cmd.has("R")) + if (cmd.has("R")) { r = cmd.getValue("R"); + } std::deque plist; std::deque qlist; @@ -288,9 +335,10 @@ void PathSegmentWalker::walk(PathSegmentVisitor &cb, const Base::Vector3d &start p1.*pz = last.*pz; if (nrot != lrot) { - double amax = std::max(fmod(fabs(a - A), 360), std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360))); + double amax = std::max(fmod(fabs(a - A), 360), + std::max(fmod(fabs(b - B), 360), fmod(fabs(c - C), 360))); double angle = amax / 180 * M_PI; - int segments = std::max(ARC_MIN_SEGMENTS, 3.0/(deviation/angle)); + int segments = std::max(ARC_MIN_SEGMENTS, 3.0 / (deviation / angle)); double da = (a - A) / segments; double db = (b - B) / segments; @@ -301,7 +349,7 @@ void PathSegmentWalker::walk(PathSegmentVisitor &cb, const Base::Vector3d &start for (int j = 1; j < segments; j++) { Base::Vector3d inter = last + dnext * j; - Base::Rotation rot = yawPitchRoll(A + da*j, B + db*j, C + dc*j); + Base::Rotation rot = yawPitchRoll(A + da * j, B + db * j, C + dc * j); Base::Vector3d rinter = compensateRotation(inter, rot, rotCenter); points.push_back(rinter); @@ -316,9 +364,9 @@ void PathSegmentWalker::walk(PathSegmentVisitor &cb, const Base::Vector3d &start double q; if (cmd.has("Q")) { q = cmd.getValue("Q"); - if (q>0) { + if (q > 0) { Base::Vector3d temp(next); - for(temp.*pz=r;temp.*pz>next.*pz;temp.*pz-=q) { + for (temp.*pz = r; temp.*pz > next.*pz; temp.*pz -= q) { Base::Vector3d pr = compensateRotation(temp, nrot, rotCenter); qlist.push_back(pr); } @@ -326,10 +374,12 @@ void PathSegmentWalker::walk(PathSegmentVisitor &cb, const Base::Vector3d &start } Base::Vector3d p3(next); - if (retract_mode == 99) // G81,G83 need to account for G99 and retract to R only + if (retract_mode == 99) { // G81,G83 need to account for G99 and retract to R only p3.*pz = p2.*pz; - else + } + else { p3.*pz = last.*pz; + } Base::Vector3d p3r = compensateRotation(p3, nrot, rotCenter); @@ -345,25 +395,29 @@ void PathSegmentWalker::walk(PathSegmentVisitor &cb, const Base::Vector3d &start B = b; C = c; lrot = nrot; - - - } else if ((name=="G38.2")||(name=="G38.3")||(name=="G38.4")||(name=="G38.5")){ + } + else if ((name == "G38.2") || (name == "G38.3") || (name == "G38.4") || (name == "G38.5")) { // Straight probe cb.g38(i, last, next); last = next; - } else if(name=="G17") { + } + else if (name == "G17") { pz = &Base::Vector3d::z; - } else if(name=="G18") { + } + else if (name == "G18") { pz = &Base::Vector3d::y; - } else if(name=="G19") { + } + else if (name == "G19") { pz = &Base::Vector3d::x; - } else if(name=="G98") { + } + else if (name == "G98") { retract_mode = 98; - } else if(name=="G99") { + } + else if (name == "G99") { retract_mode = 99; } } } -} +} // namespace Path diff --git a/src/Mod/CAM/App/PathSegmentWalker.h b/src/Mod/CAM/App/PathSegmentWalker.h index 4da7668319..264efa0c08 100644 --- a/src/Mod/CAM/App/PathSegmentWalker.h +++ b/src/Mod/CAM/App/PathSegmentWalker.h @@ -38,38 +38,52 @@ namespace Path */ class PathExport PathSegmentVisitor { - public: +public: virtual ~PathSegmentVisitor(); - virtual void setup(const Base::Vector3d &last); + virtual void setup(const Base::Vector3d& last); - virtual void g0(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts); - virtual void g1(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts); - virtual void g23(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, const Base::Vector3d ¢er); - virtual void g8x(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, - const std::deque &p, const std::deque &q); - virtual void g38(int id, const Base::Vector3d &last, const Base::Vector3d &next); + virtual void g0(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts); + virtual void g1(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts); + virtual void g23(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts, + const Base::Vector3d& center); + virtual void g8x(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts, + const std::deque& p, + const std::deque& q); + virtual void g38(int id, const Base::Vector3d& last, const Base::Vector3d& next); }; /** - * PathSegmentWalker processes a path and splits all movement commands into straight segments and calls the - * appropriate member of the provided PathSegmentVisitor. - * All non-movement commands are processed accordingly if they affect the movement commands. + * PathSegmentWalker processes a path and splits all movement commands into straight segments and + * calls the appropriate member of the provided PathSegmentVisitor. All non-movement commands are + * processed accordingly if they affect the movement commands. */ class PathExport PathSegmentWalker { public: - PathSegmentWalker(const Toolpath &tp_); + PathSegmentWalker(const Toolpath& tp_); - void walk(PathSegmentVisitor &cb, const Base::Vector3d &startPosition); + void walk(PathSegmentVisitor& cb, const Base::Vector3d& startPosition); private: - const Toolpath &tp; + const Toolpath& tp; int retract_mode; }; -} +} // namespace Path -#endif // PATHSEGMENTWALKER_H +#endif // PATHSEGMENTWALKER_H diff --git a/src/Mod/CAM/App/PreCompiled.h b/src/Mod/CAM/App/PreCompiled.h index 4ea802b3cb..470c653327 100644 --- a/src/Mod/CAM/App/PreCompiled.h +++ b/src/Mod/CAM/App/PreCompiled.h @@ -27,17 +27,17 @@ // Exporting of App classes #ifdef FC_OS_WIN32 -# define PathExport __declspec(dllexport) -//# define RobotExport __declspec(dllexport) uncomment this to use KDL -# define PartExport __declspec(dllimport) -#else // for Linux -# define PathExport -//# define RobotExport uncomment this to use KDL -# define PartExport +#define PathExport __declspec(dllexport) +// # define RobotExport __declspec(dllexport) uncomment this to use KDL +#define PartExport __declspec(dllimport) +#else // for Linux +#define PathExport +// # define RobotExport uncomment this to use KDL +#define PartExport #endif #ifdef _MSC_VER -#pragma warning( disable : 5208 ) +#pragma warning(disable : 5208) #endif #ifdef _PreComp_ @@ -57,7 +57,7 @@ #include #include -//OCC +// OCC #include #include #include @@ -100,5 +100,5 @@ #include #include -#endif // _PreComp_ +#endif // _PreComp_ #endif diff --git a/src/Mod/CAM/App/PropertyPath.cpp b/src/Mod/CAM/App/PropertyPath.cpp index b316a23e52..36772e4cd0 100644 --- a/src/Mod/CAM/App/PropertyPath.cpp +++ b/src/Mod/CAM/App/PropertyPath.cpp @@ -22,7 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -39,12 +39,10 @@ using namespace Path; TYPESYSTEM_SOURCE(Path::PropertyPath, App::Property) PropertyPath::PropertyPath() -{ -} +{} PropertyPath::~PropertyPath() -{ -} +{} void PropertyPath::setValue(const Toolpath& pa) { @@ -54,20 +52,20 @@ void PropertyPath::setValue(const Toolpath& pa) } -const Toolpath &PropertyPath::getValue()const +const Toolpath& PropertyPath::getValue() const { return _Path; } -PyObject *PropertyPath::getPyObject() +PyObject* PropertyPath::getPyObject() { return new PathPy(new Toolpath(_Path)); } -void PropertyPath::setPyObject(PyObject *value) +void PropertyPath::setPyObject(PyObject* value) { if (PyObject_TypeCheck(value, &(PathPy::Type))) { - PathPy *pcObject = static_cast(value); + PathPy* pcObject = static_cast(value); setValue(*pcObject->getToolpathPtr()); } else { @@ -77,39 +75,39 @@ void PropertyPath::setPyObject(PyObject *value) } } -App::Property *PropertyPath::Copy() const +App::Property* PropertyPath::Copy() const { - PropertyPath *prop = new PropertyPath(); + PropertyPath* prop = new PropertyPath(); prop->_Path = this->_Path; return prop; } -void PropertyPath::Paste(const App::Property &from) +void PropertyPath::Paste(const App::Property& from) { aboutToSetValue(); _Path = dynamic_cast(from)._Path; hasSetValue(); } -unsigned int PropertyPath::getMemSize () const +unsigned int PropertyPath::getMemSize() const { return _Path.getMemSize(); } -void PropertyPath::Save (Base::Writer &writer) const +void PropertyPath::Save(Base::Writer& writer) const { _Path.Save(writer); } -void PropertyPath::Restore(Base::XMLReader &reader) +void PropertyPath::Restore(Base::XMLReader& reader) { reader.readElement("Path"); - std::string file (reader.getAttribute("file") ); + std::string file(reader.getAttribute("file")); if (!file.empty()) { // initiate a file read - reader.addFile(file.c_str(),this); + reader.addFile(file.c_str(), this); } if (reader.hasAttribute("version")) { @@ -125,15 +123,15 @@ void PropertyPath::Restore(Base::XMLReader &reader) } } -void PropertyPath::SaveDocFile (Base::Writer &) const +void PropertyPath::SaveDocFile(Base::Writer&) const { // does nothing } -void PropertyPath::RestoreDocFile(Base::Reader &reader) +void PropertyPath::RestoreDocFile(Base::Reader& reader) { - App::PropertyContainer *container = getContainer(); - App::DocumentObject *obj = nullptr; + App::PropertyContainer* container = getContainer(); + App::DocumentObject* obj = nullptr; if (container->isDerivedFrom(App::DocumentObject::getClassTypeId())) { obj = static_cast(container); } @@ -150,6 +148,3 @@ void PropertyPath::RestoreDocFile(Base::Reader &reader) obj->setStatus(App::ObjectStatus::Restore, false); } } - - - diff --git a/src/Mod/CAM/App/PropertyPath.h b/src/Mod/CAM/App/PropertyPath.h index e34621c93e..713ec35899 100644 --- a/src/Mod/CAM/App/PropertyPath.h +++ b/src/Mod/CAM/App/PropertyPath.h @@ -32,7 +32,7 @@ namespace Path { /** The path property class. */ -class PathExport PropertyPath : public App::Property +class PathExport PropertyPath: public App::Property { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -45,25 +45,25 @@ public: /// set the part shape void setValue(const Toolpath&); /// get the part shape - const Toolpath &getValue() const; + const Toolpath& getValue() const; //@} /** @name Python interface */ //@{ PyObject* getPyObject() override; - void setPyObject(PyObject *value) override; + void setPyObject(PyObject* value) override; //@} /** @name Save/restore */ //@{ - void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; - void SaveDocFile (Base::Writer &writer) const override; - void RestoreDocFile(Base::Reader &reader) override; + void Save(Base::Writer& writer) const override; + void Restore(Base::XMLReader& reader) override; + void SaveDocFile(Base::Writer& writer) const override; + void RestoreDocFile(Base::Reader& reader) override; - App::Property *Copy() const override; - void Paste(const App::Property &from) override; - unsigned int getMemSize () const override; + App::Property* Copy() const override; + void Paste(const App::Property& from) override; + unsigned int getMemSize() const override; //@} private: @@ -71,7 +71,7 @@ private: }; -} //namespace Path +} // namespace Path -#endif // PROPERTYPATH_H +#endif // PROPERTYPATH_H diff --git a/src/Mod/CAM/App/Voronoi.cpp b/src/Mod/CAM/App/Voronoi.cpp index 443b747507..55aeb601c3 100644 --- a/src/Mod/CAM/App/Voronoi.cpp +++ b/src/Mod/CAM/App/Voronoi.cpp @@ -23,7 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ #define _USE_MATH_DEFINES -# include +#include #endif #include @@ -34,272 +34,307 @@ using namespace Base; using namespace Path; -TYPESYSTEM_SOURCE(Path::Voronoi , Base::BaseClass) +TYPESYSTEM_SOURCE(Path::Voronoi, Base::BaseClass) // Helpers // Voronoi::diagram_type Voronoi::diagram_type::diagram_type() - :scale(1000) + : scale(1000) +{} + +double Voronoi::diagram_type::getScale() const { + return scale; } -double Voronoi::diagram_type::getScale() const { - return scale; +void Voronoi::diagram_type::setScale(double s) +{ + scale = s; } -void Voronoi::diagram_type::setScale(double s) { - scale = s; +Base::Vector3d Voronoi::diagram_type::scaledVector(double x, double y, double z) const +{ + return Base::Vector3d(x / scale, y / scale, z); } -Base::Vector3d Voronoi::diagram_type::scaledVector(double x, double y, double z) const { - return Base::Vector3d(x / scale, y / scale, z); +Base::Vector3d Voronoi::diagram_type::scaledVector(const point_type& p, double z) const +{ + return scaledVector(p.x(), p.y(), z); } -Base::Vector3d Voronoi::diagram_type::scaledVector(const point_type &p, double z) const { - return scaledVector(p.x(), p.y(), z); -} - -Base::Vector3d Voronoi::diagram_type::scaledVector(const vertex_type &v, double z) const { - return scaledVector(v.x(), v.y(), z); +Base::Vector3d Voronoi::diagram_type::scaledVector(const vertex_type& v, double z) const +{ + return scaledVector(v.x(), v.y(), z); } -int Voronoi::diagram_type::index(const Voronoi::diagram_type::cell_type *cell) const { - auto it = cell_index.find(intptr_t(cell)); - if (it == cell_index.end()) { - return Voronoi::InvalidIndex; - } - return it->second; +int Voronoi::diagram_type::index(const Voronoi::diagram_type::cell_type* cell) const +{ + auto it = cell_index.find(intptr_t(cell)); + if (it == cell_index.end()) { + return Voronoi::InvalidIndex; + } + return it->second; } -int Voronoi::diagram_type::index(const Voronoi::diagram_type::edge_type *edge) const { - auto it = edge_index.find(intptr_t(edge)); - if (it == edge_index.end()) { - return Voronoi::InvalidIndex; - } - return it->second; +int Voronoi::diagram_type::index(const Voronoi::diagram_type::edge_type* edge) const +{ + auto it = edge_index.find(intptr_t(edge)); + if (it == edge_index.end()) { + return Voronoi::InvalidIndex; + } + return it->second; } -int Voronoi::diagram_type::index(const Voronoi::diagram_type::vertex_type *vertex) const { - auto it = vertex_index.find(intptr_t(vertex)); - if (it == vertex_index.end()) { - return Voronoi::InvalidIndex; - } - return it->second; +int Voronoi::diagram_type::index(const Voronoi::diagram_type::vertex_type* vertex) const +{ + auto it = vertex_index.find(intptr_t(vertex)); + if (it == vertex_index.end()) { + return Voronoi::InvalidIndex; + } + return it->second; } -void Voronoi::diagram_type::reIndex() { - int idx = 0; - cell_index.clear(); - edge_index.clear(); - vertex_index.clear(); +void Voronoi::diagram_type::reIndex() +{ + int idx = 0; + cell_index.clear(); + edge_index.clear(); + vertex_index.clear(); - idx = 0; - for (auto it = cells().begin(); it != cells().end(); ++it, ++idx) { - cell_index[intptr_t(&(*it))] = idx; - } - idx = 0; - for (auto it = edges().begin(); it != edges().end(); ++it, ++idx) { - edge_index[intptr_t(&(*it))] = idx; - } - idx = 0; - for (auto it = vertices().begin(); it != vertices().end(); ++it, ++idx) { - vertex_index[intptr_t(&(*it))] = idx; - } + idx = 0; + for (auto it = cells().begin(); it != cells().end(); ++it, ++idx) { + cell_index[intptr_t(&(*it))] = idx; + } + idx = 0; + for (auto it = edges().begin(); it != edges().end(); ++it, ++idx) { + edge_index[intptr_t(&(*it))] = idx; + } + idx = 0; + for (auto it = vertices().begin(); it != vertices().end(); ++it, ++idx) { + vertex_index[intptr_t(&(*it))] = idx; + } } -Voronoi::point_type Voronoi::diagram_type::retrievePoint(const Voronoi::diagram_type::cell_type *cell) const { - Voronoi::diagram_type::cell_type::source_index_type index = cell->source_index(); - Voronoi::diagram_type::cell_type::source_category_type category = cell->source_category(); - if (category == boost::polygon::SOURCE_CATEGORY_SINGLE_POINT) { - return points[index]; - } - index -= points.size(); - if (category == boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT) { - return low(segments[index]); - } else { - return high(segments[index]); - } +Voronoi::point_type +Voronoi::diagram_type::retrievePoint(const Voronoi::diagram_type::cell_type* cell) const +{ + Voronoi::diagram_type::cell_type::source_index_type index = cell->source_index(); + Voronoi::diagram_type::cell_type::source_category_type category = cell->source_category(); + if (category == boost::polygon::SOURCE_CATEGORY_SINGLE_POINT) { + return points[index]; + } + index -= points.size(); + if (category == boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT) { + return low(segments[index]); + } + else { + return high(segments[index]); + } } -Voronoi::segment_type Voronoi::diagram_type::retrieveSegment(const Voronoi::diagram_type::cell_type *cell) const { - Voronoi::diagram_type::cell_type::source_index_type index = cell->source_index() - points.size(); - return segments[index]; +Voronoi::segment_type +Voronoi::diagram_type::retrieveSegment(const Voronoi::diagram_type::cell_type* cell) const +{ + Voronoi::diagram_type::cell_type::source_index_type index = + cell->source_index() - points.size(); + return segments[index]; } // Voronoi Voronoi::Voronoi() - :vd(new diagram_type) -{ -} + : vd(new diagram_type) +{} Voronoi::~Voronoi() +{} + + +void Voronoi::addPoint(const Voronoi::point_type& p) { + Voronoi::point_type pi; + pi.x(p.x() * vd->getScale()); + pi.y(p.y() * vd->getScale()); + vd->points.push_back(pi); +} + +void Voronoi::addSegment(const Voronoi::segment_type& s) +{ + Voronoi::point_type pil, pih; + pil.x(low(s).x() * vd->getScale()); + pil.y(low(s).y() * vd->getScale()); + pih.x(high(s).x() * vd->getScale()); + pih.y(high(s).y() * vd->getScale()); + vd->segments.emplace_back(pil, pih); +} + +long Voronoi::numPoints() const +{ + return vd->points.size(); +} + +long Voronoi::numSegments() const +{ + return vd->segments.size(); } -void Voronoi::addPoint(const Voronoi::point_type &p) { - Voronoi::point_type pi; - pi.x(p.x() * vd->getScale()); - pi.y(p.y() * vd->getScale()); - vd->points.push_back(pi); +long Voronoi::numCells() const +{ + return vd->num_cells(); } -void Voronoi::addSegment(const Voronoi::segment_type &s) { - Voronoi::point_type pil, pih; - pil.x(low(s).x() * vd->getScale()); - pil.y(low(s).y() * vd->getScale()); - pih.x(high(s).x() * vd->getScale()); - pih.y(high(s).y() * vd->getScale()); - vd->segments.emplace_back(pil, pih); +long Voronoi::numEdges() const +{ + return vd->num_edges(); } -long Voronoi::numPoints() const { - return vd->points.size(); -} - -long Voronoi::numSegments() const { - return vd->segments.size(); -} - - -long Voronoi::numCells() const { - return vd->num_cells(); -} - -long Voronoi::numEdges() const { - return vd->num_edges(); -} - -long Voronoi::numVertices() const { - return vd->num_vertices(); +long Voronoi::numVertices() const +{ + return vd->num_vertices(); } void Voronoi::construct() { - vd->clear(); - construct_voronoi(vd->points.begin(), vd->points.end(), vd->segments.begin(), vd->segments.end(), static_cast(vd)); - vd->reIndex(); + vd->clear(); + construct_voronoi(vd->points.begin(), + vd->points.end(), + vd->segments.begin(), + vd->segments.end(), + static_cast(vd)); + vd->reIndex(); } -void Voronoi::colorExterior(const Voronoi::diagram_type::edge_type *edge, std::size_t colorValue) { - if (edge->color()) { - // end recursion - return; - } - edge->color(colorValue); - edge->twin()->color(colorValue); - auto v = edge->vertex1(); - if (!v || !edge->is_primary()) { - return; - } - v->color(colorValue); - auto e = v->incident_edge(); - do { - colorExterior(e, colorValue); - e = e->rot_next(); - } while (e != v->incident_edge()); -} - -void Voronoi::colorExterior(Voronoi::color_type color) { - for (diagram_type::const_edge_iterator it = vd->edges().begin(); it != vd->edges().end(); ++it) { - if (it->is_infinite()) { - colorExterior(&(*it), color); +void Voronoi::colorExterior(const Voronoi::diagram_type::edge_type* edge, std::size_t colorValue) +{ + if (edge->color()) { + // end recursion + return; } - } + edge->color(colorValue); + edge->twin()->color(colorValue); + auto v = edge->vertex1(); + if (!v || !edge->is_primary()) { + return; + } + v->color(colorValue); + auto e = v->incident_edge(); + do { + colorExterior(e, colorValue); + e = e->rot_next(); + } while (e != v->incident_edge()); } -void Voronoi::colorTwins(Voronoi::color_type color) { - for (diagram_type::const_edge_iterator it = vd->edges().begin(); it != vd->edges().end(); ++it) { - if (!it->color()) { - auto twin = it->twin(); - if (!twin->color()) { - twin->color(color); - } +void Voronoi::colorExterior(Voronoi::color_type color) +{ + for (diagram_type::const_edge_iterator it = vd->edges().begin(); it != vd->edges().end(); + ++it) { + if (it->is_infinite()) { + colorExterior(&(*it), color); + } } - } } -double Voronoi::diagram_type::angleOfSegment(int i, Voronoi::diagram_type::angle_map_t *angle) const { - Voronoi::diagram_type::angle_map_t::const_iterator a = angle ? angle->find(i) : Voronoi::diagram_type::angle_map_t::const_iterator(); - if (!angle || a == angle->end()) { - Voronoi::point_type p0 = low(segments[i]); - Voronoi::point_type p1 = high(segments[i]); - double ang = 0; - if (p0.x() == p1.x()) { - if (p0.y() < p1.y()) { - ang = M_PI_2; - } else { - ang = -M_PI_2; - } - } else { - ang = atan((p0.y() - p1.y()) / (p0.x() - p1.x())); +void Voronoi::colorTwins(Voronoi::color_type color) +{ + for (diagram_type::const_edge_iterator it = vd->edges().begin(); it != vd->edges().end(); + ++it) { + if (!it->color()) { + auto twin = it->twin(); + if (!twin->color()) { + twin->color(color); + } + } } - if (angle) { - angle->insert(angle_map_t::value_type(i, ang)); - } - return ang; - } - return a->second; } -static bool pointsMatch(const Voronoi::point_type &p0, const Voronoi::point_type &p1) { - return long(p0.x()) == long(p1.x()) && long(p0.y()) == long(p1.y()); +double Voronoi::diagram_type::angleOfSegment(int i, Voronoi::diagram_type::angle_map_t* angle) const +{ + Voronoi::diagram_type::angle_map_t::const_iterator a = + angle ? angle->find(i) : Voronoi::diagram_type::angle_map_t::const_iterator(); + if (!angle || a == angle->end()) { + Voronoi::point_type p0 = low(segments[i]); + Voronoi::point_type p1 = high(segments[i]); + double ang = 0; + if (p0.x() == p1.x()) { + if (p0.y() < p1.y()) { + ang = M_PI_2; + } + else { + ang = -M_PI_2; + } + } + else { + ang = atan((p0.y() - p1.y()) / (p0.x() - p1.x())); + } + if (angle) { + angle->insert(angle_map_t::value_type(i, ang)); + } + return ang; + } + return a->second; } -bool Voronoi::diagram_type::segmentsAreConnected(int i, int j) const { - return - pointsMatch(low(segments[i]), low(segments[j])) - || pointsMatch(low(segments[i]), high(segments[j])) - || pointsMatch(high(segments[i]), low(segments[j])) - || pointsMatch(high(segments[i]), high(segments[j])); +static bool pointsMatch(const Voronoi::point_type& p0, const Voronoi::point_type& p1) +{ + return long(p0.x()) == long(p1.x()) && long(p0.y()) == long(p1.y()); } -void Voronoi::colorColinear(Voronoi::color_type color, double degree) { - double rad = degree * M_PI / 180; - - Voronoi::diagram_type::angle_map_t angle; - int psize = vd->points.size(); - - for (diagram_type::const_edge_iterator it = vd->edges().begin(); it != vd->edges().end(); ++it) { - int i0 = it->cell()->source_index() - psize; - int i1 = it->twin()->cell()->source_index() - psize; - if (it->color() == 0 - && it->cell()->contains_segment() - && it->twin()->cell()->contains_segment() - && vd->segmentsAreConnected(i0, i1)) { - double a0 = vd->angleOfSegment(i0, &angle); - double a1 = vd->angleOfSegment(i1, &angle); - double a = a0 - a1; - if (a > M_PI_2) { - a -= M_PI; - } else if (a < -M_PI_2) { - a += M_PI; - } - if (fabs(a) < rad) { - it->color(color); - it->twin()->color(color); - } - } - } +bool Voronoi::diagram_type::segmentsAreConnected(int i, int j) const +{ + return pointsMatch(low(segments[i]), low(segments[j])) + || pointsMatch(low(segments[i]), high(segments[j])) + || pointsMatch(high(segments[i]), low(segments[j])) + || pointsMatch(high(segments[i]), high(segments[j])); } -void Voronoi::resetColor(Voronoi::color_type color) { - for (auto it = vd->cells().begin(); it != vd->cells().end(); ++it) { - if (color == 0 || it->color() == color) { - it->color(0); +void Voronoi::colorColinear(Voronoi::color_type color, double degree) +{ + double rad = degree * M_PI / 180; + + Voronoi::diagram_type::angle_map_t angle; + int psize = vd->points.size(); + + for (diagram_type::const_edge_iterator it = vd->edges().begin(); it != vd->edges().end(); + ++it) { + int i0 = it->cell()->source_index() - psize; + int i1 = it->twin()->cell()->source_index() - psize; + if (it->color() == 0 && it->cell()->contains_segment() + && it->twin()->cell()->contains_segment() && vd->segmentsAreConnected(i0, i1)) { + double a0 = vd->angleOfSegment(i0, &angle); + double a1 = vd->angleOfSegment(i1, &angle); + double a = a0 - a1; + if (a > M_PI_2) { + a -= M_PI; + } + else if (a < -M_PI_2) { + a += M_PI; + } + if (fabs(a) < rad) { + it->color(color); + it->twin()->color(color); + } + } + } +} + +void Voronoi::resetColor(Voronoi::color_type color) +{ + for (auto it = vd->cells().begin(); it != vd->cells().end(); ++it) { + if (color == 0 || it->color() == color) { + it->color(0); + } + } + for (auto it = vd->edges().begin(); it != vd->edges().end(); ++it) { + if (it->color() == color) { + it->color(0); + } + } + for (auto it = vd->vertices().begin(); it != vd->vertices().end(); ++it) { + if (it->color() == color) { + it->color(0); + } } - } - for (auto it = vd->edges().begin(); it != vd->edges().end(); ++it) { - if (it->color() == color) { - it->color(0); - } - } - for (auto it = vd->vertices().begin(); it != vd->vertices().end(); ++it) { - if (it->color() == color) { - it->color(0); - } - } } diff --git a/src/Mod/CAM/App/Voronoi.h b/src/Mod/CAM/App/Voronoi.h index 84136175ea..d7a4ac5c8c 100644 --- a/src/Mod/CAM/App/Voronoi.h +++ b/src/Mod/CAM/App/Voronoi.h @@ -34,26 +34,25 @@ #include #if (SIZE_MAX == UINT_MAX) -# define PATH_VORONOI_COLOR_MASK 0x07FFFFFFul +#define PATH_VORONOI_COLOR_MASK 0x07FFFFFFul #else -# define PATH_VORONOI_COLOR_MASK 0x07FFFFFFFFFFFFFFul +#define PATH_VORONOI_COLOR_MASK 0x07FFFFFFFFFFFFFFul #endif namespace Path { - class PathExport Voronoi - : public Base::BaseClass - { +class PathExport Voronoi: public Base::BaseClass +{ TYPESYSTEM_HEADER_WITH_OVERRIDE(); - public: - //constructors +public: + // constructors Voronoi(); ~Voronoi() override; using color_type = std::size_t; - static const int InvalidIndex = INT_MAX; - static const color_type ColorMask = PATH_VORONOI_COLOR_MASK; + static const int InvalidIndex = INT_MAX; + static const color_type ColorMask = PATH_VORONOI_COLOR_MASK; // types using coordinate_type = double; @@ -62,49 +61,47 @@ namespace Path using segment_type = boost::polygon::segment_data; using voronoi_diagram_type = boost::polygon::voronoi_diagram; - class diagram_type - : public voronoi_diagram_type - , public Base::Handled + class diagram_type: public voronoi_diagram_type, public Base::Handled { public: - diagram_type(); + diagram_type(); - double getScale() const; - void setScale(double s); + double getScale() const; + void setScale(double s); - Base::Vector3d scaledVector(double x, double y, double z) const; - Base::Vector3d scaledVector(const point_type &p, double z) const; - Base::Vector3d scaledVector(const vertex_type &v, double z) const; + Base::Vector3d scaledVector(double x, double y, double z) const; + Base::Vector3d scaledVector(const point_type& p, double z) const; + Base::Vector3d scaledVector(const vertex_type& v, double z) const; - using cell_map_type = std::map; - using edge_map_type = std::map; - using vertex_map_type = std::map; + using cell_map_type = std::map; + using edge_map_type = std::map; + using vertex_map_type = std::map; - int index(const cell_type *cell) const; - int index(const edge_type *edge) const; - int index(const vertex_type *vertex) const; + int index(const cell_type* cell) const; + int index(const edge_type* edge) const; + int index(const vertex_type* vertex) const; - void reIndex(); + void reIndex(); - std::vector points; - std::vector segments; + std::vector points; + std::vector segments; - point_type retrievePoint(const cell_type *cell) const; - segment_type retrieveSegment(const cell_type *cell) const; + point_type retrievePoint(const cell_type* cell) const; + segment_type retrieveSegment(const cell_type* cell) const; - using angle_map_t = std::map; - double angleOfSegment(int i, angle_map_t *angle = nullptr) const; - bool segmentsAreConnected(int i, int j) const; + using angle_map_t = std::map; + double angleOfSegment(int i, angle_map_t* angle = nullptr) const; + bool segmentsAreConnected(int i, int j) const; private: - double scale; - cell_map_type cell_index; - edge_map_type edge_index; - vertex_map_type vertex_index; + double scale; + cell_map_type cell_index; + edge_map_type edge_index; + vertex_map_type vertex_index; }; - void addPoint(const point_type &p); - void addSegment(const segment_type &p); + void addPoint(const point_type& p); + void addSegment(const segment_type& p); long numPoints() const; long numSegments() const; @@ -119,19 +116,26 @@ namespace Path void colorColinear(color_type color, double degree); template - T* create(int index) { - return new T(vd, index); + T* create(int index) + { + return new T(vd, index); } - double getScale() const { return vd->getScale(); } - void setScale(double scale) { vd->setScale(scale); } + double getScale() const + { + return vd->getScale(); + } + void setScale(double scale) + { + vd->setScale(scale); + } - private: +private: Base::Reference vd; friend class VoronoiPy; - void colorExterior(const Voronoi::diagram_type::edge_type *edge, std::size_t colorValue); - }; + void colorExterior(const Voronoi::diagram_type::edge_type* edge, std::size_t colorValue); +}; -} //namespace Path +} // namespace Path -#endif // PATH_VORONOI_H +#endif // PATH_VORONOI_H diff --git a/src/Mod/CAM/App/VoronoiCell.cpp b/src/Mod/CAM/App/VoronoiCell.cpp index 70671db5ba..42e267ec6e 100644 --- a/src/Mod/CAM/App/VoronoiCell.cpp +++ b/src/Mod/CAM/App/VoronoiCell.cpp @@ -28,55 +28,58 @@ using namespace Base; using namespace Path; -TYPESYSTEM_SOURCE(Path::VoronoiCell , Base::Persistence) +TYPESYSTEM_SOURCE(Path::VoronoiCell, Base::Persistence) -VoronoiCell::VoronoiCell(Voronoi::diagram_type *d, long index) - : dia(d) - , index(index) - , ptr(nullptr) +VoronoiCell::VoronoiCell(Voronoi::diagram_type* d, long index) + : dia(d) + , index(index) + , ptr(nullptr) { - if (dia && long(dia->num_cells()) > index) { - ptr = &(dia->cells()[index]); - } -} - -VoronoiCell::VoronoiCell(Voronoi::diagram_type *d, const Voronoi::diagram_type::cell_type *e) - : dia(d) - , index(Voronoi::InvalidIndex) - , ptr(e) -{ - if (d && e) { - index = dia->index(e); - } -} - -VoronoiCell::~VoronoiCell() { -} - -bool VoronoiCell::isBound() const { - if (ptr && dia.isValid() && index != Voronoi::InvalidIndex) { - if (&(dia->cells()[index]) == ptr) { - return true; + if (dia && long(dia->num_cells()) > index) { + ptr = &(dia->cells()[index]); } - } - ptr = nullptr; - return false; } -Voronoi::point_type VoronoiCell::sourcePoint() const { - int index = ptr->source_index(); - int category = ptr->source_category(); - if (category == boost::polygon::SOURCE_CATEGORY_SINGLE_POINT) { - return dia->points[index]; - } - if (category == boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT) { - return low(dia->segments[index - dia->points.size()]); - } else { - return high(dia->segments[index - dia->points.size()]); - } +VoronoiCell::VoronoiCell(Voronoi::diagram_type* d, const Voronoi::diagram_type::cell_type* e) + : dia(d) + , index(Voronoi::InvalidIndex) + , ptr(e) +{ + if (d && e) { + index = dia->index(e); + } } -Voronoi::segment_type VoronoiCell::sourceSegment() const { - return dia->segments[ptr->source_index() - dia->points.size()]; +VoronoiCell::~VoronoiCell() +{} + +bool VoronoiCell::isBound() const +{ + if (ptr && dia.isValid() && index != Voronoi::InvalidIndex) { + if (&(dia->cells()[index]) == ptr) { + return true; + } + } + ptr = nullptr; + return false; } +Voronoi::point_type VoronoiCell::sourcePoint() const +{ + int index = ptr->source_index(); + int category = ptr->source_category(); + if (category == boost::polygon::SOURCE_CATEGORY_SINGLE_POINT) { + return dia->points[index]; + } + if (category == boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT) { + return low(dia->segments[index - dia->points.size()]); + } + else { + return high(dia->segments[index - dia->points.size()]); + } +} + +Voronoi::segment_type VoronoiCell::sourceSegment() const +{ + return dia->segments[ptr->source_index() - dia->points.size()]; +} diff --git a/src/Mod/CAM/App/VoronoiCell.h b/src/Mod/CAM/App/VoronoiCell.h index bce5cb85f4..588f2fdc18 100644 --- a/src/Mod/CAM/App/VoronoiCell.h +++ b/src/Mod/CAM/App/VoronoiCell.h @@ -30,25 +30,24 @@ namespace Path class Voronoi; -class PathExport VoronoiCell - : public Base::BaseClass +class PathExport VoronoiCell: public Base::BaseClass { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: + VoronoiCell(Voronoi::diagram_type* dia = nullptr, long index = Voronoi::InvalidIndex); + VoronoiCell(Voronoi::diagram_type* dia, const Voronoi::diagram_type::cell_type* cell); + ~VoronoiCell() override; - VoronoiCell(Voronoi::diagram_type *dia = nullptr, long index = Voronoi::InvalidIndex); - VoronoiCell(Voronoi::diagram_type *dia, const Voronoi::diagram_type::cell_type *cell); - ~VoronoiCell() override; + bool isBound() const; - bool isBound() const; + Voronoi::point_type sourcePoint() const; + Voronoi::segment_type sourceSegment() const; - Voronoi::point_type sourcePoint() const; - Voronoi::segment_type sourceSegment() const; - - Base::Reference dia; - long index; - mutable const Voronoi::diagram_type::cell_type *ptr; + Base::Reference dia; + long index; + mutable const Voronoi::diagram_type::cell_type* ptr; }; -} +} // namespace Path #endif diff --git a/src/Mod/CAM/App/VoronoiCellPyImp.cpp b/src/Mod/CAM/App/VoronoiCellPyImp.cpp index abb125b9fa..3d34e3950e 100644 --- a/src/Mod/CAM/App/VoronoiCellPyImp.cpp +++ b/src/Mod/CAM/App/VoronoiCellPyImp.cpp @@ -35,169 +35,182 @@ using namespace Path; // returns a string which represents the object e.g. when printed in python std::string VoronoiCellPy::representation() const { - std::stringstream ss; - ss.precision(5); - ss << "VoronoiCell("; - VoronoiCell *c = getVoronoiCellPtr(); - if (c->isBound()) { - ss << c->ptr->source_category() << ":" << c->ptr->source_index(); - } - ss << ")"; - return ss.str(); + std::stringstream ss; + ss.precision(5); + ss << "VoronoiCell("; + VoronoiCell* c = getVoronoiCellPtr(); + if (c->isBound()) { + ss << c->ptr->source_category() << ":" << c->ptr->source_index(); + } + ss << ")"; + return ss.str(); } -PyObject *VoronoiCellPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +PyObject* VoronoiCellPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper { - // create a new instance of VoronoiCellPy and the Twin object - return new VoronoiCellPy(new VoronoiCell); + // create a new instance of VoronoiCellPy and the Twin object + return new VoronoiCellPy(new VoronoiCell); } // constructor method int VoronoiCellPy::PyInit(PyObject* args, PyObject* /*kwd*/) { - if (!PyArg_ParseTuple(args, "")) { - PyErr_SetString(PyExc_RuntimeError, "no arguments accepted"); - return -1; - } - return 0; -} - - -PyObject* VoronoiCellPy::richCompare(PyObject *lhs, PyObject *rhs, int op) { - PyObject *cmp = (op == Py_EQ) ? Py_False : Py_True; - if ( PyObject_TypeCheck(lhs, &VoronoiCellPy::Type) - && PyObject_TypeCheck(rhs, &VoronoiCellPy::Type) - && (op == Py_EQ || op == Py_NE)) { - const VoronoiCell *vl = static_cast(lhs)->getVoronoiCellPtr(); - const VoronoiCell *vr = static_cast(rhs)->getVoronoiCellPtr(); - if (vl->index == vr->index && vl->dia == vr->dia) { - cmp = (op == Py_EQ) ? Py_True : Py_False; + if (!PyArg_ParseTuple(args, "")) { + PyErr_SetString(PyExc_RuntimeError, "no arguments accepted"); + return -1; } - } - Py_INCREF(cmp); - return cmp; + return 0; } -const Voronoi::voronoi_diagram_type::cell_type* getCellFromPy(VoronoiCellPy *c, bool throwIfNotBound = true) { - auto self = c->getVoronoiCellPtr(); - if (self->isBound()) { - return self->ptr; - } - if (throwIfNotBound) { - throw Py::TypeError("Cell not bound to voronoi diagram"); - } - return nullptr; + +PyObject* VoronoiCellPy::richCompare(PyObject* lhs, PyObject* rhs, int op) +{ + PyObject* cmp = (op == Py_EQ) ? Py_False : Py_True; + if (PyObject_TypeCheck(lhs, &VoronoiCellPy::Type) + && PyObject_TypeCheck(rhs, &VoronoiCellPy::Type) && (op == Py_EQ || op == Py_NE)) { + const VoronoiCell* vl = static_cast(lhs)->getVoronoiCellPtr(); + const VoronoiCell* vr = static_cast(rhs)->getVoronoiCellPtr(); + if (vl->index == vr->index && vl->dia == vr->dia) { + cmp = (op == Py_EQ) ? Py_True : Py_False; + } + } + Py_INCREF(cmp); + return cmp; } -VoronoiCell* getVoronoiCellFromPy(const VoronoiCellPy *c, PyObject *args = nullptr) { - VoronoiCell *self = c->getVoronoiCellPtr(); - if (!self->isBound()) { - throw Py::TypeError("Cell not bound to voronoi diagram"); - } - if (args && !PyArg_ParseTuple(args, "")) { - throw Py::RuntimeError("No arguments accepted"); - } - return self; +const Voronoi::voronoi_diagram_type::cell_type* getCellFromPy(VoronoiCellPy* c, + bool throwIfNotBound = true) +{ + auto self = c->getVoronoiCellPtr(); + if (self->isBound()) { + return self->ptr; + } + if (throwIfNotBound) { + throw Py::TypeError("Cell not bound to voronoi diagram"); + } + return nullptr; } -Py::Long VoronoiCellPy::getIndex() const { - VoronoiCell *c = getVoronoiCellPtr(); - if (c->isBound()) { - return Py::Long(c->dia->index(c->ptr)); - } - return Py::Long(-1); +VoronoiCell* getVoronoiCellFromPy(const VoronoiCellPy* c, PyObject* args = nullptr) +{ + VoronoiCell* self = c->getVoronoiCellPtr(); + if (!self->isBound()) { + throw Py::TypeError("Cell not bound to voronoi diagram"); + } + if (args && !PyArg_ParseTuple(args, "")) { + throw Py::RuntimeError("No arguments accepted"); + } + return self; } -Py::Long VoronoiCellPy::getColor() const { - VoronoiCell *c = getVoronoiCellPtr(); - if (c->isBound()) { - Voronoi::color_type color = c->ptr->color() & Voronoi::ColorMask; - return Py::Long(PyLong_FromSize_t(color)); - } - return Py::Long(0); +Py::Long VoronoiCellPy::getIndex() const +{ + VoronoiCell* c = getVoronoiCellPtr(); + if (c->isBound()) { + return Py::Long(c->dia->index(c->ptr)); + } + return Py::Long(-1); } -void VoronoiCellPy::setColor(Py::Long color) { - getCellFromPy(this)->color(long(color) & Voronoi::ColorMask); +Py::Long VoronoiCellPy::getColor() const +{ + VoronoiCell* c = getVoronoiCellPtr(); + if (c->isBound()) { + Voronoi::color_type color = c->ptr->color() & Voronoi::ColorMask; + return Py::Long(PyLong_FromSize_t(color)); + } + return Py::Long(0); +} + +void VoronoiCellPy::setColor(Py::Long color) +{ + getCellFromPy(this)->color(long(color) & Voronoi::ColorMask); } Py::Long VoronoiCellPy::getSourceIndex() const { - VoronoiCell *c = getVoronoiCellFromPy(this); - long index = c->ptr->source_index(); - return Py::Long(index); + VoronoiCell* c = getVoronoiCellFromPy(this); + long index = c->ptr->source_index(); + return Py::Long(index); } Py::Int VoronoiCellPy::getSourceCategory() const { - VoronoiCell *c = getVoronoiCellFromPy(this); - return Py::Int(c->ptr->source_category()); + VoronoiCell* c = getVoronoiCellFromPy(this); + return Py::Int(c->ptr->source_category()); } Py::String VoronoiCellPy::getSourceCategoryName() const { - VoronoiCell *c = getVoronoiCellFromPy(this); - switch (c->ptr->source_category()) { - case boost::polygon::SOURCE_CATEGORY_SINGLE_POINT: return Py::String("SINGLE_POINT"); - case boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT: return Py::String("SEGMENT_START_POINT"); - case boost::polygon::SOURCE_CATEGORY_SEGMENT_END_POINT: return Py::String("SEGMENT_END_POINT"); - case boost::polygon::SOURCE_CATEGORY_INITIAL_SEGMENT: return Py::String("INITIAL_SEGMENT"); - case boost::polygon::SOURCE_CATEGORY_REVERSE_SEGMENT: return Py::String("REVERSE_SEGMENT"); - case boost::polygon::SOURCE_CATEGORY_GEOMETRY_SHIFT: return Py::String("GEOMETRY_SHIFT"); - case boost::polygon::SOURCE_CATEGORY_BITMASK: return Py::String("BITMASK"); - } - return Py::String(""); + VoronoiCell* c = getVoronoiCellFromPy(this); + switch (c->ptr->source_category()) { + case boost::polygon::SOURCE_CATEGORY_SINGLE_POINT: + return Py::String("SINGLE_POINT"); + case boost::polygon::SOURCE_CATEGORY_SEGMENT_START_POINT: + return Py::String("SEGMENT_START_POINT"); + case boost::polygon::SOURCE_CATEGORY_SEGMENT_END_POINT: + return Py::String("SEGMENT_END_POINT"); + case boost::polygon::SOURCE_CATEGORY_INITIAL_SEGMENT: + return Py::String("INITIAL_SEGMENT"); + case boost::polygon::SOURCE_CATEGORY_REVERSE_SEGMENT: + return Py::String("REVERSE_SEGMENT"); + case boost::polygon::SOURCE_CATEGORY_GEOMETRY_SHIFT: + return Py::String("GEOMETRY_SHIFT"); + case boost::polygon::SOURCE_CATEGORY_BITMASK: + return Py::String("BITMASK"); + } + return Py::String(""); } Py::Object VoronoiCellPy::getIncidentEdge() const { - VoronoiCell *c = getVoronoiCellFromPy(this); - return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(c->dia, c->ptr->incident_edge()))); + VoronoiCell* c = getVoronoiCellFromPy(this); + return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(c->dia, c->ptr->incident_edge()))); } -PyObject* VoronoiCellPy::containsPoint(PyObject *args) +PyObject* VoronoiCellPy::containsPoint(PyObject* args) { - VoronoiCell *c = getVoronoiCellFromPy(this, args); - PyObject *chk = c->ptr->contains_point() ? Py_True : Py_False; - Py_INCREF(chk); - return chk; + VoronoiCell* c = getVoronoiCellFromPy(this, args); + PyObject* chk = c->ptr->contains_point() ? Py_True : Py_False; + Py_INCREF(chk); + return chk; } -PyObject* VoronoiCellPy::containsSegment(PyObject *args) +PyObject* VoronoiCellPy::containsSegment(PyObject* args) { - VoronoiCell *c = getVoronoiCellFromPy(this, args); - PyObject *chk = c->ptr->contains_segment() ? Py_True : Py_False; - Py_INCREF(chk); - return chk; + VoronoiCell* c = getVoronoiCellFromPy(this, args); + PyObject* chk = c->ptr->contains_segment() ? Py_True : Py_False; + Py_INCREF(chk); + return chk; } -PyObject* VoronoiCellPy::isDegenerate(PyObject *args) +PyObject* VoronoiCellPy::isDegenerate(PyObject* args) { - VoronoiCell *c = getVoronoiCellFromPy(this, args); - PyObject *chk = c->ptr->is_degenerate() ? Py_True : Py_False; - Py_INCREF(chk); - return chk; + VoronoiCell* c = getVoronoiCellFromPy(this, args); + PyObject* chk = c->ptr->is_degenerate() ? Py_True : Py_False; + Py_INCREF(chk); + return chk; } -PyObject* VoronoiCellPy::getSource(PyObject *args) +PyObject* VoronoiCellPy::getSource(PyObject* args) { - double z = 0; - if (!PyArg_ParseTuple(args, "|d", &z)) { - throw Py::TypeError("Optional z argument (double) accepted"); - } + double z = 0; + if (!PyArg_ParseTuple(args, "|d", &z)) { + throw Py::TypeError("Optional z argument (double) accepted"); + } - VoronoiCell *c = getVoronoiCellFromPy(this); - if (c->ptr->contains_point()) { - Base::Vector3d v = c->dia->scaledVector(c->dia->retrievePoint(c->ptr), z); - return new Base::VectorPy(new Base::Vector3d(v)); - } - Voronoi::segment_type s = c->dia->retrieveSegment(c->ptr); - Base::Vector3d v0 = c->dia->scaledVector(low(s), z); - Base::Vector3d v1 = c->dia->scaledVector(high(s), z); - Py::List list; - list.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(v0)))); - list.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(v1)))); - return Py::new_reference_to(list); + VoronoiCell* c = getVoronoiCellFromPy(this); + if (c->ptr->contains_point()) { + Base::Vector3d v = c->dia->scaledVector(c->dia->retrievePoint(c->ptr), z); + return new Base::VectorPy(new Base::Vector3d(v)); + } + Voronoi::segment_type s = c->dia->retrieveSegment(c->ptr); + Base::Vector3d v0 = c->dia->scaledVector(low(s), z); + Base::Vector3d v1 = c->dia->scaledVector(high(s), z); + Py::List list; + list.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(v0)))); + list.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(v1)))); + return Py::new_reference_to(list); } @@ -205,11 +218,10 @@ PyObject* VoronoiCellPy::getSource(PyObject *args) PyObject* VoronoiCellPy::getCustomAttributes(const char* /*attr*/) const { - return nullptr; + return nullptr; } int VoronoiCellPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { - return 0; + return 0; } - diff --git a/src/Mod/CAM/App/VoronoiEdge.cpp b/src/Mod/CAM/App/VoronoiEdge.cpp index 0e13e8190e..343633c59d 100644 --- a/src/Mod/CAM/App/VoronoiEdge.cpp +++ b/src/Mod/CAM/App/VoronoiEdge.cpp @@ -28,37 +28,38 @@ using namespace Base; using namespace Path; -TYPESYSTEM_SOURCE(Path::VoronoiEdge , Base::Persistence) +TYPESYSTEM_SOURCE(Path::VoronoiEdge, Base::Persistence) -VoronoiEdge::VoronoiEdge(Voronoi::diagram_type *d, long index) - : dia(d) - , index(index) - , ptr(nullptr) +VoronoiEdge::VoronoiEdge(Voronoi::diagram_type* d, long index) + : dia(d) + , index(index) + , ptr(nullptr) { - if (dia && long(dia->num_edges()) > index) { - ptr = &(dia->edges()[index]); - } -} - -VoronoiEdge::VoronoiEdge(Voronoi::diagram_type *d, const Voronoi::diagram_type::edge_type *e) - : dia(d) - , index(Voronoi::InvalidIndex) - , ptr(e) -{ - if (d && e) { - index = dia->index(e); - } -} - -VoronoiEdge::~VoronoiEdge() { -} - -bool VoronoiEdge::isBound() const { - if (ptr && dia.isValid() && index != Voronoi::InvalidIndex) { - if (&(dia->edges()[index]) == ptr) { - return true; + if (dia && long(dia->num_edges()) > index) { + ptr = &(dia->edges()[index]); } - } - ptr = nullptr; - return false; +} + +VoronoiEdge::VoronoiEdge(Voronoi::diagram_type* d, const Voronoi::diagram_type::edge_type* e) + : dia(d) + , index(Voronoi::InvalidIndex) + , ptr(e) +{ + if (d && e) { + index = dia->index(e); + } +} + +VoronoiEdge::~VoronoiEdge() +{} + +bool VoronoiEdge::isBound() const +{ + if (ptr && dia.isValid() && index != Voronoi::InvalidIndex) { + if (&(dia->edges()[index]) == ptr) { + return true; + } + } + ptr = nullptr; + return false; } diff --git a/src/Mod/CAM/App/VoronoiEdge.h b/src/Mod/CAM/App/VoronoiEdge.h index 30c4f2a910..3a16597c03 100644 --- a/src/Mod/CAM/App/VoronoiEdge.h +++ b/src/Mod/CAM/App/VoronoiEdge.h @@ -32,22 +32,21 @@ namespace Path class Voronoi; -class PathExport VoronoiEdge - : public Base::BaseClass +class PathExport VoronoiEdge: public Base::BaseClass { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: + VoronoiEdge(Voronoi::diagram_type* dia = nullptr, long index = Voronoi::InvalidIndex); + VoronoiEdge(Voronoi::diagram_type* dia, const Voronoi::diagram_type::edge_type* edge); + ~VoronoiEdge() override; - VoronoiEdge(Voronoi::diagram_type *dia = nullptr, long index = Voronoi::InvalidIndex); - VoronoiEdge(Voronoi::diagram_type *dia, const Voronoi::diagram_type::edge_type *edge); - ~VoronoiEdge() override; + bool isBound() const; - bool isBound() const; - - Base::Reference dia; - long index; - mutable const Voronoi::diagram_type::edge_type *ptr; + Base::Reference dia; + long index; + mutable const Voronoi::diagram_type::edge_type* ptr; }; -} +} // namespace Path #endif diff --git a/src/Mod/CAM/App/VoronoiEdgePyImp.cpp b/src/Mod/CAM/App/VoronoiEdgePyImp.cpp index 8f96f55307..9015e49d52 100644 --- a/src/Mod/CAM/App/VoronoiEdgePyImp.cpp +++ b/src/Mod/CAM/App/VoronoiEdgePyImp.cpp @@ -22,8 +22,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include +#include +#include #endif #include "Mod/Part/App/Geometry.h" @@ -37,620 +37,687 @@ using namespace Path; -namespace { +namespace +{ - Voronoi::point_type pointFromVertex(const Voronoi::vertex_type v) { +Voronoi::point_type pointFromVertex(const Voronoi::vertex_type v) +{ Voronoi::point_type pt; pt.x(v.x()); pt.y(v.y()); return pt; - } +} - Voronoi::point_type orthognalProjection(const Voronoi::point_type &point, const Voronoi::segment_type &segment) { +Voronoi::point_type orthognalProjection(const Voronoi::point_type& point, + const Voronoi::segment_type& segment) +{ // move segment so it goes through the origin (s) Voronoi::point_type offset; { - offset.x(low(segment).x()); - offset.y(low(segment).y()); + offset.x(low(segment).x()); + offset.y(low(segment).y()); } Voronoi::point_type s; { - s.x(high(segment).x() - offset.x()); - s.y(high(segment).y() - offset.y()); + s.x(high(segment).x() - offset.x()); + s.y(high(segment).y() - offset.y()); } // move point accordingly so it maintains it's relation to s (p) Voronoi::point_type p; { - p.x(point.x() - offset.x()); - p.y(point.y() - offset.y()); + p.x(point.x() - offset.x()); + p.y(point.y() - offset.y()); } // calculate the orthogonal projection of p onto s - // ((p dot s) / (s dot s)) * s (https://en.wikibooks.org/wiki/Linear_Algebra/Orthogonal_Projection_Onto_a_Line) - // and it back by original offset to get the projected point + // ((p dot s) / (s dot s)) * s + // (https://en.wikibooks.org/wiki/Linear_Algebra/Orthogonal_Projection_Onto_a_Line) and it back + // by original offset to get the projected point const double proj = (p.x() * s.x() + p.y() * s.y()) / (s.x() * s.x() + s.y() * s.y() + std::numeric_limits::epsilon()); Voronoi::point_type pt; { - pt.x(offset.x() + proj * s.x()); - pt.y(offset.y() + proj * s.y()); + pt.x(offset.x() + proj * s.x()); + pt.y(offset.y() + proj * s.y()); } return pt; - } +} - double length(const Voronoi::point_type &p) { +double length(const Voronoi::point_type& p) +{ return sqrt(p.x() * p.x() + p.y() * p.y()); - } +} - int sideOf(const Voronoi::point_type &p, const Voronoi::segment_type &s) { - Voronoi::coordinate_type dxp = p.x() - low(s).x(); - Voronoi::coordinate_type dyp = p.y() - low(s).y(); +int sideOf(const Voronoi::point_type& p, const Voronoi::segment_type& s) +{ + Voronoi::coordinate_type dxp = p.x() - low(s).x(); + Voronoi::coordinate_type dyp = p.y() - low(s).y(); Voronoi::coordinate_type dxs = high(s).x() - low(s).x(); Voronoi::coordinate_type dys = high(s).y() - low(s).y(); double d = -dxs * dyp + dys * dxp; if (d < 0) { - return -1; + return -1; } if (d > 0) { - return +1; + return +1; } return 0; - } +} - template - double distanceBetween(const pt0_type &p0, const pt1_type &p1, double scale) { +template +double distanceBetween(const pt0_type& p0, const pt1_type& p1, double scale) +{ Voronoi::point_type dist; dist.x(p0.x() - p1.x()); dist.y(p0.y() - p1.y()); return length(dist) / scale; - } +} - template - double signedDistanceBetween(const pt0_type &p0, const pt1_type &p1, double scale) { +template +double signedDistanceBetween(const pt0_type& p0, const pt1_type& p1, double scale) +{ if (length(p0) > length(p1)) { - return -distanceBetween(p0, p1, scale); + return -distanceBetween(p0, p1, scale); } return distanceBetween(p0, p1, scale); - } +} - void addDistanceBetween(const Voronoi::diagram_type::vertex_type *v0, const Voronoi::point_type &p1, Py::List *list, double scale) { +void addDistanceBetween(const Voronoi::diagram_type::vertex_type* v0, + const Voronoi::point_type& p1, + Py::List* list, + double scale) +{ if (v0) { - list->append(Py::Float(distanceBetween(*v0, p1, scale))); - } else { - Py_INCREF(Py_None); - list->append(Py::asObject(Py_None)); + list->append(Py::Float(distanceBetween(*v0, p1, scale))); } - } + else { + Py_INCREF(Py_None); + list->append(Py::asObject(Py_None)); + } +} - void addProjectedDistanceBetween(const Voronoi::diagram_type::vertex_type *v0, const Voronoi::segment_type &segment, Py::List *list, double scale) { +void addProjectedDistanceBetween(const Voronoi::diagram_type::vertex_type* v0, + const Voronoi::segment_type& segment, + Py::List* list, + double scale) +{ if (v0) { - Voronoi::point_type p0; - { - p0.x(v0->x()); - p0.y(v0->y()); - } - Voronoi::point_type p1 = orthognalProjection(p0, segment); - list->append(Py::Float(distanceBetween(*v0, p1, scale))); - } else { - Py_INCREF(Py_None); - list->append(Py::asObject(Py_None)); + Voronoi::point_type p0; + { + p0.x(v0->x()); + p0.y(v0->y()); + } + Voronoi::point_type p1 = orthognalProjection(p0, segment); + list->append(Py::Float(distanceBetween(*v0, p1, scale))); } - } + else { + Py_INCREF(Py_None); + list->append(Py::asObject(Py_None)); + } +} - bool addDistancesToPoint(const VoronoiEdge *edge, Voronoi::point_type p, Py::List *list, double scale) { +bool addDistancesToPoint(const VoronoiEdge* edge, + Voronoi::point_type p, + Py::List* list, + double scale) +{ addDistanceBetween(edge->ptr->vertex0(), p, list, scale); addDistanceBetween(edge->ptr->vertex1(), p, list, scale); return true; - } +} - bool retrieveDistances(const VoronoiEdge *edge, Py::List *list) { - const Voronoi::diagram_type::cell_type *c0 = edge->ptr->cell(); +bool retrieveDistances(const VoronoiEdge* edge, Py::List* list) +{ + const Voronoi::diagram_type::cell_type* c0 = edge->ptr->cell(); if (c0->contains_point()) { - return addDistancesToPoint(edge, edge->dia->retrievePoint(c0), list, edge->dia->getScale()); + return addDistancesToPoint(edge, edge->dia->retrievePoint(c0), list, edge->dia->getScale()); } - const Voronoi::diagram_type::cell_type *c1 = edge->ptr->twin()->cell(); + const Voronoi::diagram_type::cell_type* c1 = edge->ptr->twin()->cell(); if (c1->contains_point()) { - return addDistancesToPoint(edge, edge->dia->retrievePoint(c1), list, edge->dia->getScale()); + return addDistancesToPoint(edge, edge->dia->retrievePoint(c1), list, edge->dia->getScale()); } // at this point both cells are sourced from segments and it does not matter which one we use Voronoi::segment_type segment = edge->dia->retrieveSegment(c0); addProjectedDistanceBetween(edge->ptr->vertex0(), segment, list, edge->dia->getScale()); addProjectedDistanceBetween(edge->ptr->vertex1(), segment, list, edge->dia->getScale()); return false; - } +} - bool pointsMatch(const Voronoi::point_type &p0, const Voronoi::point_type &p1, double scale) { +bool pointsMatch(const Voronoi::point_type& p0, const Voronoi::point_type& p1, double scale) +{ return 1e-6 > distanceBetween(p0, p1, scale); - } +} - bool isPointOnSegment(const Voronoi::point_type &point, const Voronoi::segment_type &segment, double scale) { +bool isPointOnSegment(const Voronoi::point_type& point, + const Voronoi::segment_type& segment, + double scale) +{ return pointsMatch(point, low(segment), scale) || pointsMatch(point, high(segment), scale); - } +} - template - PyObject* makeLineSegment(const VoronoiEdge *e, const T &p0, double z0, const T &p1, double z1) { +template +PyObject* makeLineSegment(const VoronoiEdge* e, const T& p0, double z0, const T& p1, double z1) +{ Part::GeomLineSegment p; p.setPoints(e->dia->scaledVector(p0, z0), e->dia->scaledVector(p1, z1)); Handle(Geom_Curve) h = Handle(Geom_Curve)::DownCast(p.handle()); BRepBuilderAPI_MakeEdge mkBuilder(h, h->FirstParameter(), h->LastParameter()); return new Part::TopoShapeEdgePy(new Part::TopoShape(mkBuilder.Shape())); - } +} +} // namespace + +std::ostream& operator<<(std::ostream& os, const Voronoi::vertex_type& v) +{ + return os << '(' << v.x() << ", " << v.y() << ')'; } -std::ostream& operator<<(std::ostream& os, const Voronoi::vertex_type &v) { - return os << '(' << v.x() << ", " << v.y() << ')'; +std::ostream& operator<<(std::ostream& os, const Voronoi::point_type& p) +{ + return os << '(' << p.x() << ", " << p.y() << ')'; } -std::ostream& operator<<(std::ostream& os, const Voronoi::point_type &p) { - return os << '(' << p.x() << ", " << p.y() << ')'; -} - -std::ostream& operator<<(std::ostream& os, const Voronoi::segment_type &s) { - return os << '<' << low(s) << ", " << high(s) << '>'; +std::ostream& operator<<(std::ostream& os, const Voronoi::segment_type& s) +{ + return os << '<' << low(s) << ", " << high(s) << '>'; } // returns a string which represents the object e.g. when printed in python std::string VoronoiEdgePy::representation() const { - std::stringstream ss; - ss.precision(5); - ss << "VoronoiEdge("; - VoronoiEdge *e = getVoronoiEdgePtr(); - if (e->isBound()) { - const Voronoi::diagram_type::vertex_type *v0 = e->ptr->vertex0(); - const Voronoi::diagram_type::vertex_type *v1 = e->ptr->vertex1(); - if (v0) { - ss << "[" << (v0->x() / e->dia->getScale()) << ", " << (v0->y() / e->dia->getScale()) << "]"; - } else { - ss << "[~]"; + std::stringstream ss; + ss.precision(5); + ss << "VoronoiEdge("; + VoronoiEdge* e = getVoronoiEdgePtr(); + if (e->isBound()) { + const Voronoi::diagram_type::vertex_type* v0 = e->ptr->vertex0(); + const Voronoi::diagram_type::vertex_type* v1 = e->ptr->vertex1(); + if (v0) { + ss << "[" << (v0->x() / e->dia->getScale()) << ", " << (v0->y() / e->dia->getScale()) + << "]"; + } + else { + ss << "[~]"; + } + ss << ", "; + if (v1) { + ss << "[" << (v1->x() / e->dia->getScale()) << ", " << (v1->y() / e->dia->getScale()) + << "]"; + } + else { + ss << "[~]"; + } } - ss << ", "; - if (v1) { - ss << "[" << (v1->x() / e->dia->getScale()) << ", " << (v1->y() / e->dia->getScale()) << "]"; - } else { - ss << "[~]"; - } - } - ss << ")"; - return ss.str(); + ss << ")"; + return ss.str(); } -PyObject *VoronoiEdgePy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +PyObject* VoronoiEdgePy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper { - // create a new instance of VoronoiEdgePy and the Twin object - return new VoronoiEdgePy(new VoronoiEdge); + // create a new instance of VoronoiEdgePy and the Twin object + return new VoronoiEdgePy(new VoronoiEdge); } // constructor method int VoronoiEdgePy::PyInit(PyObject* args, PyObject* /*kwd*/) { - if (!PyArg_ParseTuple(args, "")) { - PyErr_SetString(PyExc_RuntimeError, "no arguments accepted"); - return -1; - } - return 0; -} - - -PyObject* VoronoiEdgePy::richCompare(PyObject *lhs, PyObject *rhs, int op) { - PyObject *cmp = (op == Py_EQ) ? Py_False : Py_True; - if ( PyObject_TypeCheck(lhs, &VoronoiEdgePy::Type) - && PyObject_TypeCheck(rhs, &VoronoiEdgePy::Type) - && (op == Py_EQ || op == Py_NE)) { - const VoronoiEdge *vl = static_cast(lhs)->getVoronoiEdgePtr(); - const VoronoiEdge *vr = static_cast(rhs)->getVoronoiEdgePtr(); - if (vl->dia == vr->dia && vl->index == vr->index) { - cmp = (op == Py_EQ) ? Py_True : Py_False; + if (!PyArg_ParseTuple(args, "")) { + PyErr_SetString(PyExc_RuntimeError, "no arguments accepted"); + return -1; } - } - Py_INCREF(cmp); - return cmp; + return 0; } -const Voronoi::voronoi_diagram_type::edge_type* getEdgeFromPy(VoronoiEdgePy *e, bool throwIfNotBound = true) { - auto self = e->getVoronoiEdgePtr(); - if (self->isBound()) { - return self->ptr; - } - if (throwIfNotBound) { - throw Py::TypeError("Edge not bound to voronoi diagram"); - } - return nullptr; + +PyObject* VoronoiEdgePy::richCompare(PyObject* lhs, PyObject* rhs, int op) +{ + PyObject* cmp = (op == Py_EQ) ? Py_False : Py_True; + if (PyObject_TypeCheck(lhs, &VoronoiEdgePy::Type) + && PyObject_TypeCheck(rhs, &VoronoiEdgePy::Type) && (op == Py_EQ || op == Py_NE)) { + const VoronoiEdge* vl = static_cast(lhs)->getVoronoiEdgePtr(); + const VoronoiEdge* vr = static_cast(rhs)->getVoronoiEdgePtr(); + if (vl->dia == vr->dia && vl->index == vr->index) { + cmp = (op == Py_EQ) ? Py_True : Py_False; + } + } + Py_INCREF(cmp); + return cmp; } -VoronoiEdge* getVoronoiEdgeFromPy(const VoronoiEdgePy *e, PyObject *args = nullptr) { - VoronoiEdge *self = e->getVoronoiEdgePtr(); - if (!self->isBound()) { - throw Py::TypeError("Edge not bound to voronoi diagram"); - } - if (args && !PyArg_ParseTuple(args, "")) { - throw Py::RuntimeError("No arguments accepted"); - } - return self; +const Voronoi::voronoi_diagram_type::edge_type* getEdgeFromPy(VoronoiEdgePy* e, + bool throwIfNotBound = true) +{ + auto self = e->getVoronoiEdgePtr(); + if (self->isBound()) { + return self->ptr; + } + if (throwIfNotBound) { + throw Py::TypeError("Edge not bound to voronoi diagram"); + } + return nullptr; } -Py::Long VoronoiEdgePy::getIndex() const { - VoronoiEdge *e = getVoronoiEdgePtr(); - if (e->isBound()) { - return Py::Long(e->dia->index(e->ptr)); - } - return Py::Long(-1); +VoronoiEdge* getVoronoiEdgeFromPy(const VoronoiEdgePy* e, PyObject* args = nullptr) +{ + VoronoiEdge* self = e->getVoronoiEdgePtr(); + if (!self->isBound()) { + throw Py::TypeError("Edge not bound to voronoi diagram"); + } + if (args && !PyArg_ParseTuple(args, "")) { + throw Py::RuntimeError("No arguments accepted"); + } + return self; } -Py::Long VoronoiEdgePy::getColor() const { - VoronoiEdge *e = getVoronoiEdgePtr(); - if (e->isBound()) { - Voronoi::color_type color = e->ptr->color() & Voronoi::ColorMask; - return Py::Long(PyLong_FromSize_t(color)); - } - return Py::Long(0); +Py::Long VoronoiEdgePy::getIndex() const +{ + VoronoiEdge* e = getVoronoiEdgePtr(); + if (e->isBound()) { + return Py::Long(e->dia->index(e->ptr)); + } + return Py::Long(-1); } -void VoronoiEdgePy::setColor(Py::Long color) { - getEdgeFromPy(this)->color(long(color) & Voronoi::ColorMask); +Py::Long VoronoiEdgePy::getColor() const +{ + VoronoiEdge* e = getVoronoiEdgePtr(); + if (e->isBound()) { + Voronoi::color_type color = e->ptr->color() & Voronoi::ColorMask; + return Py::Long(PyLong_FromSize_t(color)); + } + return Py::Long(0); +} + +void VoronoiEdgePy::setColor(Py::Long color) +{ + getEdgeFromPy(this)->color(long(color) & Voronoi::ColorMask); } Py::List VoronoiEdgePy::getVertices() const { - Py::List list; - VoronoiEdge *e = getVoronoiEdgePtr(); - if (e->isBound()) { - auto v0 = e->ptr->vertex0(); - auto v1 = e->ptr->vertex1(); - if (v0) { - list.append(Py::asObject(new VoronoiVertexPy(new VoronoiVertex(e->dia, v0)))); - } else { - Py_INCREF(Py_None); - list.append(Py::asObject(Py_None)); + Py::List list; + VoronoiEdge* e = getVoronoiEdgePtr(); + if (e->isBound()) { + auto v0 = e->ptr->vertex0(); + auto v1 = e->ptr->vertex1(); + if (v0) { + list.append(Py::asObject(new VoronoiVertexPy(new VoronoiVertex(e->dia, v0)))); + } + else { + Py_INCREF(Py_None); + list.append(Py::asObject(Py_None)); + } + if (v1) { + list.append(Py::asObject(new VoronoiVertexPy(new VoronoiVertex(e->dia, v1)))); + } + else { + Py_INCREF(Py_None); + list.append(Py::asObject(Py_None)); + } } - if (v1) { - list.append(Py::asObject(new VoronoiVertexPy(new VoronoiVertex(e->dia, v1)))); - } else { - Py_INCREF(Py_None); - list.append(Py::asObject(Py_None)); - } - } - return list; + return list; } Py::Object VoronoiEdgePy::getTwin() const { - VoronoiEdge *e = getVoronoiEdgeFromPy(this); - return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(e->dia, e->ptr->twin()))); + VoronoiEdge* e = getVoronoiEdgeFromPy(this); + return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(e->dia, e->ptr->twin()))); } Py::Object VoronoiEdgePy::getNext() const { - VoronoiEdge *e = getVoronoiEdgeFromPy(this); - return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(e->dia, e->ptr->next()))); + VoronoiEdge* e = getVoronoiEdgeFromPy(this); + return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(e->dia, e->ptr->next()))); } Py::Object VoronoiEdgePy::getPrev() const { - VoronoiEdge *e = getVoronoiEdgeFromPy(this); - return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(e->dia, e->ptr->prev()))); + VoronoiEdge* e = getVoronoiEdgeFromPy(this); + return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(e->dia, e->ptr->prev()))); } Py::Object VoronoiEdgePy::getRotNext() const { - VoronoiEdge *e = getVoronoiEdgeFromPy(this); - return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(e->dia, e->ptr->rot_next()))); + VoronoiEdge* e = getVoronoiEdgeFromPy(this); + return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(e->dia, e->ptr->rot_next()))); } Py::Object VoronoiEdgePy::getRotPrev() const { - VoronoiEdge *e = getVoronoiEdgeFromPy(this); - return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(e->dia, e->ptr->rot_prev()))); + VoronoiEdge* e = getVoronoiEdgeFromPy(this); + return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(e->dia, e->ptr->rot_prev()))); } Py::Object VoronoiEdgePy::getCell() const { - VoronoiEdge *e = getVoronoiEdgeFromPy(this); - return Py::asObject(new VoronoiCellPy(new VoronoiCell(e->dia, e->ptr->cell()))); + VoronoiEdge* e = getVoronoiEdgeFromPy(this); + return Py::asObject(new VoronoiCellPy(new VoronoiCell(e->dia, e->ptr->cell()))); } -PyObject* VoronoiEdgePy::isFinite(PyObject *args) +PyObject* VoronoiEdgePy::isFinite(PyObject* args) { - VoronoiEdge *e = getVoronoiEdgeFromPy(this, args); - PyObject *chk = e->ptr->is_finite() ? Py_True : Py_False; - Py_INCREF(chk); - return chk; + VoronoiEdge* e = getVoronoiEdgeFromPy(this, args); + PyObject* chk = e->ptr->is_finite() ? Py_True : Py_False; + Py_INCREF(chk); + return chk; } -PyObject* VoronoiEdgePy::isInfinite(PyObject *args) +PyObject* VoronoiEdgePy::isInfinite(PyObject* args) { - VoronoiEdge *e = getVoronoiEdgeFromPy(this, args); - PyObject *chk = e->ptr->is_infinite() ? Py_True : Py_False; - Py_INCREF(chk); - return chk; + VoronoiEdge* e = getVoronoiEdgeFromPy(this, args); + PyObject* chk = e->ptr->is_infinite() ? Py_True : Py_False; + Py_INCREF(chk); + return chk; } -PyObject* VoronoiEdgePy::isLinear(PyObject *args) +PyObject* VoronoiEdgePy::isLinear(PyObject* args) { - VoronoiEdge *e = getVoronoiEdgeFromPy(this, args); - PyObject *chk = e->ptr->is_linear() ? Py_True : Py_False; - Py_INCREF(chk); - return chk; + VoronoiEdge* e = getVoronoiEdgeFromPy(this, args); + PyObject* chk = e->ptr->is_linear() ? Py_True : Py_False; + Py_INCREF(chk); + return chk; } -PyObject* VoronoiEdgePy::isCurved(PyObject *args) +PyObject* VoronoiEdgePy::isCurved(PyObject* args) { - VoronoiEdge *e = getVoronoiEdgeFromPy(this, args); - PyObject *chk = e->ptr->is_curved() ? Py_True : Py_False; - Py_INCREF(chk); - return chk; + VoronoiEdge* e = getVoronoiEdgeFromPy(this, args); + PyObject* chk = e->ptr->is_curved() ? Py_True : Py_False; + Py_INCREF(chk); + return chk; } -PyObject* VoronoiEdgePy::isPrimary(PyObject *args) +PyObject* VoronoiEdgePy::isPrimary(PyObject* args) { - VoronoiEdge *e = getVoronoiEdgeFromPy(this, args); - PyObject *chk = e->ptr->is_primary() ? Py_True : Py_False; - Py_INCREF(chk); - return chk; + VoronoiEdge* e = getVoronoiEdgeFromPy(this, args); + PyObject* chk = e->ptr->is_primary() ? Py_True : Py_False; + Py_INCREF(chk); + return chk; } -PyObject* VoronoiEdgePy::isSecondary(PyObject *args) +PyObject* VoronoiEdgePy::isSecondary(PyObject* args) { - VoronoiEdge *e = getVoronoiEdgeFromPy(this, args); - PyObject *chk = e->ptr->is_secondary() ? Py_True : Py_False; - Py_INCREF(chk); - return chk; + VoronoiEdge* e = getVoronoiEdgeFromPy(this, args); + PyObject* chk = e->ptr->is_secondary() ? Py_True : Py_False; + Py_INCREF(chk); + return chk; } -PyObject* VoronoiEdgePy::isBorderline(PyObject *args) +PyObject* VoronoiEdgePy::isBorderline(PyObject* args) { - VoronoiEdge *e = getVoronoiEdgeFromPy(this, args); - PyObject *chk = Py_False; - if (e->isBound() && !e->ptr->is_linear()) { - Voronoi::point_type point = e->ptr->cell()->contains_point() ? e->dia->retrievePoint(e->ptr->cell()) : e->dia->retrievePoint(e->ptr->twin()->cell()); - Voronoi::segment_type segment = e->ptr->cell()->contains_point() ? e->dia->retrieveSegment(e->ptr->twin()->cell()) : e->dia->retrieveSegment(e->ptr->cell()); - if (isPointOnSegment(point, segment, e->dia->getScale())) { - chk = Py_True; + VoronoiEdge* e = getVoronoiEdgeFromPy(this, args); + PyObject* chk = Py_False; + if (e->isBound() && !e->ptr->is_linear()) { + Voronoi::point_type point = e->ptr->cell()->contains_point() + ? e->dia->retrievePoint(e->ptr->cell()) + : e->dia->retrievePoint(e->ptr->twin()->cell()); + Voronoi::segment_type segment = e->ptr->cell()->contains_point() + ? e->dia->retrieveSegment(e->ptr->twin()->cell()) + : e->dia->retrieveSegment(e->ptr->cell()); + if (isPointOnSegment(point, segment, e->dia->getScale())) { + chk = Py_True; + } } - } - Py_INCREF(chk); - return chk; + Py_INCREF(chk); + return chk; } -PyObject* VoronoiEdgePy::toShape(PyObject *args) +PyObject* VoronoiEdgePy::toShape(PyObject* args) { - double z0 = 0.0; - double z1 = DBL_MAX; - int dbg = 0; - if (!PyArg_ParseTuple(args, "|ddp", &z0, &z1, &dbg)) { - throw Py::RuntimeError("no, one or two arguments of type double accepted"); - } - if (z1 == DBL_MAX) { - z1 = z0; - } - VoronoiEdge *e = getVoronoiEdgePtr(); - if (e->isBound()) { - if (e->ptr->is_linear()) { - if (e->ptr->is_finite()) { - auto v0 = e->ptr->vertex0(); - auto v1 = e->ptr->vertex1(); - if (v0 && v1) { - return makeLineSegment(e, *v0, z0, *v1, z1); - } - } else { - // infinite linear, need to clip somehow - const Voronoi::diagram_type::cell_type *c0 = e->ptr->cell(); - const Voronoi::diagram_type::cell_type *c1 = e->ptr->twin()->cell(); - Voronoi::point_type origin; - Voronoi::point_type direction; - if (c0->contains_point() && c1->contains_point()) { - Voronoi::point_type p0 = e->dia->retrievePoint(c0); - Voronoi::point_type p1 = e->dia->retrievePoint(c1); - origin.x((p0.x() + p1.x()) / 2.); - origin.y((p0.y() + p1.y()) / 2.); - direction.x(p0.y() - p1.y()); - direction.y(p1.x() - p0.x()); - } else { - origin = c0->contains_segment() ? e->dia->retrievePoint(c1) : e->dia->retrievePoint(c0); - Voronoi::segment_type segment = c0->contains_segment() ? e->dia->retrieveSegment(c0) : e->dia->retrieveSegment(c1); - Voronoi::coordinate_type dx = high(segment).x() - low(segment).x(); - Voronoi::coordinate_type dy = high(segment).y() - low(segment).y(); - if ((low(segment) == origin) ^ c0->contains_point()) { - direction.x(dy); - direction.y(-dx); - } else { - direction.x(-dy); - direction.y(dx); - } - } - double k = 2.5; // <-- need something smarter here - Voronoi::point_type begin; - Voronoi::point_type end; - if (e->ptr->vertex0()) { - begin.x(e->ptr->vertex0()->x()); - begin.y(e->ptr->vertex0()->y()); - } else { - begin.x(origin.x() - direction.x() * k); - begin.y(origin.y() - direction.y() * k); - } - if (e->ptr->vertex1()) { - end.x(e->ptr->vertex1()->x()); - end.y(e->ptr->vertex1()->y()); - } else { - end.x(origin.x() + direction.x() * k); - end.y(origin.y() + direction.y() * k); - } - return makeLineSegment(e, begin, z0, end, z1); - } - } else { - // parabolic curve, which is always formed by a point and an edge - Voronoi::point_type point = e->ptr->cell()->contains_point() ? e->dia->retrievePoint(e->ptr->cell()) : e->dia->retrievePoint(e->ptr->twin()->cell()); - Voronoi::segment_type segment = e->ptr->cell()->contains_point() ? e->dia->retrieveSegment(e->ptr->twin()->cell()) : e->dia->retrieveSegment(e->ptr->cell()); - // the location is the mid point between the normal on the segment through point - // this is only the mid point of the segment if the parabola is symmetric - - if (isPointOnSegment(point, segment, e->dia->getScale())) { - return makeLineSegment(e, low(segment), z0, high(segment), z1); - } - - Voronoi::point_type loc; - { - Voronoi::point_type proj = orthognalProjection(point, segment); - // the location is the mid point between the projection on the segment and the point - loc.x((proj.x() + point.x()) / 2); - loc.y((proj.y() + point.y()) / 2); - } - Voronoi::point_type axis; - { - axis.x(point.x() - loc.x()); - axis.y(point.y() - loc.y()); - } - Voronoi::segment_type xaxis; - { - xaxis.low(point); - xaxis.high(loc); - } - - // determine distances of the end points from the x-axis, those are the parameters for - // the arc of the parabola in the horizontal plane - auto pt0 = pointFromVertex(*e->ptr->vertex0()); - auto pt1 = pointFromVertex(*e->ptr->vertex1()); - Voronoi::point_type pt0x = orthognalProjection(pt0, xaxis); - Voronoi::point_type pt1x = orthognalProjection(pt1, xaxis); - double dist0 = distanceBetween(pt0, pt0x, e->dia->getScale()) * sideOf(pt0, xaxis); - double dist1 = distanceBetween(pt1, pt1x, e->dia->getScale()) * sideOf(pt1, xaxis); - if (dist1 < dist0) { - // if the parabola is traversed in the revere direction we need to use the points - // on the other side of the parabola - 'beauty of symmetric geometries - dist0 = -dist0; - dist1 = -dist1; - } - - // at this point we have the direction of the x-axis and the two end points p0 and p1 - // which means we know the plane of the parabola - auto p0 = e->dia->scaledVector(pt0, z0); - auto p1 = e->dia->scaledVector(pt1, z1); - // we get a third point by moving p0 along the axis of the parabola - auto p_ = p0 + e->dia->scaledVector(axis, 0); - - // normal of the plane defined by those 3 points - auto norm = ((p_ - p0).Cross(p1 - p0)).Normalize(); - - // the next thing to figure out is the z level of the x-axis, - double zx = z0 - (dist0 / (dist0 - dist1)) * (z0 - z1); - - auto locn = e->dia->scaledVector(loc, zx); - auto xdir = e->dia->scaledVector(axis, zx); - - double focal; - if (z0 == z1) { - // focal length if parabola in the xy-plane is simply half the distance between the - // point and segment - aka the distance between point and location, aka the length of axis - focal = length(axis) / e->dia->getScale(); - if (dbg) { - std::cerr << "focal = " << length(axis) << "/" << e->dia->getScale() << "\n"; - } - } else { - // if the parabola is not in the xy-plane we need to find the - // (x,y) coordinates of a point on the parabola in the parabola's - // coordinate system. - // see: http://amsi.org.au/ESA_Senior_Years/SeniorTopic2/2a/2a_2content_10.html - // note that above website uses Y as the symmetry axis of the parabola whereas - // OCC uses X as the symmetry axis. The math below is in the website's system. - // We already know 2 points on the parabola (p0 and p1), we know their X values - // (dist0 and dist1) if the parabola is in the xy-plane, and we know their orthogonal - // projection onto the parabola's symmetry axis Y (pt0x and pt1x). The resulting Y - // values are the distance between the parabola's location (loc) and the respective - // orthogonal projection. Pythagoras gives us the X values, using the X from the - // xy-plane and the difference in z. - // Note that this calculation also gives correct results if the parabola is in - // the xy-plane (z0 == z1), it's just that above calculation is so much simpler. - double flenX0 = sqrt(dist0 * dist0 + (z0 - zx) * (z0 - zx)); - double flenX1 = sqrt(dist1 * dist1 + (zx - z1) * (zx - z1)); - double flenX; - double flenY; - // if one of the points is the location, we have to use the other to get sensible values - if (fabs(dist0) > fabs(dist1)) { - flenX = flenX0; - flenY = distanceBetween(loc, pt0x, e->dia->getScale()); - } else { - flenX = flenX1; - flenY = distanceBetween(loc, pt1x, e->dia->getScale()); - } - // parabola: (x - p)^2 = 4*focal*(y - q) | (p,q) ... location of parabola - focal = (flenX * flenX) / (4 * fabs(flenY)); - if (dbg) { - std::cerr << "segment" << segment << ", point" << point << std::endl; - std::cerr << " loc" << loc << ", axis" << axis << std::endl; - std::cerr << " dist0(" << dist0 << " : " << flenX0 << ", dist1(" << dist1 << " : " << flenX1 << ")" << std::endl; - std::cerr << " z(" << z0 << ", " << zx << ", " << z1 << ")" << std::endl; - std::cerr << " focal = (" << flenX << " * " << flenX << ") / (4 * fabs(" << flenY << "))\n"; - } - // use new X values to set the parameters - dist0 = dist0 >= 0 ? flenX0 : -flenX0; - dist1 = dist1 >= 0 ? flenX1 : -flenX1; - } - - gp_Pnt pbLocn(locn.x, locn.y, locn.z); - gp_Dir pbNorm(norm.x, norm.y, norm.z); - gp_Dir pbXdir(xdir.x, xdir.y, 0); - - gp_Ax2 pb(pbLocn, pbNorm, pbXdir); - Handle(Geom_Parabola) parabola = new Geom_Parabola(pb, focal); - - Part::GeomArcOfParabola arc; - arc.setHandle(parabola); - arc.setRange(dist0, dist1, false); - - // get a shape for the parabola arc - Handle(Geom_Curve) h = Handle(Geom_Curve)::DownCast(arc.handle()); - BRepBuilderAPI_MakeEdge mkBuilder(h, h->FirstParameter(), h->LastParameter()); - return new Part::TopoShapeEdgePy(new Part::TopoShape(mkBuilder.Shape())); + double z0 = 0.0; + double z1 = DBL_MAX; + int dbg = 0; + if (!PyArg_ParseTuple(args, "|ddp", &z0, &z1, &dbg)) { + throw Py::RuntimeError("no, one or two arguments of type double accepted"); } - } - Py_INCREF(Py_None); - return Py_None; -} - - -PyObject* VoronoiEdgePy::getDistances(PyObject *args) -{ - VoronoiEdge *e = getVoronoiEdgeFromPy(this, args); - Py::List list; - retrieveDistances(e, &list); - return Py::new_reference_to(list); -} - -PyObject* VoronoiEdgePy::getSegmentAngle(PyObject *args) -{ - VoronoiEdge *e = getVoronoiEdgeFromPy(this, args); - - if (e->ptr->cell()->contains_segment() && e->ptr->twin()->cell()->contains_segment()) { - int i0 = e->ptr->cell()->source_index() - e->dia->points.size(); - int i1 = e->ptr->twin()->cell()->source_index() - e->dia->points.size(); - if (e->dia->segmentsAreConnected(i0, i1)) { - double a0 = e->dia->angleOfSegment(i0); - double a1 = e->dia->angleOfSegment(i1); - double a = a0 - a1; - if (a > M_PI_2) { - a -= M_PI; - } else if (a < -M_PI_2) { - a += M_PI; - } - return Py::new_reference_to(Py::Float(a)); + if (z1 == DBL_MAX) { + z1 = z0; } - } - Py_INCREF(Py_None); - return Py_None; + VoronoiEdge* e = getVoronoiEdgePtr(); + if (e->isBound()) { + if (e->ptr->is_linear()) { + if (e->ptr->is_finite()) { + auto v0 = e->ptr->vertex0(); + auto v1 = e->ptr->vertex1(); + if (v0 && v1) { + return makeLineSegment(e, *v0, z0, *v1, z1); + } + } + else { + // infinite linear, need to clip somehow + const Voronoi::diagram_type::cell_type* c0 = e->ptr->cell(); + const Voronoi::diagram_type::cell_type* c1 = e->ptr->twin()->cell(); + Voronoi::point_type origin; + Voronoi::point_type direction; + if (c0->contains_point() && c1->contains_point()) { + Voronoi::point_type p0 = e->dia->retrievePoint(c0); + Voronoi::point_type p1 = e->dia->retrievePoint(c1); + origin.x((p0.x() + p1.x()) / 2.); + origin.y((p0.y() + p1.y()) / 2.); + direction.x(p0.y() - p1.y()); + direction.y(p1.x() - p0.x()); + } + else { + origin = c0->contains_segment() ? e->dia->retrievePoint(c1) + : e->dia->retrievePoint(c0); + Voronoi::segment_type segment = c0->contains_segment() + ? e->dia->retrieveSegment(c0) + : e->dia->retrieveSegment(c1); + Voronoi::coordinate_type dx = high(segment).x() - low(segment).x(); + Voronoi::coordinate_type dy = high(segment).y() - low(segment).y(); + if ((low(segment) == origin) ^ c0->contains_point()) { + direction.x(dy); + direction.y(-dx); + } + else { + direction.x(-dy); + direction.y(dx); + } + } + double k = 2.5; // <-- need something smarter here + Voronoi::point_type begin; + Voronoi::point_type end; + if (e->ptr->vertex0()) { + begin.x(e->ptr->vertex0()->x()); + begin.y(e->ptr->vertex0()->y()); + } + else { + begin.x(origin.x() - direction.x() * k); + begin.y(origin.y() - direction.y() * k); + } + if (e->ptr->vertex1()) { + end.x(e->ptr->vertex1()->x()); + end.y(e->ptr->vertex1()->y()); + } + else { + end.x(origin.x() + direction.x() * k); + end.y(origin.y() + direction.y() * k); + } + return makeLineSegment(e, begin, z0, end, z1); + } + } + else { + // parabolic curve, which is always formed by a point and an edge + Voronoi::point_type point = e->ptr->cell()->contains_point() + ? e->dia->retrievePoint(e->ptr->cell()) + : e->dia->retrievePoint(e->ptr->twin()->cell()); + Voronoi::segment_type segment = e->ptr->cell()->contains_point() + ? e->dia->retrieveSegment(e->ptr->twin()->cell()) + : e->dia->retrieveSegment(e->ptr->cell()); + // the location is the mid point between the normal on the segment through point + // this is only the mid point of the segment if the parabola is symmetric + + if (isPointOnSegment(point, segment, e->dia->getScale())) { + return makeLineSegment(e, low(segment), z0, high(segment), z1); + } + + Voronoi::point_type loc; + { + Voronoi::point_type proj = orthognalProjection(point, segment); + // the location is the mid point between the projection on the segment and the point + loc.x((proj.x() + point.x()) / 2); + loc.y((proj.y() + point.y()) / 2); + } + Voronoi::point_type axis; + { + axis.x(point.x() - loc.x()); + axis.y(point.y() - loc.y()); + } + Voronoi::segment_type xaxis; + { + xaxis.low(point); + xaxis.high(loc); + } + + // determine distances of the end points from the x-axis, those are the parameters for + // the arc of the parabola in the horizontal plane + auto pt0 = pointFromVertex(*e->ptr->vertex0()); + auto pt1 = pointFromVertex(*e->ptr->vertex1()); + Voronoi::point_type pt0x = orthognalProjection(pt0, xaxis); + Voronoi::point_type pt1x = orthognalProjection(pt1, xaxis); + double dist0 = distanceBetween(pt0, pt0x, e->dia->getScale()) * sideOf(pt0, xaxis); + double dist1 = distanceBetween(pt1, pt1x, e->dia->getScale()) * sideOf(pt1, xaxis); + if (dist1 < dist0) { + // if the parabola is traversed in the revere direction we need to use the points + // on the other side of the parabola - 'beauty of symmetric geometries + dist0 = -dist0; + dist1 = -dist1; + } + + // at this point we have the direction of the x-axis and the two end points p0 and p1 + // which means we know the plane of the parabola + auto p0 = e->dia->scaledVector(pt0, z0); + auto p1 = e->dia->scaledVector(pt1, z1); + // we get a third point by moving p0 along the axis of the parabola + auto p_ = p0 + e->dia->scaledVector(axis, 0); + + // normal of the plane defined by those 3 points + auto norm = ((p_ - p0).Cross(p1 - p0)).Normalize(); + + // the next thing to figure out is the z level of the x-axis, + double zx = z0 - (dist0 / (dist0 - dist1)) * (z0 - z1); + + auto locn = e->dia->scaledVector(loc, zx); + auto xdir = e->dia->scaledVector(axis, zx); + + double focal; + if (z0 == z1) { + // focal length if parabola in the xy-plane is simply half the distance between the + // point and segment - aka the distance between point and location, aka the length + // of axis + focal = length(axis) / e->dia->getScale(); + if (dbg) { + std::cerr << "focal = " << length(axis) << "/" << e->dia->getScale() << "\n"; + } + } + else { + // if the parabola is not in the xy-plane we need to find the + // (x,y) coordinates of a point on the parabola in the parabola's + // coordinate system. + // see: http://amsi.org.au/ESA_Senior_Years/SeniorTopic2/2a/2a_2content_10.html + // note that above website uses Y as the symmetry axis of the parabola whereas + // OCC uses X as the symmetry axis. The math below is in the website's system. + // We already know 2 points on the parabola (p0 and p1), we know their X values + // (dist0 and dist1) if the parabola is in the xy-plane, and we know their + // orthogonal projection onto the parabola's symmetry axis Y (pt0x and pt1x). The + // resulting Y values are the distance between the parabola's location (loc) and the + // respective orthogonal projection. Pythagoras gives us the X values, using the X + // from the xy-plane and the difference in z. Note that this calculation also gives + // correct results if the parabola is in the xy-plane (z0 == z1), it's just that + // above calculation is so much simpler. + double flenX0 = sqrt(dist0 * dist0 + (z0 - zx) * (z0 - zx)); + double flenX1 = sqrt(dist1 * dist1 + (zx - z1) * (zx - z1)); + double flenX; + double flenY; + // if one of the points is the location, we have to use the other to get sensible + // values + if (fabs(dist0) > fabs(dist1)) { + flenX = flenX0; + flenY = distanceBetween(loc, pt0x, e->dia->getScale()); + } + else { + flenX = flenX1; + flenY = distanceBetween(loc, pt1x, e->dia->getScale()); + } + // parabola: (x - p)^2 = 4*focal*(y - q) | (p,q) ... location of parabola + focal = (flenX * flenX) / (4 * fabs(flenY)); + if (dbg) { + std::cerr << "segment" << segment << ", point" << point << std::endl; + std::cerr << " loc" << loc << ", axis" << axis << std::endl; + std::cerr << " dist0(" << dist0 << " : " << flenX0 << ", dist1(" << dist1 + << " : " << flenX1 << ")" << std::endl; + std::cerr << " z(" << z0 << ", " << zx << ", " << z1 << ")" << std::endl; + std::cerr << " focal = (" << flenX << " * " << flenX << ") / (4 * fabs(" + << flenY << "))\n"; + } + // use new X values to set the parameters + dist0 = dist0 >= 0 ? flenX0 : -flenX0; + dist1 = dist1 >= 0 ? flenX1 : -flenX1; + } + + gp_Pnt pbLocn(locn.x, locn.y, locn.z); + gp_Dir pbNorm(norm.x, norm.y, norm.z); + gp_Dir pbXdir(xdir.x, xdir.y, 0); + + gp_Ax2 pb(pbLocn, pbNorm, pbXdir); + Handle(Geom_Parabola) parabola = new Geom_Parabola(pb, focal); + + Part::GeomArcOfParabola arc; + arc.setHandle(parabola); + arc.setRange(dist0, dist1, false); + + // get a shape for the parabola arc + Handle(Geom_Curve) h = Handle(Geom_Curve)::DownCast(arc.handle()); + BRepBuilderAPI_MakeEdge mkBuilder(h, h->FirstParameter(), h->LastParameter()); + return new Part::TopoShapeEdgePy(new Part::TopoShape(mkBuilder.Shape())); + } + } + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject* VoronoiEdgePy::getDistances(PyObject* args) +{ + VoronoiEdge* e = getVoronoiEdgeFromPy(this, args); + Py::List list; + retrieveDistances(e, &list); + return Py::new_reference_to(list); +} + +PyObject* VoronoiEdgePy::getSegmentAngle(PyObject* args) +{ + VoronoiEdge* e = getVoronoiEdgeFromPy(this, args); + + if (e->ptr->cell()->contains_segment() && e->ptr->twin()->cell()->contains_segment()) { + int i0 = e->ptr->cell()->source_index() - e->dia->points.size(); + int i1 = e->ptr->twin()->cell()->source_index() - e->dia->points.size(); + if (e->dia->segmentsAreConnected(i0, i1)) { + double a0 = e->dia->angleOfSegment(i0); + double a1 = e->dia->angleOfSegment(i1); + double a = a0 - a1; + if (a > M_PI_2) { + a -= M_PI; + } + else if (a < -M_PI_2) { + a += M_PI; + } + return Py::new_reference_to(Py::Float(a)); + } + } + Py_INCREF(Py_None); + return Py_None; } // custom attributes get/set PyObject* VoronoiEdgePy::getCustomAttributes(const char* /*attr*/) const { - return nullptr; + return nullptr; } int VoronoiEdgePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { - return 0; + return 0; } - diff --git a/src/Mod/CAM/App/VoronoiPyImp.cpp b/src/Mod/CAM/App/VoronoiPyImp.cpp index 6e00af1538..c0842f2f03 100644 --- a/src/Mod/CAM/App/VoronoiPyImp.cpp +++ b/src/Mod/CAM/App/VoronoiPyImp.cpp @@ -38,303 +38,327 @@ using namespace Path; // returns a string which represents the object e.g. when printed in python std::string VoronoiPy::representation() const { - std::stringstream ss; - ss.precision(5); - ss << "VoronoiDiagram(" - << "{" << getVoronoiPtr()->numSegments() << ", " << getVoronoiPtr()->numPoints() << "}" - << " -> " - << "{" << getVoronoiPtr()->numCells() << ", " << getVoronoiPtr()->numEdges() << ", " << getVoronoiPtr()->numVertices() << "}" - << ")"; - return ss.str(); + std::stringstream ss; + ss.precision(5); + ss << "VoronoiDiagram(" + << "{" << getVoronoiPtr()->numSegments() << ", " << getVoronoiPtr()->numPoints() << "}" + << " -> " + << "{" << getVoronoiPtr()->numCells() << ", " << getVoronoiPtr()->numEdges() << ", " + << getVoronoiPtr()->numVertices() << "}" + << ")"; + return ss.str(); } -PyObject *VoronoiPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +PyObject* VoronoiPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper { - // create a new instance of VoronoiPy and its twin object - return new VoronoiPy(new Voronoi); + // create a new instance of VoronoiPy and its twin object + return new VoronoiPy(new Voronoi); } // constructor int VoronoiPy::PyInit(PyObject* args, PyObject* /*kwds*/) { - Voronoi *vo = getVoronoiPtr(); - double scale = vo->getScale(); - if (!PyArg_ParseTuple(args, "|d", &scale)) { - PyErr_SetString(PyExc_RuntimeError, "scale argument (double) accepted, default = 1000"); - return -1; - } - vo->setScale(scale); - return 0; -} - -Voronoi::point_type getPointFromPy(PyObject *obj) { - if (obj) { - if (PyObject_TypeCheck(obj, &Base::VectorPy::Type)) { - Base::Vector3d *vect = (static_cast(obj))->getVectorPtr(); - return Voronoi::point_type(vect->x, vect->y); - } else if (PyObject_TypeCheck(obj, Base::Vector2dPy::type_object())) { - Base::Vector2d vect = Py::toVector2d(obj); - return Voronoi::point_type(vect.x, vect.y); + Voronoi* vo = getVoronoiPtr(); + double scale = vo->getScale(); + if (!PyArg_ParseTuple(args, "|d", &scale)) { + PyErr_SetString(PyExc_RuntimeError, "scale argument (double) accepted, default = 1000"); + return -1; } - } - throw Py::TypeError("Points must be Base::Vector or Base::Vector2d"); - return Voronoi::point_type(); + vo->setScale(scale); + return 0; } -PyObject* VoronoiPy::addPoint(PyObject *args) { - PyObject *obj = nullptr; - if (PyArg_ParseTuple(args, "O", &obj)) { - getVoronoiPtr()->addPoint(getPointFromPy(obj)); - } - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* VoronoiPy::addSegment(PyObject *args) { - PyObject *objBegin = nullptr; - PyObject *objEnd = nullptr; - - if (PyArg_ParseTuple(args, "OO", &objBegin, &objEnd)) { - auto p0 = getPointFromPy(objBegin); - auto p1 = getPointFromPy(objEnd); - getVoronoiPtr()->addSegment(Voronoi::segment_type(p0, p1)); - } - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* VoronoiPy::construct(PyObject *args) { - if (!PyArg_ParseTuple(args, "")) { - throw Py::RuntimeError("no arguments accepted"); - } - getVoronoiPtr()->construct(); - - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* VoronoiPy::numCells(PyObject *args) +Voronoi::point_type getPointFromPy(PyObject* obj) { - if (!PyArg_ParseTuple(args, "")) { - throw Py::RuntimeError("no arguments accepted"); - } - return PyLong_FromLong(getVoronoiPtr()->numCells()); + if (obj) { + if (PyObject_TypeCheck(obj, &Base::VectorPy::Type)) { + Base::Vector3d* vect = (static_cast(obj))->getVectorPtr(); + return Voronoi::point_type(vect->x, vect->y); + } + else if (PyObject_TypeCheck(obj, Base::Vector2dPy::type_object())) { + Base::Vector2d vect = Py::toVector2d(obj); + return Voronoi::point_type(vect.x, vect.y); + } + } + throw Py::TypeError("Points must be Base::Vector or Base::Vector2d"); + return Voronoi::point_type(); } -PyObject* VoronoiPy::numEdges(PyObject *args) +PyObject* VoronoiPy::addPoint(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) { - throw Py::RuntimeError("no arguments accepted"); - } - return PyLong_FromLong(getVoronoiPtr()->numEdges()); + PyObject* obj = nullptr; + if (PyArg_ParseTuple(args, "O", &obj)) { + getVoronoiPtr()->addPoint(getPointFromPy(obj)); + } + Py_INCREF(Py_None); + return Py_None; } -PyObject* VoronoiPy::numVertices(PyObject *args) +PyObject* VoronoiPy::addSegment(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) { - throw Py::RuntimeError("no arguments accepted"); - } - return PyLong_FromLong(getVoronoiPtr()->numVertices()); + PyObject* objBegin = nullptr; + PyObject* objEnd = nullptr; + + if (PyArg_ParseTuple(args, "OO", &objBegin, &objEnd)) { + auto p0 = getPointFromPy(objBegin); + auto p1 = getPointFromPy(objEnd); + getVoronoiPtr()->addSegment(Voronoi::segment_type(p0, p1)); + } + Py_INCREF(Py_None); + return Py_None; } -Py::List VoronoiPy::getVertices() const { - Py::List list; - for (int i=0; inumVertices(); ++i) { - list.append(Py::asObject(new VoronoiVertexPy(getVoronoiPtr()->create(i)))); - } - return list; +PyObject* VoronoiPy::construct(PyObject* args) +{ + if (!PyArg_ParseTuple(args, "")) { + throw Py::RuntimeError("no arguments accepted"); + } + getVoronoiPtr()->construct(); + + Py_INCREF(Py_None); + return Py_None; } -Py::List VoronoiPy::getEdges() const { - Py::List list; - for (int i=0; inumEdges(); ++i) { - list.append(Py::asObject(new VoronoiEdgePy(getVoronoiPtr()->create(i)))); - } - return list; +PyObject* VoronoiPy::numCells(PyObject* args) +{ + if (!PyArg_ParseTuple(args, "")) { + throw Py::RuntimeError("no arguments accepted"); + } + return PyLong_FromLong(getVoronoiPtr()->numCells()); } -Py::List VoronoiPy::getCells() const { - Py::List list; - for (int i=0; inumCells(); ++i) { - list.append(Py::asObject(new VoronoiCellPy(getVoronoiPtr()->create(i)))); - } - return list; +PyObject* VoronoiPy::numEdges(PyObject* args) +{ + if (!PyArg_ParseTuple(args, "")) { + throw Py::RuntimeError("no arguments accepted"); + } + return PyLong_FromLong(getVoronoiPtr()->numEdges()); } -using exterior_map_t = std::map; -using coordinate_map_t = std::map >; +PyObject* VoronoiPy::numVertices(PyObject* args) +{ + if (!PyArg_ParseTuple(args, "")) { + throw Py::RuntimeError("no arguments accepted"); + } + return PyLong_FromLong(getVoronoiPtr()->numVertices()); +} + +Py::List VoronoiPy::getVertices() const +{ + Py::List list; + for (int i = 0; i < getVoronoiPtr()->numVertices(); ++i) { + list.append(Py::asObject(new VoronoiVertexPy(getVoronoiPtr()->create(i)))); + } + return list; +} + +Py::List VoronoiPy::getEdges() const +{ + Py::List list; + for (int i = 0; i < getVoronoiPtr()->numEdges(); ++i) { + list.append(Py::asObject(new VoronoiEdgePy(getVoronoiPtr()->create(i)))); + } + return list; +} + +Py::List VoronoiPy::getCells() const +{ + Py::List list; + for (int i = 0; i < getVoronoiPtr()->numCells(); ++i) { + list.append(Py::asObject(new VoronoiCellPy(getVoronoiPtr()->create(i)))); + } + return list; +} + +using exterior_map_t = std::map; +using coordinate_map_t = std::map>; #define VORONOI_USE_EXTERIOR_CACHE 1 -static bool callbackWithVertex(Voronoi::diagram_type *dia, PyObject *callback, const Voronoi::diagram_type::vertex_type *v, bool &bail, exterior_map_t &cache) { - bool rc = false; - if (!bail && v->color() == 0) { +static bool callbackWithVertex(Voronoi::diagram_type* dia, + PyObject* callback, + const Voronoi::diagram_type::vertex_type* v, + bool& bail, + exterior_map_t& cache) +{ + bool rc = false; + if (!bail && v->color() == 0) { #if VORONOI_USE_EXTERIOR_CACHE - auto it = cache.find(uintptr_t(v)); - if (it == cache.end()) { + auto it = cache.find(uintptr_t(v)); + if (it == cache.end()) { #endif - PyObject *vx = new VoronoiVertexPy(new VoronoiVertex(dia, v)); - PyObject *arglist = Py_BuildValue("(O)", vx); + PyObject* vx = new VoronoiVertexPy(new VoronoiVertex(dia, v)); + PyObject* arglist = Py_BuildValue("(O)", vx); #if PY_VERSION_HEX < 0x03090000 - PyObject *result = PyEval_CallObject(callback, arglist); + PyObject* result = PyEval_CallObject(callback, arglist); #else - PyObject *result = PyObject_CallObject(callback, arglist); + PyObject* result = PyObject_CallObject(callback, arglist); #endif - Py_DECREF(arglist); - Py_DECREF(vx); - if (!result) { - bail = true; - } else { - rc = result == Py_True; - Py_DECREF(result); - cache.insert(exterior_map_t::value_type(uintptr_t(v), rc)); - } -#if VORONOI_USE_EXTERIOR_CACHE - } else { - rc = it->second; - } -#else - (void)cache; -#endif - } - return rc; -} - -PyObject* VoronoiPy::colorExterior(PyObject *args) { - Voronoi::color_type color = 0; - PyObject *callback = nullptr; - if (!PyArg_ParseTuple(args, "k|O", &color, &callback)) { - throw Py::RuntimeError("colorExterior requires an integer (color) argument"); - } - Voronoi *vo = getVoronoiPtr(); - vo->colorExterior(color); - if (callback) { - exterior_map_t cache; - coordinate_map_t pts; - for (auto e = vo->vd->edges().begin(); e != vo->vd->edges().end(); ++e) { - if (e->is_finite() && e->color() == 0) { - const Voronoi::diagram_type::vertex_type *v0 = e->vertex0(); - const Voronoi::diagram_type::vertex_type *v1 = e->vertex1(); - bool bail = false; - if (callbackWithVertex(vo->vd, callback, v0, bail, cache) && callbackWithVertex(vo->vd, callback, v1, bail, cache)) { - vo->colorExterior(&(*e), color); - } else if (!bail && callbackWithVertex(vo->vd, callback, v1, bail, cache)) { - if (pts.empty()) { - for (auto s = vo->vd->segments.begin(); s != vo->vd->segments.end(); ++s) { - pts[low(*s).x()].insert(low(*s).y()); - pts[high(*s).x()].insert(high(*s).y()); + Py_DECREF(arglist); + Py_DECREF(vx); + if (!result) { + bail = true; } - } - auto ys = pts.find(int32_t(v0->x())); - if (ys != pts.end() && ys->second.find(v0->y()) != ys->second.end()) { - vo->colorExterior(&(*e), color); - } + else { + rc = result == Py_True; + Py_DECREF(result); + cache.insert(exterior_map_t::value_type(uintptr_t(v), rc)); + } +#if VORONOI_USE_EXTERIOR_CACHE } - if (bail) { - return nullptr; + else { + rc = it->second; } - } +#else + (void)cache; +#endif } - } - - Py_INCREF(Py_None); - return Py_None; + return rc; } -PyObject* VoronoiPy::colorTwins(PyObject *args) { - Voronoi::color_type color = 0; - if (!PyArg_ParseTuple(args, "k", &color)) { - throw Py::RuntimeError("colorTwins requires an integer (color) argument"); - } - getVoronoiPtr()->colorTwins(color); - - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* VoronoiPy::colorColinear(PyObject *args) { - Voronoi::color_type color = 0; - double degree = 10.; - if (!PyArg_ParseTuple(args, "k|d", &color, °ree)) { - throw Py::RuntimeError("colorColinear requires an integer (color) and optionally a derivation in degrees argument (default 10)"); - } - getVoronoiPtr()->colorColinear(color, degree); - - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* VoronoiPy::resetColor(PyObject *args) { - Voronoi::color_type color = 0; - if (!PyArg_ParseTuple(args, "k", &color)) { - throw Py::RuntimeError("clearColor requires an integer (color) argument"); - } - - getVoronoiPtr()->resetColor(color); - - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* VoronoiPy::getPoints(PyObject *args) { - double z = 0; - if (!PyArg_ParseTuple(args, "|d", &z)) { - throw Py::RuntimeError("Optional z argument (double) accepted"); - } - Voronoi *vo = getVoronoiPtr(); - Py::List list; - for (auto it = vo->vd->points.begin(); it != vo->vd->points.end(); ++it) { - list.append(Py::asObject(new Base::VectorPy(new Base::Vector3d(vo->vd->scaledVector(*it, z))))); - } - return Py::new_reference_to(list); -} - -PyObject* VoronoiPy::getSegments(PyObject *args) { - double z = 0; - if (!PyArg_ParseTuple(args, "|d", &z)) { - throw Py::RuntimeError("Optional z argument (double) accepted"); - } - Voronoi *vo = getVoronoiPtr(); - Py::List list; - for (auto it = vo->vd->segments.begin(); it != vo->vd->segments.end(); ++it) { - PyObject *p0 = new Base::VectorPy(new Base::Vector3d(vo->vd->scaledVector(low(*it), z))); - PyObject *p1 = new Base::VectorPy(new Base::Vector3d(vo->vd->scaledVector(high(*it), z))); - PyObject *tp = PyTuple_New(2); - PyTuple_SetItem(tp, 0, p0); - PyTuple_SetItem(tp, 1, p1); - list.append(Py::asObject(tp)); - } - return Py::new_reference_to(list); -} - -PyObject* VoronoiPy::numPoints(PyObject *args) +PyObject* VoronoiPy::colorExterior(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) { - throw Py::RuntimeError("no arguments accepted"); - } - return PyLong_FromLong(getVoronoiPtr()->vd->points.size()); + Voronoi::color_type color = 0; + PyObject* callback = nullptr; + if (!PyArg_ParseTuple(args, "k|O", &color, &callback)) { + throw Py::RuntimeError("colorExterior requires an integer (color) argument"); + } + Voronoi* vo = getVoronoiPtr(); + vo->colorExterior(color); + if (callback) { + exterior_map_t cache; + coordinate_map_t pts; + for (auto e = vo->vd->edges().begin(); e != vo->vd->edges().end(); ++e) { + if (e->is_finite() && e->color() == 0) { + const Voronoi::diagram_type::vertex_type* v0 = e->vertex0(); + const Voronoi::diagram_type::vertex_type* v1 = e->vertex1(); + bool bail = false; + if (callbackWithVertex(vo->vd, callback, v0, bail, cache) + && callbackWithVertex(vo->vd, callback, v1, bail, cache)) { + vo->colorExterior(&(*e), color); + } + else if (!bail && callbackWithVertex(vo->vd, callback, v1, bail, cache)) { + if (pts.empty()) { + for (auto s = vo->vd->segments.begin(); s != vo->vd->segments.end(); ++s) { + pts[low(*s).x()].insert(low(*s).y()); + pts[high(*s).x()].insert(high(*s).y()); + } + } + auto ys = pts.find(int32_t(v0->x())); + if (ys != pts.end() && ys->second.find(v0->y()) != ys->second.end()) { + vo->colorExterior(&(*e), color); + } + } + if (bail) { + return nullptr; + } + } + } + } + + Py_INCREF(Py_None); + return Py_None; } -PyObject* VoronoiPy::numSegments(PyObject *args) +PyObject* VoronoiPy::colorTwins(PyObject* args) { - if (!PyArg_ParseTuple(args, "")) { - throw Py::RuntimeError("no arguments accepted"); - } - return PyLong_FromLong(getVoronoiPtr()->vd->segments.size()); + Voronoi::color_type color = 0; + if (!PyArg_ParseTuple(args, "k", &color)) { + throw Py::RuntimeError("colorTwins requires an integer (color) argument"); + } + getVoronoiPtr()->colorTwins(color); + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* VoronoiPy::colorColinear(PyObject* args) +{ + Voronoi::color_type color = 0; + double degree = 10.; + if (!PyArg_ParseTuple(args, "k|d", &color, °ree)) { + throw Py::RuntimeError("colorColinear requires an integer (color) and optionally a " + "derivation in degrees argument (default 10)"); + } + getVoronoiPtr()->colorColinear(color, degree); + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* VoronoiPy::resetColor(PyObject* args) +{ + Voronoi::color_type color = 0; + if (!PyArg_ParseTuple(args, "k", &color)) { + throw Py::RuntimeError("clearColor requires an integer (color) argument"); + } + + getVoronoiPtr()->resetColor(color); + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* VoronoiPy::getPoints(PyObject* args) +{ + double z = 0; + if (!PyArg_ParseTuple(args, "|d", &z)) { + throw Py::RuntimeError("Optional z argument (double) accepted"); + } + Voronoi* vo = getVoronoiPtr(); + Py::List list; + for (auto it = vo->vd->points.begin(); it != vo->vd->points.end(); ++it) { + list.append( + Py::asObject(new Base::VectorPy(new Base::Vector3d(vo->vd->scaledVector(*it, z))))); + } + return Py::new_reference_to(list); +} + +PyObject* VoronoiPy::getSegments(PyObject* args) +{ + double z = 0; + if (!PyArg_ParseTuple(args, "|d", &z)) { + throw Py::RuntimeError("Optional z argument (double) accepted"); + } + Voronoi* vo = getVoronoiPtr(); + Py::List list; + for (auto it = vo->vd->segments.begin(); it != vo->vd->segments.end(); ++it) { + PyObject* p0 = new Base::VectorPy(new Base::Vector3d(vo->vd->scaledVector(low(*it), z))); + PyObject* p1 = new Base::VectorPy(new Base::Vector3d(vo->vd->scaledVector(high(*it), z))); + PyObject* tp = PyTuple_New(2); + PyTuple_SetItem(tp, 0, p0); + PyTuple_SetItem(tp, 1, p1); + list.append(Py::asObject(tp)); + } + return Py::new_reference_to(list); +} + +PyObject* VoronoiPy::numPoints(PyObject* args) +{ + if (!PyArg_ParseTuple(args, "")) { + throw Py::RuntimeError("no arguments accepted"); + } + return PyLong_FromLong(getVoronoiPtr()->vd->points.size()); +} + +PyObject* VoronoiPy::numSegments(PyObject* args) +{ + if (!PyArg_ParseTuple(args, "")) { + throw Py::RuntimeError("no arguments accepted"); + } + return PyLong_FromLong(getVoronoiPtr()->vd->segments.size()); } // custom attributes get/set -PyObject *VoronoiPy::getCustomAttributes(const char* /*attr*/) const +PyObject* VoronoiPy::getCustomAttributes(const char* /*attr*/) const { - return nullptr; + return nullptr; } int VoronoiPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { - return 0; + return 0; } - - diff --git a/src/Mod/CAM/App/VoronoiVertex.cpp b/src/Mod/CAM/App/VoronoiVertex.cpp index 72a325af07..1f6c226972 100644 --- a/src/Mod/CAM/App/VoronoiVertex.cpp +++ b/src/Mod/CAM/App/VoronoiVertex.cpp @@ -28,37 +28,38 @@ using namespace Base; using namespace Path; -TYPESYSTEM_SOURCE(Path::VoronoiVertex , Base::Persistence) +TYPESYSTEM_SOURCE(Path::VoronoiVertex, Base::Persistence) -VoronoiVertex::VoronoiVertex(Voronoi::diagram_type *d, long index) - : dia(d) - , index(index) - , ptr(nullptr) +VoronoiVertex::VoronoiVertex(Voronoi::diagram_type* d, long index) + : dia(d) + , index(index) + , ptr(nullptr) { - if (dia && long(dia->num_vertices()) > index) { - ptr = &(dia->vertices()[index]); - } -} - -VoronoiVertex::VoronoiVertex(Voronoi::diagram_type *d, const Voronoi::diagram_type::vertex_type *v) - : dia(d) - , index(Voronoi::InvalidIndex) - , ptr(v) -{ - if (dia && v) { - index = dia->index(v); - } -} - -VoronoiVertex::~VoronoiVertex() { -} - -bool VoronoiVertex::isBound() const { - if (ptr && dia.isValid() && index != Voronoi::InvalidIndex) { - if (&(dia->vertices()[index]) == ptr) { - return true; + if (dia && long(dia->num_vertices()) > index) { + ptr = &(dia->vertices()[index]); } - } - ptr = nullptr; - return false; +} + +VoronoiVertex::VoronoiVertex(Voronoi::diagram_type* d, const Voronoi::diagram_type::vertex_type* v) + : dia(d) + , index(Voronoi::InvalidIndex) + , ptr(v) +{ + if (dia && v) { + index = dia->index(v); + } +} + +VoronoiVertex::~VoronoiVertex() +{} + +bool VoronoiVertex::isBound() const +{ + if (ptr && dia.isValid() && index != Voronoi::InvalidIndex) { + if (&(dia->vertices()[index]) == ptr) { + return true; + } + } + ptr = nullptr; + return false; } diff --git a/src/Mod/CAM/App/VoronoiVertex.h b/src/Mod/CAM/App/VoronoiVertex.h index fb83d87d08..fb5bb9e960 100644 --- a/src/Mod/CAM/App/VoronoiVertex.h +++ b/src/Mod/CAM/App/VoronoiVertex.h @@ -32,22 +32,21 @@ namespace Path class Voronoi; -class PathExport VoronoiVertex - : public Base::BaseClass +class PathExport VoronoiVertex: public Base::BaseClass { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: + VoronoiVertex(Voronoi::diagram_type* dia = nullptr, long index = Voronoi::InvalidIndex); + VoronoiVertex(Voronoi::diagram_type* dia, const Voronoi::diagram_type::vertex_type* v); + ~VoronoiVertex() override; - VoronoiVertex(Voronoi::diagram_type *dia = nullptr, long index = Voronoi::InvalidIndex); - VoronoiVertex(Voronoi::diagram_type *dia, const Voronoi::diagram_type::vertex_type *v); - ~VoronoiVertex() override; + bool isBound() const; - bool isBound() const; - - Base::Reference dia; - long index; - mutable const Voronoi::diagram_type::vertex_type *ptr; + Base::Reference dia; + long index; + mutable const Voronoi::diagram_type::vertex_type* ptr; }; -} +} // namespace Path #endif diff --git a/src/Mod/CAM/App/VoronoiVertexPyImp.cpp b/src/Mod/CAM/App/VoronoiVertexPyImp.cpp index 06a9651197..9b88d5f7ed 100644 --- a/src/Mod/CAM/App/VoronoiVertexPyImp.cpp +++ b/src/Mod/CAM/App/VoronoiVertexPyImp.cpp @@ -35,133 +35,142 @@ using namespace Path; // returns a string which represents the object e.g. when printed in python std::string VoronoiVertexPy::representation() const { - std::stringstream ss; - ss.precision(5); - ss << "VoronoiVertex("; - VoronoiVertex *v = getVoronoiVertexPtr(); - if (v->isBound()) { - ss << "[" << (v->ptr->x() / v->dia->getScale()) << ", " << (v->ptr->y() / v->dia->getScale()) << "]"; - } - ss << ")"; - return ss.str(); + std::stringstream ss; + ss.precision(5); + ss << "VoronoiVertex("; + VoronoiVertex* v = getVoronoiVertexPtr(); + if (v->isBound()) { + ss << "[" << (v->ptr->x() / v->dia->getScale()) << ", " + << (v->ptr->y() / v->dia->getScale()) << "]"; + } + ss << ")"; + return ss.str(); } -PyObject *VoronoiVertexPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +PyObject* VoronoiVertexPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper { - // create a new instance of VoronoiVertexPy and the Twin object - return new VoronoiVertexPy(new VoronoiVertex); + // create a new instance of VoronoiVertexPy and the Twin object + return new VoronoiVertexPy(new VoronoiVertex); } // constructor method int VoronoiVertexPy::PyInit(PyObject* args, PyObject* /*kwd*/) { - if (!PyArg_ParseTuple(args, "")) { - PyErr_SetString(PyExc_RuntimeError, "no arguments accepted"); - return -1; - } - return 0; -} - - -PyObject* VoronoiVertexPy::richCompare(PyObject *lhs, PyObject *rhs, int op) { - PyObject *cmp = (op == Py_EQ) ? Py_False : Py_True; - if ( PyObject_TypeCheck(lhs, &VoronoiVertexPy::Type) - && PyObject_TypeCheck(rhs, &VoronoiVertexPy::Type) - && (op == Py_EQ || op == Py_NE)) { - const VoronoiVertex *vl = static_cast(lhs)->getVoronoiVertexPtr(); - const VoronoiVertex *vr = static_cast(rhs)->getVoronoiVertexPtr(); - if (vl->index == vr->index && vl->dia == vr->dia) { - cmp = (op == Py_EQ) ? Py_True : Py_False; + if (!PyArg_ParseTuple(args, "")) { + PyErr_SetString(PyExc_RuntimeError, "no arguments accepted"); + return -1; } - } - Py_INCREF(cmp); - return cmp; -} - -const Voronoi::voronoi_diagram_type::vertex_type* getVertexFromPy(VoronoiVertexPy *v, bool throwIfNotBound = true) { - auto self = v->getVoronoiVertexPtr(); - if (self->isBound()) { - return self->ptr; - } - if (throwIfNotBound) { - throw Py::TypeError("Vertex not bound to voronoi diagram"); - } - return nullptr; -} - -VoronoiVertex* getVoronoiVertexFromPy(const VoronoiVertexPy *v, PyObject *args = nullptr) { - VoronoiVertex *self = v->getVoronoiVertexPtr(); - if (!self->isBound()) { - throw Py::TypeError("Vertex not bound to voronoi diagram"); - } - if (args && !PyArg_ParseTuple(args, "")) { - throw Py::RuntimeError("No arguments accepted"); - } - return self; + return 0; } -Py::Long VoronoiVertexPy::getIndex() const { - VoronoiVertex *v = getVoronoiVertexPtr(); - if (v->isBound()) { - return Py::Long(v->dia->index(v->ptr)); - } - return Py::Long(-1); +PyObject* VoronoiVertexPy::richCompare(PyObject* lhs, PyObject* rhs, int op) +{ + PyObject* cmp = (op == Py_EQ) ? Py_False : Py_True; + if (PyObject_TypeCheck(lhs, &VoronoiVertexPy::Type) + && PyObject_TypeCheck(rhs, &VoronoiVertexPy::Type) && (op == Py_EQ || op == Py_NE)) { + const VoronoiVertex* vl = static_cast(lhs)->getVoronoiVertexPtr(); + const VoronoiVertex* vr = static_cast(rhs)->getVoronoiVertexPtr(); + if (vl->index == vr->index && vl->dia == vr->dia) { + cmp = (op == Py_EQ) ? Py_True : Py_False; + } + } + Py_INCREF(cmp); + return cmp; } -Py::Long VoronoiVertexPy::getColor() const { - VoronoiVertex *v = getVoronoiVertexPtr(); - if (v->isBound()) { - Voronoi::color_type color = v->ptr->color() & Voronoi::ColorMask; - return Py::Long(PyLong_FromSize_t(color)); - } - return Py::Long(0); +const Voronoi::voronoi_diagram_type::vertex_type* getVertexFromPy(VoronoiVertexPy* v, + bool throwIfNotBound = true) +{ + auto self = v->getVoronoiVertexPtr(); + if (self->isBound()) { + return self->ptr; + } + if (throwIfNotBound) { + throw Py::TypeError("Vertex not bound to voronoi diagram"); + } + return nullptr; } -void VoronoiVertexPy::setColor(Py::Long color) { - getVertexFromPy(this)->color(long(color) & Voronoi::ColorMask); +VoronoiVertex* getVoronoiVertexFromPy(const VoronoiVertexPy* v, PyObject* args = nullptr) +{ + VoronoiVertex* self = v->getVoronoiVertexPtr(); + if (!self->isBound()) { + throw Py::TypeError("Vertex not bound to voronoi diagram"); + } + if (args && !PyArg_ParseTuple(args, "")) { + throw Py::RuntimeError("No arguments accepted"); + } + return self; +} + + +Py::Long VoronoiVertexPy::getIndex() const +{ + VoronoiVertex* v = getVoronoiVertexPtr(); + if (v->isBound()) { + return Py::Long(v->dia->index(v->ptr)); + } + return Py::Long(-1); +} + +Py::Long VoronoiVertexPy::getColor() const +{ + VoronoiVertex* v = getVoronoiVertexPtr(); + if (v->isBound()) { + Voronoi::color_type color = v->ptr->color() & Voronoi::ColorMask; + return Py::Long(PyLong_FromSize_t(color)); + } + return Py::Long(0); +} + +void VoronoiVertexPy::setColor(Py::Long color) +{ + getVertexFromPy(this)->color(long(color) & Voronoi::ColorMask); } Py::Float VoronoiVertexPy::getX() const { - VoronoiVertex *v = getVoronoiVertexFromPy(this); - return Py::Float(v->ptr->x() / v->dia->getScale()); + VoronoiVertex* v = getVoronoiVertexFromPy(this); + return Py::Float(v->ptr->x() / v->dia->getScale()); } Py::Float VoronoiVertexPy::getY() const { - VoronoiVertex *v = getVoronoiVertexFromPy(this); - return Py::Float(v->ptr->y() / v->dia->getScale()); + VoronoiVertex* v = getVoronoiVertexFromPy(this); + return Py::Float(v->ptr->y() / v->dia->getScale()); } -Py::Object VoronoiVertexPy::getIncidentEdge() const { - VoronoiVertex *v = getVoronoiVertexFromPy(this); - return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(v->dia, v->ptr->incident_edge()))); -} - -PyObject* VoronoiVertexPy::toPoint(PyObject *args) +Py::Object VoronoiVertexPy::getIncidentEdge() const { - double z = 0.0; - if (!PyArg_ParseTuple(args, "|d", &z)) { - throw Py::RuntimeError("single argument of type double accepted"); - } - VoronoiVertex *v = getVoronoiVertexPtr(); - if (v->isBound()) { - return new Base::VectorPy(new Base::Vector3d(v->ptr->x() / v->dia->getScale(), v->ptr->y() / v->dia->getScale(), z)); - } - Py_INCREF(Py_None); - return Py_None; + VoronoiVertex* v = getVoronoiVertexFromPy(this); + return Py::asObject(new VoronoiEdgePy(new VoronoiEdge(v->dia, v->ptr->incident_edge()))); +} + +PyObject* VoronoiVertexPy::toPoint(PyObject* args) +{ + double z = 0.0; + if (!PyArg_ParseTuple(args, "|d", &z)) { + throw Py::RuntimeError("single argument of type double accepted"); + } + VoronoiVertex* v = getVoronoiVertexPtr(); + if (v->isBound()) { + return new Base::VectorPy(new Base::Vector3d(v->ptr->x() / v->dia->getScale(), + v->ptr->y() / v->dia->getScale(), + z)); + } + Py_INCREF(Py_None); + return Py_None; } // custom attributes get/set PyObject* VoronoiVertexPy::getCustomAttributes(const char* /*attr*/) const { - return nullptr; + return nullptr; } int VoronoiVertexPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { - return 0; + return 0; } - diff --git a/src/Mod/CAM/Gui/AppPathGui.cpp b/src/Mod/CAM/Gui/AppPathGui.cpp index 84dbb84a1c..856d3424c9 100644 --- a/src/Mod/CAM/Gui/AppPathGui.cpp +++ b/src/Mod/CAM/Gui/AppPathGui.cpp @@ -47,14 +47,15 @@ void loadPathResource() Gui::Translator::instance()->refresh(); } -namespace PathGui { +namespace PathGui +{ extern PyObject* initModule(); } /* Python entry */ PyMOD_INIT_FUNC(PathGui) { - if (!Gui::Application::Instance) { + if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); PyMOD_Return(nullptr); } @@ -62,7 +63,7 @@ PyMOD_INIT_FUNC(PathGui) Base::Interpreter().runString("import PartGui"); Base::Interpreter().runString("import Path"); } - catch(const Base::Exception& e) { + catch (const Base::Exception& e) { PyErr_SetString(PyExc_ImportError, e.what()); PyMOD_Return(nullptr); } @@ -73,21 +74,21 @@ PyMOD_INIT_FUNC(PathGui) CreatePathCommands(); // addition objects - PathGui::ViewProviderPath ::init(); - PathGui::ViewProviderPathCompound ::init(); + PathGui::ViewProviderPath ::init(); + PathGui::ViewProviderPathCompound ::init(); PathGui::ViewProviderPathCompoundPython ::init(); - PathGui::ViewProviderPathShape ::init(); - PathGui::ViewProviderPathPython ::init(); - PathGui::ViewProviderArea ::init(); - PathGui::ViewProviderAreaPython ::init(); - PathGui::ViewProviderAreaView ::init(); - PathGui::ViewProviderAreaViewPython ::init(); + PathGui::ViewProviderPathShape ::init(); + PathGui::ViewProviderPathPython ::init(); + PathGui::ViewProviderArea ::init(); + PathGui::ViewProviderAreaPython ::init(); + PathGui::ViewProviderAreaView ::init(); + PathGui::ViewProviderAreaViewPython ::init(); - // add resources and reloads the translators + // add resources and reloads the translators loadPathResource(); // register preferences pages - new Gui::PrefPageProducer (QT_TRANSLATE_NOOP("QObject","CAM")); + new Gui::PrefPageProducer(QT_TRANSLATE_NOOP("QObject", "CAM")); PyMOD_Return(mod); } diff --git a/src/Mod/CAM/Gui/AppPathGuiPy.cpp b/src/Mod/CAM/Gui/AppPathGuiPy.cpp index 6f0c7a1ca6..bc137ab50a 100644 --- a/src/Mod/CAM/Gui/AppPathGuiPy.cpp +++ b/src/Mod/CAM/Gui/AppPathGuiPy.cpp @@ -22,8 +22,8 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include +#include +#include #endif #include @@ -39,37 +39,44 @@ #include "ui_DlgProcessorChooser.h" -namespace PathGui { -class Module : public Py::ExtensionModule +namespace PathGui +{ +class Module: public Py::ExtensionModule { public: - Module() : Py::ExtensionModule("PathGui") + Module() + : Py::ExtensionModule("PathGui") { - add_varargs_method("open",&Module::open, - "open(filename): Opens a GCode file as a new document" - ); - add_varargs_method("insert",&Module::insert, - "insert(filename,docname): Imports a given GCode file into the given document" - ); - add_varargs_method("export",&Module::exporter, - "export(objectslist,filename): Exports a given list of Path objects to a GCode file" - ); - initialize("This module is the PathGui module."); // register with Python + add_varargs_method("open", + &Module::open, + "open(filename): Opens a GCode file as a new document"); + add_varargs_method( + "insert", + &Module::insert, + "insert(filename,docname): Imports a given GCode file into the given document"); + add_varargs_method( + "export", + &Module::exporter, + "export(objectslist,filename): Exports a given list of Path objects to a GCode file"); + initialize("This module is the PathGui module."); // register with Python } - ~Module() override {} + ~Module() override + {} private: Py::Object open(const Py::Tuple& args) { char* Name; - if (!PyArg_ParseTuple(args.ptr(), "et","utf-8",&Name)) + if (!PyArg_ParseTuple(args.ptr(), "et", "utf-8", &Name)) { throw Py::Exception(); + } std::string EncodedName = std::string(Name); PyMem_Free(Name); Base::FileInfo fi(EncodedName); - if (!fi.exists()) + if (!fi.exists()) { throw Py::RuntimeError("File not found"); + } Gui::WaitCursor wc; wc.restoreCursor(); @@ -78,8 +85,10 @@ private: std::string path = App::Application::getHomePath(); path += "Mod/CAM/Path/Post/scripts/"; QDir dir1(QString::fromUtf8(path.c_str()), QString::fromLatin1("*_pre.py")); - std::string cMacroPath = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") - ->GetASCII("MacroPath",App::Application::getUserMacroDir().c_str()); + std::string cMacroPath = + App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") + ->GetASCII("MacroPath", App::Application::getUserMacroDir().c_str()); QDir dir2(QString::fromUtf8(cMacroPath.c_str()), QString::fromLatin1("*_pre.py")); QFileInfoList list = dir1.entryInfoList(); list << dir2.entryInfoList(); @@ -98,22 +107,24 @@ private: std::ostringstream pre; std::ostringstream cmd; if (processor.empty()) { - App::Document *pcDoc = App::GetApplication().newDocument(); - Gui::Command::runCommand(Gui::Command::Gui,"import Path"); + App::Document* pcDoc = App::GetApplication().newDocument(); + Gui::Command::runCommand(Gui::Command::Gui, "import Path"); cmd << "Path.read(\"" << EncodedName << "\",\"" << pcDoc->getName() << "\")"; - Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); - } else { + Gui::Command::runCommand(Gui::Command::Gui, cmd.str().c_str()); + } + else { for (int i = 0; i < list.size(); ++i) { QFileInfo fileInfo = list.at(i); if (fileInfo.baseName().toStdString() == processor) { if (fileInfo.absoluteFilePath().contains(QString::fromLatin1("scripts"))) { pre << "from Path.Post.scripts import " << processor; - } else { + } + else { pre << "import " << processor; } - Gui::Command::runCommand(Gui::Command::Gui,pre.str().c_str()); + Gui::Command::runCommand(Gui::Command::Gui, pre.str().c_str()); cmd << processor << ".open(\"" << EncodedName << "\")"; - Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); + Gui::Command::runCommand(Gui::Command::Gui, cmd.str().c_str()); } } } @@ -128,15 +139,17 @@ private: Py::Object insert(const Py::Tuple& args) { char* Name; - char* DocName=nullptr; - if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&DocName)) + char* DocName = nullptr; + if (!PyArg_ParseTuple(args.ptr(), "et|s", "utf-8", &Name, &DocName)) { throw Py::Exception(); + } std::string EncodedName = std::string(Name); PyMem_Free(Name); Base::FileInfo fi(EncodedName); - if (!fi.exists()) + if (!fi.exists()) { throw Py::RuntimeError("File not found"); + } Gui::WaitCursor wc; wc.restoreCursor(); @@ -145,8 +158,10 @@ private: std::string path = App::Application::getHomePath(); path += "Mod/CAM/Path/Post/scripts/"; QDir dir1(QString::fromUtf8(path.c_str()), QString::fromLatin1("*_pre.py")); - std::string cMacroPath = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") - ->GetASCII("MacroPath",App::Application::getUserMacroDir().c_str()); + std::string cMacroPath = + App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") + ->GetASCII("MacroPath", App::Application::getUserMacroDir().c_str()); QDir dir2(QString::fromUtf8(cMacroPath.c_str()), QString::fromLatin1("*_pre.py")); QFileInfoList list = dir1.entryInfoList(); list << dir2.entryInfoList(); @@ -162,11 +177,13 @@ private: } processor = Dlg.getProcessor(); - App::Document *pcDoc = nullptr; - if (DocName) + App::Document* pcDoc = nullptr; + if (DocName) { pcDoc = App::GetApplication().getDocument(DocName); - else + } + else { pcDoc = App::GetApplication().getActiveDocument(); + } if (!pcDoc) { pcDoc = App::GetApplication().newDocument(DocName); @@ -175,21 +192,24 @@ private: std::ostringstream pre; std::ostringstream cmd; if (processor.empty()) { - Gui::Command::runCommand(Gui::Command::Gui,"import Path"); + Gui::Command::runCommand(Gui::Command::Gui, "import Path"); cmd << "Path.read(\"" << EncodedName << "\",\"" << pcDoc->getName() << "\")"; - Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); - } else { + Gui::Command::runCommand(Gui::Command::Gui, cmd.str().c_str()); + } + else { for (int i = 0; i < list.size(); ++i) { QFileInfo fileInfo = list.at(i); if (fileInfo.baseName().toStdString() == processor) { if (fileInfo.absoluteFilePath().contains(QString::fromLatin1("scripts"))) { pre << "from Path.Post.scripts import " << processor; - } else { + } + else { pre << "import " << processor; } - Gui::Command::runCommand(Gui::Command::Gui,pre.str().c_str()); - cmd << processor << ".insert(\"" << EncodedName << "\",\"" << pcDoc->getName() << "\")"; - Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); + Gui::Command::runCommand(Gui::Command::Gui, pre.str().c_str()); + cmd << processor << ".insert(\"" << EncodedName << "\",\"" + << pcDoc->getName() << "\")"; + Gui::Command::runCommand(Gui::Command::Gui, cmd.str().c_str()); } } } @@ -205,8 +225,9 @@ private: { PyObject* object; char* Name; - if (!PyArg_ParseTuple(args.ptr(), "Oet",&object,"utf-8",&Name)) + if (!PyArg_ParseTuple(args.ptr(), "Oet", &object, "utf-8", &Name)) { throw Py::Exception(); + } std::string EncodedName = std::string(Name); PyMem_Free(Name); @@ -215,14 +236,17 @@ private: try { Py::Sequence objlist(object); - if (objlist.size() == 0) + if (objlist.size() == 0) { throw Py::RuntimeError("No object to export"); + } std::string path = App::Application::getHomePath(); path += "Mod/CAM/Path/Post/scripts/"; QDir dir1(QString::fromUtf8(path.c_str()), QString::fromLatin1("*_post.py")); - std::string cMacroPath = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") - ->GetASCII("MacroPath",App::Application::getUserMacroDir().c_str()); + std::string cMacroPath = + App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") + ->GetASCII("MacroPath", App::Application::getUserMacroDir().c_str()); QDir dir2(QString::fromUtf8(cMacroPath.c_str()), QString::fromLatin1("*_post.py")); QFileInfoList list = dir1.entryInfoList(); list << dir2.entryInfoList(); @@ -242,30 +266,38 @@ private: std::ostringstream cmd; if (processor.empty()) { if (objlist.size() > 1) { - throw Py::RuntimeError("Cannot export more than one object without using a post script"); + throw Py::RuntimeError( + "Cannot export more than one object without using a post script"); } PyObject* item = objlist[0].ptr(); if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) { - App::DocumentObject* obj = static_cast(item)->getDocumentObjectPtr(); + App::DocumentObject* obj = + static_cast(item)->getDocumentObjectPtr(); App::Document* doc = obj->getDocument(); - Gui::Command::runCommand(Gui::Command::Gui,"import Path"); - cmd << "Path.write(FreeCAD.getDocument(\"" << doc->getName() << "\").getObject(\"" << obj->getNameInDocument() << "\"),\"" << EncodedName << "\")"; - Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); - } else { + Gui::Command::runCommand(Gui::Command::Gui, "import Path"); + cmd << "Path.write(FreeCAD.getDocument(\"" << doc->getName() + << "\").getObject(\"" << obj->getNameInDocument() << "\"),\"" << EncodedName + << "\")"; + Gui::Command::runCommand(Gui::Command::Gui, cmd.str().c_str()); + } + else { return Py::None(); } - } else { + } + else { for (int i = 0; i < list.size(); ++i) { QFileInfo fileInfo = list.at(i); if (fileInfo.baseName().toStdString() == processor) { if (fileInfo.absoluteFilePath().contains(QString::fromLatin1("scripts"))) { pre << "from Path.Post.scripts import " << processor; - } else { + } + else { pre << "import " << processor; } - Gui::Command::runCommand(Gui::Command::Gui,pre.str().c_str()); - cmd << processor << ".export(__objs__,\"" << EncodedName << "\",\"" << arguments << "\")"; - Gui::Command::runCommand(Gui::Command::Gui,cmd.str().c_str()); + Gui::Command::runCommand(Gui::Command::Gui, pre.str().c_str()); + cmd << processor << ".export(__objs__,\"" << EncodedName << "\",\"" + << arguments << "\")"; + Gui::Command::runCommand(Gui::Command::Gui, cmd.str().c_str()); } } } @@ -283,4 +315,4 @@ PyObject* initModule() return Base::Interpreter().addModule(new Module); } -} // namespace PathGui +} // namespace PathGui diff --git a/src/Mod/CAM/Gui/Command.cpp b/src/Mod/CAM/Gui/Command.cpp index fa5deb9a6b..5dfc86410d 100644 --- a/src/Mod/CAM/Gui/Command.cpp +++ b/src/Mod/CAM/Gui/Command.cpp @@ -22,7 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -35,20 +35,21 @@ #include -// Path Area ##################################################################################################### +// Path Area +// ##################################################################################################### DEF_STD_CMD_A(CmdPathArea) CmdPathArea::CmdPathArea() - :Command("CAM_Area") + : Command("CAM_Area") { - sAppModule = "Path"; - sGroup = QT_TR_NOOP("CAM"); - sMenuText = QT_TR_NOOP("Area"); - sToolTipText = QT_TR_NOOP("Creates a feature area from selected objects"); - sWhatsThis = "CAM_Area"; - sStatusTip = sToolTipText; - sPixmap = "CAM_Area"; + sAppModule = "Path"; + sGroup = QT_TR_NOOP("CAM"); + sMenuText = QT_TR_NOOP("Area"); + sToolTipText = QT_TR_NOOP("Creates a feature area from selected objects"); + sWhatsThis = "CAM_Area"; + sStatusTip = sToolTipText; + sPixmap = "CAM_Area"; } void CmdPathArea::activated(int iMsg) @@ -58,21 +59,23 @@ void CmdPathArea::activated(int iMsg) std::ostringstream sources; std::string areaName; bool addView = true; - for(const Gui::SelectionObject &selObj : - getSelection().getSelectionEx(nullptr, Part::Feature::getClassTypeId())) - { - const Part::Feature *pcObj = static_cast(selObj.getObject()); - const std::vector &subnames = selObj.getSubNames(); - if(addView && !areaName.empty()) addView = false; + for (const Gui::SelectionObject& selObj : + getSelection().getSelectionEx(nullptr, Part::Feature::getClassTypeId())) { + const Part::Feature* pcObj = static_cast(selObj.getObject()); + const std::vector& subnames = selObj.getSubNames(); + if (addView && !areaName.empty()) { + addView = false; + } - if(subnames.empty()) { - if(addView && pcObj->isDerivedFrom()) + if (subnames.empty()) { + if (addView && pcObj->isDerivedFrom()) { areaName = pcObj->getNameInDocument(); + } sources << "FreeCAD.activeDocument()." << pcObj->getNameInDocument() << ","; continue; } - for(const std::string &name : subnames) { - if(name.compare(0,4,"Face") && name.compare(0,4,"Edge")) { + for (const std::string& name : subnames) { + if (name.compare(0, 4, "Face") && name.compare(0, 4, "Edge")) { Base::Console().Error("Selected shape is not 2D\n"); return; } @@ -82,33 +85,44 @@ void CmdPathArea::activated(int iMsg) std::string sub_fname = getUniqueObjectName(subname.str().c_str()); std::ostringstream cmd; - cmd << "FreeCAD.activeDocument().addObject('Part::Feature','" << sub_fname << - "').Shape = PathCommands.findShape(FreeCAD.activeDocument()." << - pcObj->getNameInDocument() << ".Shape,'" << name << "'"; - if(!name.compare(0,4,"Edge")) + cmd << "FreeCAD.activeDocument().addObject('Part::Feature','" << sub_fname + << "').Shape = PathCommands.findShape(FreeCAD.activeDocument()." + << pcObj->getNameInDocument() << ".Shape,'" << name << "'"; + if (!name.compare(0, 4, "Edge")) { cmd << ",'Wires'"; + } cmd << ')'; cmds.push_back(cmd.str()); sources << "FreeCAD.activeDocument()." << sub_fname << ","; } } - if(addView && !areaName.empty()) { + if (addView && !areaName.empty()) { std::string FeatName = getUniqueObjectName("FeatureAreaView"); openCommand(QT_TRANSLATE_NOOP("Command", "Create Path Area View")); - doCommand(Doc,"FreeCAD.activeDocument().addObject('Path::FeatureAreaView','%s')",FeatName.c_str()); - doCommand(Doc,"FreeCAD.activeDocument().%s.Source = FreeCAD.activeDocument().%s", - FeatName.c_str(),areaName.c_str()); + doCommand(Doc, + "FreeCAD.activeDocument().addObject('Path::FeatureAreaView','%s')", + FeatName.c_str()); + doCommand(Doc, + "FreeCAD.activeDocument().%s.Source = FreeCAD.activeDocument().%s", + FeatName.c_str(), + areaName.c_str()); commitCommand(); updateActive(); return; } std::string FeatName = getUniqueObjectName("FeatureArea"); openCommand(QT_TRANSLATE_NOOP("Command", "Create Path Area")); - doCommand(Doc,"import PathCommands"); - for(const std::string &cmd : cmds) - doCommand(Doc,"%s", cmd.c_str()); - doCommand(Doc,"FreeCAD.activeDocument().addObject('Path::FeatureArea','%s')",FeatName.c_str()); - doCommand(Doc,"FreeCAD.activeDocument().%s.Sources = [ %s ]",FeatName.c_str(),sources.str().c_str()); + doCommand(Doc, "import PathCommands"); + for (const std::string& cmd : cmds) { + doCommand(Doc, "%s", cmd.c_str()); + } + doCommand(Doc, + "FreeCAD.activeDocument().addObject('Path::FeatureArea','%s')", + FeatName.c_str()); + doCommand(Doc, + "FreeCAD.activeDocument().%s.Sources = [ %s ]", + FeatName.c_str(), + sources.str().c_str()); commitCommand(); updateActive(); } @@ -122,15 +136,15 @@ bool CmdPathArea::isActive() DEF_STD_CMD_A(CmdPathAreaWorkplane) CmdPathAreaWorkplane::CmdPathAreaWorkplane() - :Command("CAM_Area_Workplane") + : Command("CAM_Area_Workplane") { - sAppModule = "Path"; - sGroup = QT_TR_NOOP("CAM"); - sMenuText = QT_TR_NOOP("Area workplane"); - sToolTipText = QT_TR_NOOP("Select a workplane for a FeatureArea"); - sWhatsThis = "CAM_Area_Workplane"; - sStatusTip = sToolTipText; - sPixmap = "CAM_Area_Workplane"; + sAppModule = "Path"; + sGroup = QT_TR_NOOP("CAM"); + sMenuText = QT_TR_NOOP("Area workplane"); + sToolTipText = QT_TR_NOOP("Select a workplane for a FeatureArea"); + sWhatsThis = "CAM_Area_Workplane"; + sStatusTip = sToolTipText; + sPixmap = "CAM_Area_Workplane"; } void CmdPathAreaWorkplane::activated(int iMsg) @@ -141,39 +155,40 @@ void CmdPathAreaWorkplane::activated(int iMsg) std::string planeSubname; std::string planeName; - for(Gui::SelectionObject &selObj : - getSelection().getSelectionEx(nullptr, Part::Feature::getClassTypeId())) - { - const std::vector &subnames = selObj.getSubNames(); - if(subnames.size()>1) { + for (Gui::SelectionObject& selObj : + getSelection().getSelectionEx(nullptr, Part::Feature::getClassTypeId())) { + const std::vector& subnames = selObj.getSubNames(); + if (subnames.size() > 1) { Base::Console().Error("Please select one sub shape object for plane only\n"); return; } - const Part::Feature *pcObj = static_cast(selObj.getObject()); - if(subnames.empty()) { - if(pcObj->isDerivedFrom()) { - if(!areaName.empty()){ + const Part::Feature* pcObj = static_cast(selObj.getObject()); + if (subnames.empty()) { + if (pcObj->isDerivedFrom()) { + if (!areaName.empty()) { Base::Console().Error("Please select one FeatureArea only\n"); return; } areaName = pcObj->getNameInDocument(); continue; } - for (TopExp_Explorer it(pcObj->Shape.getShape().getShape(), TopAbs_SHELL); it.More(); it.Next()) { + for (TopExp_Explorer it(pcObj->Shape.getShape().getShape(), TopAbs_SHELL); it.More(); + it.Next()) { Base::Console().Error("Selected shape is not 2D\n"); return; } } - if(!planeName.empty()){ + if (!planeName.empty()) { Base::Console().Error("Please select one shape object for plane only\n"); return; - }else{ + } + else { planeSubname = planeName = pcObj->getNameInDocument(); planeSubname += ".Shape"; } - for(const std::string &name : subnames) { - if(name.compare(0,4,"Face") && name.compare(0,4,"Edge")) { + for (const std::string& name : subnames) { + if (name.compare(0, 4, "Face") && name.compare(0, 4, "Edge")) { Base::Console().Error("Selected shape is not 2D\n"); return; } @@ -182,20 +197,23 @@ void CmdPathAreaWorkplane::activated(int iMsg) planeSubname = subname.str(); } } - if(areaName.empty()) { + if (areaName.empty()) { Base::Console().Error("Please select one FeatureArea\n"); return; } - if(planeName.empty()) { + if (planeName.empty()) { Base::Console().Error("Please select one shape object\n"); return; } openCommand(QT_TRANSLATE_NOOP("Command", "Select Workplane for Path Area")); - doCommand(Doc,"import PathCommands"); - doCommand(Doc,"FreeCAD.activeDocument().%s.WorkPlane = PathCommands.findShape(" - "FreeCAD.activeDocument().%s)", areaName.c_str(),planeSubname.c_str()); - doCommand(Doc,"FreeCAD.activeDocument().%s.ViewObject.Visibility = True",areaName.c_str()); + doCommand(Doc, "import PathCommands"); + doCommand(Doc, + "FreeCAD.activeDocument().%s.WorkPlane = PathCommands.findShape(" + "FreeCAD.activeDocument().%s)", + areaName.c_str(), + planeSubname.c_str()); + doCommand(Doc, "FreeCAD.activeDocument().%s.ViewObject.Visibility = True", areaName.c_str()); commitCommand(); updateActive(); } @@ -206,21 +224,22 @@ bool CmdPathAreaWorkplane::isActive() } -// Path compound ##################################################################################################### +// Path compound +// ##################################################################################################### DEF_STD_CMD_A(CmdPathCompound) CmdPathCompound::CmdPathCompound() - :Command("CAM_Compound") + : Command("CAM_Compound") { - sAppModule = "Path"; - sGroup = QT_TR_NOOP("CAM"); - sMenuText = QT_TR_NOOP("Compound"); - sToolTipText = QT_TR_NOOP("Creates a compound from selected toolpaths"); - sWhatsThis = "CAM_Compound"; - sStatusTip = sToolTipText; - sPixmap = "CAM_Compound"; + sAppModule = "Path"; + sGroup = QT_TR_NOOP("CAM"); + sMenuText = QT_TR_NOOP("Compound"); + sToolTipText = QT_TR_NOOP("Creates a compound from selected toolpaths"); + sWhatsThis = "CAM_Compound"; + sStatusTip = sToolTipText; + sPixmap = "CAM_Compound"; } void CmdPathCompound::activated(int iMsg) @@ -230,24 +249,34 @@ void CmdPathCompound::activated(int iMsg) if (!Sel.empty()) { std::ostringstream cmd; cmd << "["; - Path::Feature *pcPathObject; - for (std::vector::const_iterator it=Sel.begin();it!=Sel.end();++it) { + Path::Feature* pcPathObject; + for (std::vector::const_iterator it = Sel.begin(); + it != Sel.end(); + ++it) { if ((*it).pObject->isDerivedFrom()) { pcPathObject = static_cast((*it).pObject); cmd << "FreeCAD.activeDocument()." << pcPathObject->getNameInDocument() << ","; - } else { - Base::Console().Error("Only Path objects must be selected before running this command\n"); + } + else { + Base::Console().Error( + "Only Path objects must be selected before running this command\n"); return; } } cmd << "]"; std::string FeatName = getUniqueObjectName("PathCompound"); openCommand(QT_TRANSLATE_NOOP("Command", "Create Path Compound")); - doCommand(Doc,"FreeCAD.activeDocument().addObject('Path::FeatureCompound','%s')",FeatName.c_str()); - doCommand(Doc,"FreeCAD.activeDocument().%s.Group = %s",FeatName.c_str(),cmd.str().c_str()); + doCommand(Doc, + "FreeCAD.activeDocument().addObject('Path::FeatureCompound','%s')", + FeatName.c_str()); + doCommand(Doc, + "FreeCAD.activeDocument().%s.Group = %s", + FeatName.c_str(), + cmd.str().c_str()); commitCommand(); updateActive(); - } else { + } + else { Base::Console().Error("At least one Path object must be selected\n"); return; } @@ -258,21 +287,22 @@ bool CmdPathCompound::isActive() return hasActiveDocument(); } - // Path Shape ##################################################################################################### +// Path Shape +// ##################################################################################################### DEF_STD_CMD_A(CmdPathShape) CmdPathShape::CmdPathShape() - :Command("CAM_Shape") + : Command("CAM_Shape") { - sAppModule = "Path"; - sGroup = QT_TR_NOOP("CAM"); - sMenuText = QT_TR_NOOP("From Shape"); - sToolTipText = QT_TR_NOOP("Creates a toolpath from a selected shape"); - sWhatsThis = "CAM_Shape"; - sStatusTip = sToolTipText; - sPixmap = "CAM_Shape"; + sAppModule = "Path"; + sGroup = QT_TR_NOOP("CAM"); + sMenuText = QT_TR_NOOP("From Shape"); + sToolTipText = QT_TR_NOOP("Creates a toolpath from a selected shape"); + sWhatsThis = "CAM_Shape"; + sStatusTip = sToolTipText; + sPixmap = "CAM_Shape"; } void CmdPathShape::activated(int iMsg) @@ -280,19 +310,19 @@ void CmdPathShape::activated(int iMsg) Q_UNUSED(iMsg); std::list cmds; std::ostringstream sources; - for(const Gui::SelectionObject &selObj : - getSelection().getSelectionEx(nullptr, Part::Feature::getClassTypeId())) - { - const Part::Feature *pcObj = static_cast(selObj.getObject()); - const std::vector &subnames = selObj.getSubNames(); - if(subnames.empty()) { + for (const Gui::SelectionObject& selObj : + getSelection().getSelectionEx(nullptr, Part::Feature::getClassTypeId())) { + const Part::Feature* pcObj = static_cast(selObj.getObject()); + const std::vector& subnames = selObj.getSubNames(); + if (subnames.empty()) { sources << "FreeCAD.activeDocument()." << pcObj->getNameInDocument() << ","; continue; } - for(const std::string &name : subnames) { - if(name.compare(0,4,"Face") && name.compare(0,4,"Edge")) { + for (const std::string& name : subnames) { + if (name.compare(0, 4, "Face") && name.compare(0, 4, "Edge")) { Base::Console().Warning("Ignored shape %s %s\n", - pcObj->getNameInDocument(), name.c_str()); + pcObj->getNameInDocument(), + name.c_str()); continue; } @@ -301,11 +331,12 @@ void CmdPathShape::activated(int iMsg) std::string sub_fname = getUniqueObjectName(subname.str().c_str()); std::ostringstream cmd; - cmd << "FreeCAD.activeDocument().addObject('Part::Feature','" << sub_fname << - "').Shape = PathCommands.findShape(FreeCAD.activeDocument()." << - pcObj->getNameInDocument() << ".Shape,'" << name << "'"; - if(!name.compare(0,4,"Edge")) + cmd << "FreeCAD.activeDocument().addObject('Part::Feature','" << sub_fname + << "').Shape = PathCommands.findShape(FreeCAD.activeDocument()." + << pcObj->getNameInDocument() << ".Shape,'" << name << "'"; + if (!name.compare(0, 4, "Edge")) { cmd << ",'Wires'"; + } cmd << ')'; cmds.push_back(cmd.str()); sources << "FreeCAD.activeDocument()." << sub_fname << ","; @@ -313,11 +344,17 @@ void CmdPathShape::activated(int iMsg) } std::string FeatName = getUniqueObjectName("PathShape"); openCommand(QT_TRANSLATE_NOOP("Command", "Create Path Shape")); - doCommand(Doc,"import PathCommands"); - for(const std::string &cmd : cmds) + doCommand(Doc, "import PathCommands"); + for (const std::string& cmd : cmds) { doCommand(Doc, "%s", cmd.c_str()); - doCommand(Doc,"FreeCAD.activeDocument().addObject('Path::FeatureShape','%s')",FeatName.c_str()); - doCommand(Doc,"FreeCAD.activeDocument().%s.Sources = [ %s ]",FeatName.c_str(),sources.str().c_str()); + } + doCommand(Doc, + "FreeCAD.activeDocument().addObject('Path::FeatureShape','%s')", + FeatName.c_str()); + doCommand(Doc, + "FreeCAD.activeDocument().%s.Sources = [ %s ]", + FeatName.c_str(), + sources.str().c_str()); commitCommand(); updateActive(); } @@ -328,10 +365,9 @@ bool CmdPathShape::isActive() } - void CreatePathCommands() { - Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); + Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); rcCmdMgr.addCommand(new CmdPathCompound()); rcCmdMgr.addCommand(new CmdPathShape()); rcCmdMgr.addCommand(new CmdPathArea()); diff --git a/src/Mod/CAM/Gui/DlgProcessorChooser.cpp b/src/Mod/CAM/Gui/DlgProcessorChooser.cpp index c6b67fba01..05a99c69be 100644 --- a/src/Mod/CAM/Gui/DlgProcessorChooser.cpp +++ b/src/Mod/CAM/Gui/DlgProcessorChooser.cpp @@ -22,7 +22,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -35,17 +35,20 @@ using namespace PathGui; /* TRANSLATOR PathGui::DlgProcessorChooser */ -DlgProcessorChooser::DlgProcessorChooser(std::vector &scriptnames, bool withArguments) - : QDialog(Gui::getMainWindow()), ui(new Ui_DlgProcessorChooser) +DlgProcessorChooser::DlgProcessorChooser(std::vector& scriptnames, bool withArguments) + : QDialog(Gui::getMainWindow()) + , ui(new Ui_DlgProcessorChooser) { ui->setupUi(this); ui->comboBox->addItem(tr("None")); - for (std::vector::const_iterator it = scriptnames.begin(); it != scriptnames.end(); ++it) + for (std::vector::const_iterator it = scriptnames.begin(); it != scriptnames.end(); + ++it) { ui->comboBox->addItem(QString::fromUtf8((*it).c_str())); + } QMetaObject::connectSlotsByName(this); if (withArguments) { - ui->argsLabel->setEnabled(true); - ui->argsLineEdit->setEnabled(true); + ui->argsLabel->setEnabled(true); + ui->argsLineEdit->setEnabled(true); } } @@ -61,7 +64,7 @@ std::string DlgProcessorChooser::getProcessor() std::string DlgProcessorChooser::getArguments() { - return arguments; + return arguments; } void DlgProcessorChooser::accept() @@ -69,7 +72,8 @@ void DlgProcessorChooser::accept() if (ui->comboBox->currentText() == tr("None")) { processor = ""; arguments = ""; - } else { + } + else { processor = ui->comboBox->currentText().toUtf8().data(); arguments = ui->argsLineEdit->text().toUtf8().data(); } diff --git a/src/Mod/CAM/Gui/DlgProcessorChooser.h b/src/Mod/CAM/Gui/DlgProcessorChooser.h index 2cb7ae3021..3927b78bd7 100644 --- a/src/Mod/CAM/Gui/DlgProcessorChooser.h +++ b/src/Mod/CAM/Gui/DlgProcessorChooser.h @@ -28,14 +28,15 @@ class Ui_DlgProcessorChooser; -namespace PathGui { +namespace PathGui +{ -class DlgProcessorChooser : public QDialog +class DlgProcessorChooser: public QDialog { Q_OBJECT public: - explicit DlgProcessorChooser(std::vector &scriptnames, bool withArguments = false); + explicit DlgProcessorChooser(std::vector& scriptnames, bool withArguments = false); ~DlgProcessorChooser() override; std::string getProcessor(); @@ -50,6 +51,6 @@ private: std::string processor, arguments; }; -} +} // namespace PathGui -#endif // PATH_DlgProcessorChooser_H +#endif // PATH_DlgProcessorChooser_H diff --git a/src/Mod/CAM/Gui/DlgSettingsPathColor.cpp b/src/Mod/CAM/Gui/DlgSettingsPathColor.cpp index deacfed191..68f04e3c67 100644 --- a/src/Mod/CAM/Gui/DlgSettingsPathColor.cpp +++ b/src/Mod/CAM/Gui/DlgSettingsPathColor.cpp @@ -82,7 +82,7 @@ void DlgSettingsPathColor::loadSettings() /** * Sets the strings of the subwidgets using the current language. */ -void DlgSettingsPathColor::changeEvent(QEvent *e) +void DlgSettingsPathColor::changeEvent(QEvent* e) { if (e->type() == QEvent::LanguageChange) { ui->retranslateUi(this); @@ -93,4 +93,3 @@ void DlgSettingsPathColor::changeEvent(QEvent *e) } #include "moc_DlgSettingsPathColor.cpp" - diff --git a/src/Mod/CAM/Gui/DlgSettingsPathColor.h b/src/Mod/CAM/Gui/DlgSettingsPathColor.h index 797f29d102..89749c5401 100644 --- a/src/Mod/CAM/Gui/DlgSettingsPathColor.h +++ b/src/Mod/CAM/Gui/DlgSettingsPathColor.h @@ -27,27 +27,28 @@ #include #include -namespace PathGui { +namespace PathGui +{ class Ui_DlgSettingsPathColor; -class DlgSettingsPathColor : public Gui::Dialog::PreferencePage +class DlgSettingsPathColor: public Gui::Dialog::PreferencePage { - Q_OBJECT + Q_OBJECT public: - explicit DlgSettingsPathColor(QWidget* parent = nullptr); - ~DlgSettingsPathColor() override; + explicit DlgSettingsPathColor(QWidget* parent = nullptr); + ~DlgSettingsPathColor() override; - void saveSettings() override; - void loadSettings() override; + void saveSettings() override; + void loadSettings() override; protected: - void changeEvent(QEvent *e) override; + void changeEvent(QEvent* e) override; private: - std::unique_ptr ui; + std::unique_ptr ui; }; -} // namespace PathGui +} // namespace PathGui -#endif // PATHGUI_DIALOG_DLGSETTINGSPATHCOLOR_H +#endif // PATHGUI_DIALOG_DLGSETTINGSPATHCOLOR_H diff --git a/src/Mod/CAM/Gui/PreCompiled.h b/src/Mod/CAM/Gui/PreCompiled.h index ed8cef500f..ed1229b9b5 100644 --- a/src/Mod/CAM/Gui/PreCompiled.h +++ b/src/Mod/CAM/Gui/PreCompiled.h @@ -27,19 +27,19 @@ // Importing of App classes #ifdef FC_OS_WIN32 -# define PartExport __declspec(dllimport) -# define PathExport __declspec(dllimport) -# define PartGuiExport __declspec(dllexport) -# define PathGuiExport __declspec(dllexport) -#else // for Linux -# define PartExport -# define PathExport -# define PartGuiExport -# define PathGuiExport +#define PartExport __declspec(dllimport) +#define PathExport __declspec(dllimport) +#define PartGuiExport __declspec(dllexport) +#define PathGuiExport __declspec(dllexport) +#else // for Linux +#define PartExport +#define PathExport +#define PartGuiExport +#define PathGuiExport #endif #ifdef _MSC_VER -# pragma warning( disable : 4273 ) +#pragma warning(disable : 4273) #endif #ifdef _PreComp_ @@ -69,6 +69,6 @@ #include #include -#endif //_PreComp_ +#endif //_PreComp_ -#endif // PATHGUI_PRECOMPILED_H +#endif // PATHGUI_PRECOMPILED_H diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM.ts b/src/Mod/CAM/Gui/Resources/translations/CAM.ts index 21bffd5569..a41d329635 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM.ts @@ -5436,7 +5436,7 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6818,12 +6818,12 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -6894,7 +6894,7 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7211,7 +7211,7 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8352,7 +8352,7 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_be.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_be.ts index b6e16455d5..bf71fa0104 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_be.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_be.ts @@ -3716,7 +3716,7 @@ Ordering by operation will do each operation in all coordinate systems before mo Тады ўсе аперацыі будуць выконвацца там у тым жа парадку. Гэтае карысна, калі аператар можа бяспечна загружаць працу ў адну сістэму каардынат, а станок выконвае працу ў іншай. -Упарадкаванне па інструменту прывядзе да найменшай колькасці змен інструмента. +Упарадкаванне па інструменту прывядзе да найменшай колькасці змен інструмента. Будзе праведзена змена інструмента, потым усе аперацыі ва ўсіх сістэмах каардынат перад зменай інструментаў. Упарадкаванне па аперацыях выканае кожную аперацыю ва ўсіх сістэмах каардынат перад пераходам да наступнай аперацыі. @@ -5611,7 +5611,7 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. Адсячэнне для выдалення калінеарных адрэзкаў (градусаў). Першапачаткова = 10.0. @@ -7001,12 +7001,12 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7086,7 +7086,7 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. <b>Заўвага</b>: У дыялогавым акне паказваюцца каманды вызначэння шляху ў асноўных адзінках FreeCAD (мм/с). Значэнні будуць пераўтвораныя ў патрэбныя адзінкі вымярэння падчас пасляапрацоўкі. @@ -7404,7 +7404,7 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity Нумар інструменту {} - гэта састарэлы інструмент. Састарэлыя інструменты не падтрымліваюцца функцыяй Path-Sanity @@ -8549,7 +8549,7 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Працоўны каталог такарных разцоў {} мае патрэбу ва ўкладзеных каталогах: {} diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_ca.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_ca.ts index fb743a3c30..348c785f43 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_ca.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_ca.ts @@ -5559,9 +5559,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_cs.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_cs.ts index 7a809630a6..186f93b90a 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_cs.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_cs.ts @@ -5557,7 +5557,7 @@ Výchozí: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. Cutoff pro odstranění kolineárních segmentů (stupňů). výchozí = 10,0. @@ -6945,23 +6945,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7031,9 +7031,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7349,9 +7349,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Nástroj číslo {} je starší nástroj. Starší nástroje nejsou + Nástroj číslo {} je starší nástroj. Starší nástroje nejsou podporovány nástrojem Path-Sanity @@ -8491,10 +8491,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_da.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_da.ts index 39713208d7..7d76a9a05f 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_da.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_da.ts @@ -5559,9 +5559,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_de.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_de.ts index 1d27c4f136..c914f71453 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_de.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_de.ts @@ -2296,7 +2296,7 @@ Wenn die angegebene Höhe 0 ist, wird die halbe Höhe des Teils verwendet. Ist d Radius of the fillet on the tag's top edge. If the radius is bigger than that which the tag shape itself supports, the resulting shape will be that of a dome. - Radius der Abrundung an der oberen Kante des Stegs. + Radius der Abrundung an der oberen Kante des Stegs. Wenn der Radius größer ist als der Radius, den der Steg selbst unterstützt, wird die Form einer Kuppel gebildet. @@ -5556,7 +5556,7 @@ Standard: "3 mm" - Das Werkzeug sollte in diesem Fall auf Verbindungsfahrten imm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. Obergrenze zum Entfernen von kolinearen Segmenten (Grad). Standard = 10.0. @@ -6943,23 +6943,23 @@ Abbruch der OP-Erstellung - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - Das aktuell ausgewählte Einheitenschema: + Das aktuell ausgewählte Einheitenschema: '{}' für dieses Dokument - verwendet keine 'Minuten' für Geschwindigkeitswerte. - -CNC-Maschinen benötigen die Vorschubgeschwindigkeit in -Einheit/Minute. Um einen korrekten G-Code sicherzustellen: + verwendet keine 'Minuten' für Geschwindigkeitswerte. + +CNC-Maschinen benötigen die Vorschubgeschwindigkeit in +Einheit/Minute. Um einen korrekten G-Code sicherzustellen: Ein Minuten-basiertes Einheitenschema in den Einstellungen auswählen. Zum Beispiel: 'Metrisch, Kleine Teile & CNC' @@ -7029,9 +7029,9 @@ Zum Beispiel: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Hinweis</b>: Dieser Dialog zeigt Werkzeugweg-Befehle in FreeCAD-Basiseinheiten (mm/s) an. + <b>Hinweis</b>: Dieser Dialog zeigt Werkzeugweg-Befehle in FreeCAD-Basiseinheiten (mm/s) an. Werte werden erst im Postprozessor in die gewünschte Einheit konvertiert. @@ -7347,9 +7347,9 @@ Zum Beispiel: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Werkzeugnummer {} ist ein veraltetes Werkzeug. Veraltete Werkzeuge werden nicht durch + Werkzeugnummer {} ist ein veraltetes Werkzeug. Veraltete Werkzeuge werden nicht durch Path-Sanity unterstützt @@ -8489,10 +8489,10 @@ Zum Beispiel: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Das Werkzeugspitzen Arbeitsverzeichnis {} benötigt folgende Unterverzeichnisse: - {} + {} Sollen diese erstellt werden? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_el.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_el.ts index 37c7618623..8d9809f308 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_el.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_el.ts @@ -5559,9 +5559,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_es-AR.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_es-AR.ts index 3fc9edff75..c36df45277 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_es-AR.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_es-AR.ts @@ -2453,7 +2453,7 @@ Si se deja vacío, el directorio macro es usado. This can be helpful when almost all jobs will be processed by the same machine with a similar setup. If left empty no template will be preselected. - La plantilla por defecto a seleccionar al crear un nuevo Trabajo. + La plantilla por defecto a seleccionar al crear un nuevo Trabajo. Esto puede ser útil cuando casi todos los trabajos serán procesados por la misma máquina con una configuración similar. @@ -5559,9 +5559,9 @@ Por defecto: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Corte para eliminar segmentos colineales (grados). + Corte para eliminar segmentos colineales (grados). por defecto=10.0. @@ -6946,23 +6946,23 @@ Abortando la creación de la op - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7032,9 +7032,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7350,9 +7350,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8492,10 +8492,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Directorio de trabajo de herramienta {} necesita estos sudirectorios: - {} + {} ¿Crearlos? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_es-ES.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_es-ES.ts index b2c5e150e4..873db58317 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_es-ES.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_es-ES.ts @@ -2453,7 +2453,7 @@ Si se deja vacío, el directorio macro es usado. This can be helpful when almost all jobs will be processed by the same machine with a similar setup. If left empty no template will be preselected. - La plantilla por defecto a seleccionar al crear un nuevo Trabajo. + La plantilla por defecto a seleccionar al crear un nuevo Trabajo. Esto puede ser útil cuando casi todos los trabajos serán procesados por la misma máquina con una configuración similar. @@ -5559,9 +5559,9 @@ Por defecto: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Corte para eliminar segmentos colineales (grados). + Corte para eliminar segmentos colineales (grados). por defecto=10.0. @@ -6946,23 +6946,23 @@ Abortando la creación de la op - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7032,9 +7032,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7350,9 +7350,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8492,10 +8492,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Directorio de trabajo de herramienta {} necesita estos sudirectorios: - {} + {} ¿Crearlos? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_eu.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_eu.ts index cad505f94e..4bee8d6d87 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_eu.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_eu.ts @@ -188,7 +188,7 @@ Enable to include values of the SetupSheet in the template. Any values of the SetupSheet that are changed from their default are preselected. If this field not selected the current SetupSheet was not modified. - Gaitu hau konfigurazio-orriaren balioak txantiloian sartzeko. + Gaitu hau konfigurazio-orriaren balioak txantiloian sartzeko. Jatorrizko balioetatik aldatu diren konfigurazio-orriko balio guztiak hautatuko dira. Eremu hau hautatuta ez badago, uneko konfigurazio-orria ez da aldatu. @@ -1899,7 +1899,7 @@ Azken aukera pieza gordinaren area osoaren aurpegirako erabili daiteke, hurrengo The amount by which the tool is laterally displaced on each cycle of the pattern, specified in percent of the tool diameter. A step over of 100% results in no overlap between two different cycles. - Tresna saiheska zenbat desplazatuko den ereduaren ziklo bakoitzean, tresnaren diametroaren ehunekoetan adierazita. + Tresna saiheska zenbat desplazatuko den ereduaren ziklo bakoitzean, tresnaren diametroaren ehunekoetan adierazita. Gainditzea % 100ekoa bada, ez da gainjartzerik egongo zikloen artean. @@ -5559,9 +5559,9 @@ Balio lehenetsia: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Trontzatu segmentu lerrokideak kentzeko (graduak). + Trontzatu segmentu lerrokideak kentzeko (graduak). Lehenetsia=10.0. @@ -6946,23 +6946,23 @@ Aukeren sorrera abortatzen - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7032,9 +7032,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7350,9 +7350,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8492,7 +8492,7 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Tresna-atalaren laneko direktorioak ({}) honako azpidirektorioak behar ditu: {} diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_fi.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_fi.ts index 3273baad09..6fa03f8cea 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_fi.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_fi.ts @@ -5559,9 +5559,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_fr.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_fr.ts index 171be9088b..99f8cc7bdc 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_fr.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_fr.ts @@ -3929,7 +3929,7 @@ Valeur par défaut : "5 mm" If multiple coordinate systems are in use, setting this to TRUE will cause the gcode to be written to multiple output files as controlled by the 'order by' property. For example, if ordering by Fixture, the first output file will be for the first fixture and separate file for the second. - Si plusieurs systèmes de coordonnées sont utilisés, la valeur TRUE permet d'écrire le G-code dans plusieurs fichiers de sortie, comme le prévoit la propriété "Trier par". + Si plusieurs systèmes de coordonnées sont utilisés, la valeur TRUE permet d'écrire le G-code dans plusieurs fichiers de sortie, comme le prévoit la propriété "Trier par". Par exemple, si le classement par outil, le premier fichier de sortie sera pour la première fixation et un fichier séparé pour la seconde. @@ -5572,7 +5572,7 @@ Rotationnel : balayage rotationnel sur le 4ᵉ axe. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. Seuil de décision pour la suppression des segments colinéaires (degrés), par défaut = 10.0. @@ -6956,12 +6956,12 @@ Annulation de la création de l'opération - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7039,7 +7039,7 @@ Par exemple : CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. <b>Remarque </b>: cette boîte de dialogue montre les commandes de parcours avec les unités de base de FreeCAD (mm/s). Les valeurs seront converties dans l'unité souhaitée pendant le post-traitement. @@ -7357,7 +7357,7 @@ Les valeurs seront converties dans l'unité souhaitée pendant le post-traitemen - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity L'outil {} est un vieil outil. Les vieux outils ne sont pas pris en charge par l'outil Rechercher des erreurs. @@ -8498,10 +8498,10 @@ Les valeurs seront converties dans l'unité souhaitée pendant le post-traitemen Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Le répertoire de travail des outils coupants {} a besoin de ces sous-répertoires : - {} + {} Voulez-vous les créer ? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_gl.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_gl.ts index 8e682f3c1e..57db47088c 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_gl.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_gl.ts @@ -4112,23 +4112,23 @@ Default: 3 mm Path - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -5551,9 +5551,9 @@ For example: - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -7024,9 +7024,9 @@ Aborting op creation CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7343,9 +7343,9 @@ Aborting op creation - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8422,10 +8422,10 @@ Aborting op creation Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_hr.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_hr.ts index 7f7838c236..f3c26faef6 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_hr.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_hr.ts @@ -1908,7 +1908,7 @@ Ovo se može koristiti za obradu cijelog područja obrade kako bi se osigurala u The amount by which the tool is laterally displaced on each cycle of the pattern, specified in percent of the tool diameter. A step over of 100% results in no overlap between two different cycles. - Količina pomaka alata u bočnom smjeru u svakom ciklusu uzorka (step over), specificirana u procentima promjera alata. + Količina pomaka alata u bočnom smjeru u svakom ciklusu uzorka (step over), specificirana u procentima promjera alata. Preklapanje od 100% rezultira bez preklapanja između dva različita ciklusa. @@ -1949,7 +1949,7 @@ Preklapanje od 100% rezultira bez preklapanja između dva različita ciklusa.Expression set as the StartDepth of a newly created operation. Default: OpStartDepth - Izraz postavljen kao Početna dubina novo kreirane operacije. + Izraz postavljen kao Početna dubina novo kreirane operacije. Zadano: OpStartDepth. @@ -1958,7 +1958,7 @@ Zadano: OpStartDepth. Expression set as the FinalDepth for a newly created operation. Default: OpFinalDepth - Izraz postavljen kao Završna dubina novo kreirane operacije. + Izraz postavljen kao Završna dubina novo kreirane operacije. Zadano: OpFinalDepth @@ -1967,7 +1967,7 @@ Zadano: OpFinalDepth Expression set as the StepDown of a newly created operation. Default: OpToolDiameter - Izraz postavljen kao Korak upuštanja novo kreirane operacije. + Izraz postavljen kao Korak upuštanja novo kreirane operacije. Zadano: OpToolDiameter @@ -2295,7 +2295,7 @@ Ako je zadana visina 0, priprema će koristiti polovicu visine dijela. Ako je vi Default height of holding tags. If the specified height is 0 the dressup will use half the height of the part. Should the height be bigger than the height of the part the dressup will reduce the height to the height of the part. - Zadana visina mostića držača. + Zadana visina mostića držača. Ako je zadana visina 0, priprema će koristiti polovicu visine dijela. Ako je visina veća od visine dijela, priprema će smanjiti visinu na visinu dijela. @@ -2452,7 +2452,7 @@ If the radius is bigger than that which the tag shape itself supports, the resul Path to look for templates, post processors, tool tables and other external files. If left empty the macro directory is used. - Putanja za traženje predložaka, post-procesora, tablica alata i drugih vanjskih datoteka. + Putanja za traženje predložaka, post-procesora, tablica alata i drugih vanjskih datoteka. Ako je prazno koristi se mapa makroa. @@ -2463,9 +2463,9 @@ Ako je prazno koristi se mapa makroa. This can be helpful when almost all jobs will be processed by the same machine with a similar setup. If left empty no template will be preselected. - Zadani predložak koji će se odabrati prilikom stvaranja novog posla. + Zadani predložak koji će se odabrati prilikom stvaranja novog posla. -To može biti korisno kada su gotovo svi poslovi obrađeni istim strojem sa sličnim postavkama. +To može biti korisno kada su gotovo svi poslovi obrađeni istim strojem sa sličnim postavkama. Ako se ostavi prazno, nijedan predložak neće biti unaprijed odabran. @@ -2638,8 +2638,8 @@ See the file save policy below on how to deal with name conflicts. References to Tool Bits and their shapes can either be stored with an absolute path or with a relative path to the search path. Generally it is recommended to use relative paths due to their flexibility and robustness to layout changes. Should multiple tools or tool shapes with the same name exist in different directories it can be required to use absolute paths. - Reference na alatne nastavake i njihove oblike mogu se pohraniti s apsolutnom putanjom ili relativnom putanjom do putanje pretraživanja. -Općenito se preporučuje korištenje relativnih putanja zbog njihove fleksibilnosti i otpornosti na promjene rasporeda. + Reference na alatne nastavake i njihove oblike mogu se pohraniti s apsolutnom putanjom ili relativnom putanjom do putanje pretraživanja. +Općenito se preporučuje korištenje relativnih putanja zbog njihove fleksibilnosti i otpornosti na promjene rasporeda. Ako u različitim direktorijima postoje više alata ili oblika alata s istim imenom, možda će biti potrebno koristiti apsolutne putanje. @@ -3950,7 +3950,7 @@ If <span style=" font-style:italic;">order by</span> is se Expression set as the StartDepth of a newly created operation. Default: OpStartDepth - Izraz postavljen kao Početna dubina novo kreirane operacije. + Izraz postavljen kao Početna dubina novo kreirane operacije. Zadano: OpStartDepth. @@ -3959,7 +3959,7 @@ Zadano: OpStartDepth. Expression set as the FinalDepth for a newly created operation. Default: OpFinalDepth - Izraz postavljen kao Završna dubina novo kreirane operacije. + Izraz postavljen kao Završna dubina novo kreirane operacije. Zadano: OpFinalDepth @@ -3973,7 +3973,7 @@ Zadano: OpFinalDepth Expression set as the StepDown of a newly created operation. Default: OpToolDiameter - Izraz postavljen kao Korak upuštanja novo kreirane operacije. + Izraz postavljen kao Korak upuštanja novo kreirane operacije. Zadano: OpToolDiameter @@ -4941,7 +4941,7 @@ Visina potpornih mostića. Lower limit of the turning diameter - Donja granica okretnog promjera + Donja granica okretnog promjera @@ -5433,7 +5433,7 @@ Visina potpornih mostića. Reverse the cut order of the stepover paths. For circular cut patterns, begin at the outside and work toward the center. - Obrnite redoslijed glodanja preklapajućih staza. Za kružne uzorke glodanja, + Obrnite redoslijed glodanja preklapajućih staza. Za kružne uzorke glodanja, započnite s vanjske strane i radite prema sredini. @@ -5582,9 +5582,9 @@ započnite s vanjske strane i radite prema sredini. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Gornja granica za uklanjanje kolinearnih segmenata (u stupnjevima). + Gornja granica za uklanjanje kolinearnih segmenata (u stupnjevima). zadana vrijednost = 10,0. @@ -6979,23 +6979,23 @@ Prekidam OP-stvaranje. - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7065,7 +7065,7 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. <b>Napomena<b>: Ovaj dijalog prikazuje Naredbe staze u osnovnim jedinicama FreeCAD-a (mm/s). Vrijednosti će se pretvoriti u željenu jedinicu tijekom naknadne obrade. @@ -7382,9 +7382,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8532,10 +8532,10 @@ Razmotrite specificiranje Materijala obrade Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Radni direktorij alatnih nastavaka {} treba poddirektorije: - {} + {} Stvori ih? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_hu.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_hu.ts index 93b84e0e87..b5a659839a 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_hu.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_hu.ts @@ -258,7 +258,7 @@ Vegye figyelembe, hogy ez a lehetőség ki van kapcsolva, ha a munkában egy meg Enable all operations for which the configuration values should be exported. Note that only operations which currently have configuration values set are listed. - Engedélyezze az összes olyan műveletet, amelyre a konfigurációs értékeket exportálni kell. + Engedélyezze az összes olyan műveletet, amelyre a konfigurációs értékeket exportálni kell. Ne feledje, hogy csak olyan műveletek vannak felsorolva, amelyek jelenleg konfigurációs értékekkel rendelkeznek. @@ -738,9 +738,9 @@ Az alap tárgy határoló keretéből származó készletek esetében ez az öss You can add feature for processing by selecting them and then pressing Add. If a feature is accidentally added to the list it can be removed through Remove and will no longer be processed. Reset deletes all current items from the list and fills the list with all circular holes eligible for the operation from the model. You can again refine the list afterwards by enabling/disabling, removing and adding features. - A furat jellemzőinek és a kapcsolódó furat meghatározott sugarának meghatározása. + A furat jellemzőinek és a kapcsolódó furat meghatározott sugarának meghatározása. -A feldolgozáshoz használható funkciót úgy adhat hozzá, hogy kiválasztja őket, majd megnyomja a Hozzáadás gombot. Ha egy funkció véletlenül hozzáadódik a listához, az eltávolítható az Eltávolítás segítségével, és a továbbiakban nem lesz feldolgozva. +A feldolgozáshoz használható funkciót úgy adhat hozzá, hogy kiválasztja őket, majd megnyomja a Hozzáadás gombot. Ha egy funkció véletlenül hozzáadódik a listához, az eltávolítható az Eltávolítás segítségével, és a továbbiakban nem lesz feldolgozva. A Visszaállítás törli az összes aktuális elemet a listából, és kitölti a listát a modellből a műveletre jogosult összes kör alakú furattal. Ezt követően ismét finomíthatja a listát a funkciók engedélyezésével/letiltásával, eltávolításával és hozzáadásával. @@ -5551,9 +5551,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Vágási érték a colinear szakaszok eltávolításához (fokban). + Vágási érték a colinear szakaszok eltávolításához (fokban). alapértelmezett=10.0. @@ -6939,22 +6939,22 @@ Az op-létrehozás megszakítása - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - Az aktuálisan kiválasztott egységséma: + Az aktuálisan kiválasztott egységséma: '{}' ehhez a dokumentumhoz - Nem használja a ' perc ' értékeket a sebességértékekhez. -A CNC-gépek megkövetelik, hogy az előtolási sebesség a következő mértékegységben legyen megadva -egység/perc. A helyes G-kód biztosítása érdekében: + Nem használja a ' perc ' értékeket a sebességértékekhez. +A CNC-gépek megkövetelik, hogy az előtolási sebesség a következő mértékegységben legyen megadva +egység/perc. A helyes G-kód biztosítása érdekében: Válasszon perc alapú sémát a beállításokban. Például: Például: 'Metrikus, kis alkatrészek és CNC' @@ -7024,9 +7024,9 @@ Például: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Megjegyzés</b>: Ez a párbeszédablak a FreeCAD alapegységekben (mm/s) jeleníti meg az elérési út parancsokat. + <b>Megjegyzés</b>: Ez a párbeszédablak a FreeCAD alapegységekben (mm/s) jeleníti meg az elérési út parancsokat. Az értékek az utófeldolgozás során a kívánt egységre konvertálódnak. @@ -7342,9 +7342,9 @@ Például: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - A {} számú eszköz egy örökölt eszköz. Az örökölt eszközök + A {} számú eszköz egy örökölt eszköz. Az örökölt eszközök Path-Sanity által nem támogatottak @@ -8484,10 +8484,10 @@ Például: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? A szerszámbetét munkakönyvtárnak {} a következő könyvtárakra van szüksége: - {} + {} Hozza létre őket? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_id.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_id.ts index 613e5976bc..153367ecf9 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_id.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_id.ts @@ -5512,9 +5512,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6910,23 +6910,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7009,9 +7009,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7328,9 +7328,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8417,10 +8417,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_it.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_it.ts index ab7d944279..2e8a0fbac0 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_it.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_it.ts @@ -5559,9 +5559,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? La cartella di lavoro Utensile {} ha bisogno di queste sottocartelle: - {} + {} Crearle? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_ja.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_ja.ts index fb36f8f8a0..0e35153640 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_ja.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_ja.ts @@ -5559,9 +5559,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,12 +6947,12 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7031,9 +7031,9 @@ CNC工作機械に指令を送るGコードでは、送り速度を1分間当た CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7349,9 +7349,9 @@ CNC工作機械に指令を送るGコードでは、送り速度を1分間当た - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8491,10 +8491,10 @@ CNC工作機械に指令を送るGコードでは、送り速度を1分間当た Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_ka.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_ka.ts index 1012736eda..4cc09fee74 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_ka.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_ka.ts @@ -5557,9 +5557,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - ამოჭერით კოლინეარული სეგმენტების წასაშლელად (გრადუსები). + ამოჭერით კოლინეარული სეგმენტების წასაშლელად (გრადუსები). ნაგულისხმევია=10.0. @@ -6943,23 +6943,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7029,9 +7029,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>შენიშვნა</b>: ეს ფანჯარა ტრაექტორიის ბრძანებებს FreeCAD-ის საბაზისო ერთეულებში (მმ/წმ) გაჩვენებთ. + <b>შენიშვნა</b>: ეს ფანჯარა ტრაექტორიის ბრძანებებს FreeCAD-ის საბაზისო ერთეულებში (მმ/წმ) გაჩვენებთ. მნიშვნელობები სასურველ ერთეულებში გადაყვანილი პოსტპროცესინგისას იქნება. @@ -7347,9 +7347,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8489,10 +8489,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_ko.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_ko.ts index 1c9f7e2926..3487cc2504 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_ko.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_ko.ts @@ -188,7 +188,7 @@ Enable to include values of the SetupSheet in the template. Any values of the SetupSheet that are changed from their default are preselected. If this field not selected the current SetupSheet was not modified. - 기본형의 '설정값시트'에 있는 값을 포함 할 수 있게 합니다. + 기본형의 '설정값시트'에 있는 값을 포함 할 수 있게 합니다. 설정값시트에 있는 모든 값은 기본값으로 부터 변경하려면 그 항목이 미리 선택되어져 있어야 합니다. 이 칸을 사용하여 선택 되어 있지 않으면 현재의 설정값시트에 있는 값은 재설정 되지 않습니다. @@ -259,7 +259,7 @@ Note that this option is disabled if a stock object from an existing solid is us Enable all operations for which the configuration values should be exported. Note that only operations which currently have configuration values set are listed. - 설정값을 옮겨 나갈 수 있게 모든 작업명이 가능하게 하세요. + 설정값을 옮겨 나갈 수 있게 모든 작업명이 가능하게 하세요. 주의할 것은 현재 설정값 세트를 갖고 있는 작업명만 목록에 수록되어 있다는 겁니다. @@ -5557,9 +5557,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6945,23 +6945,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7031,9 +7031,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7349,9 +7349,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8491,10 +8491,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_lt.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_lt.ts index b9c50842da..89cfc2999f 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_lt.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_lt.ts @@ -5559,9 +5559,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_nl.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_nl.ts index 6875f9e52b..e8e506ec9d 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_nl.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_nl.ts @@ -5559,9 +5559,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_pl.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_pl.ts index a6bf3cd960..da7c8b2ad5 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_pl.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_pl.ts @@ -117,7 +117,7 @@ Select a template to be used for the job. In case there are no templates you can create one through the popup menu of an existing job. Name the file job_*.json and place it in the macro or the path directory (see preferences) in order to be selectable from this list. Wybierz szablon, który będzie używany dla zadania. W przypadku braku szablonów -można je utworzyć za pomocą menu podręcznego istniejącego zadania. +można je utworzyć za pomocą menu podręcznego istniejącego zadania. Nazwij plik job_*.json i umieść go w katalogu "makro" lub "path" (patrz preferencje), aby można go było wybrać z tej listy. @@ -264,7 +264,7 @@ Należy pamiętać, że opcja ta jest wyłączona, jeśli w zadaniu używany jes Enable all operations for which the configuration values should be exported. Note that only operations which currently have configuration values set are listed. - Włącz wszystkie operacje, dla których wartości konfiguracyjne powinny być wyeksportowane. + Włącz wszystkie operacje, dla których wartości konfiguracyjne powinny być wyeksportowane. Należy pamiętać, że na liście znajdują się tylko operacje, dla których aktualnie ustawiono wartości konfiguracyjne. @@ -653,7 +653,7 @@ W przypadku zapasów z obwiedni obiektu podstawowego oznacza to dodatkowy materi If checked the path is constrained by the solid. Otherwise the volume of the solid describes a 'keep out' zone - Jeśli opcja ta jest zaznaczona, ścieżka jest ograniczona przez bryłę. + Jeśli opcja ta jest zaznaczona, ścieżka jest ograniczona przez bryłę. W przeciwnym razie objętość bryły opisuje strefę "trzymaj się z daleka". @@ -1392,7 +1392,7 @@ Ta druga opcja może być użyta do planowania całego obszaru półfabrykatu, a The cutting mode assumes that the cut on one side of the tool bit represents the resulting part and the other side is either already milled away or will be removed later on. Climb mode is when the tool bit is moved into the cut on each rotation, whereas in conventional mode the tool bit's rotation and the tool's lateral movement are in the same direction - Tryb obróbki zakłada, że skrawanie po jednej stronie końcówki narzędzia reprezentuje powstałą część, a druga strona jest już obrobiona lub zostanie wykończona później. + Tryb obróbki zakłada, że skrawanie po jednej stronie końcówki narzędzia reprezentuje powstałą część, a druga strona jest już obrobiona lub zostanie wykończona później. Tryb podejścia oznacza, że końcówka narzędzia jest przesuwana podczas obróbki przy każdym obrocie, podczas gdy w trybie konwencjonalnym obrót końcówki narzędzia i ruch boczny narzędzia następują w tym samym kierunku. @@ -1586,11 +1586,11 @@ Tryb podejścia oznacza, że końcówka narzędzia jest przesuwana podczas obró Check if you want this profile operation to also be applied to cylindrical holes, which normally get drilled. This can be useful if no drill of adequate size is available or the number of holes don't warrant a tool change. Note that the cut side and direction is reversed in respect to the specified values - Sprawdź, czy chcesz, aby ta operacja profilowania była również stosowana -do otworów cylindrycznych, które zwykle są wiercone. -Może to być przydatne, jeśli nie jest dostępne wiertło o odpowiednim rozmiarze -lub liczba otworów nie uzasadnia zmiany narzędzia. -Należy pamiętać, że strona i kierunek skrawania + Sprawdź, czy chcesz, aby ta operacja profilowania była również stosowana +do otworów cylindrycznych, które zwykle są wiercone. +Może to być przydatne, jeśli nie jest dostępne wiertło o odpowiednim rozmiarze +lub liczba otworów nie uzasadnia zmiany narzędzia. +Należy pamiętać, że strona i kierunek skrawania są odwrócone w stosunku do określonych wartości. @@ -1811,7 +1811,7 @@ są odwrócone w stosunku do określonych wartości. Planar: Flat, 3D surface scan. Rotational: 4th-axis rotational scan. - Planarny: Skanowanie płaskie, powierzchniowe 3D. + Planarny: Skanowanie płaskie, powierzchniowe 3D. Obrotowy: Skanowanie obrotowe w 4 osiach. @@ -2142,13 +2142,13 @@ Domyślna wartość = 10 Endmill offset for the finishing pass run. Use small value like -0.2 mm to help clean "fuzzy skin" or other artefacts. - Przesunięcie frezowania końcowego dla przejścia końcowego. + Przesunięcie frezowania końcowego dla przejścia końcowego. Użyj małej wartości, takiej jak -0,2 mm, aby wyczyścić "rozmytą powierzchnię" lub inne niedoskonałości. After carving travel again the path to remove artifacts and imperfections - Po wycięciu ponownie przejdź ścieżkę, + Po wycięciu ponownie przejdź ścieżkę, aby usunąć wszelkie defekty i niedoskonałości. @@ -2159,7 +2159,7 @@ aby usunąć wszelkie defekty i niedoskonałości. Optimize path to avoid raising endmill when moving to adjacent edges. May result in sub-millimeter inaccuracies. - Zoptymalizuj ścieżkę, aby uniknąć unoszenia frezu podczas przechodzenia do sąsiednich krawędzi. + Zoptymalizuj ścieżkę, aby uniknąć unoszenia frezu podczas przechodzenia do sąsiednich krawędzi. Może to spowodować niedokładności poniżej milimetra. @@ -2319,7 +2319,7 @@ Jeśli podana wysokość jest równa 0, to operacja wykańczająca użyje połow If the radius is bigger than that which the tag shape itself supports, the resulting shape will be that of a dome. Promień zaokrąglenia na górnej krawędzi pola mocującego. -Jeśli promień jest większy niż ten, który utrzymuje sam kształt podpory, +Jeśli promień jest większy niż ten, który utrzymuje sam kształt podpory, wynikowy kształt będzie kopułą. @@ -2534,8 +2534,8 @@ Zobacz zasady zapisywania plików poniżej, aby dowiedzieć się, jak radzić so Choose how to deal with potential file name conflicts. Always open a dialog, only open a dialog if the output file already exists, overwrite any existing file or add a unique (3 digit) sequential ID to the file name. Wybierz sposób postępowania z potencjalnymi konfliktami nazw plików: -- zawsze otwieraj okno dialogowe, -- otwieraj okno dialogowe tylko wtedy, gdy plik wyjściowy już istnieje, +- zawsze otwieraj okno dialogowe, +- otwieraj okno dialogowe tylko wtedy, gdy plik wyjściowy już istnieje, - nadpisz istniejący plik lub dodaj unikalny (3 cyfry) identyfikator sekwencyjny do nazwy pliku. @@ -2546,8 +2546,8 @@ Zobacz zasady zapisywania plików poniżej, aby dowiedzieć się, jak radzić so It doesn't seem there are any post processor scripts installed. Please add some into your macro directory and make sure the file name ends with &quot;_post.py&quot;. - Wygląda na to, że nie ma zainstalowanych żadnych skryptów postprocesora. -Proszę dodać kilka do katalogu z makrodefinicjami i upewnić się, + Wygląda na to, że nie ma zainstalowanych żadnych skryptów postprocesora. +Proszę dodać kilka do katalogu z makrodefinicjami i upewnić się, że nazwa pliku kończy się na "_post.py". @@ -2558,7 +2558,7 @@ Proszę dodać kilka do katalogu z makrodefinicjami i upewnić się, Optional arguments passed to the default Post Processor specified above. See the Post Processor's documentation for supported arguments. - Opcjonalne argumenty przekazywane do domyślnego postprocesora określonego powyżej. + Opcjonalne argumenty przekazywane do domyślnego postprocesora określonego powyżej. Zapoznaj się z dokumentacją postprocesora, aby zobaczyć obsługiwane argumenty. @@ -2850,8 +2850,8 @@ Should multiple tools or tool shapes with the same name exist in different direc If OpenCAMLib is installed with Python bindings it can be used by some additional 3D operations. NOTE: Enabling OpenCAMLib here requires a restart of FreeCAD to take effect. - Jeśli OpenCAMLib jest zainstalowany z zależnościami Python, -może być używany przez niektóre dodatkowe operacje 3D. + Jeśli OpenCAMLib jest zainstalowany z zależnościami Python, +może być używany przez niektóre dodatkowe operacje 3D. UWAGA: Włączenie OpenCAMLib w tym miejscu wymaga ponownego uruchomienia FreeCAD. @@ -3053,7 +3053,7 @@ UWAGA: Włączenie OpenCAMLib w tym miejscu wymaga ponownego uruchomienia FreeCA <html><head/><body><p>List of bone locations (with all bones at that location) that are part of this dressup. The list is determined by the corners in the profile and the selected <span style=" font-weight:600;">Side</span> for the bones. </p><p>You can <span style=" font-weight:600;">un-check</span> the bones you don't want to be dressed up.</p><p>If a bone is <span style=" font-weight:600;">grayed out</span> it means that it is already dressed up by a previous dressup. Or put another way, if you dress up this dogbone dressup again you will only be able to select the bones that are un-checked here.</p><p>If this list is empty it probably means you're trying to create bones on the wrong side of the profile.</p></body></html> - <html><head/><body><p>Lista lokalizacji zacięć (wraz z wszystkimi zacięciami w tej lokalizacji), które są częścią tego wykończenia. + <html><head/><body><p>Lista lokalizacji zacięć (wraz z wszystkimi zacięciami w tej lokalizacji), które są częścią tego wykończenia. Lista ta jest określana na podstawie narożników w profilu i wybranej<span style=" font-weight:600;">Strony</span> dla zacięć. </p><p>Możesz <span style=" font-weight:600;">odznaczyć</span> zacięcia, których nie chcesz wykańczać.</p><p>Jeśli zacięcie jest <span style=" font-weight:600;">wyszarzone</span> to znaczy, że zostało już wykończone. Innymi słowy, jeśli wykończysz to zacięcie ponownie, będziesz mógł wybrać tylko zacięcia, które są tu odznaczone.</p><p>Jeśli ta lista jest pusta, prawdopodobnie próbujesz utworzyć zacięcia po złej stronie profilu.</p></body></html> @@ -3124,8 +3124,8 @@ Lista ta jest określana na podstawie narożników w profilu i wybranej<span Height of holding tag. Note that resulting tag might be smaller if the tag's width and angle result in a triangular shape. - Wysokość pola mocującego. -Zauważ, że powstałe znaczniki mogą być mniejsze, + Wysokość pola mocującego. +Zauważ, że powstałe znaczniki mogą być mniejsze, jeśli szerokość i kąt znacznika skutkują trójkątnym kształtem. @@ -3141,8 +3141,8 @@ jeśli szerokość i kąt znacznika skutkują trójkątnym kształtem. List of current tags. Edit coordinates by double click or Edit button. Tags are automatically disabled if they overlap with the previous tag, or don't lie on the base wire. - Lista bieżących znaczników. - Współrzędne można edytować za pomocą dwukrotnego kliknięcia lub przycisku Edytuj. + Lista bieżących znaczników. + Współrzędne można edytować za pomocą dwukrotnego kliknięcia lub przycisku Edytuj. Znaczniki są automatycznie wyłączane, jeśli nakładają się na poprzedni znacznik lub nie leżą na linii bazowej. @@ -3943,9 +3943,9 @@ Domyślnie: 5mm If multiple coordinate systems are in use, setting this to TRUE will cause the gcode to be written to multiple output files as controlled by the 'order by' property. For example, if ordering by Fixture, the first output file will be for the first fixture and separate file for the second. - Jeśli używane są różne układy współrzędnych, wybranie tej opcji spowoduje, -że G-code zostanie zapisany do wielu plików wyjściowych, zgodnie z właściwością "Sortuj według". -Na przykład, jeśli chcesz wykonać uporządkowanie według oprzyrządowania, + Jeśli używane są różne układy współrzędnych, wybranie tej opcji spowoduje, +że G-code zostanie zapisany do wielu plików wyjściowych, zgodnie z właściwością "Sortuj według". +Na przykład, jeśli chcesz wykonać uporządkowanie według oprzyrządowania, pierwszy plik wyjściowy będzie dla pierwszego oprzyrządowania i kolejny dla drugiego. @@ -5089,7 +5089,7 @@ Domyślnie: 3 mm The direction of the circular cuts, ClockWise (Climb), or CounterClockWise (Conventional) - Kierunek wykonywania obróbki okrężnej, zgodnie z ruchem wskazówek zegara (podejście) + Kierunek wykonywania obróbki okrężnej, zgodnie z ruchem wskazówek zegara (podejście) lub przeciwnie do ruchu wskazówek zegara (konwencjonalnie) @@ -5376,7 +5376,7 @@ lub przeciwnie do ruchu wskazówek zegara (konwencjonalnie) Planar: Flat, 3D surface scan. Rotational: 4th-axis rotational scan. - Planarny: Skanowanie płaskie, powierzchniowe 3D. + Planarny: Skanowanie płaskie, powierzchniowe 3D. Obrotowy: Skanowanie obrotowe w 4 osiach. @@ -5532,13 +5532,13 @@ Climb (zgodnie z ruchem wskazówek zegara) lub Conventional (odwrotnie do ruchu Set thread's pitch - used for metric threads - Ustaw skok gwintu, + Ustaw skok gwintu, używane dla gwintów metrycznych. Set thread's TPI (turns per inch) - used for imperial threads - Ustaw skok gwintu (TPI, liczba zwojów na cal), + Ustaw skok gwintu (TPI, liczba zwojów na cal), używane dla gwintów calowych. @@ -5588,9 +5588,9 @@ używane dla gwintów calowych. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Wartość graniczna dla usuwania odcinków współliniowych (w stopniach). + Wartość graniczna dla usuwania odcinków współliniowych (w stopniach). domyślnie = 10,0. @@ -5796,8 +5796,8 @@ OL Dropcutter* lub Eksperymentalny (nieoparty na OCL). Stock Material property is deprecated. Removing the Material property. Please use native material system to assign a ShapeMaterial - Właściwość Materiał półfabrykatu jest przestarzała. -Usunięcie właściwości Materiał. + Właściwość Materiał półfabrykatu jest przestarzała. +Usunięcie właściwości Materiał. Użyj wbudowanego systemu materiałów, aby przypisać właściwość MateriałKształtu. @@ -6979,23 +6979,23 @@ Przerwanie procesu tworzenia - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - Aktualnie wybrany układ jednostek: + Aktualnie wybrany układ jednostek: "{}" dla tego dokumentu - Nie używa "minut" dla wartości prędkości. - -Maszyny CNC wymagają, aby prędkość posuwu była wyrażona w -jednostkach / minutę. Aby zapewnić prawidłowe generowanieStandardowe USA G-code: + Nie używa "minut" dla wartości prędkości. + +Maszyny CNC wymagają, aby prędkość posuwu była wyrażona w +jednostkach / minutę. Aby zapewnić prawidłowe generowanieStandardowe USA G-code: Wybierz w preferencjach schemat oparty na minutach. Na przykład: "Metryczny dla mniejszych części i CNC (mm, mm/min)" @@ -7065,9 +7065,9 @@ Na przykład: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Uwaga</b>: To okno pokazuje polecenia środowiska CAM w podstawowych jednostkach dla FreeCAD (mm/s). + <b>Uwaga</b>: To okno pokazuje polecenia środowiska CAM w podstawowych jednostkach dla FreeCAD (mm/s). Wartości zostaną przekonwertowane na żądaną jednostkę podczas przetwarzania końcowego. @@ -7383,7 +7383,7 @@ Na przykład: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity Narzędzie numer {} jest narzędziem starszego typu. Starsze narzędzia nie są obsługiwane przez funkcję Bezpieczeństwo CAM @@ -7634,7 +7634,7 @@ Starsze narzędzia nie są obsługiwane przez funkcję Bezpieczeństwo CAM Adaptive operation couldn't determine the boundary wire. Did you select base geometry? - Operacja adaptacyjna nie mogła określić linii granicznej. + Operacja adaptacyjna nie mogła określić linii granicznej. Czy geometria bazowa została wybrana? @@ -7897,13 +7897,13 @@ Czy geometria bazowa została wybrana? Custom points are identical. No slot path will be generated - Punkty niestandardowe są identyczne. + Punkty niestandardowe są identyczne. Żadna ścieżka wpustu nie zostanie wygenerowana. Custom points not at same Z height. No slot path will be generated - Niestandardowe punkty nie na tej samej wysokości Z. + Niestandardowe punkty nie na tej samej wysokości Z. Żadna ścieżka wpustu nie zostanie wygenerowana @@ -8529,10 +8529,10 @@ Czy geometria bazowa została wybrana? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Katalog roboczy narzędzia {} potrzebuje tych katalogów: - {} + {} Utwórz je? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_pt-BR.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_pt-BR.ts index 2fdc45982c..39e901affb 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_pt-BR.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_pt-BR.ts @@ -5551,9 +5551,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6939,23 +6939,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7025,9 +7025,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7343,9 +7343,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8485,10 +8485,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_pt-PT.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_pt-PT.ts index ddc6c5a3ec..b67f35e2ea 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_pt-PT.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_pt-PT.ts @@ -5559,9 +5559,9 @@ Padrão: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_ro.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_ro.ts index 0d15c6c4f3..ed6b74163e 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_ro.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_ro.ts @@ -5562,9 +5562,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6950,23 +6950,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7036,9 +7036,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7354,9 +7354,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8496,10 +8496,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_ru.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_ru.ts index 9c9d24f475..a54ed48bf2 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_ru.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_ru.ts @@ -5557,7 +5557,7 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. Отсечка для удаления коллинеарных сегментов (градусы). по умолчанию = 10.0. @@ -6945,23 +6945,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7031,7 +7031,7 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. <b>Примечание</b>: В этом диалоговом окне команды пути отображаются в базовых единицах FreeCAD (мм/с). Значения будут преобразованы в нужные единицы во время постобработки. @@ -7349,7 +7349,7 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity Инструмент номер {} является устаревшим инструментом. Устаревшие инструменты не при поддержке Path-Sanity @@ -8491,10 +8491,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Рабочий каталог тулбета {} нуждается в этих папках: - {} + {} Создать их? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_sl.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_sl.ts index 5de9110535..a9a6106e1c 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_sl.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_sl.ts @@ -5559,9 +5559,9 @@ Privzeto: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_sr-CS.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_sr-CS.ts index bd0a2ae250..920c7b5a5d 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_sr-CS.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_sr-CS.ts @@ -5559,9 +5559,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_sr.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_sr.ts index 0db9f1a1a1..b0c6e7930b 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_sr.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_sr.ts @@ -5559,9 +5559,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_sv-SE.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_sv-SE.ts index 1424ea11c0..e68a4bb5fa 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_sv-SE.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_sv-SE.ts @@ -5559,9 +5559,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_tr.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_tr.ts index 54b6b3657d..32357daab9 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_tr.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_tr.ts @@ -5559,9 +5559,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_uk.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_uk.ts index aed22a5f0f..cf74a793ae 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_uk.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_uk.ts @@ -5560,9 +5560,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6948,23 +6948,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - Поточна вибрана схема одиниці виміру: + Поточна вибрана схема одиниці виміру: '{}' для цього документа - Не використовує 'хвилини' для значень швидкості. - -Верстати з ЧПК вимагають, щоб швидкість подачі була виражена в -одиницях/хвилину. Для забезпечення правильного G-коду: + Не використовує 'хвилини' для значень швидкості. + +Верстати з ЧПК вимагають, щоб швидкість подачі була виражена в +одиницях/хвилину. Для забезпечення правильного G-коду: Виберіть схему на основі хвилин у налаштуваннях. Наприклад: 'Метрична, Дрібні деталі та ЧПК' @@ -7034,9 +7034,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7352,9 +7352,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8494,10 +8494,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_val-ES.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_val-ES.ts index 05d510cfb2..94a951796c 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_val-ES.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_val-ES.ts @@ -5559,9 +5559,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_zh-CN.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_zh-CN.ts index 7b1b6a81bb..0053f172d9 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_zh-CN.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_zh-CN.ts @@ -5559,7 +5559,7 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. 用于删除共线线段的剪切(度)。 默认=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? 刀头工作目录 {} 需要以下几个目录: - {} + {} 现在创建? diff --git a/src/Mod/CAM/Gui/Resources/translations/CAM_zh-TW.ts b/src/Mod/CAM/Gui/Resources/translations/CAM_zh-TW.ts index 448e1fed3d..76f1c2cf0a 100644 --- a/src/Mod/CAM/Gui/Resources/translations/CAM_zh-TW.ts +++ b/src/Mod/CAM/Gui/Resources/translations/CAM_zh-TW.ts @@ -5559,9 +5559,9 @@ Default: 3 mm - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. - Cutoff for removing colinear segments (degrees). + Cutoff for removing colinear segments (degrees). default=10.0. @@ -6947,23 +6947,23 @@ Aborting op creation - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' 'US Customary' 'Imperial Decimal' - The currently selected unit schema: + The currently selected unit schema: '{}' for this document - Does not use 'minutes' for velocity values. - -CNC machines require feed rate to be expressed in -unit/minute. To ensure correct G-code: + Does not use 'minutes' for velocity values. + +CNC machines require feed rate to be expressed in +unit/minute. To ensure correct G-code: Select a minute-based schema in preferences. For example: 'Metric, Small Parts & CNC' @@ -7033,9 +7033,9 @@ For example: CAM_Inspect - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. - <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). + <b>Note</b>: This dialog shows Path Commands in FreeCAD base units (mm/s). Values will be converted to the desired unit during post processing. @@ -7351,9 +7351,9 @@ For example: - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity - Tool number {} is a legacy tool. Legacy tools not + Tool number {} is a legacy tool. Legacy tools not supported by Path-Sanity @@ -8493,10 +8493,10 @@ For example: Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? Toolbit Working directory {} needs these sudirectories: - {} + {} Create them? diff --git a/src/Mod/CAM/Gui/TaskDlgPathCompound.cpp b/src/Mod/CAM/Gui/TaskDlgPathCompound.cpp index aec3a06a08..1f86280c1c 100644 --- a/src/Mod/CAM/Gui/TaskDlgPathCompound.cpp +++ b/src/Mod/CAM/Gui/TaskDlgPathCompound.cpp @@ -23,7 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include #endif #include @@ -45,8 +45,9 @@ using namespace Gui; // TaskWidget //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TaskWidgetPathCompound::TaskWidgetPathCompound(ViewProviderPathCompound *CompoundView,QWidget *parent) - : TaskBox(Gui::BitmapFactory().pixmap("CAM_Compound"),tr("Compound paths"),true, parent) +TaskWidgetPathCompound::TaskWidgetPathCompound(ViewProviderPathCompound* CompoundView, + QWidget* parent) + : TaskBox(Gui::BitmapFactory().pixmap("CAM_Compound"), tr("Compound paths"), true, parent) { // we need a separate container widget to add all controls to proxy = new QWidget(this); @@ -56,9 +57,11 @@ TaskWidgetPathCompound::TaskWidgetPathCompound(ViewProviderPathCompound *Compoun this->groupLayout()->addWidget(proxy); - Path::FeatureCompound* pcCompound = static_cast(CompoundView->getObject()); - const std::vector &Paths = pcCompound->Group.getValues(); - for (std::vector::const_iterator it= Paths.begin();it!=Paths.end();++it) { + Path::FeatureCompound* pcCompound = + static_cast(CompoundView->getObject()); + const std::vector& Paths = pcCompound->Group.getValues(); + for (std::vector::const_iterator it = Paths.begin(); it != Paths.end(); + ++it) { QString name = QString::fromLatin1((*it)->getNameInDocument()); name += QString::fromLatin1(" ("); name += QString::fromUtf8((*it)->Label.getValue()); @@ -72,10 +75,10 @@ TaskWidgetPathCompound::~TaskWidgetPathCompound() delete ui; } -std::vector TaskWidgetPathCompound::getList() const { +std::vector TaskWidgetPathCompound::getList() const +{ std::vector names; - for(int i = 0; i < ui->PathsList->count(); i++) - { + for (int i = 0; i < ui->PathsList->count(); i++) { QListWidgetItem* item = ui->PathsList->item(i); QString name = item->text(); QStringList result; @@ -86,7 +89,7 @@ std::vector TaskWidgetPathCompound::getList() const { return names; } -void TaskWidgetPathCompound::changeEvent(QEvent *e) +void TaskWidgetPathCompound::changeEvent(QEvent* e) { TaskBox::changeEvent(e); if (e->type() == QEvent::LanguageChange) { @@ -98,25 +101,24 @@ void TaskWidgetPathCompound::changeEvent(QEvent *e) // TaskDialog //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TaskDlgPathCompound::TaskDlgPathCompound(PathGui::ViewProviderPathCompound *obj) - : TaskDialog(),CompoundView(obj) +TaskDlgPathCompound::TaskDlgPathCompound(PathGui::ViewProviderPathCompound* obj) + : TaskDialog() + , CompoundView(obj) { assert(CompoundView); - (void)CompoundView; // fix clang warning - parameter = new TaskWidgetPathCompound(CompoundView); + (void)CompoundView; // fix clang warning + parameter = new TaskWidgetPathCompound(CompoundView); Content.push_back(parameter); } TaskDlgPathCompound::~TaskDlgPathCompound() -{ -} +{} //==== calls from the TaskView =============================================================== void TaskDlgPathCompound::open() -{ -} +{} void TaskDlgPathCompound::clicked(int button) { @@ -126,12 +128,13 @@ void TaskDlgPathCompound::clicked(int button) bool TaskDlgPathCompound::accept() { std::vector paths; - Path::FeatureCompound* pcCompound = static_cast(CompoundView->getObject()); + Path::FeatureCompound* pcCompound = + static_cast(CompoundView->getObject()); App::Document* pcDoc = static_cast(pcCompound->getDocument()); std::vector names = parameter->getList(); - for(std::size_t i = 0; i < names.size(); i++) - { - App::DocumentObject* pcPath = static_cast(pcDoc->getObject(names[i].c_str())); + for (std::size_t i = 0; i < names.size(); i++) { + App::DocumentObject* pcPath = + static_cast(pcDoc->getObject(names[i].c_str())); paths.push_back(pcPath); } pcCompound->Group.setValues(paths); @@ -146,8 +149,7 @@ bool TaskDlgPathCompound::reject() } void TaskDlgPathCompound::helpRequested() -{ -} +{} #include "moc_TaskDlgPathCompound.cpp" diff --git a/src/Mod/CAM/Gui/TaskDlgPathCompound.h b/src/Mod/CAM/Gui/TaskDlgPathCompound.h index 7ddb9a0679..c0148e28f2 100644 --- a/src/Mod/CAM/Gui/TaskDlgPathCompound.h +++ b/src/Mod/CAM/Gui/TaskDlgPathCompound.h @@ -32,21 +32,23 @@ class Ui_TaskDlgPathCompound; -namespace PathGui { +namespace PathGui +{ /// Widget -class TaskWidgetPathCompound : public Gui::TaskView::TaskBox +class TaskWidgetPathCompound: public Gui::TaskView::TaskBox { Q_OBJECT public: - explicit TaskWidgetPathCompound(ViewProviderPathCompound *CompoundView, QWidget *parent=nullptr); + explicit TaskWidgetPathCompound(ViewProviderPathCompound* CompoundView, + QWidget* parent = nullptr); ~TaskWidgetPathCompound() override; std::vector getList() const; protected: - void changeEvent(QEvent *e) override; + void changeEvent(QEvent* e) override; private: QWidget* proxy; @@ -54,12 +56,12 @@ private: }; /// Task Dialog -class PathGuiExport TaskDlgPathCompound : public Gui::TaskView::TaskDialog +class PathGuiExport TaskDlgPathCompound: public Gui::TaskView::TaskDialog { Q_OBJECT public: - TaskDlgPathCompound(PathGui::ViewProviderPathCompound *); + TaskDlgPathCompound(PathGui::ViewProviderPathCompound*); ~TaskDlgPathCompound() override; public: @@ -76,15 +78,16 @@ public: /// returns for Close and Help button QDialogButtonBox::StandardButtons getStandardButtons() const override - { return QDialogButtonBox::Ok|QDialogButtonBox::Cancel; } + { + return QDialogButtonBox::Ok | QDialogButtonBox::Cancel; + } protected: - PathGui::ViewProviderPathCompound *CompoundView; - TaskWidgetPathCompound *parameter; + PathGui::ViewProviderPathCompound* CompoundView; + TaskWidgetPathCompound* parameter; }; +} // namespace PathGui -} //namespace RobotGui - -#endif // PATHGUI_TASKDLGPATHCOMPOUND_H +#endif // PATHGUI_TASKDLGPATHCOMPOUND_H diff --git a/src/Mod/CAM/Gui/ViewProviderArea.cpp b/src/Mod/CAM/Gui/ViewProviderArea.cpp index b559b67a10..a13e47b9c8 100644 --- a/src/Mod/CAM/Gui/ViewProviderArea.cpp +++ b/src/Mod/CAM/Gui/ViewProviderArea.cpp @@ -38,13 +38,12 @@ ViewProviderArea::ViewProviderArea() } ViewProviderArea::~ViewProviderArea() -{ -} +{} std::vector ViewProviderArea::claimChildren() const { return std::vector( - static_cast(getObject())->Sources.getValues()); + static_cast(getObject())->Sources.getValues()); } bool ViewProviderArea::canDragObjects() const @@ -61,7 +60,8 @@ void ViewProviderArea::dragObject(App::DocumentObject* obj) { Path::FeatureArea* area = static_cast(getObject()); std::vector sources = area->Sources.getValues(); - for (std::vector::iterator it = sources.begin(); it != sources.end(); ++it) { + for (std::vector::iterator it = sources.begin(); it != sources.end(); + ++it) { if (*it == obj) { sources.erase(it); area->Sources.setValues(sources); @@ -92,22 +92,27 @@ void ViewProviderArea::updateData(const App::Property* prop) { PartGui::ViewProviderPart::updateData(prop); if (prop->isDerivedFrom()) { - std::vector pShapes = static_cast(prop)->getValues(); - for (std::vector::iterator it = pShapes.begin(); it != pShapes.end(); ++it) { - if (*it) + std::vector pShapes = + static_cast(prop)->getValues(); + for (std::vector::iterator it = pShapes.begin(); it != pShapes.end(); + ++it) { + if (*it) { Gui::Application::Instance->hideViewProvider(*it); + } } } } -bool ViewProviderArea::onDelete(const std::vector &) +bool ViewProviderArea::onDelete(const std::vector&) { // get the input shapes Path::FeatureArea* area = static_cast(getObject()); - std::vector pShapes =area->Sources.getValues(); - for (std::vector::iterator it = pShapes.begin(); it != pShapes.end(); ++it) { - if (*it) + std::vector pShapes = area->Sources.getValues(); + for (std::vector::iterator it = pShapes.begin(); it != pShapes.end(); + ++it) { + if (*it) { Gui::Application::Instance->showViewProvider(*it); + } } return true; } @@ -122,15 +127,15 @@ ViewProviderAreaView::ViewProviderAreaView() } ViewProviderAreaView::~ViewProviderAreaView() -{ -} +{} std::vector ViewProviderAreaView::claimChildren() const { std::vector ret; Path::FeatureAreaView* feature = static_cast(getObject()); - if(feature->Source.getValue()) + if (feature->Source.getValue()) { ret.push_back(feature->Source.getValue()); + } return ret; } @@ -144,7 +149,7 @@ bool ViewProviderAreaView::canDragObject(App::DocumentObject* obj) const return obj && obj->isDerivedFrom(); } -void ViewProviderAreaView::dragObject(App::DocumentObject* ) +void ViewProviderAreaView::dragObject(App::DocumentObject*) { Path::FeatureAreaView* feature = static_cast(getObject()); feature->Source.setValue(nullptr); @@ -169,12 +174,13 @@ void ViewProviderAreaView::dropObject(App::DocumentObject* obj) void ViewProviderAreaView::updateData(const App::Property* prop) { PartGui::ViewProviderPlaneParametric::updateData(prop); - if (prop->isDerivedFrom()) + if (prop->isDerivedFrom()) { Gui::Application::Instance->hideViewProvider( - static_cast(prop)->getValue()); + static_cast(prop)->getValue()); + } } -bool ViewProviderAreaView::onDelete(const std::vector &) +bool ViewProviderAreaView::onDelete(const std::vector&) { Path::FeatureAreaView* feature = static_cast(getObject()); Gui::Application::Instance->showViewProvider(feature->Source.getValue()); @@ -183,7 +189,8 @@ bool ViewProviderAreaView::onDelete(const std::vector &) // Python object ----------------------------------------------------------------------- -namespace Gui { +namespace Gui +{ /// @cond DOXERR PROPERTY_SOURCE_TEMPLATE(PathGui::ViewProviderAreaPython, PathGui::ViewProviderArea) PROPERTY_SOURCE_TEMPLATE(PathGui::ViewProviderAreaViewPython, PathGui::ViewProviderAreaView) @@ -192,5 +199,4 @@ PROPERTY_SOURCE_TEMPLATE(PathGui::ViewProviderAreaViewPython, PathGui::ViewProvi // explicit template instantiation template class PathGuiExport ViewProviderFeaturePythonT; template class PathGuiExport ViewProviderFeaturePythonT; -} - +} // namespace Gui diff --git a/src/Mod/CAM/Gui/ViewProviderArea.h b/src/Mod/CAM/Gui/ViewProviderArea.h index fd02803330..917678ceb1 100644 --- a/src/Mod/CAM/Gui/ViewProviderArea.h +++ b/src/Mod/CAM/Gui/ViewProviderArea.h @@ -30,7 +30,7 @@ namespace PathGui { -class PathGuiExport ViewProviderArea : public PartGui::ViewProviderPlaneParametric +class PathGuiExport ViewProviderArea: public PartGui::ViewProviderPlaneParametric { PROPERTY_HEADER_WITH_OVERRIDE(PathGui::ViewProviderArea); @@ -41,7 +41,7 @@ public: /// grouping handling std::vector claimChildren() const override; void updateData(const App::Property*) override; - bool onDelete(const std::vector &) override; + bool onDelete(const std::vector&) override; /// drag and drop bool canDragObjects() const override; @@ -55,7 +55,7 @@ public: using ViewProviderAreaPython = Gui::ViewProviderFeaturePythonT; -class PathGuiExport ViewProviderAreaView : public PartGui::ViewProviderPlaneParametric +class PathGuiExport ViewProviderAreaView: public PartGui::ViewProviderPlaneParametric { PROPERTY_HEADER_WITH_OVERRIDE(PathGui::ViewProviderAreaView); @@ -64,7 +64,7 @@ public: ~ViewProviderAreaView() override; std::vector claimChildren() const override; void updateData(const App::Property*) override; - bool onDelete(const std::vector &) override; + bool onDelete(const std::vector&) override; /// drag and drop bool canDragObjects() const override; @@ -77,7 +77,7 @@ public: using ViewProviderAreaViewPython = Gui::ViewProviderFeaturePythonT; -} //namespace PathGui +} // namespace PathGui -#endif // PATH_ViewProviderArea_H +#endif // PATH_ViewProviderArea_H diff --git a/src/Mod/CAM/Gui/ViewProviderPath.cpp b/src/Mod/CAM/Gui/ViewProviderPath.cpp index 096326767c..db66793bb7 100644 --- a/src/Mod/CAM/Gui/ViewProviderPath.cpp +++ b/src/Mod/CAM/Gui/ViewProviderPath.cpp @@ -23,19 +23,19 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include +#include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #endif #include @@ -58,64 +58,74 @@ using namespace PathGui; using namespace Path; using namespace PartGui; -namespace PathGui { +namespace PathGui +{ -class PathSelectionObserver: public Gui::SelectionObserver { +class PathSelectionObserver: public Gui::SelectionObserver +{ public: - static void init() { - static PathSelectionObserver *instance; - if(!instance) + static void init() + { + static PathSelectionObserver* instance; + if (!instance) { instance = new PathSelectionObserver(); + } } - void setArrow(SoSwitch *pcSwitch=nullptr) { - if(pcSwitch==pcLastArrowSwitch) + void setArrow(SoSwitch* pcSwitch = nullptr) + { + if (pcSwitch == pcLastArrowSwitch) { return; - if(pcLastArrowSwitch) { + } + if (pcLastArrowSwitch) { pcLastArrowSwitch->whichChild = -1; pcLastArrowSwitch->unref(); pcLastArrowSwitch = nullptr; } - if(pcSwitch) { + if (pcSwitch) { pcSwitch->ref(); pcSwitch->whichChild = 0; pcLastArrowSwitch = pcSwitch; } } - void onSelectionChanged(const Gui::SelectionChanges& msg) override { - if(msg.Type == Gui::SelectionChanges::RmvPreselect) { + void onSelectionChanged(const Gui::SelectionChanges& msg) override + { + if (msg.Type == Gui::SelectionChanges::RmvPreselect) { setArrow(); return; } - if(msg.Type!=Gui::SelectionChanges::SetPreselect - && msg.Type!=Gui::SelectionChanges::MovePreselect) + if (msg.Type != Gui::SelectionChanges::SetPreselect + && msg.Type != Gui::SelectionChanges::MovePreselect) { return; + } auto obj = msg.Object.getObject(); - if(!obj) + if (!obj) { return; + } Base::Matrix4D mat; - auto sobj = obj->getSubObject(msg.pSubName,nullptr,&mat); - if(!sobj) + auto sobj = obj->getSubObject(msg.pSubName, nullptr, &mat); + if (!sobj) { return; + } Base::Matrix4D linkMat; - auto linked = sobj->getLinkedObject(true,&linkMat,false); + auto linked = sobj->getLinkedObject(true, &linkMat, false); auto vp = Base::freecad_dynamic_cast( - Application::Instance->getViewProvider(linked)); - if(!vp) { + Application::Instance->getViewProvider(linked)); + if (!vp) { setArrow(); return; } - if(vp->pt0Index >= 0) { + if (vp->pt0Index >= 0) { mat *= linkMat; mat.inverse(); - Base::Vector3d pt = mat*Base::Vector3d(msg.x,msg.y,msg.z); - if(vp->pcLineCoords->point.getNum() > 0){ + Base::Vector3d pt = mat * Base::Vector3d(msg.x, msg.y, msg.z); + if (vp->pcLineCoords->point.getNum() > 0) { auto ptTo = vp->pcLineCoords->point.getValues(vp->pt0Index); - SbVec3f ptFrom(pt.x,pt.y,pt.z); - if(ptTo && ptFrom != *ptTo) { - vp->pcArrowTransform->pointAt(ptFrom,*ptTo); + SbVec3f ptFrom(pt.x, pt.y, pt.z); + if (ptTo && ptFrom != *ptTo) { + vp->pcArrowTransform->pointAt(ptFrom, *ptTo); setArrow(vp->pcArrowSwitch); return; } @@ -124,42 +134,73 @@ public: setArrow(); } - SoSwitch *pcLastArrowSwitch = nullptr; + SoSwitch* pcLastArrowSwitch = nullptr; }; -} +} // namespace PathGui ////////////////////////////////////////////////////////////////////////////// PROPERTY_SOURCE(PathGui::ViewProviderPath, Gui::ViewProviderGeometryObject) ViewProviderPath::ViewProviderPath() - :pt0Index(-1),blockPropertyChange(false),edgeStart(-1),coordStart(-1),coordEnd(-1) + : pt0Index(-1) + , blockPropertyChange(false) + , edgeStart(-1) + , coordStart(-1) + , coordEnd(-1) { - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/CAM"); - unsigned long lcol = hGrp->GetUnsigned("DefaultNormalPathColor",11141375UL); // dark green (0,170,0) - float lr,lg,lb; - lr = ((lcol >> 24) & 0xff) / 255.0; lg = ((lcol >> 16) & 0xff) / 255.0; lb = ((lcol >> 8) & 0xff) / 255.0; - unsigned long mcol = hGrp->GetUnsigned("DefaultPathMarkerColor",1442775295UL); // lime green (85,255,0) - float mr,mg,mb; - mr = ((mcol >> 24) & 0xff) / 255.0; mg = ((mcol >> 16) & 0xff) / 255.0; mb = ((mcol >> 8) & 0xff) / 255.0; - int lwidth = hGrp->GetInt("DefaultPathLineWidth",1); - ADD_PROPERTY_TYPE(NormalColor,(lr,lg,lb),"Path",App::Prop_None,"The color of the feed rate moves"); - ADD_PROPERTY_TYPE(MarkerColor,(mr,mg,mb),"Path",App::Prop_None,"The color of the markers"); - ADD_PROPERTY_TYPE(LineWidth,(lwidth),"Path",App::Prop_None,"The line width of this path"); - ADD_PROPERTY_TYPE(ShowNodes,(false),"Path",App::Prop_None,"Turns the display of nodes on/off"); + ParameterGrp::handle hGrp = + App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/CAM"); + unsigned long lcol = + hGrp->GetUnsigned("DefaultNormalPathColor", 11141375UL); // dark green (0,170,0) + float lr, lg, lb; + lr = ((lcol >> 24) & 0xff) / 255.0; + lg = ((lcol >> 16) & 0xff) / 255.0; + lb = ((lcol >> 8) & 0xff) / 255.0; + unsigned long mcol = + hGrp->GetUnsigned("DefaultPathMarkerColor", 1442775295UL); // lime green (85,255,0) + float mr, mg, mb; + mr = ((mcol >> 24) & 0xff) / 255.0; + mg = ((mcol >> 16) & 0xff) / 255.0; + mb = ((mcol >> 8) & 0xff) / 255.0; + int lwidth = hGrp->GetInt("DefaultPathLineWidth", 1); + ADD_PROPERTY_TYPE(NormalColor, + (lr, lg, lb), + "Path", + App::Prop_None, + "The color of the feed rate moves"); + ADD_PROPERTY_TYPE(MarkerColor, + (mr, mg, mb), + "Path", + App::Prop_None, + "The color of the markers"); + ADD_PROPERTY_TYPE(LineWidth, (lwidth), "Path", App::Prop_None, "The line width of this path"); + ADD_PROPERTY_TYPE(ShowNodes, + (false), + "Path", + App::Prop_None, + "Turns the display of nodes on/off"); - ShowCountConstraints.LowerBound=0; - ShowCountConstraints.UpperBound=INT_MAX; - ShowCountConstraints.StepSize=1; + ShowCountConstraints.LowerBound = 0; + ShowCountConstraints.UpperBound = INT_MAX; + ShowCountConstraints.StepSize = 1; ShowCount.setConstraints(&ShowCountConstraints); - StartIndexConstraints.LowerBound=0; - StartIndexConstraints.UpperBound=INT_MAX; - StartIndexConstraints.StepSize=1; + StartIndexConstraints.LowerBound = 0; + StartIndexConstraints.UpperBound = INT_MAX; + StartIndexConstraints.StepSize = 1; StartIndex.setConstraints(&StartIndexConstraints); - ADD_PROPERTY_TYPE(StartPosition,(Base::Vector3d()),"Show",App::Prop_None,"Tool initial position"); - ADD_PROPERTY_TYPE(StartIndex,(0),"Show",App::Prop_None,"The index of first GCode to show"); - ADD_PROPERTY_TYPE(ShowCount,(0),"Show",App::Prop_None,"Number of movement GCode to show, 0 means all"); + ADD_PROPERTY_TYPE(StartPosition, + (Base::Vector3d()), + "Show", + App::Prop_None, + "Tool initial position"); + ADD_PROPERTY_TYPE(StartIndex, (0), "Show", App::Prop_None, "The index of first GCode to show"); + ADD_PROPERTY_TYPE(ShowCount, + (0), + "Show", + App::Prop_None, + "Number of movement GCode to show, 0 means all"); pcLineCoords = new SoCoordinate3(); pcLineCoords->ref(); @@ -174,7 +215,10 @@ ViewProviderPath::ViewProviderPath() pcMarkerStyle = new SoDrawStyle(); pcMarkerStyle->ref(); pcMarkerStyle->style = SoDrawStyle::POINTS; - pcMarkerStyle->pointSize = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View")->GetInt("MarkerSize", 4); + pcMarkerStyle->pointSize = + App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/View") + ->GetInt("MarkerSize", 4); pcDrawStyle = new SoDrawStyle(); pcDrawStyle->ref(); @@ -222,9 +266,9 @@ ViewProviderPath::ViewProviderPath() DisplayMode.setStatus(App::Property::Status::Hidden, true); - static const char *SelectionStyleEnum[] = {"Shape","BoundBox","None",nullptr}; + static const char* SelectionStyleEnum[] = {"Shape", "BoundBox", "None", nullptr}; SelectionStyle.setEnums(SelectionStyleEnum); - unsigned long sstyle = hGrp->GetInt("DefaultSelectionStyle",0); + unsigned long sstyle = hGrp->GetInt("DefaultSelectionStyle", 0); SelectionStyle.setValue(sstyle); PathSelectionObserver::init(); @@ -244,7 +288,7 @@ ViewProviderPath::~ViewProviderPath() pcArrowSwitch->unref(); } -void ViewProviderPath::attach(App::DocumentObject *pcObj) +void ViewProviderPath::attach(App::DocumentObject* pcObj) { inherited::attach(pcObj); @@ -273,15 +317,17 @@ void ViewProviderPath::attach(App::DocumentObject *pcObj) addDisplayMaskMode(pcPathRoot, "Waypoints"); } -bool ViewProviderPath::useNewSelectionModel() const { - return SelectionStyle.getValue()!=2; +bool ViewProviderPath::useNewSelectionModel() const +{ + return SelectionStyle.getValue() != 2; } void ViewProviderPath::setDisplayMode(const char* ModeName) { - if ( strcmp("Waypoints",ModeName)==0 ) + if (strcmp("Waypoints", ModeName) == 0) { setDisplayMaskMode("Waypoints"); - inherited::setDisplayMode( ModeName ); + } + inherited::setDisplayMode(ModeName); } std::vector ViewProviderPath::getDisplayModes() const @@ -293,20 +339,21 @@ std::vector ViewProviderPath::getDisplayModes() const std::string ViewProviderPath::getElement(const SoDetail* detail) const { - if(edgeStart>=0 && detail && detail->getTypeId() == SoLineDetail::getClassTypeId()) { + if (edgeStart >= 0 && detail && detail->getTypeId() == SoLineDetail::getClassTypeId()) { const SoLineDetail* line_detail = static_cast(detail); - int index = line_detail->getLineIndex()+edgeStart; - if(index>=0 && index<(int)edge2Command.size()) { + int index = line_detail->getLineIndex() + edgeStart; + if (index >= 0 && index < (int)edge2Command.size()) { index = edge2Command[index]; Path::Feature* pcPathObj = static_cast(pcObject); - const Toolpath &tp = pcPathObj->Path.getValue(); - if(index<(int)tp.getSize()) { + const Toolpath& tp = pcPathObj->Path.getValue(); + if (index < (int)tp.getSize()) { std::stringstream str; - str << index+1 << " " << tp.getCommand(index).toGCode(6,false); + str << index + 1 << " " << tp.getCommand(index).toGCode(6, false); pt0Index = line_detail->getPoint0()->getCoordinateIndex(); - if(pt0Index<0 || pt0Index>=pcLineCoords->point.getNum()) + if (pt0Index < 0 || pt0Index >= pcLineCoords->point.getNum()) { pt0Index = -1; - return boost::replace_all_copy(str.str(),".",","); + } + return boost::replace_all_copy(str.str(), ".", ","); } } } @@ -319,11 +366,11 @@ SoDetail* ViewProviderPath::getDetail(const char* subelement) const { int index = std::atoi(subelement); SoDetail* detail = nullptr; - if (index>0 && index<=(int)command2Edge.size()) { - index = command2Edge[index-1]; - if(index>=0 && edgeStart>=0 && edgeStart<=index) { + if (index > 0 && index <= (int)command2Edge.size()) { + index = command2Edge[index - 1]; + if (index >= 0 && edgeStart >= 0 && edgeStart <= index) { detail = new SoLineDetail(); - static_cast(detail)->setLineIndex(index-edgeStart); + static_cast(detail)->setLineIndex(index - edgeStart); } } return detail; @@ -331,113 +378,145 @@ SoDetail* ViewProviderPath::getDetail(const char* subelement) const void ViewProviderPath::onChanged(const App::Property* prop) { - if(blockPropertyChange) + if (blockPropertyChange) { return; + } if (prop == &LineWidth) { pcDrawStyle->lineWidth = LineWidth.getValue(); - } else if (prop == &NormalColor) { - if (!colorindex.empty() && coordStart>=0 && coordStart<(int)colorindex.size()) { + } + else if (prop == &NormalColor) { + if (!colorindex.empty() && coordStart >= 0 && coordStart < (int)colorindex.size()) { const App::Color& c = NormalColor.getValue(); - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/CAM"); - unsigned long rcol = hGrp->GetUnsigned("DefaultRapidPathColor",2852126975UL); // dark red (170,0,0) - float rr,rg,rb; - rr = ((rcol >> 24) & 0xff) / 255.0; rg = ((rcol >> 16) & 0xff) / 255.0; rb = ((rcol >> 8) & 0xff) / 255.0; + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/CAM"); + unsigned long rcol = + hGrp->GetUnsigned("DefaultRapidPathColor", 2852126975UL); // dark red (170,0,0) + float rr, rg, rb; + rr = ((rcol >> 24) & 0xff) / 255.0; + rg = ((rcol >> 16) & 0xff) / 255.0; + rb = ((rcol >> 8) & 0xff) / 255.0; - unsigned long pcol = hGrp->GetUnsigned("DefaultProbePathColor",4293591295UL); // yellow (255,255,5) - float pr,pg,pb; - pr = ((pcol >> 24) & 0xff) / 255.0; pg = ((pcol >> 16) & 0xff) / 255.0; pb = ((pcol >> 8) & 0xff) / 255.0; + unsigned long pcol = + hGrp->GetUnsigned("DefaultProbePathColor", 4293591295UL); // yellow (255,255,5) + float pr, pg, pb; + pr = ((pcol >> 24) & 0xff) / 255.0; + pg = ((pcol >> 16) & 0xff) / 255.0; + pb = ((pcol >> 8) & 0xff) / 255.0; pcMatBind->value = SoMaterialBinding::PER_PART; // resizing and writing the color vector: - int count = coordEnd-coordStart; - if(count > (int)colorindex.size()-coordStart) count = colorindex.size()-coordStart; + int count = coordEnd - coordStart; + if (count > (int)colorindex.size() - coordStart) { + count = colorindex.size() - coordStart; + } pcLineColor->diffuseColor.setNum(count); SbColor* colors = pcLineColor->diffuseColor.startEditing(); - for(int i=0;idiffuseColor.finishEditing(); } - } else if (prop == &MarkerColor) { + } + else if (prop == &MarkerColor) { const App::Color& c = MarkerColor.getValue(); - pcMarkerColor->rgb.setValue(c.r,c.g,c.b); - } else if(prop == &ShowNodes) { - pcMarkerSwitch->whichChild = ShowNodes.getValue()?0:-1; - } else if (prop == &ShowCount || prop==&StartIndex) { + pcMarkerColor->rgb.setValue(c.r, c.g, c.b); + } + else if (prop == &ShowNodes) { + pcMarkerSwitch->whichChild = ShowNodes.getValue() ? 0 : -1; + } + else if (prop == &ShowCount || prop == &StartIndex) { bool vis = isShow(); - if (vis) hide(); - updateVisual(); - if (vis) show(); - } else if (prop == &StartPosition) { - if(pcLineCoords->point.getNum()){ - const Base::Vector3d &pt = StartPosition.getValue(); - pcLineCoords->point.set1Value(0,pt.x,pt.y,pt.z); - pcMarkerCoords->point.set1Value(0,pt.x,pt.y,pt.z); + if (vis) { + hide(); } - } else { + updateVisual(); + if (vis) { + show(); + } + } + else if (prop == &StartPosition) { + if (pcLineCoords->point.getNum()) { + const Base::Vector3d& pt = StartPosition.getValue(); + pcLineCoords->point.set1Value(0, pt.x, pt.y, pt.z); + pcMarkerCoords->point.set1Value(0, pt.x, pt.y, pt.z); + } + } + else { inherited::onChanged(prop); - if(prop == &SelectionStyle && SelectionStyle.getValue()==2) + if (prop == &SelectionStyle && SelectionStyle.getValue() == 2) { hideSelection(); + } } } -void ViewProviderPath::showBoundingBox(bool show) { - if(show) { - if(!pcLineCoords->point.getNum()) +void ViewProviderPath::showBoundingBox(bool show) +{ + if (show) { + if (!pcLineCoords->point.getNum()) { return; + } } inherited::showBoundingBox(show); } -unsigned long ViewProviderPath::getBoundColor() const { - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/CAM"); - if(SelectionStyle.getValue() == 0 || !Selectable.getValue()) - return hGrp->GetUnsigned("DefaultBBoxNormalColor",4294967295UL); // white (255,255,255) - else - return hGrp->GetUnsigned("DefaultBBoxSelectionColor",0xc8ffff00UL); // rgb(0,85,255) +unsigned long ViewProviderPath::getBoundColor() const +{ + ParameterGrp::handle hGrp = + App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/CAM"); + if (SelectionStyle.getValue() == 0 || !Selectable.getValue()) { + return hGrp->GetUnsigned("DefaultBBoxNormalColor", 4294967295UL); // white (255,255,255) + } + else { + return hGrp->GetUnsigned("DefaultBBoxSelectionColor", 0xc8ffff00UL); // rgb(0,85,255) + } } -void ViewProviderPath::updateShowConstraints() { +void ViewProviderPath::updateShowConstraints() +{ Path::Feature* pcPathObj = static_cast(pcObject); - const Toolpath &tp = pcPathObj->Path.getValue(); + const Toolpath& tp = pcPathObj->Path.getValue(); StartIndexConstraints.UpperBound = tp.getSize(); if (StartIndex.getValue() >= (long)tp.getSize()) { - int start = ((int)tp.getSize())-ShowCount.getValue(); - if(start>=(int)tp.getSize()) - start=tp.getSize()-1; - if(start<0) start = 0; + int start = ((int)tp.getSize()) - ShowCount.getValue(); + if (start >= (int)tp.getSize()) { + start = tp.getSize() - 1; + } + if (start < 0) { + start = 0; + } blockPropertyChange = true; StartIndex.setValue(start); blockPropertyChange = false; StartIndex.purgeTouched(); } - StartIndexConstraints.StepSize = ShowCount.getValue()>2?ShowCount.getValue()-2:1; + StartIndexConstraints.StepSize = ShowCount.getValue() > 2 ? ShowCount.getValue() - 2 : 1; } void ViewProviderPath::updateData(const App::Property* prop) { Path::Feature* pcPathObj = static_cast(pcObject); - if(prop == &pcPathObj->Path) { + if (prop == &pcPathObj->Path) { updateVisual(true); return; } inherited::updateData(prop); } -void ViewProviderPath::hideSelection() { +void ViewProviderPath::hideSelection() +{ // Clear selection SoSelectionElementAction saction(Gui::SoSelectionElementAction::None); saction.apply(pcLines); @@ -450,28 +529,26 @@ void ViewProviderPath::hideSelection() { pcArrowSwitch->whichChild = -1; } -class VisualPathSegmentVisitor -: public PathSegmentVisitor +class VisualPathSegmentVisitor: public PathSegmentVisitor { public: - VisualPathSegmentVisitor( - const Toolpath &tp, - SoCoordinate3 *pcLineCoords_, - SoCoordinate3 *pcMarkerCoords_, - std::vector &command2Edge_, - std::deque &edge2Command_, - std::deque &edgeIndices_, - std::vector &colorindex_, - std::deque &points_, - std::deque &markers_) - : pcLineCoords(pcLineCoords_) - , pcMarkerCoords(pcMarkerCoords_) - , command2Edge(command2Edge_) - , edge2Command(edge2Command_) - , edgeIndices(edgeIndices_) - , colorindex(colorindex_) - , points(points_) - , markers(markers_) + VisualPathSegmentVisitor(const Toolpath& tp, + SoCoordinate3* pcLineCoords_, + SoCoordinate3* pcMarkerCoords_, + std::vector& command2Edge_, + std::deque& edge2Command_, + std::deque& edgeIndices_, + std::vector& colorindex_, + std::deque& points_, + std::deque& markers_) + : pcLineCoords(pcLineCoords_) + , pcMarkerCoords(pcMarkerCoords_) + , command2Edge(command2Edge_) + , edge2Command(edge2Command_) + , edgeIndices(edgeIndices_) + , colorindex(colorindex_) + , points(points_) + , markers(markers_) { pcLineCoords->point.deleteValues(0); pcMarkerCoords->point.deleteValues(0); @@ -482,36 +559,50 @@ public: colorindex.clear(); - command2Edge.resize(tp.getSize(),-1); + command2Edge.resize(tp.getSize(), -1); } - void setup(const Base::Vector3d &last) override + void setup(const Base::Vector3d& last) override { points.push_back(last); markers.push_back(last); } - void g0(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts) override + void g0(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts) override { (void)last; gx(id, &next, pts, 0); } - void g1(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts) override + void g1(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts) override { (void)last; gx(id, &next, pts, 1); } - void g23(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, const Base::Vector3d ¢er) override + void g23(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts, + const Base::Vector3d& center) override { (void)last; gx(id, &next, pts, 1); markers.push_back(center); } - void g8x(int id, const Base::Vector3d &last, const Base::Vector3d &next, const std::deque &pts, - const std::deque &p, const std::deque &q) override + void g8x(int id, + const Base::Vector3d& last, + const Base::Vector3d& next, + const std::deque& pts, + const std::deque& p, + const std::deque& q) override { (void)last; @@ -529,7 +620,7 @@ public: markers.push_back(next); colorindex.push_back(1); - for (std::deque::const_iterator it=q.begin(); q.end() != it; ++it) { + for (std::deque::const_iterator it = q.begin(); q.end() != it; ++it) { markers.push_back(*it); } @@ -540,7 +631,7 @@ public: pushCommand(id); } - void g38(int id, const Base::Vector3d &last, const Base::Vector3d &next) override + void g38(int id, const Base::Vector3d& last, const Base::Vector3d& next) override { #if 0 Base::Vector3d p1(next.x,next.y,last.z); @@ -556,29 +647,30 @@ public: pushCommand(id); #else - (void)last; - const std::deque pts{}; - gx(id, &next, pts, 2); + (void)last; + const std::deque pts {}; + gx(id, &next, pts, 2); #endif } private: - SoCoordinate3 *pcLineCoords; - SoCoordinate3 *pcMarkerCoords; + SoCoordinate3* pcLineCoords; + SoCoordinate3* pcMarkerCoords; - std::vector &command2Edge; - std::deque &edge2Command; - std::deque &edgeIndices; + std::vector& command2Edge; + std::deque& edge2Command; + std::deque& edgeIndices; - std::vector &colorindex; - std::deque &points; - std::deque &markers; + std::vector& colorindex; + std::deque& points; + std::deque& markers; - virtual void gx(int id, const Base::Vector3d *next, const std::deque &pts, int color) + virtual void + gx(int id, const Base::Vector3d* next, const std::deque& pts, int color) { - for (std::deque::const_iterator it=pts.begin(); pts.end() != it; ++it) { - points.push_back(*it); - colorindex.push_back(color); + for (std::deque::const_iterator it = pts.begin(); pts.end() != it; ++it) { + points.push_back(*it); + colorindex.push_back(color); } if (next) { @@ -590,14 +682,16 @@ private: } } - void pushCommand(int id) { - command2Edge[id] = edgeIndices.size(); - edgeIndices.push_back(points.size()); - edge2Command.push_back(id); + void pushCommand(int id) + { + command2Edge[id] = edgeIndices.size(); + edgeIndices.push_back(points.size()); + edge2Command.push_back(id); } }; -void ViewProviderPath::updateVisual(bool rebuild) { +void ViewProviderPath::updateVisual(bool rebuild) +{ hideSelection(); @@ -605,22 +699,22 @@ void ViewProviderPath::updateVisual(bool rebuild) { pcLines->coordIndex.deleteValues(0); - if(rebuild) { + if (rebuild) { Path::Feature* pcPathObj = static_cast(pcObject); - const Toolpath &tp = pcPathObj->Path.getValue(); + const Toolpath& tp = pcPathObj->Path.getValue(); std::deque points; std::deque markers; VisualPathSegmentVisitor collect(tp, - pcLineCoords, - pcMarkerCoords, - command2Edge, - edge2Command, - edgeIndices, - colorindex, - points, - markers); + pcLineCoords, + pcMarkerCoords, + command2Edge, + edge2Command, + edgeIndices, + colorindex, + points, + markers); PathSegmentWalker segments(tp); segments.walk(collect, StartPosition.getValue()); @@ -629,14 +723,16 @@ void ViewProviderPath::updateVisual(bool rebuild) { if (!edgeIndices.empty()) { pcLineCoords->point.setNum(points.size()); SbVec3f* verts = pcLineCoords->point.startEditing(); - int i=0; - for(const auto &pt : points) - verts[i++].setValue(pt.x,pt.y,pt.z); + int i = 0; + for (const auto& pt : points) { + verts[i++].setValue(pt.x, pt.y, pt.z); + } pcLineCoords->point.finishEditing(); pcMarkerCoords->point.setNum(markers.size()); - for(unsigned int i=0;ipoint.set1Value(i,markers[i].x,markers[i].y,markers[i].z); + for (unsigned int i = 0; i < markers.size(); i++) { + pcMarkerCoords->point.set1Value(i, markers[i].x, markers[i].y, markers[i].z); + } recomputeBoundingBox(); } @@ -645,42 +741,48 @@ void ViewProviderPath::updateVisual(bool rebuild) { // count = index + separators edgeStart = -1; int i; - for(i=StartIndex.getValue();i<(int)command2Edge.size();++i) - if((edgeStart=command2Edge[i])>=0) break; + for (i = StartIndex.getValue(); i < (int)command2Edge.size(); ++i) { + if ((edgeStart = command2Edge[i]) >= 0) { + break; + } + } - if(edgeStart<0) + if (edgeStart < 0) { return; + } - if(i!=StartIndex.getValue() && StartIndex.getValue()!=0) { + if (i != StartIndex.getValue() && StartIndex.getValue() != 0) { blockPropertyChange = true; StartIndex.setValue(i); blockPropertyChange = false; StartIndex.purgeTouched(); } - int edgeEnd = edgeStart+ShowCount.getValue(); - if(edgeEnd==edgeStart || edgeEnd>(int)edgeIndices.size()) + int edgeEnd = edgeStart + ShowCount.getValue(); + if (edgeEnd == edgeStart || edgeEnd > (int)edgeIndices.size()) { edgeEnd = edgeIndices.size(); + } // coord index start - coordStart = edgeStart==0?0:(edgeIndices[edgeStart-1]-1); - coordEnd = edgeIndices[edgeEnd-1]; + coordStart = edgeStart == 0 ? 0 : (edgeIndices[edgeStart - 1] - 1); + coordEnd = edgeIndices[edgeEnd - 1]; // count = coord indices + index separators - int count = coordEnd-coordStart+2*(edgeEnd-edgeStart-1)+1; + int count = coordEnd - coordStart + 2 * (edgeEnd - edgeStart - 1) + 1; pcLines->coordIndex.setNum(count); - int32_t *idx = pcLines->coordIndex.startEditing(); - i=0; + int32_t* idx = pcLines->coordIndex.startEditing(); + i = 0; int start = coordStart; - for(int e=edgeStart;e!=edgeEnd;++e) { - for(int end=edgeIndices[e];startcoordIndex.finishEditing(); - assert(i==count); + assert(i == count); NormalColor.touch(); } @@ -688,7 +790,7 @@ void ViewProviderPath::updateVisual(bool rebuild) { void ViewProviderPath::recomputeBoundingBox() { // update the boundbox - double MinX,MinY,MinZ,MaxX,MaxY,MaxZ; + double MinX, MinY, MinZ, MaxX, MaxY, MaxZ; MinX = 999999999.0; MinY = 999999999.0; MinZ = 999999999.0; @@ -698,17 +800,29 @@ void ViewProviderPath::recomputeBoundingBox() Path::Feature* pcPathObj = static_cast(pcObject); Base::Placement pl = *(&pcPathObj->Placement.getValue()); Base::Vector3d pt; - for (int i=1;ipoint.getNum();i++) { + for (int i = 1; i < pcLineCoords->point.getNum(); i++) { pt.x = pcLineCoords->point[i].getValue()[0]; pt.y = pcLineCoords->point[i].getValue()[1]; pt.z = pcLineCoords->point[i].getValue()[2]; - pl.multVec(pt,pt); - if (pt.x < MinX) MinX = pt.x; - if (pt.y < MinY) MinY = pt.y; - if (pt.z < MinZ) MinZ = pt.z; - if (pt.x > MaxX) MaxX = pt.x; - if (pt.y > MaxY) MaxY = pt.y; - if (pt.z > MaxZ) MaxZ = pt.z; + pl.multVec(pt, pt); + if (pt.x < MinX) { + MinX = pt.x; + } + if (pt.y < MinY) { + MinY = pt.y; + } + if (pt.z < MinZ) { + MinZ = pt.z; + } + if (pt.x > MaxX) { + MaxX = pt.x; + } + if (pt.y > MaxY) { + MaxY = pt.y; + } + if (pt.z > MaxZ) { + MaxZ = pt.z; + } } pcBoundingBox->minBounds.setValue(MinX, MinY, MinZ); pcBoundingBox->maxBounds.setValue(MaxX, MaxY, MaxZ); @@ -721,11 +835,12 @@ QIcon ViewProviderPath::getIcon() const // Python object ----------------------------------------------------------------------- -namespace Gui { +namespace Gui +{ /// @cond DOXERR PROPERTY_SOURCE_TEMPLATE(PathGui::ViewProviderPathPython, PathGui::ViewProviderPath) /// @endcond // explicit template instantiation template class PathGuiExport ViewProviderFeaturePythonT; -} +} // namespace Gui diff --git a/src/Mod/CAM/Gui/ViewProviderPath.h b/src/Mod/CAM/Gui/ViewProviderPath.h index 49fb3d88bd..6270d8fe97 100644 --- a/src/Mod/CAM/Gui/ViewProviderPath.h +++ b/src/Mod/CAM/Gui/ViewProviderPath.h @@ -44,7 +44,7 @@ namespace PathGui class PathSelectionObserver; -class PathGuiExport ViewProviderPath : public Gui::ViewProviderGeometryObject +class PathGuiExport ViewProviderPath: public Gui::ViewProviderGeometryObject { PROPERTY_HEADER_WITH_OVERRIDE(PathGui::ViewProviderPath); using inherited = ViewProviderGeometryObject; @@ -58,17 +58,17 @@ public: // Display properties App::PropertyInteger LineWidth; - App::PropertyColor NormalColor; - App::PropertyColor MarkerColor; - App::PropertyBool ShowNodes; - App::PropertyVector StartPosition; + App::PropertyColor NormalColor; + App::PropertyColor MarkerColor; + App::PropertyBool ShowNodes; + App::PropertyVector StartPosition; App::PropertyIntegerConstraint StartIndex; - App::PropertyIntegerConstraint::Constraints StartIndexConstraints; + App::PropertyIntegerConstraint::Constraints StartIndexConstraints; App::PropertyIntegerConstraint ShowCount; - App::PropertyIntegerConstraint::Constraints ShowCountConstraints; + App::PropertyIntegerConstraint::Constraints ShowCountConstraints; - void attach(App::DocumentObject *pcObject) override; + void attach(App::DocumentObject* pcObject) override; void setDisplayMode(const char* ModeName) override; std::vector getDisplayModes() const override; void updateData(const App::Property*) override; @@ -76,7 +76,7 @@ public: QIcon getIcon() const override; bool useNewSelectionModel() const override; - std::string getElement(const SoDetail *) const override; + std::string getElement(const SoDetail*) const override; SoDetail* getDetail(const char* subelement) const override; void updateShowConstraints(); @@ -88,38 +88,36 @@ public: friend class PathSelectionObserver; protected: - void onChanged(const App::Property* prop) override; unsigned long getBoundColor() const override; - SoCoordinate3 * pcLineCoords; - SoCoordinate3 * pcMarkerCoords; - SoDrawStyle * pcDrawStyle; - SoDrawStyle * pcMarkerStyle; - PartGui::SoBrepEdgeSet * pcLines; - SoMaterial * pcLineColor; - SoBaseColor * pcMarkerColor; - SoMaterialBinding * pcMatBind; - std::vector colorindex; - SoSwitch * pcMarkerSwitch; - SoSwitch * pcArrowSwitch; - SoTransform * pcArrowTransform; + SoCoordinate3* pcLineCoords; + SoCoordinate3* pcMarkerCoords; + SoDrawStyle* pcDrawStyle; + SoDrawStyle* pcMarkerStyle; + PartGui::SoBrepEdgeSet* pcLines; + SoMaterial* pcLineColor; + SoBaseColor* pcMarkerColor; + SoMaterialBinding* pcMatBind; + std::vector colorindex; + SoSwitch* pcMarkerSwitch; + SoSwitch* pcArrowSwitch; + SoTransform* pcArrowTransform; - std::vector command2Edge; - std::deque edge2Command; - std::deque edgeIndices; + std::vector command2Edge; + std::deque edge2Command; + std::deque edgeIndices; mutable int pt0Index; bool blockPropertyChange; int edgeStart; int coordStart; int coordEnd; +}; - }; +using ViewProviderPathPython = Gui::ViewProviderFeaturePythonT; - using ViewProviderPathPython = Gui::ViewProviderFeaturePythonT; - -} //namespace PathGui +} // namespace PathGui -#endif // PATH_VIEWPROVIDERPATH_H +#endif // PATH_VIEWPROVIDERPATH_H diff --git a/src/Mod/CAM/Gui/ViewProviderPathCompound.cpp b/src/Mod/CAM/Gui/ViewProviderPathCompound.cpp index 6641dcb4b4..9fbcc17d2a 100644 --- a/src/Mod/CAM/Gui/ViewProviderPathCompound.cpp +++ b/src/Mod/CAM/Gui/ViewProviderPathCompound.cpp @@ -49,9 +49,10 @@ void ViewProviderPathCompound::unsetEdit(int ModNum) Gui::Control().closeDialog(); } -std::vector ViewProviderPathCompound::claimChildren()const +std::vector ViewProviderPathCompound::claimChildren() const { - return std::vector(static_cast(getObject())->Group.getValues()); + return std::vector( + static_cast(getObject())->Group.getValues()); } bool ViewProviderPathCompound::canDragObjects() const @@ -61,7 +62,7 @@ bool ViewProviderPathCompound::canDragObjects() const void ViewProviderPathCompound::dragObject(App::DocumentObject* obj) { - static_cast(getObject())->removeObject(obj); + static_cast(getObject())->removeObject(obj); } bool ViewProviderPathCompound::canDropObjects() const @@ -71,7 +72,7 @@ bool ViewProviderPathCompound::canDropObjects() const void ViewProviderPathCompound::dropObject(App::DocumentObject* obj) { - static_cast(getObject())->addObject(obj); + static_cast(getObject())->addObject(obj); } QIcon ViewProviderPathCompound::getIcon() const @@ -81,11 +82,12 @@ QIcon ViewProviderPathCompound::getIcon() const // Python object ----------------------------------------------------------------------- -namespace Gui { +namespace Gui +{ /// @cond DOXERR PROPERTY_SOURCE_TEMPLATE(PathGui::ViewProviderPathCompoundPython, PathGui::ViewProviderPathCompound) /// @endcond // explicit template instantiation template class PathGuiExport ViewProviderFeaturePythonT; -} +} // namespace Gui diff --git a/src/Mod/CAM/Gui/ViewProviderPathCompound.h b/src/Mod/CAM/Gui/ViewProviderPathCompound.h index c7ab64b138..9e697af753 100644 --- a/src/Mod/CAM/Gui/ViewProviderPathCompound.h +++ b/src/Mod/CAM/Gui/ViewProviderPathCompound.h @@ -34,7 +34,6 @@ class PathGuiExport ViewProviderPathCompound: public ViewProviderPath PROPERTY_HEADER_WITH_OVERRIDE(PathGui::ViewProviderPathCompound); public: - std::vector claimChildren() const override; bool canDragObjects() const override; void dragObject(App::DocumentObject*) override; @@ -45,12 +44,11 @@ public: protected: bool setEdit(int ModNum) override; void unsetEdit(int ModNum) override; - }; using ViewProviderPathCompoundPython = Gui::ViewProviderFeaturePythonT; -} //namespace PathGui +} // namespace PathGui -#endif // PATH_ViewProviderPathCompound_H +#endif // PATH_ViewProviderPathCompound_H diff --git a/src/Mod/CAM/Gui/ViewProviderPathShape.cpp b/src/Mod/CAM/Gui/ViewProviderPathShape.cpp index d4bd7f7bca..c9b0f9aa42 100644 --- a/src/Mod/CAM/Gui/ViewProviderPathShape.cpp +++ b/src/Mod/CAM/Gui/ViewProviderPathShape.cpp @@ -42,7 +42,7 @@ QIcon ViewProviderPathShape::getIcon() const std::vector ViewProviderPathShape::claimChildren() const { return std::vector( - static_cast(getObject())->Sources.getValues()); + static_cast(getObject())->Sources.getValues()); } bool ViewProviderPathShape::canDragObjects() const @@ -57,9 +57,10 @@ bool ViewProviderPathShape::canDragObject(App::DocumentObject* obj) const void ViewProviderPathShape::dragObject(App::DocumentObject* obj) { - Path::FeatureShape *feature = static_cast(getObject()); + Path::FeatureShape* feature = static_cast(getObject()); std::vector sources = feature->Sources.getValues(); - for (std::vector::iterator it = sources.begin(); it != sources.end(); ++it) { + for (std::vector::iterator it = sources.begin(); it != sources.end(); + ++it) { if (*it == obj) { sources.erase(it); feature->Sources.setValues(sources); @@ -80,7 +81,7 @@ bool ViewProviderPathShape::canDropObject(App::DocumentObject* obj) const void ViewProviderPathShape::dropObject(App::DocumentObject* obj) { - Path::FeatureShape *feature = static_cast(getObject()); + Path::FeatureShape* feature = static_cast(getObject()); std::vector sources = feature->Sources.getValues(); sources.push_back(obj); feature->Sources.setValues(sources); @@ -90,22 +91,27 @@ void ViewProviderPathShape::updateData(const App::Property* prop) { PathGui::ViewProviderPath::updateData(prop); if (prop->isDerivedFrom()) { - std::vector pShapes = static_cast(prop)->getValues(); - for (std::vector::iterator it = pShapes.begin(); it != pShapes.end(); ++it) { - if (*it) + std::vector pShapes = + static_cast(prop)->getValues(); + for (std::vector::iterator it = pShapes.begin(); it != pShapes.end(); + ++it) { + if (*it) { Gui::Application::Instance->hideViewProvider(*it); + } } } } -bool ViewProviderPathShape::onDelete(const std::vector &) +bool ViewProviderPathShape::onDelete(const std::vector&) { // get the input shapes - Path::FeatureShape *feature = static_cast(getObject()); - std::vector pShapes =feature->Sources.getValues(); - for (std::vector::iterator it = pShapes.begin(); it != pShapes.end(); ++it) { - if (*it) + Path::FeatureShape* feature = static_cast(getObject()); + std::vector pShapes = feature->Sources.getValues(); + for (std::vector::iterator it = pShapes.begin(); it != pShapes.end(); + ++it) { + if (*it) { Gui::Application::Instance->showViewProvider(*it); + } } return true; } diff --git a/src/Mod/CAM/Gui/ViewProviderPathShape.h b/src/Mod/CAM/Gui/ViewProviderPathShape.h index 4b83fa717f..899a2d0b99 100644 --- a/src/Mod/CAM/Gui/ViewProviderPathShape.h +++ b/src/Mod/CAM/Gui/ViewProviderPathShape.h @@ -34,11 +34,10 @@ class PathGuiExport ViewProviderPathShape: public ViewProviderPath PROPERTY_HEADER_WITH_OVERRIDE(PathGui::ViewProviderPathShape); public: - /// grouping handling std::vector claimChildren() const override; void updateData(const App::Property*) override; - bool onDelete(const std::vector &) override; + bool onDelete(const std::vector&) override; /// drag and drop bool canDragObjects() const override; @@ -51,7 +50,7 @@ public: QIcon getIcon() const override; }; -} //namespace PathGui +} // namespace PathGui -#endif // PATH_ViewProviderPathShape_H +#endif // PATH_ViewProviderPathShape_H diff --git a/src/Mod/CAM/Path/Base/Drillable.py b/src/Mod/CAM/Path/Base/Drillable.py index cf173a76c4..7d98d9d688 100644 --- a/src/Mod/CAM/Path/Base/Drillable.py +++ b/src/Mod/CAM/Path/Base/Drillable.py @@ -19,14 +19,11 @@ def checkForBlindHole(baseshape, selectedFace): circularFaces = [ f for f in baseshape.Faces - if len(f.OuterWire.Edges) == 1 - and type(f.OuterWire.Edges[0].Curve) == Part.Circle + if len(f.OuterWire.Edges) == 1 and type(f.OuterWire.Edges[0].Curve) == Part.Circle ] circularFaceEdges = [f.OuterWire.Edges[0] for f in circularFaces] - commonedges = [ - i for i in selectedFace.Edges for x in circularFaceEdges if i.isSame(x) - ] + commonedges = [i for i in selectedFace.Edges for x in circularFaceEdges if i.isSame(x)] bottomface = None for f in circularFaces: @@ -48,9 +45,7 @@ def isDrillableCylinder(obj, candidate, tooldiameter=None, vector=App.Vector(0, matchVector = vector is not None Path.Log.debug( - "\n match tool diameter {} \n match vector {}".format( - matchToolDiameter, matchVector - ) + "\n match tool diameter {} \n match vector {}".format(matchToolDiameter, matchVector) ) def raisedFeature(obj, candidate): @@ -70,9 +65,7 @@ def isDrillableCylinder(obj, candidate, tooldiameter=None, vector=App.Vector(0, candidate.BoundBox.ZMin, ) - return obj.isInside(startLidCenter, 1e-6, False) or obj.isInside( - endLidCenter, 1e-6, False - ) + return obj.isInside(startLidCenter, 1e-6, False) or obj.isInside(endLidCenter, 1e-6, False) def getSeam(candidate): # Finds the vertical seam edge in a cylinder @@ -104,9 +97,7 @@ def isDrillableCylinder(obj, candidate, tooldiameter=None, vector=App.Vector(0, bottomface = checkForBlindHole(obj, candidate) Path.Log.track("candidate is a blind hole") - if ( - bottomface is not None and matchVector - ): # blind holes only drillable at exact vector + if bottomface is not None and matchVector: # blind holes only drillable at exact vector result = compareVecs(bottomface.normalAt(0, 0), vector, exact=True) Path.Log.track(result) return result @@ -125,9 +116,7 @@ def isDrillableFace(obj, candidate, tooldiameter=None, vector=App.Vector(0, 0, 1 matchToolDiameter = tooldiameter is not None matchVector = vector is not None Path.Log.debug( - "\n match tool diameter {} \n match vector {}".format( - matchToolDiameter, matchVector - ) + "\n match tool diameter {} \n match vector {}".format(matchToolDiameter, matchVector) ) if not type(candidate.Surface) == Part.Plane: @@ -177,9 +166,7 @@ def isDrillableEdge( matchToolDiameter = tooldiameter is not None matchVector = vector is not None Path.Log.debug( - "\n match tool diameter {} \n match vector {}".format( - matchToolDiameter, matchVector - ) + "\n match tool diameter {} \n match vector {}".format(matchToolDiameter, matchVector) ) edge = candidate @@ -210,9 +197,7 @@ def isDrillableEdge( return True -def isDrillable( - obj, candidate, tooldiameter=None, vector=App.Vector(0, 0, 1), allowPartial=False -): +def isDrillable(obj, candidate, tooldiameter=None, vector=App.Vector(0, 0, 1), allowPartial=False): """ Checks candidates to see if they can be drilled at the given vector. Candidates can be either faces - circular or cylindrical or circular edges. @@ -295,7 +280,7 @@ def getDrillableTargets(obj, ToolDiameter=None, vector=App.Vector(0, 0, 1)): shp = obj.Shape results = [] - for i in range(1, len(shp.Faces)+1): + for i in range(1, len(shp.Faces) + 1): fname = "Face{}".format(i) Path.Log.debug(fname) candidate = obj.getSubObject(fname) @@ -304,9 +289,7 @@ def getDrillableTargets(obj, ToolDiameter=None, vector=App.Vector(0, 0, 1)): continue try: - drillable = isDrillable( - shp, candidate, tooldiameter=ToolDiameter, vector=vector - ) + drillable = isDrillable(shp, candidate, tooldiameter=ToolDiameter, vector=vector) Path.Log.debug("fname: {} : drillable {}".format(fname, drillable)) except Exception as e: Path.Log.debug(e) diff --git a/src/Mod/CAM/Path/Base/FeedRate.py b/src/Mod/CAM/Path/Base/FeedRate.py index 187a7a412a..0a98b45032 100644 --- a/src/Mod/CAM/Path/Base/FeedRate.py +++ b/src/Mod/CAM/Path/Base/FeedRate.py @@ -49,21 +49,9 @@ def setFeedRate(commandlist, ToolController): VertFeed value will be used, otherwise the HorizFeed value will be used instead.""" def _isVertical(currentposition, command): - x = ( - command.Parameters["X"] - if "X" in command.Parameters - else currentposition.x - ) - y = ( - command.Parameters["Y"] - if "Y" in command.Parameters - else currentposition.y - ) - z = ( - command.Parameters["Z"] - if "Z" in command.Parameters - else currentposition.z - ) + x = command.Parameters["X"] if "X" in command.Parameters else currentposition.x + y = command.Parameters["Y"] if "Y" in command.Parameters else currentposition.y + z = command.Parameters["Z"] if "Z" in command.Parameters else currentposition.z endpoint = FreeCAD.Vector(x, y, z) if Path.Geom.pointsCoincide(currentposition, endpoint): return True diff --git a/src/Mod/CAM/Path/Base/Generator/dogboneII.py b/src/Mod/CAM/Path/Base/Generator/dogboneII.py index ca21480755..8083e04454 100644 --- a/src/Mod/CAM/Path/Base/Generator/dogboneII.py +++ b/src/Mod/CAM/Path/Base/Generator/dogboneII.py @@ -32,7 +32,8 @@ PI = math.pi class Kink(object): """A Kink represents the angle at which two moves connect. - A positive kink angle represents a move to the left, and a negative angle represents a move to the right.""" + A positive kink angle represents a move to the left, and a negative angle represents a move to the right. + """ def __init__(self, m0, m1): if m1 is None: @@ -108,17 +109,13 @@ class Bone(object): def kink_to_path(kink, g0=False): - return Path.Path( - [PathLanguage.instruction_to_command(instr) for instr in [kink.m0, kink.m1]] - ) + return Path.Path([PathLanguage.instruction_to_command(instr) for instr in [kink.m0, kink.m1]]) def bone_to_path(bone, g0=False): kink = bone.kink cmds = [] - if g0 and not Path.Geom.pointsCoincide( - kink.m0.positionBegin(), FreeCAD.Vector(0, 0, 0) - ): + if g0 and not Path.Geom.pointsCoincide(kink.m0.positionBegin(), FreeCAD.Vector(0, 0, 0)): pos = kink.m0.positionBegin() param = {} if not Path.Geom.isRoughly(pos.x, 0): @@ -145,12 +142,8 @@ def generate_bone(kink, length, angle): moveIn = PathLanguage.MoveStraight(kink.position(), "G1", {"X": p0.x + dx}) moveOut = PathLanguage.MoveStraight(moveIn.positionEnd(), "G1", {"X": p0.x}) else: - moveIn = PathLanguage.MoveStraight( - kink.position(), "G1", {"X": p0.x + dx, "Y": p0.y + dy} - ) - moveOut = PathLanguage.MoveStraight( - moveIn.positionEnd(), "G1", {"X": p0.x, "Y": p0.y} - ) + moveIn = PathLanguage.MoveStraight(kink.position(), "G1", {"X": p0.x + dx, "Y": p0.y + dy}) + moveOut = PathLanguage.MoveStraight(moveIn.positionEnd(), "G1", {"X": p0.x, "Y": p0.y}) return Bone(kink, angle, length, [moveIn, moveOut]) diff --git a/src/Mod/CAM/Path/Base/Generator/drill.py b/src/Mod/CAM/Path/Base/Generator/drill.py index 73b43ddd48..4ce9a848a1 100644 --- a/src/Mod/CAM/Path/Base/Generator/drill.py +++ b/src/Mod/CAM/Path/Base/Generator/drill.py @@ -38,7 +38,13 @@ else: def generate( - edge, dwelltime=0.0, peckdepth=0.0, repeat=1, retractheight=None, chipBreak=False, feedRetract=False + edge, + dwelltime=0.0, + peckdepth=0.0, + repeat=1, + retractheight=None, + chipBreak=False, + feedRetract=False, ): """ Generates Gcode for drilling a single hole. diff --git a/src/Mod/CAM/Path/Base/Generator/helix.py b/src/Mod/CAM/Path/Base/Generator/helix.py index 982ce3957a..f81b501739 100644 --- a/src/Mod/CAM/Path/Base/Generator/helix.py +++ b/src/Mod/CAM/Path/Base/Generator/helix.py @@ -146,9 +146,7 @@ def generate( def helix_cut_r(r): commandlist = [] arc_cmd = "G2" if direction == "Climb" else "G3" - commandlist.append( - Path.Command("G0", {"X": startPoint.x + r, "Y": startPoint.y}) - ) + commandlist.append(Path.Command("G0", {"X": startPoint.x + r, "Y": startPoint.y})) commandlist.append(Path.Command("G1", {"Z": startPoint.z})) for i in range(1, turncount + 1): commandlist.append( diff --git a/src/Mod/CAM/Path/Base/Generator/rotation.py b/src/Mod/CAM/Path/Base/Generator/rotation.py index fae6e8cf70..c0f1f4205b 100644 --- a/src/Mod/CAM/Path/Base/Generator/rotation.py +++ b/src/Mod/CAM/Path/Base/Generator/rotation.py @@ -82,9 +82,7 @@ def __getCRotation(normalVector, cMin=-360, cMax=360): with either the +y or -y axis. multiple poses may be possible. Returns a list of all valid poses """ - Path.Log.debug( - "normalVector: {} cMin: {} cMax: {}".format(normalVector, cMin, cMax) - ) + Path.Log.debug("normalVector: {} cMin: {} cMax: {}".format(normalVector, cMin, cMax)) angle = relAngle(normalVector, refAxis.y) @@ -173,9 +171,7 @@ def generate(normalVector, aMin=-360, aMax=360, cMin=-360, cMax=360, compound=Fa # Get the candidate A rotation for the new vector aResult = __getARotation(newvec, aMin, aMax) - Path.Log.debug( - "\n=====\nFor C Rotation: {}\n Calculated A {}\n".format(result, aResult) - ) + Path.Log.debug("\n=====\nFor C Rotation: {}\n Calculated A {}\n".format(result, aResult)) if aResult is not None: solutions.append({"A": aResult, "C": result}) diff --git a/src/Mod/CAM/Path/Base/Generator/threadmilling.py b/src/Mod/CAM/Path/Base/Generator/threadmilling.py index aa7efa3f76..a18562f30e 100644 --- a/src/Mod/CAM/Path/Base/Generator/threadmilling.py +++ b/src/Mod/CAM/Path/Base/Generator/threadmilling.py @@ -140,9 +140,7 @@ def generate(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, st path.append(Path.Command("G0", {"Z": thread.zStart})) else: path.append( - Path.Command( - "G0", {"X": center.x, "Y": center.y + elevator, "Z": thread.zStart} - ) + Path.Command("G0", {"X": center.x, "Y": center.y + elevator, "Z": thread.zStart}) ) path.append(Path.Command("G1", {"Y": yMax})) @@ -172,9 +170,7 @@ def generate(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, st y = thread.adjustY(center.y, r * dy) x = thread.adjustX(center.x, r * dx) _comment(path, "finish-thread") - path.append( - Path.Command(thread.cmd, {"X": x, "Y": y, "Z": thread.zFinal, "J": r}) - ) + path.append(Path.Command(thread.cmd, {"X": x, "Y": y, "Z": thread.zFinal, "J": r})) _comment(path, "finish-thread") a = math.atan2(y - center.y, x - center.x) @@ -185,9 +181,7 @@ def generate(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, st elevatorX = x - dx elevatorY = y - dy - Path.Log.debug( - "({:.2f}, {:.2f}) -> ({:.2f}, {:.2f})".format(x, y, elevatorX, elevatorY) - ) + Path.Log.debug("({:.2f}, {:.2f}) -> ({:.2f}, {:.2f})".format(x, y, elevatorX, elevatorY)) if leadInOut: _comment(path, "lead-out") diff --git a/src/Mod/CAM/Path/Base/Generator/toolchange.py b/src/Mod/CAM/Path/Base/Generator/toolchange.py index 02ad2475c4..e3c6d00261 100644 --- a/src/Mod/CAM/Path/Base/Generator/toolchange.py +++ b/src/Mod/CAM/Path/Base/Generator/toolchange.py @@ -43,9 +43,7 @@ class SpindleDirection(Enum): CCW = "M4" -def generate( - toolnumber, toollabel, spindlespeed=0, spindledirection=SpindleDirection.OFF -): +def generate(toolnumber, toollabel, spindlespeed=0, spindledirection=SpindleDirection.OFF): """ Generates Gcode for a simple toolchange. @@ -91,9 +89,7 @@ def generateSubstitute(newTC, oldTC=None): if newTC.ToolNumber != oldTC.ToolNumber: # Full toolchange return newTC.Path.Commands - if (newTC.SpindleSpeed != oldTC.SpindleSpeed) or ( - newTC.SpindleDir != oldTC.SpindleDir - ): + if (newTC.SpindleSpeed != oldTC.SpindleSpeed) or (newTC.SpindleDir != oldTC.SpindleDir): if newTC.SpindleDir == "Forward": sd = SpindleDirection.CW elif newTC.SpindleDir == "Reverse": diff --git a/src/Mod/CAM/Path/Base/Gui/GetPoint.py b/src/Mod/CAM/Path/Base/Gui/GetPoint.py index 0b893b6e42..50a48c7de7 100644 --- a/src/Mod/CAM/Path/Base/Gui/GetPoint.py +++ b/src/Mod/CAM/Path/Base/Gui/GetPoint.py @@ -80,15 +80,9 @@ class TaskPanel: self.formPoint.YGlobal.editingFinished.connect(self.updatePoint) self.formPoint.ZGlobal.editingFinished.connect(self.updatePoint) - self.formPoint.XGlobal.setProperty( - "unit", FreeCAD.Units.MilliMetre.getUserPreferred()[2] - ) - self.formPoint.YGlobal.setProperty( - "unit", FreeCAD.Units.MilliMetre.getUserPreferred()[2] - ) - self.formPoint.ZGlobal.setProperty( - "unit", FreeCAD.Units.MilliMetre.getUserPreferred()[2] - ) + self.formPoint.XGlobal.setProperty("unit", FreeCAD.Units.MilliMetre.getUserPreferred()[2]) + self.formPoint.YGlobal.setProperty("unit", FreeCAD.Units.MilliMetre.getUserPreferred()[2]) + self.formPoint.ZGlobal.setProperty("unit", FreeCAD.Units.MilliMetre.getUserPreferred()[2]) def addEscapeShortcut(self): """addEscapeShortcut() ... internal function - do not call.""" @@ -97,9 +91,7 @@ class TaskPanel: self.escape = QtGui.QAction(self.formPoint) self.escape.setText("Done") self.escape.setShortcut(QtGui.QKeySequence.fromString("Esc")) - QtCore.QObject.connect( - self.escape, QtCore.SIGNAL("triggered()"), self.pointDone - ) + QtCore.QObject.connect(self.escape, QtCore.SIGNAL("triggered()"), self.pointDone) self.formPoint.addAction(self.escape) def removeEscapeShortcut(self): @@ -115,7 +107,8 @@ class TaskPanel: start is an optional Vector indicating from where to start Snapper. This is mostly used when editing existing points. Snapper also creates a dotted line indicating from where the original point started from. If start is specified the Snapper UI is closed on the first point the user enters. If start remains None, then Snapper is kept open - until the user explicitly closes Snapper. This lets the user enter multiple points in quick succession.""" + until the user explicitly closes Snapper. This lets the user enter multiple points in quick succession. + """ # there's no get point without Snapper, if it's not loaded, need to do that explicitly if not hasattr(FreeCADGui, "Snapper"): @@ -163,10 +156,7 @@ class TaskPanel: def click(cb): event = cb.getEvent() - if ( - event.getButton() == 1 - and event.getState() == coin.SoMouseButtonEvent.DOWN - ): + if event.getButton() == 1 and event.getState() == coin.SoMouseButtonEvent.DOWN: if self.obj: accept() diff --git a/src/Mod/CAM/Path/Base/Gui/PreferencesAdvanced.py b/src/Mod/CAM/Path/Base/Gui/PreferencesAdvanced.py index 92d85a6386..1cab794e0a 100644 --- a/src/Mod/CAM/Path/Base/Gui/PreferencesAdvanced.py +++ b/src/Mod/CAM/Path/Base/Gui/PreferencesAdvanced.py @@ -48,9 +48,7 @@ class AdvancedPreferencesPage: def loadSettings(self): Path.Log.track() - self.form.WarningSuppressAllSpeeds.setChecked( - Path.Preferences.suppressAllSpeedsWarning() - ) + self.form.WarningSuppressAllSpeeds.setChecked(Path.Preferences.suppressAllSpeedsWarning()) self.form.WarningSuppressRapidSpeeds.setChecked( Path.Preferences.suppressRapidSpeedsWarning(False) ) @@ -60,12 +58,8 @@ class AdvancedPreferencesPage: self.form.EnableAdvancedOCLFeatures.setChecked( Path.Preferences.advancedOCLFeaturesEnabled() ) - self.form.WarningSuppressOpenCamLib.setChecked( - Path.Preferences.suppressOpenCamLibWarning() - ) - self.form.WarningSuppressVelocity.setChecked( - Path.Preferences.suppressVelocity() - ) + self.form.WarningSuppressOpenCamLib.setChecked(Path.Preferences.suppressOpenCamLibWarning()) + self.form.WarningSuppressVelocity.setChecked(Path.Preferences.suppressVelocity()) self.updateSelection() def updateSelection(self, state=None): diff --git a/src/Mod/CAM/Path/Base/Gui/PropertyBag.py b/src/Mod/CAM/Path/Base/Gui/PropertyBag.py index d40c95f3bc..77ac9a033c 100644 --- a/src/Mod/CAM/Path/Base/Gui/PropertyBag.py +++ b/src/Mod/CAM/Path/Base/Gui/PropertyBag.py @@ -179,9 +179,7 @@ class PropertyCreate(object): return self.form.propertyGroup.currentText().strip() def propertyType(self): - return PathPropertyBag.SupportedPropertyType[ - self.form.propertyType.currentText() - ].strip() + return PathPropertyBag.SupportedPropertyType[self.form.propertyType.currentText()].strip() def propertyInfo(self): return self.form.propertyInfo.toPlainText().strip() @@ -200,9 +198,7 @@ class PropertyCreate(object): # property exists - this is an edit operation self.form.propertyName.setText(name) if self.propertyIsEnumeration(): - self.form.propertyEnum.setText( - ",".join(self.obj.getEnumerationsOfProperty(name)) - ) + self.form.propertyEnum.setText(",".join(self.obj.getEnumerationsOfProperty(name))) self.form.propertyInfo.setText(self.obj.getDocumentationOfProperty(name)) self.form.labelName.setEnabled(False) @@ -247,27 +243,15 @@ class TaskPanel(object): val = PathUtil.getPropertyValueString(self.obj, name) info = self.obj.getDocumentationOfProperty(name) - self.model.setData( - self.model.index(i, self.ColumnName), name, QtCore.Qt.EditRole - ) + self.model.setData(self.model.index(i, self.ColumnName), name, QtCore.Qt.EditRole) # self.model.setData(self.model.index(i, self.ColumnType), typ, QtCore.Qt.EditRole) - self.model.setData( - self.model.index(i, self.ColumnVal), self.obj, Delegate.RoleObject - ) - self.model.setData( - self.model.index(i, self.ColumnVal), name, Delegate.RoleProperty - ) - self.model.setData( - self.model.index(i, self.ColumnVal), val, QtCore.Qt.DisplayRole - ) + self.model.setData(self.model.index(i, self.ColumnVal), self.obj, Delegate.RoleObject) + self.model.setData(self.model.index(i, self.ColumnVal), name, Delegate.RoleProperty) + self.model.setData(self.model.index(i, self.ColumnVal), val, QtCore.Qt.DisplayRole) - self.model.setData( - self.model.index(i, self.ColumnName), typ, QtCore.Qt.ToolTipRole - ) + self.model.setData(self.model.index(i, self.ColumnName), typ, QtCore.Qt.ToolTipRole) # self.model.setData(self.model.index(i, self.ColumnType), info, QtCore.Qt.ToolTipRole) - self.model.setData( - self.model.index(i, self.ColumnVal), info, QtCore.Qt.ToolTipRole - ) + self.model.setData(self.model.index(i, self.ColumnVal), info, QtCore.Qt.ToolTipRole) self.model.item(i, self.ColumnName).setEditable(False) # self.model.item(i, self.ColumnType).setEditable(False) @@ -276,9 +260,7 @@ class TaskPanel(object): Path.Log.track() self.delegate = Delegate(self.form) - self.model = QtGui.QStandardItemModel( - len(self.props), len(self.TableHeaders), self.form - ) + self.model = QtGui.QStandardItemModel(len(self.props), len(self.TableHeaders), self.form) self.model.setHorizontalHeaderLabels(self.TableHeaders) for i, name in enumerate(self.props): @@ -382,14 +364,10 @@ class TaskPanel(object): # this can happen if the old enumeration value doesn't exist anymore pass newVal = PathUtil.getPropertyValueString(obj, prop) - self.model.setData( - self.model.index(row, self.ColumnVal), newVal, QtCore.Qt.DisplayRole - ) + self.model.setData(self.model.index(row, self.ColumnVal), newVal, QtCore.Qt.DisplayRole) # self.model.setData(self.model.index(row, self.ColumnType), info, QtCore.Qt.ToolTipRole) - self.model.setData( - self.model.index(row, self.ColumnVal), info, QtCore.Qt.ToolTipRole - ) + self.model.setData(self.model.index(row, self.ColumnVal), info, QtCore.Qt.ToolTipRole) def propertyModify(self): Path.Log.track() diff --git a/src/Mod/CAM/Path/Base/Gui/SetupSheet.py b/src/Mod/CAM/Path/Base/Gui/SetupSheet.py index beac01ca1b..dabcbb610d 100644 --- a/src/Mod/CAM/Path/Base/Gui/SetupSheet.py +++ b/src/Mod/CAM/Path/Base/Gui/SetupSheet.py @@ -165,9 +165,7 @@ class OpTaskPanel: self.model.setData(self.model.index(i, 0), isset, QtCore.Qt.EditRole) self.model.setData(self.model.index(i, 1), name, QtCore.Qt.EditRole) self.model.setData(self.model.index(i, 2), prop, Delegate.PropertyRole) - self.model.setData( - self.model.index(i, 2), prop.displayString(), QtCore.Qt.DisplayRole - ) + self.model.setData(self.model.index(i, 2), prop.displayString(), QtCore.Qt.DisplayRole) self.model.item(i, 0).setCheckable(True) self.model.item(i, 0).setText("") @@ -201,9 +199,7 @@ class OpTaskPanel: propName = self.propertyName(name) enabled = self.model.item(i, 0).checkState() == QtCore.Qt.Checked if enabled and not prop.getValue() is None: - if prop.setupProperty( - self.obj, propName, self.propertyGroup(), prop.getValue() - ): + if prop.setupProperty(self.obj, propName, self.propertyGroup(), prop.getValue()): propertiesCreatedRemoved = True else: if hasattr(self.obj, propName): @@ -222,10 +218,7 @@ class OpsDefaultEditor: self.form = form self.obj = obj self.ops = sorted( - [ - OpTaskPanel(self.obj, name, op) - for name, op in PathSetupSheet._RegisteredOps.items() - ], + [OpTaskPanel(self.obj, name, op) for name, op in PathSetupSheet._RegisteredOps.items()], key=lambda op: op.name, ) if form: @@ -305,9 +298,7 @@ class GlobalEditor(object): updateExpression("StartDepthExpression", self.form.setupStartDepthExpr) updateExpression("FinalDepthExpression", self.form.setupFinalDepthExpr) updateExpression("StepDownExpression", self.form.setupStepDownExpr) - updateExpression( - "ClearanceHeightExpression", self.form.setupClearanceHeightExpr - ) + updateExpression("ClearanceHeightExpression", self.form.setupClearanceHeightExpr) updateExpression("SafeHeightExpression", self.form.setupSafeHeightExpr) self.clearanceHeightOffs.updateProperty() self.safeHeightOffs.updateProperty() diff --git a/src/Mod/CAM/Path/Base/Gui/Util.py b/src/Mod/CAM/Path/Base/Gui/Util.py index af349a3444..2d311b1cb1 100644 --- a/src/Mod/CAM/Path/Base/Gui/Util.py +++ b/src/Mod/CAM/Path/Base/Gui/Util.py @@ -79,7 +79,7 @@ def updateInputField(obj, prop, widget, onBeforeChange=None): else: if hasattr(obj, "ExpressionEngine"): exprSet = False - for (prp, expr) in obj.ExpressionEngine: + for prp, expr in obj.ExpressionEngine: if prp == prop: exprSet = True Path.Log.debug('prop = "expression": {} = "{}"'.format(prp, expr)) @@ -100,9 +100,7 @@ def updateInputField(obj, prop, widget, onBeforeChange=None): widget.update() if isDiff: - Path.Log.debug( - "updateInputField(%s, %s): %.2f -> %.2f" % (obj.Label, prop, attr, value) - ) + Path.Log.debug("updateInputField(%s, %s): %.2f -> %.2f" % (obj.Label, prop, attr, value)) if onBeforeChange: onBeforeChange(obj) PathUtil.setProperty(obj, prop, value) @@ -164,9 +162,7 @@ class QuantitySpinBox(QtCore.QObject): self.widget.setProperty("binding", "%s.%s" % (obj.Name, prop)) self.valid = True else: - Path.Log.warning( - "Cannot find property {} of {}".format(prop, obj.Label) - ) + Path.Log.warning("Cannot find property {} of {}".format(prop, obj.Label)) self.valid = False else: self.valid = False @@ -216,13 +212,11 @@ class QuantitySpinBox(QtCore.QObject): """updateProperty() ... update the bound property with the value from the spin box""" Path.Log.track(self.prop, self.valid) if self.valid: - return updateInputField( - self.obj, self.prop, self.widget, self.onBeforeChange - ) + return updateInputField(self.obj, self.prop, self.widget, self.onBeforeChange) return None def _hasExpression(self): - for (prop, exp) in self.obj.ExpressionEngine: + for prop, exp in self.obj.ExpressionEngine: if prop == self.prop: return exp return None diff --git a/src/Mod/CAM/Path/Base/Language.py b/src/Mod/CAM/Path/Base/Language.py index b157ebbc71..d32e8723a6 100644 --- a/src/Mod/CAM/Path/Base/Language.py +++ b/src/Mod/CAM/Path/Base/Language.py @@ -59,9 +59,7 @@ class Instruction(object): def positionEnd(self): """positionEnd() ... returns a Vector of the end position""" - return FreeCAD.Vector( - self.x(self.begin.x), self.y(self.begin.y), self.z(self.begin.z) - ) + return FreeCAD.Vector(self.x(self.begin.x), self.y(self.begin.y), self.z(self.begin.z)) def pathLength(self): """pathLength() ... returns the length in mm""" @@ -75,9 +73,7 @@ class Instruction(object): def isPlunge(self): """isPlunge() ... return true if this moves up or down""" - return self.isMove() and not Path.Geom.isRoughly( - self.begin.z, self.z(self.begin.z) - ) + return self.isMove() and not Path.Geom.isRoughly(self.begin.z, self.z(self.begin.z)) def leadsInto(self, instr): """leadsInto(instr) ... return true if instr is a continuation of self""" diff --git a/src/Mod/CAM/Path/Base/SetupSheet.py b/src/Mod/CAM/Path/Base/SetupSheet.py index 4d72df3059..642fbf90c9 100644 --- a/src/Mod/CAM/Path/Base/SetupSheet.py +++ b/src/Mod/CAM/Path/Base/SetupSheet.py @@ -112,17 +112,13 @@ class SetupSheet: "App::PropertySpeed", "VertRapid", "ToolController", - QT_TRANSLATE_NOOP( - "App::Property", "Default speed for horizontal rapid moves." - ), + QT_TRANSLATE_NOOP("App::Property", "Default speed for horizontal rapid moves."), ) obj.addProperty( "App::PropertySpeed", "HorizRapid", "ToolController", - QT_TRANSLATE_NOOP( - "App::Property", "Default speed for vertical rapid moves." - ), + QT_TRANSLATE_NOOP("App::Property", "Default speed for vertical rapid moves."), ) obj.addProperty( "App::PropertyStringList", @@ -149,9 +145,7 @@ class SetupSheet: "App::PropertyString", "SafeHeightExpression", "OperationHeights", - QT_TRANSLATE_NOOP( - "App::Property", "Expression for the safe height of new operations." - ), + QT_TRANSLATE_NOOP("App::Property", "Expression for the safe height of new operations."), ) obj.addProperty( "App::PropertyLength", @@ -191,31 +185,19 @@ class SetupSheet: "App::PropertyString", "StepDownExpression", "OperationDepths", - QT_TRANSLATE_NOOP( - "App::Property", "Expression used for step down of new operations." - ), + QT_TRANSLATE_NOOP("App::Property", "Expression used for step down of new operations."), ) obj.SafeHeightOffset = self.decodeAttributeString(self.DefaultSafeHeightOffset) - obj.ClearanceHeightOffset = self.decodeAttributeString( - self.DefaultClearanceHeightOffset - ) - obj.SafeHeightExpression = self.decodeAttributeString( - self.DefaultSafeHeightExpression - ) + obj.ClearanceHeightOffset = self.decodeAttributeString(self.DefaultClearanceHeightOffset) + obj.SafeHeightExpression = self.decodeAttributeString(self.DefaultSafeHeightExpression) obj.ClearanceHeightExpression = self.decodeAttributeString( self.DefaultClearanceHeightExpression ) - obj.StartDepthExpression = self.decodeAttributeString( - self.DefaultStartDepthExpression - ) - obj.FinalDepthExpression = self.decodeAttributeString( - self.DefaultFinalDepthExpression - ) - obj.StepDownExpression = self.decodeAttributeString( - self.DefaultStepDownExpression - ) + obj.StartDepthExpression = self.decodeAttributeString(self.DefaultStartDepthExpression) + obj.FinalDepthExpression = self.decodeAttributeString(self.DefaultFinalDepthExpression) + obj.StepDownExpression = self.decodeAttributeString(self.DefaultStepDownExpression) obj.CoolantModes = self.DefaultCoolantModes obj.CoolantMode = self.DefaultCoolantModes @@ -314,12 +296,8 @@ class SetupSheet: if includeHeights: attrs[Template.SafeHeightOffset] = self.obj.SafeHeightOffset.UserString attrs[Template.SafeHeightExpression] = self.obj.SafeHeightExpression - attrs[ - Template.ClearanceHeightOffset - ] = self.obj.ClearanceHeightOffset.UserString - attrs[ - Template.ClearanceHeightExpression - ] = self.obj.ClearanceHeightExpression + attrs[Template.ClearanceHeightOffset] = self.obj.ClearanceHeightOffset.UserString + attrs[Template.ClearanceHeightExpression] = self.obj.ClearanceHeightExpression if includeDepths: attrs[Template.StartDepthExpression] = self.obj.StartDepthExpression @@ -333,9 +311,7 @@ class SetupSheet: for propName in op.properties(): prop = OpPropertyName(opName, propName) if hasattr(self.obj, prop): - settings[propName] = PathUtil.getPropertyValueString( - self.obj, prop - ) + settings[propName] = PathUtil.getPropertyValueString(self.obj, prop) attrs[opName] = settings return attrs @@ -364,15 +340,11 @@ class SetupSheet: def encodeAttributeString(self, attr): """encodeAttributeString(attr) ... return the encoded string of a template attribute.""" - return str( - attr.replace(self.expressionReference(), self.TemplateReference) - ) + return str(attr.replace(self.expressionReference(), self.TemplateReference)) def decodeAttributeString(self, attr): """decodeAttributeString(attr) ... return the decoded string of a template attribute.""" - return str( - attr.replace(self.TemplateReference, self.expressionReference()) - ) + return str(attr.replace(self.TemplateReference, self.expressionReference())) def encodeTemplateAttributes(self, attrs): """encodeTemplateAttributes(attrs) ... return a dictionary with all values encoded.""" diff --git a/src/Mod/CAM/Path/Base/SetupSheetOpPrototype.py b/src/Mod/CAM/Path/Base/SetupSheetOpPrototype.py index e9c2749f1d..7052494f5a 100644 --- a/src/Mod/CAM/Path/Base/SetupSheetOpPrototype.py +++ b/src/Mod/CAM/Path/Base/SetupSheetOpPrototype.py @@ -130,9 +130,7 @@ class PropertyFloat(Property): try: return float(string) except ValueError: - Path.Log.error( - f"{self.category}.{self.name} [{self.propType}] : '{string}'" - ) + Path.Log.error(f"{self.category}.{self.name} [{self.propType}] : '{string}'") raise @@ -144,9 +142,7 @@ class PropertyInteger(Property): try: return int(string) except ValueError: - Path.Log.error( - f"{self.category}.{self.name} [{self.propType}] : '{string}'" - ) + Path.Log.error(f"{self.category}.{self.name} [{self.propType}] : '{string}'") raise @@ -163,9 +159,7 @@ class PropertyBool(Property): try: return bool(string) except ValueError: - Path.Log.error( - f"{self.category}.{self.name} [{self.propType}] : '{string}'" - ) + Path.Log.error(f"{self.category}.{self.name} [{self.propType}] : '{string}'") raise diff --git a/src/Mod/CAM/Path/Base/Util.py b/src/Mod/CAM/Path/Base/Util.py index 1c3ef84a26..3de8266d5f 100644 --- a/src/Mod/CAM/Path/Base/Util.py +++ b/src/Mod/CAM/Path/Base/Util.py @@ -53,10 +53,7 @@ def _getProperty(obj, prop): attr = getattr(o, name) if o == attr: - Path.Log.debug( - translate("PathGui", "%s has no property %s (%s)") - % (obj.Label, prop, name) - ) + Path.Log.debug(translate("PathGui", "%s has no property %s (%s)") % (obj.Label, prop, name)) return (None, None, None) # Path.Log.debug("found property %s of %s (%s: %s)" % (prop, obj.Label, name, attr)) @@ -105,9 +102,7 @@ def isValidBaseObject(obj): if obj.TypeId in NotValidBaseTypeIds: Path.Log.debug("%s is blacklisted (%s)" % (obj.Label, obj.TypeId)) return False - if hasattr(obj, "Sheets") or hasattr( - obj, "TagText" - ): # Arch.Panels and Arch.PanelCut + if hasattr(obj, "Sheets") or hasattr(obj, "TagText"): # Arch.Panels and Arch.PanelCut Path.Log.debug("%s is not an Arch.Panel" % (obj.Label)) return False import Part @@ -157,5 +152,3 @@ def clearExpressionEngine(obj): if hasattr(obj, "ExpressionEngine"): for attr, expr in obj.ExpressionEngine: obj.setExpression(attr, None) - - diff --git a/src/Mod/CAM/Path/Dressup/Boundary.py b/src/Mod/CAM/Path/Dressup/Boundary.py index 58af8071fa..04a6828edc 100644 --- a/src/Mod/CAM/Path/Dressup/Boundary.py +++ b/src/Mod/CAM/Path/Dressup/Boundary.py @@ -157,9 +157,7 @@ class PathBoundary: tc = PathDressup.toolController(self.baseOp) self.safeHeight = float(PathUtil.opProperty(self.baseOp, "SafeHeight")) - self.clearanceHeight = float( - PathUtil.opProperty(self.baseOp, "ClearanceHeight") - ) + self.clearanceHeight = float(PathUtil.opProperty(self.baseOp, "ClearanceHeight")) self.strG0ZsafeHeight = Path.Command( # was a Feed rate with G1 "G0", {"Z": self.safeHeight, "F": tc.VertRapid.Value} ) @@ -195,9 +193,7 @@ class PathBoundary: bogusX or bogusY ): # don't insert false paths based on bogus m/c position commands.extend( - self.boundaryCommands( - lastExit, pos, tc.VertFeed.Value - ) + self.boundaryCommands(lastExit, pos, tc.VertFeed.Value) ) lastExit = None commands.append(cmd) @@ -209,9 +205,7 @@ class PathBoundary: lastExit = pos pos = Path.Geom.commandEndPoint(cmd, pos) else: - Path.Log.track( - _vstr(pos), _vstr(lastExit), len(inside), len(outside), cmd - ) + Path.Log.track(_vstr(pos), _vstr(lastExit), len(inside), len(outside), cmd) # cmd pierces boundary while inside or outside: ie = [e for e in inside if Path.Geom.edgeConnectsTo(e, pos)] @@ -226,9 +220,7 @@ class PathBoundary: if lastExit: if not (bogusX or bogusY): commands.extend( - self.boundaryCommands( - lastExit, pos, tc.VertFeed.Value - ) + self.boundaryCommands(lastExit, pos, tc.VertFeed.Value) ) lastExit = None Path.Log.track(e, flip) @@ -249,19 +241,13 @@ class PathBoundary: pos = newPos lastExit = newPos else: - oe = [ - e - for e in outside - if Path.Geom.edgeConnectsTo(e, pos) - ] + oe = [e for e in outside if Path.Geom.edgeConnectsTo(e, pos)] Path.Log.track(oe) if oe: e = oe[0] ptL = e.valueAt(e.LastParameter) flip = Path.Geom.pointsCoincide(pos, ptL) - newPos = ( - e.valueAt(e.FirstParameter) if flip else ptL - ) + newPos = e.valueAt(e.FirstParameter) if flip else ptL # outside edges are never taken at this point (see swap of # inside/outside above) - so just move along ... outside.remove(e) @@ -301,8 +287,7 @@ def Create(base, name="DressupPathBoundary"): if not base.isDerivedFrom("Path::Feature"): Path.Log.error( - translate("CAM_DressupPathBoundary", "The selected object is not a path") - + "\n" + translate("CAM_DressupPathBoundary", "The selected object is not a path") + "\n" ) return None diff --git a/src/Mod/CAM/Path/Dressup/DogboneII.py b/src/Mod/CAM/Path/Dressup/DogboneII.py index df6f4957eb..e6354e8391 100644 --- a/src/Mod/CAM/Path/Dressup/DogboneII.py +++ b/src/Mod/CAM/Path/Dressup/DogboneII.py @@ -234,9 +234,7 @@ class Proxy(object): "App::PropertyEnumeration", "Incision", "Dressup", - QT_TRANSLATE_NOOP( - "App::Property", "The algorithm to determine the bone length" - ), + QT_TRANSLATE_NOOP("App::Property", "The algorithm to determine the bone length"), ) obj.Incision = Incision.All obj.Incision = Incision.Adaptive @@ -245,9 +243,7 @@ class Proxy(object): "App::PropertyLength", "Custom", "Dressup", - QT_TRANSLATE_NOOP( - "App::Property", "Dressup length if incision is set to 'custom'" - ), + QT_TRANSLATE_NOOP("App::Property", "Dressup length if incision is set to 'custom'"), ) obj.Custom = 0.0 @@ -301,11 +297,7 @@ class Proxy(object): thisMove = instr bone = None if thisMove.isPlunge(): - if ( - lastMove - and moveAfterPlunge - and lastMove.leadsInto(moveAfterPlunge) - ): + if lastMove and moveAfterPlunge and lastMove.leadsInto(moveAfterPlunge): bone = self.createBone(obj, lastMove, moveAfterPlunge) lastMove = None moveAfterPlunge = None @@ -318,8 +310,7 @@ class Proxy(object): if bone: enabled = not len(bones) in obj.BoneBlacklist if enabled and not ( - dressingUpDogbone - and obj.Base.Proxy.includesBoneAt(bone.position()) + dressingUpDogbone and obj.Base.Proxy.includesBoneAt(bone.position()) ): maneuver.addInstructions(bone.instr) else: diff --git a/src/Mod/CAM/Path/Dressup/Gui/AxisMap.py b/src/Mod/CAM/Path/Dressup/Gui/AxisMap.py index d6da52e895..e78d61784f 100644 --- a/src/Mod/CAM/Path/Dressup/Gui/AxisMap.py +++ b/src/Mod/CAM/Path/Dressup/Gui/AxisMap.py @@ -87,15 +87,11 @@ class ObjectDressup: for p in path: if p.Name in Path.Geom.CmdMoveArc: - curVec = FreeCAD.Vector( - currLocation["X"], currLocation["Y"], currLocation["Z"] - ) + curVec = FreeCAD.Vector(currLocation["X"], currLocation["Y"], currLocation["Z"]) arcwire = Path.Geom.edgeForCmd(p, curVec) pointlist = arcwire.discretize(Deflection=d) for point in pointlist: - newcommand = Path.Command( - "G1", {"X": point.x, "Y": point.y, "Z": point.z} - ) + newcommand = Path.Command("G1", {"X": point.x, "Y": point.y, "Z": point.z}) newcommandlist.append(newcommand) currLocation.update(newcommand.Parameters) else: @@ -127,12 +123,8 @@ class ObjectDressup: newparams = dict(c.Parameters) remapvar = newparams.pop(inAxis, None) if remapvar is not None: - newparams[outAxis] = self._linear2angular( - obj.Radius, remapvar - ) - locdiff = dict( - set(newparams.items()) - set(currLocation.items()) - ) + newparams[outAxis] = self._linear2angular(obj.Radius, remapvar) + locdiff = dict(set(newparams.items()) - set(currLocation.items())) if ( len(locdiff) == 1 and outAxis in locdiff ): # pure rotation. Calculate rotational feed rate @@ -140,9 +132,7 @@ class ObjectDressup: feed = c.Parameters["F"] else: feed = currLocation["F"] - newparams.update( - {"F": self._linear2angular(obj.Radius, feed)} - ) + newparams.update({"F": self._linear2angular(obj.Radius, feed)}) newcommand = Path.Command(c.Name, newparams) newcommandlist.append(newcommand) currLocation.update(newparams) @@ -262,9 +252,7 @@ class CommandPathDressup: "Pixmap": "CAM_Dressup", "MenuText": QT_TRANSLATE_NOOP("CAM_DressupAxisMap", "Axis Map"), "Accel": "", - "ToolTip": QT_TRANSLATE_NOOP( - "CAM_DressupAxisMap", "Remap one axis to another." - ), + "ToolTip": QT_TRANSLATE_NOOP("CAM_DressupAxisMap", "Remap one axis to another."), } def IsActive(self): @@ -289,9 +277,7 @@ class CommandPathDressup: ) return if selection[0].isDerivedFrom("Path::FeatureCompoundPython"): - FreeCAD.Console.PrintError( - translate("CAM_Dressup", "Please select a toolpath object") - ) + FreeCAD.Console.PrintError(translate("CAM_Dressup", "Please select a toolpath object")) return # everything ok! @@ -310,9 +296,7 @@ class CommandPathDressup: FreeCADGui.doCommand( "obj.ViewObject.Proxy = Path.Dressup.Gui.AxisMap.ViewProviderDressup(obj.ViewObject)" ) - FreeCADGui.doCommand( - "Gui.ActiveDocument.getObject(base.Name).Visibility = False" - ) + FreeCADGui.doCommand("Gui.ActiveDocument.getObject(base.Name).Visibility = False") FreeCADGui.doCommand("obj.ViewObject.Document.setEdit(obj.ViewObject, 0)") # FreeCAD.ActiveDocument.commitTransaction() # Final `commitTransaction()` called via TaskPanel.accept() FreeCAD.ActiveDocument.recompute() diff --git a/src/Mod/CAM/Path/Dressup/Gui/Boundary.py b/src/Mod/CAM/Path/Dressup/Gui/Boundary.py index 542eb49c61..56482c31b3 100644 --- a/src/Mod/CAM/Path/Dressup/Gui/Boundary.py +++ b/src/Mod/CAM/Path/Dressup/Gui/Boundary.py @@ -59,7 +59,9 @@ class TaskPanel(object): self.stockEdit = None def getStandardButtons(self): - return QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Cancel + return ( + QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Cancel + ) def modifyStandardButtons(self, buttonBox): self.buttonBox = buttonBox @@ -122,9 +124,7 @@ class TaskPanel(object): def setupCreateBoxEdit(): Path.Log.track(index, force) if force or not self.stockCreateBox: - self.stockCreateBox = PathJobGui.StockCreateBoxEdit( - self.obj, self.form, force - ) + self.stockCreateBox = PathJobGui.StockCreateBoxEdit(self.obj, self.form, force) self.stockEdit = self.stockCreateBox def setupCreateCylinderEdit(): @@ -147,9 +147,7 @@ class TaskPanel(object): return False if index == -1: - if self.obj.Stock is None or PathJobGui.StockFromBaseBoundBoxEdit.IsStock( - self.obj - ): + if self.obj.Stock is None or PathJobGui.StockFromBaseBoundBoxEdit.IsStock(self.obj): setupFromBaseEdit() elif PathJobGui.StockCreateBoxEdit.IsStock(self.obj): setupCreateBoxEdit() @@ -159,8 +157,7 @@ class TaskPanel(object): setupFromExisting() else: Path.Log.error( - translate("PathJob", "Unsupported stock object %s") - % self.obj.Stock.Label + translate("PathJob", "Unsupported stock object %s") % self.obj.Stock.Label ) else: if index == PathJobGui.StockFromBaseBoundBoxEdit.Index: @@ -275,8 +272,7 @@ class CommandPathDressupPathBoundary: selection = FreeCADGui.Selection.getSelection() if len(selection) != 1: Path.Log.error( - translate("CAM_DressupPathBoundary", "Please select one toolpath object") - + "\n" + translate("CAM_DressupPathBoundary", "Please select one toolpath object") + "\n" ) return baseObject = selection[0] diff --git a/src/Mod/CAM/Path/Dressup/Gui/Dogbone.py b/src/Mod/CAM/Path/Dressup/Gui/Dogbone.py index f3b4a8d619..a6a08ad604 100644 --- a/src/Mod/CAM/Path/Dressup/Gui/Dogbone.py +++ b/src/Mod/CAM/Path/Dressup/Gui/Dogbone.py @@ -55,9 +55,7 @@ def debugMarker(vector, label, color=None, radius=0.5): obj = FreeCAD.ActiveDocument.addObject("Part::Sphere", label) obj.Label = label obj.Radius = radius - obj.Placement = FreeCAD.Placement( - vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0) - ) + obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0)) if color: obj.ViewObject.ShapeColor = color @@ -68,9 +66,7 @@ def debugCircle(vector, r, label, color=None): obj.Label = label obj.Radius = r obj.Height = 1 - obj.Placement = FreeCAD.Placement( - vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0) - ) + obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0)) obj.ViewObject.Transparency = 90 if color: obj.ViewObject.ShapeColor = color @@ -118,9 +114,7 @@ def edgesForCommands(cmds, startPt): if cmd.Name in Path.Geom.CmdMoveStraight: edges.append(Part.Edge(Part.LineSegment(lastPt, pt))) elif cmd.Name in Path.Geom.CmdMoveArc: - center = lastPt + pointFromCommand( - cmd, FreeCAD.Vector(0, 0, 0), "I", "J", "K" - ) + center = lastPt + pointFromCommand(cmd, FreeCAD.Vector(0, 0, 0), "I", "J", "K") A = lastPt - center B = pt - center d = -B.x * A.y + B.y * A.x @@ -307,9 +301,7 @@ class Chord(object): def isANoopMove(self): Path.Log.debug( - "{}.isANoopMove(): {}".format( - self, Path.Geom.pointsCoincide(self.Start, self.End) - ) + "{}.isANoopMove(): {}".format(self, Path.Geom.pointsCoincide(self.Start, self.End)) ) return Path.Geom.pointsCoincide(self.Start, self.End) @@ -450,9 +442,7 @@ class ObjectDressup(object): "App::PropertyEnumeration", "Incision", "Dressup", - QT_TRANSLATE_NOOP( - "App::Property", "The algorithm to determine the bone length" - ), + QT_TRANSLATE_NOOP("App::Property", "The algorithm to determine the bone length"), ) obj.Incision = Incision.All obj.Incision = Incision.Adaptive @@ -528,9 +518,7 @@ class ObjectDressup(object): Path.Log.debug("Taking tangent as intersect %s" % tangent) ppt = pivot + tangent else: - Path.Log.debug( - "Taking chord start as intersect %s" % edge.Vertexes[0].Point - ) + Path.Log.debug("Taking chord start as intersect %s" % edge.Vertexes[0].Point) ppt = edge.Vertexes[0].Point # debugMarker(ppt, "ptt.%d-%s.in" % (self.boneId, d), color, 0.2) Path.Log.debug(" --> (%.2f, %.2f)" % (ppt.x, ppt.y)) @@ -540,9 +528,7 @@ class ObjectDressup(object): param = edge.Curve.parameter(point) return edge.FirstParameter <= param <= edge.LastParameter - def smoothChordCommands( - self, bone, inChord, outChord, edge, wire, corner, smooth, color=None - ): + def smoothChordCommands(self, bone, inChord, outChord, edge, wire, corner, smooth, color=None): if smooth == 0: Path.Log.info(" No smoothing requested") return [bone.lastCommand, outChord.g1Command(bone.F)] @@ -587,9 +573,7 @@ class ObjectDressup(object): % (e.Curve.Center.x, e.Curve.Center.y, e.Curve.Radius) ) for pt in DraftGeomUtils.findIntersection(edge, e, True, findAll=True): - if not Path.Geom.pointsCoincide(pt, corner) and self.pointIsOnEdge( - pt, e - ): + if not Path.Geom.pointsCoincide(pt, corner) and self.pointIsOnEdge(pt, e): # debugMarker(pt, "candidate-%d-%s" % (self.boneId, d), color, 0.05) Path.Log.debug(" -> candidate") distance = (pt - refPoint).Length @@ -602,9 +586,7 @@ class ObjectDressup(object): if pivot: # debugCircle(pivot, self.toolRadius, "pivot.%d-%s" % (self.boneId, d), color) - pivotEdge = Part.Edge( - Part.Circle(pivot, FreeCAD.Vector(0, 0, 1), self.toolRadius) - ) + pivotEdge = Part.Edge(Part.Circle(pivot, FreeCAD.Vector(0, 0, 1), self.toolRadius)) t1 = self.findPivotIntersection( pivot, pivotEdge, inChord.asEdge(), inChord.End, d, color ) @@ -699,9 +681,7 @@ class ObjectDressup(object): boneArc = Part.Arc(vt1, vm2, vb1) # boneArc = Part.Circle(FreeCAD.Vector(length, 0, 0), FreeCAD.Vector(0,0,1), self.toolRadius) boneWire = Part.Shape([boneTop, boneArc, boneBot, boneLid]) - boneWire.rotate( - FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), boneAngle * 180 / math.pi - ) + boneWire.rotate(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), boneAngle * 180 / math.pi) boneWire.translate(bone.inChord.End) self.boneShapes = [cornerShape, boneWire] @@ -852,9 +832,7 @@ class ObjectDressup(object): # debugCircle(e2.Curve.Center, e2.Curve.Radius, "bone.%d-2" % (self.boneId), (0.,1.,0.)) if Path.Geom.pointsCoincide( pt, e1.valueAt(e1.LastParameter) - ) or Path.Geom.pointsCoincide( - pt, e2.valueAt(e2.FirstParameter) - ): + ) or Path.Geom.pointsCoincide(pt, e2.valueAt(e2.FirstParameter)): continue # debugMarker(pt, "it", (0.0, 1.0, 1.0)) # 1. remove all redundant commands @@ -871,9 +849,7 @@ class ObjectDressup(object): center = e2.Curve.Center offset = center - pt c2Params = c2.Parameters - c2Params.update( - {"I": offset.x, "J": offset.y, "K": offset.z} - ) + c2Params.update({"I": offset.x, "J": offset.y, "K": offset.z}) c2 = Path.Command(c2.Name, c2Params) bones = [c2] bones.extend(bone2.commands[j + 1 :]) @@ -900,9 +876,7 @@ class ObjectDressup(object): lastChord = Chord() # the last chord lastCommand = None # the command that generated the last chord lastBone = None # track last bone for optimizations - oddsAndEnds = ( - [] - ) # track chords that are connected to plunges - in case they form a loop + oddsAndEnds = [] # track chords that are connected to plunges - in case they form a loop boneId = 1 self.bones = [] @@ -910,7 +884,7 @@ class ObjectDressup(object): self.length = 0 # boneIserted = False - for (i, thisCommand) in enumerate(PathUtils.getPathWithPlacement(obj.Base).Commands): + for i, thisCommand in enumerate(PathUtils.getPathWithPlacement(obj.Base).Commands): # if i > 14: # if lastCommand: # commands.append(lastCommand) @@ -942,23 +916,17 @@ class ObjectDressup(object): if lastBone: Path.Log.info(" removing potential path crossing") # debugMarker(thisChord.Start, "it", (1.0, 0.0, 1.0)) - commands, bones = self.removePathCrossing( - commands, lastBone, bone - ) + commands, bones = self.removePathCrossing(commands, lastBone, bone) commands.extend(bones[:-1]) lastCommand = bones[-1] lastBone = bone elif lastCommand and thisChord.isAPlungeMove(): Path.Log.info(" Looking for connection in odds and ends") haveNewLastCommand = False - for chord in ( - chord for chord in oddsAndEnds if lastChord.connectsTo(chord) - ): + for chord in (chord for chord in oddsAndEnds if lastChord.connectsTo(chord)): if self.shouldInsertDogbone(obj, lastChord, chord): Path.Log.info(" and there is one") - Path.Log.debug( - " odd/end={} last={}".format(chord, lastChord) - ) + Path.Log.debug(" odd/end={} last={}".format(chord, lastChord)) bone = Bone( boneId, obj, @@ -973,9 +941,7 @@ class ObjectDressup(object): if lastBone: Path.Log.info(" removing potential path crossing") # debugMarker(chord.Start, "it", (0.0, 1.0, 1.0)) - commands, bones = self.removePathCrossing( - commands, lastBone, bone - ) + commands, bones = self.removePathCrossing(commands, lastBone, bone) commands.extend(bones[:-1]) lastCommand = bones[-1] haveNewLastCommand = True @@ -1060,7 +1026,7 @@ class ObjectDressup(object): # If the receiver was loaded from file, then it never generated the bone list. if not hasattr(self, "bones"): self.execute(obj) - for (nr, loc, enabled, inaccessible) in self.bones: + for nr, loc, enabled, inaccessible in self.bones: item = state.get((loc[0], loc[1])) if item: item[2].append(nr) @@ -1176,10 +1142,7 @@ class TaskPanel(object): item.setCheckState(QtCore.Qt.CheckState.Unchecked) flags = QtCore.Qt.ItemFlag.ItemIsSelectable if not inaccessible: - flags |= ( - QtCore.Qt.ItemFlag.ItemIsEnabled - | QtCore.Qt.ItemFlag.ItemIsUserCheckable - ) + flags |= QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsUserCheckable item.setFlags(flags) item.setData(self.DataIds, ids) item.setData(self.DataKey, ids[0]) @@ -1281,9 +1244,7 @@ class SelObserver(object): PST.clear() def addSelection(self, doc, obj, sub, pnt): - FreeCADGui.doCommand( - "Gui.Selection.addSelection(FreeCAD.ActiveDocument." + obj + ")" - ) + FreeCADGui.doCommand("Gui.Selection.addSelection(FreeCAD.ActiveDocument." + obj + ")") FreeCADGui.updateGui() @@ -1384,8 +1345,7 @@ class CommandDressupDogbone(object): baseObject = selection[0] if not baseObject.isDerivedFrom("Path::Feature"): FreeCAD.Console.PrintError( - translate("CAM_DressupDogbone", "The selected object is not a toolpath") - + "\n" + translate("CAM_DressupDogbone", "The selected object is not a toolpath") + "\n" ) return @@ -1393,8 +1353,7 @@ class CommandDressupDogbone(object): FreeCAD.ActiveDocument.openTransaction("Create Dogbone Dress-up") FreeCADGui.addModule("Path.Dressup.Gui.Dogbone") FreeCADGui.doCommand( - "Path.Dressup.Gui.Dogbone.Create(FreeCAD.ActiveDocument.%s)" - % baseObject.Name + "Path.Dressup.Gui.Dogbone.Create(FreeCAD.ActiveDocument.%s)" % baseObject.Name ) # FreeCAD.ActiveDocument.commitTransaction() # Final `commitTransaction()` called via TaskPanel.accept() FreeCAD.ActiveDocument.recompute() diff --git a/src/Mod/CAM/Path/Dressup/Gui/DogboneII.py b/src/Mod/CAM/Path/Dressup/Gui/DogboneII.py index 198beecf57..0f89835e68 100644 --- a/src/Mod/CAM/Path/Dressup/Gui/DogboneII.py +++ b/src/Mod/CAM/Path/Dressup/Gui/DogboneII.py @@ -163,9 +163,7 @@ class TaskPanel(object): markers = [] self.form.bones.clear() - for item in sorted( - itemList, key=lambda item: item.data(self.DataState).boneIDs()[0] - ): + for item in sorted(itemList, key=lambda item: item.data(self.DataState).boneIDs()[0]): self.form.bones.addItem(item) state = item.data(self.DataState) loc = state.boneTip() @@ -208,9 +206,7 @@ class TaskPanel(object): def setFields(self): self.setupCombo(self.form.styleCombo, self.obj.Style, DogboneII.Style.All) self.setupCombo(self.form.sideCombo, self.obj.Side, DogboneII.Side.All) - self.setupCombo( - self.form.incisionCombo, self.obj.Incision, DogboneII.Incision.All - ) + self.setupCombo(self.form.incisionCombo, self.obj.Incision, DogboneII.Incision.All) self.form.custom.setMinimum(0.0) self.form.custom.setDecimals(3) self.form.custom.setValue(self.obj.Custom) @@ -251,9 +247,7 @@ class SelObserver(object): PST.clear() def addSelection(self, doc, obj, sub, pnt): - FreeCADGui.doCommand( - "Gui.Selection.addSelection(FreeCAD.ActiveDocument." + obj + ")" - ) + FreeCADGui.doCommand("Gui.Selection.addSelection(FreeCAD.ActiveDocument." + obj + ")") FreeCADGui.updateGui() @@ -352,8 +346,7 @@ class CommandDressupDogboneII(object): baseObject = selection[0] if not baseObject.isDerivedFrom("Path::Feature"): FreeCAD.Console.PrintError( - translate("CAM_DressupDogbone", "The selected object is not a toolpath") - + "\n" + translate("CAM_DressupDogbone", "The selected object is not a toolpath") + "\n" ) return @@ -361,8 +354,7 @@ class CommandDressupDogboneII(object): FreeCAD.ActiveDocument.openTransaction("Create Dogbone Dress-up") FreeCADGui.addModule("Path.Dressup.Gui.DogboneII") FreeCADGui.doCommand( - "Path.Dressup.Gui.DogboneII.Create(FreeCAD.ActiveDocument.%s)" - % baseObject.Name + "Path.Dressup.Gui.DogboneII.Create(FreeCAD.ActiveDocument.%s)" % baseObject.Name ) # FreeCAD.ActiveDocument.commitTransaction() # Final `commitTransaction()` called via TaskPanel.accept() FreeCAD.ActiveDocument.recompute() diff --git a/src/Mod/CAM/Path/Dressup/Gui/Dragknife.py b/src/Mod/CAM/Path/Dressup/Gui/Dragknife.py index 102fd9ed7f..30cdc09854 100644 --- a/src/Mod/CAM/Path/Dressup/Gui/Dragknife.py +++ b/src/Mod/CAM/Path/Dressup/Gui/Dragknife.py @@ -70,9 +70,7 @@ class ObjectDressup: "App::PropertyFloat", "offset", "Path", - QT_TRANSLATE_NOOP( - "App::Property", "Distance the point trails behind the spindle" - ), + QT_TRANSLATE_NOOP("App::Property", "Distance the point trails behind the spindle"), ) obj.addProperty( "App::PropertyFloat", @@ -137,9 +135,7 @@ class ObjectDressup: currCommand.Placement.Base ) # Calculate vector at start of arc else: - radvector = arcLoc.sub( - prevCommand.Placement.Base - ) # Calculate vector at end of arc + radvector = arcLoc.sub(prevCommand.Placement.Base) # Calculate vector at end of arc v1 = radvector.cross(FreeCAD.Vector(0, 0, 1)) if currCommand.Name in ["G2", "G02"]: @@ -149,9 +145,7 @@ class ObjectDressup: prevCommand.Placement.Base ) # Straight segments are easy - myAngle = D.angle( - v1, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1) - ) + myAngle = D.angle(v1, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1)) return myAngle def getIncidentAngle(self, queue): @@ -175,9 +169,7 @@ class ObjectDressup: offset = obj.offset # Find the center of the old arc - C = FreeCAD.Base.Vector( - queue[2].x + queue[1].I, queue[2].y + queue[1].J, currLocation["Z"] - ) + C = FreeCAD.Base.Vector(queue[2].x + queue[1].I, queue[2].y + queue[1].J, currLocation["Z"]) # Find radius of old arc R = math.hypot(queue[1].I, queue[1].J) @@ -241,9 +233,7 @@ class ObjectDressup: # find angle of original center to startpoint v1 = queue[1].Placement.Base.sub(arccenter) - segAngle = D.angle( - v1, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1) - ) + segAngle = D.angle(v1, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1)) # Find angle subtended by the offset theta = offset / R @@ -299,9 +289,7 @@ class ObjectDressup: v1 = queue[1].Placement.Base.sub(queue[2].Placement.Base) # extend the current segment to comp for offset - segAngle = D.angle( - v1, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1) - ) + segAngle = D.angle(v1, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1)) xoffset = math.cos(segAngle) * offset yoffset = math.sin(segAngle) * offset @@ -343,9 +331,7 @@ class ObjectDressup: v2 = queue[0].Placement.Base.sub(queue[1].Placement.Base) # calc arc endpoints to twist to - segAngle = D.angle( - v2, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1) - ) + segAngle = D.angle(v2, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1)) xoffset = math.cos(segAngle) * offset yoffset = math.sin(segAngle) * offset newX = queue[1].x + xoffset @@ -356,9 +342,7 @@ class ObjectDressup: J = offsetvector.y # add the arc move - arcmove = Path.Command( - arcdir, {"X": newX, "Y": newY, "I": I, "J": J} - ) # add G2/G3 move + arcmove = Path.Command(arcdir, {"X": newX, "Y": newY, "I": I, "J": J}) # add G2/G3 move results.append(arcmove) currLocation.update(arcmove.Parameters) @@ -497,15 +481,9 @@ class TaskPanel: def __init__(self, obj): self.obj = obj self.form = FreeCADGui.PySideUic.loadUi(":/panels/DragKnifeEdit.ui") - self.filterAngle = PathGuiUtil.QuantitySpinBox( - self.form.filterAngle, obj, "filterAngle" - ) - self.offsetDistance = PathGuiUtil.QuantitySpinBox( - self.form.offsetDistance, obj, "offset" - ) - self.pivotHeight = PathGuiUtil.QuantitySpinBox( - self.form.pivotHeight, obj, "pivotheight" - ) + self.filterAngle = PathGuiUtil.QuantitySpinBox(self.form.filterAngle, obj, "filterAngle") + self.offsetDistance = PathGuiUtil.QuantitySpinBox(self.form.offsetDistance, obj, "offset") + self.pivotHeight = PathGuiUtil.QuantitySpinBox(self.form.pivotHeight, obj, "pivotheight") FreeCAD.ActiveDocument.openTransaction("Edit Dragknife Dress-up") @@ -618,14 +596,12 @@ class CommandDressupDragknife: selection = FreeCADGui.Selection.getSelection() if len(selection) != 1: FreeCAD.Console.PrintError( - translate("CAM_DressupDragKnife", "Please select one toolpath object") - + "\n" + translate("CAM_DressupDragKnife", "Please select one toolpath object") + "\n" ) return if not selection[0].isDerivedFrom("Path::Feature"): FreeCAD.Console.PrintError( - translate("CAM_DressupDragKnife", "The selected object is not a toolpath") - + "\n" + translate("CAM_DressupDragKnife", "The selected object is not a toolpath") + "\n" ) return if selection[0].isDerivedFrom("Path::FeatureCompoundPython"): @@ -649,9 +625,7 @@ class CommandDressupDragknife: FreeCADGui.doCommand( "obj.ViewObject.Proxy = Path.Dressup.Gui.Dragknife.ViewProviderDressup(obj.ViewObject)" ) - FreeCADGui.doCommand( - "Gui.ActiveDocument.getObject(base.Name).Visibility = False" - ) + FreeCADGui.doCommand("Gui.ActiveDocument.getObject(base.Name).Visibility = False") FreeCADGui.doCommand("obj.filterAngle = 20") FreeCADGui.doCommand("obj.offset = 2") FreeCADGui.doCommand("obj.pivotheight = 4") diff --git a/src/Mod/CAM/Path/Dressup/Gui/LeadInOut.py b/src/Mod/CAM/Path/Dressup/Gui/LeadInOut.py index ba7f389d3d..4bc39ee3e0 100644 --- a/src/Mod/CAM/Path/Dressup/Gui/LeadInOut.py +++ b/src/Mod/CAM/Path/Dressup/Gui/LeadInOut.py @@ -126,9 +126,7 @@ class ObjectDressup: "App::PropertyBool", "IncludeLayers", "Path", - QT_TRANSLATE_NOOP( - "App::Property", "Apply LeadInOut to layers within an operation" - ), + QT_TRANSLATE_NOOP("App::Property", "Apply LeadInOut to layers within an operation"), ) obj.Proxy = self @@ -164,15 +162,13 @@ class ObjectDressup: if obj.Length <= 0: Path.Log.error( - translate("CAM_DressupLeadInOut", "Length/Radius positive not Null") - + "\n" + translate("CAM_DressupLeadInOut", "Length/Radius positive not Null") + "\n" ) obj.Length = 0.1 if obj.LengthOut <= 0: Path.Log.error( - translate("CAM_DressupLeadInOut", "Length/Radius positive not Null") - + "\n" + translate("CAM_DressupLeadInOut", "Length/Radius positive not Null") + "\n" ) obj.LengthOut = 0.1 @@ -203,22 +199,18 @@ class ObjectDressup: # move to clearance height if first: - travel.append(PathLanguage.MoveStraight( - None, "G0", {"Z": op.ClearanceHeight.Value})) + travel.append(PathLanguage.MoveStraight(None, "G0", {"Z": op.ClearanceHeight.Value})) # move to correct xy-position - travel.append(PathLanguage.MoveStraight( - None, "G0", {"X": pos.x, "Y": pos.y})) + travel.append(PathLanguage.MoveStraight(None, "G0", {"X": pos.x, "Y": pos.y})) # move to correct z-position (either rapidly or in two steps) if obj.RapidPlunge: travel.append(PathLanguage.MoveStraight(None, "G0", {"Z": pos.z})) else: if first or not obj.KeepToolDown: - travel.append(PathLanguage.MoveStraight( - None, "G0", {"Z": op.SafeHeight.Value})) - travel.append(PathLanguage.MoveStraight( - None, "G1", {"Z": pos.z, "F": vertfeed})) + travel.append(PathLanguage.MoveStraight(None, "G0", {"Z": op.SafeHeight.Value})) + travel.append(PathLanguage.MoveStraight(None, "G1", {"Z": pos.z, "F": vertfeed})) return travel @@ -228,8 +220,7 @@ class ObjectDressup: # move to clearance height if last or not obj.KeepToolDown: - travel.append(PathLanguage.MoveStraight( - None, "G0", {"Z": op.ClearanceHeight.Value})) + travel.append(PathLanguage.MoveStraight(None, "G0", {"Z": op.ClearanceHeight.Value})) return travel @@ -272,8 +263,7 @@ class ObjectDressup: length = obj.Length.Value angle = move.anglesOfTangents()[0] tangent = -self.angleToVector(angle) * length - normal = self.angleToVector( - angle + self.getArcDirection(obj)) * length + normal = self.angleToVector(angle + self.getArcDirection(obj)) * length # prepend the selected lead-in if obj.StyleOn == "Arc": @@ -316,8 +306,7 @@ class ObjectDressup: length = obj.LengthOut.Value angle = move.anglesOfTangents()[1] tangent = self.angleToVector(angle) * length - normal = self.angleToVector( - angle + self.getArcDirection(obj)) * length + normal = self.angleToVector(angle + self.getArcDirection(obj)) * length # append the selected lead-out if obj.StyleOff == "Arc": @@ -340,9 +329,11 @@ class ObjectDressup: return lead def isCuttingMove(self, obj, instr): - return (instr.isMove() - and not instr.isRapid() - and (not obj.IncludeLayers or not instr.isPlunge())) + return ( + instr.isMove() + and not instr.isRapid() + and (not obj.IncludeLayers or not instr.isPlunge()) + ) def findLastCuttingMoveIndex(self, obj, source): for i in range(len(source) - 1, -1, -1): @@ -351,8 +342,7 @@ class ObjectDressup: return None def generateLeadInOutCurve(self, obj): - source = PathLanguage.Maneuver.FromPath( - PathUtils.getPathWithPlacement(obj.Base)).instr + source = PathLanguage.Maneuver.FromPath(PathUtils.getPathWithPlacement(obj.Base)).instr maneuver = PathLanguage.Maneuver() # Knowing weather a given instruction is the first cutting move is easy, @@ -479,21 +469,17 @@ class CommandPathDressupLeadInOut: selection = FreeCADGui.Selection.getSelection() if len(selection) != 1: Path.Log.error( - translate("CAM_DressupLeadInOut", "Please select one toolpath object") - + "\n" + translate("CAM_DressupLeadInOut", "Please select one toolpath object") + "\n" ) return baseObject = selection[0] if not baseObject.isDerivedFrom("Path::Feature"): Path.Log.error( - translate("CAM_DressupLeadInOut", "The selected object is not a toolpath") - + "\n" + translate("CAM_DressupLeadInOut", "The selected object is not a toolpath") + "\n" ) return if baseObject.isDerivedFrom("Path::FeatureCompoundPython"): - Path.Log.error( - translate("CAM_DressupLeadInOut", "Please select a Profile object") - ) + Path.Log.error(translate("CAM_DressupLeadInOut", "Please select a Profile object")) return # everything ok! @@ -512,9 +498,7 @@ class CommandPathDressupLeadInOut: FreeCADGui.doCommand( "obj.ViewObject.Proxy = Path.Dressup.Gui.LeadInOut.ViewProviderDressup(obj.ViewObject)" ) - FreeCADGui.doCommand( - "Gui.ActiveDocument.getObject(base.Name).Visibility = False" - ) + FreeCADGui.doCommand("Gui.ActiveDocument.getObject(base.Name).Visibility = False") App.ActiveDocument.commitTransaction() App.ActiveDocument.recompute() diff --git a/src/Mod/CAM/Path/Dressup/Gui/RampEntry.py b/src/Mod/CAM/Path/Dressup/Gui/RampEntry.py index d8fa6fbdc8..26ebd52fe5 100644 --- a/src/Mod/CAM/Path/Dressup/Gui/RampEntry.py +++ b/src/Mod/CAM/Path/Dressup/Gui/RampEntry.py @@ -242,12 +242,7 @@ class ObjectDressup: p0 = edge.Vertexes[0].Point p1 = edge.Vertexes[1].Point rampangle = self.angle - if ( - bb.XLength < 1e-6 - and bb.YLength < 1e-6 - and bb.ZLength > 0 - and p0.z > p1.z - ): + if bb.XLength < 1e-6 and bb.YLength < 1e-6 and bb.ZLength > 0 and p0.z > p1.z: # check if above ignoreAbove parameter - do not generate ramp if it is newEdge, cont = self.checkIgnoreAbove(edge) @@ -292,9 +287,7 @@ class ObjectDressup: if i >= len(edges): break if len(rampedges) == 0: - Path.Log.debug( - "No suitable edges for ramping, plunge will remain as such" - ) + Path.Log.debug("No suitable edges for ramping, plunge will remain as such") outedges.append(edge) else: if not covered: @@ -303,9 +296,7 @@ class ObjectDressup: for redge in rampedges: l = l + redge.Length if self.method == "RampMethod3": - rampangle = math.degrees( - math.atan(l / (plungelen / 2)) - ) + rampangle = math.degrees(math.atan(l / (plungelen / 2))) else: rampangle = math.degrees(math.atan(l / plungelen)) Path.Log.warning( @@ -317,15 +308,11 @@ class ObjectDressup: # Path.Log.debug("Doing ramp to edges: {}".format(rampedges)) if self.method == "RampMethod1": outedges.extend( - self.createRampMethod1( - rampedges, p0, projectionlen, rampangle - ) + self.createRampMethod1(rampedges, p0, projectionlen, rampangle) ) elif self.method == "RampMethod2": outedges.extend( - self.createRampMethod2( - rampedges, p0, projectionlen, rampangle - ) + self.createRampMethod2(rampedges, p0, projectionlen, rampangle) ) else: # if the ramp cannot be covered with Method3, revert to Method1 @@ -334,15 +321,11 @@ class ObjectDressup: if (not covered) and allowBounce: projectionlen = projectionlen * 2 outedges.extend( - self.createRampMethod1( - rampedges, p0, projectionlen, rampangle - ) + self.createRampMethod1(rampedges, p0, projectionlen, rampangle) ) else: outedges.extend( - self.createRampMethod3( - rampedges, p0, projectionlen, rampangle - ) + self.createRampMethod3(rampedges, p0, projectionlen, rampangle) ) else: outedges.append(edge) @@ -366,12 +349,7 @@ class ObjectDressup: bb = edge.BoundBox p0 = edge.Vertexes[0].Point p1 = edge.Vertexes[1].Point - if ( - bb.XLength < 1e-6 - and bb.YLength < 1e-6 - and bb.ZLength > 0 - and p0.z > p1.z - ): + if bb.XLength < 1e-6 and bb.YLength < 1e-6 and bb.ZLength > 0 and p0.z > p1.z: # plungelen = abs(p0.z-p1.z) Path.Log.debug( "Found plunge move at X:{} Y:{} From Z:{} to Z{}, Searching for closed loop".format( @@ -429,17 +407,12 @@ class ObjectDressup: p0 = edge.Vertexes[0].Point p1 = edge.Vertexes[1].Point if p0.z > self.ignoreAbove and ( - p1.z > self.ignoreAbove - or Path.Geom.isRoughly(p1.z, self.ignoreAbove.Value) + p1.z > self.ignoreAbove or Path.Geom.isRoughly(p1.z, self.ignoreAbove.Value) ): Path.Log.debug("Whole plunge move above 'ignoreAbove', ignoring") return (edge, True) - elif p0.z > self.ignoreAbove and not Path.Geom.isRoughly( - p0.z, self.ignoreAbove.Value - ): - Path.Log.debug( - "Plunge move partially above 'ignoreAbove', splitting into two" - ) + elif p0.z > self.ignoreAbove and not Path.Geom.isRoughly(p0.z, self.ignoreAbove.Value): + Path.Log.debug("Plunge move partially above 'ignoreAbove', splitting into two") newPoint = FreeCAD.Base.Vector(p0.x, p0.y, self.ignoreAbove) return (Part.makeLine(p0, newPoint), False) else: @@ -473,10 +446,7 @@ class ObjectDressup: def createRampEdge(self, originalEdge, startPoint, endPoint): # Path.Log.debug("Create edge from [{},{},{}] to [{},{},{}]".format(startPoint.x,startPoint.y, startPoint.z, endPoint.x, endPoint.y, endPoint.z)) - if ( - type(originalEdge.Curve) == Part.Line - or type(originalEdge.Curve) == Part.LineSegment - ): + if type(originalEdge.Curve) == Part.Line or type(originalEdge.Curve) == Part.LineSegment: return Part.makeLine(startPoint, endPoint) elif type(originalEdge.Curve) == Part.Circle: firstParameter = originalEdge.Curve.parameter(startPoint) @@ -705,9 +675,7 @@ class ObjectDressup: Path.Geom.xy(p0), Path.Geom.xy(rampedges[-1].valueAt(rampedges[-1].LastParameter)), ): - Path.Log.debug( - "The ramp forms a closed wire, needless to move on original Z height" - ) + Path.Log.debug("The ramp forms a closed wire, needless to move on original Z height") else: for i, redge in enumerate(rampedges): if redge.Length >= rampremaining: @@ -829,9 +797,7 @@ class ObjectDressup: if cmd.Name in ["G1", "G2", "G3", "G01", "G02", "G03"]: if zVal is not None and zVal2 != zVal: - if Path.Geom.isRoughly(xVal, xVal2) and Path.Geom.isRoughly( - yVal, yVal2 - ): + if Path.Geom.isRoughly(xVal, xVal2) and Path.Geom.isRoughly(yVal, yVal2): # this is a straight plunge params["F"] = vertFeed else: @@ -914,21 +880,17 @@ class CommandPathDressupRampEntry: selection = FreeCADGui.Selection.getSelection() if len(selection) != 1: Path.Log.error( - translate("CAM_DressupRampEntry", "Please select one toolpath object") - + "\n" + translate("CAM_DressupRampEntry", "Please select one toolpath object") + "\n" ) return baseObject = selection[0] if not baseObject.isDerivedFrom("Path::Feature"): Path.Log.error( - translate("CAM_DressupRampEntry", "The selected object is not a toolpath") - + "\n" + translate("CAM_DressupRampEntry", "The selected object is not a toolpath") + "\n" ) return if baseObject.isDerivedFrom("Path::FeatureCompoundPython"): - Path.Log.error( - translate("CAM_DressupRampEntry", "Please select a Profile object") - ) + Path.Log.error(translate("CAM_DressupRampEntry", "Please select a Profile object")) return # everything ok! @@ -946,9 +908,7 @@ class CommandPathDressupRampEntry: FreeCADGui.doCommand( "obj.ViewObject.Proxy = Path.Dressup.Gui.RampEntry.ViewProviderDressup(obj.ViewObject)" ) - FreeCADGui.doCommand( - "Gui.ActiveDocument.getObject(base.Name).Visibility = False" - ) + FreeCADGui.doCommand("Gui.ActiveDocument.getObject(base.Name).Visibility = False") FreeCADGui.doCommand("dbo.setup(obj)") # FreeCAD.ActiveDocument.commitTransaction() # Final `commitTransaction()` called via TaskPanel.accept() FreeCAD.ActiveDocument.recompute() diff --git a/src/Mod/CAM/Path/Dressup/Gui/TagPreferences.py b/src/Mod/CAM/Path/Dressup/Gui/TagPreferences.py index 9d30390c55..fa8915c583 100644 --- a/src/Mod/CAM/Path/Dressup/Gui/TagPreferences.py +++ b/src/Mod/CAM/Path/Dressup/Gui/TagPreferences.py @@ -42,71 +42,53 @@ class HoldingTagPreferences: @classmethod def defaultWidth(cls, ifNotSet): - value = Path.Preferences.preferences().GetFloat( - cls.DefaultHoldingTagWidth, ifNotSet - ) + value = Path.Preferences.preferences().GetFloat(cls.DefaultHoldingTagWidth, ifNotSet) if value == 0.0: return ifNotSet return value @classmethod def defaultHeight(cls, ifNotSet): - value = Path.Preferences.preferences().GetFloat( - cls.DefaultHoldingTagHeight, ifNotSet - ) + value = Path.Preferences.preferences().GetFloat(cls.DefaultHoldingTagHeight, ifNotSet) if value == 0.0: return ifNotSet return value @classmethod def defaultAngle(cls, ifNotSet=45.0): - value = Path.Preferences.preferences().GetFloat( - cls.DefaultHoldingTagAngle, ifNotSet - ) + value = Path.Preferences.preferences().GetFloat(cls.DefaultHoldingTagAngle, ifNotSet) if value < 10.0: return ifNotSet return value @classmethod def defaultCount(cls, ifNotSet=4): - value = Path.Preferences.preferences().GetUnsigned( - cls.DefaultHoldingTagCount, ifNotSet - ) + value = Path.Preferences.preferences().GetUnsigned(cls.DefaultHoldingTagCount, ifNotSet) if value < 2: return float(ifNotSet) return float(value) @classmethod def defaultRadius(cls, ifNotSet=0.0): - return Path.Preferences.preferences().GetFloat( - cls.DefaultHoldingTagRadius, ifNotSet - ) + return Path.Preferences.preferences().GetFloat(cls.DefaultHoldingTagRadius, ifNotSet) def __init__(self): if FreeCAD.GuiUp: import FreeCADGui - self.form = FreeCADGui.PySideUic.loadUi( - ":/preferences/PathDressupHoldingTags.ui" - ) + self.form = FreeCADGui.PySideUic.loadUi(":/preferences/PathDressupHoldingTags.ui") self.label = translate("CAM_DressupTag", "Holding Tag") def loadSettings(self): self.form.ifWidth.setText( - FreeCAD.Units.Quantity( - self.defaultWidth(0), FreeCAD.Units.Length - ).UserString + FreeCAD.Units.Quantity(self.defaultWidth(0), FreeCAD.Units.Length).UserString ) self.form.ifHeight.setText( - FreeCAD.Units.Quantity( - self.defaultHeight(0), FreeCAD.Units.Length - ).UserString + FreeCAD.Units.Quantity(self.defaultHeight(0), FreeCAD.Units.Length).UserString ) self.form.dsbAngle.setValue(self.defaultAngle()) self.form.ifRadius.setText( - FreeCAD.Units.Quantity( - self.defaultRadius(), FreeCAD.Units.Length - ).UserString + FreeCAD.Units.Quantity(self.defaultRadius(), FreeCAD.Units.Length).UserString ) self.form.sbCount.setValue(self.defaultCount()) diff --git a/src/Mod/CAM/Path/Dressup/Gui/Tags.py b/src/Mod/CAM/Path/Dressup/Gui/Tags.py index 9e3a707e0a..6e3eefc6a2 100644 --- a/src/Mod/CAM/Path/Dressup/Gui/Tags.py +++ b/src/Mod/CAM/Path/Dressup/Gui/Tags.py @@ -75,7 +75,9 @@ class PathDressupTagTaskPanel: self.editItem = None def getStandardButtons(self): - return QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Cancel + return ( + QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Cancel + ) def clicked(self, button): if button == QtGui.QDialogButtonBox.Apply: @@ -240,9 +242,7 @@ class PathDressupTagTaskPanel: self.Positions.append(FreeCAD.Vector(point.x, point.y, 0)) self.updateTagsView() else: - Path.Log.notice( - "ignore new tag at %s (obj=%s, on-path=%d" % (point, obj, 0) - ) + Path.Log.notice("ignore new tag at %s (obj=%s, on-path=%d" % (point, obj, 0)) def addNewTag(self): self.tags = self.getTags(True) @@ -346,14 +346,10 @@ class HoldingTagMarker: def setEnabled(self, enabled): self.enabled = enabled if enabled: - self.material.diffuseColor = ( - self.color[0] if not self.selected else self.color[2] - ) + self.material.diffuseColor = self.color[0] if not self.selected else self.color[2] self.material.transparency = 0.0 else: - self.material.diffuseColor = ( - self.color[1] if not self.selected else self.color[2] - ) + self.material.diffuseColor = self.color[1] if not self.selected else self.color[2] self.material.transparency = 0.6 @@ -393,9 +389,7 @@ class PathDressupTagViewProvider: pref = Path.Preferences.preferences() # R G B A - npc = pref.GetUnsigned( - "DefaultPathMarkerColor", ((85 * 256 + 255) * 256 + 0) * 256 + 255 - ) + npc = pref.GetUnsigned("DefaultPathMarkerColor", ((85 * 256 + 255) * 256 + 0) * 256 + 255) hpc = pref.GetUnsigned( "DefaultHighlightPathColor", ((255 * 256 + 125) * 256 + 0) * 256 + 255 ) @@ -420,9 +414,7 @@ class PathDressupTagViewProvider: if self.obj and self.obj.Base: for i in self.obj.Base.InList: - if hasattr(i, "Group") and self.obj.Base.Name in [ - o.Name for o in i.Group - ]: + if hasattr(i, "Group") and self.obj.Base.Name in [o.Name for o in i.Group]: i.Group = [o for o in i.Group if o.Name != self.obj.Base.Name] if self.obj.Base.ViewObject: self.obj.Base.ViewObject.Visibility = False @@ -459,9 +451,7 @@ class PathDressupTagViewProvider: self.switch.removeChild(tag.sep) tags = [] for i, p in enumerate(positions): - tag = HoldingTagMarker( - self.obj.Proxy.pointAtBottom(self.obj, p), self.colors - ) + tag = HoldingTagMarker(self.obj.Proxy.pointAtBottom(self.obj, p), self.colors) tag.setEnabled(not i in disabled) tags.append(tag) self.switch.addChild(tag.sep) @@ -523,9 +513,7 @@ class PathDressupTagViewProvider: z = self.tags[0].point.z p = FreeCAD.Vector(x, y, z) for i, tag in enumerate(self.tags): - if Path.Geom.pointsCoincide( - p, tag.point, tag.sphere.radius.getValue() * 1.3 - ): + if Path.Geom.pointsCoincide(p, tag.point, tag.sphere.radius.getValue() * 1.3): return i return -1 @@ -576,9 +564,7 @@ class CommandPathDressupTag: # check that the selection contains exactly what we want selection = FreeCADGui.Selection.getSelection() if len(selection) != 1: - Path.Log.error( - translate("CAM_DressupTag", "Please select one toolpath object") + "\n" - ) + Path.Log.error(translate("CAM_DressupTag", "Please select one toolpath object") + "\n") return baseObject = selection[0] diff --git a/src/Mod/CAM/Path/Dressup/Gui/ZCorrect.py b/src/Mod/CAM/Path/Dressup/Gui/ZCorrect.py index d4c038c5b4..435f699a06 100644 --- a/src/Mod/CAM/Path/Dressup/Gui/ZCorrect.py +++ b/src/Mod/CAM/Path/Dressup/Gui/ZCorrect.py @@ -65,9 +65,7 @@ class ObjectDressup: "App::PropertyFile", "probefile", "ProbeData", - QT_TRANSLATE_NOOP( - "App::Property", "The point file from the surface probing." - ), + QT_TRANSLATE_NOOP("App::Property", "The point file from the surface probing."), ) obj.Proxy = self obj.addProperty("Part::PropertyPartShape", "interpSurface", "Path") @@ -75,9 +73,7 @@ class ObjectDressup: "App::PropertyDistance", "ArcInterpolate", "Interpolate", - QT_TRANSLATE_NOOP( - "App::Property", "Deflection distance for arc interpolation" - ), + QT_TRANSLATE_NOOP("App::Property", "Deflection distance for arc interpolation"), ) obj.addProperty( "App::PropertyDistance", @@ -173,10 +169,7 @@ class ObjectDressup: Path.Log.debug(" curLoc:{}".format(currLocation)) newparams = dict(c.Parameters) zval = newparams.get("Z", currLocation["Z"]) - if ( - c.Name - in Path.Geom.CmdMoveStraight + Path.Geom.CmdMoveArc - ): + if c.Name in Path.Geom.CmdMoveStraight + Path.Geom.CmdMoveArc: curVec = FreeCAD.Vector( currLocation["X"], currLocation["Y"], @@ -196,9 +189,7 @@ class ObjectDressup: else: pointlist = [v.Point for v in arcwire.Vertexes] for point in pointlist: - offset = self._bilinearInterpolate( - surface, point.x, point.y - ) + offset = self._bilinearInterpolate(surface, point.x, point.y) commandparams = { "X": point.x, @@ -226,9 +217,7 @@ class TaskPanel: self.obj = obj self.form = FreeCADGui.PySideUic.loadUi(":/panels/ZCorrectEdit.ui") FreeCAD.ActiveDocument.openTransaction("Edit Z Correction Dress-up") - self.interpshape = FreeCAD.ActiveDocument.addObject( - "Part::Feature", "InterpolationSurface" - ) + self.interpshape = FreeCAD.ActiveDocument.addObject("Part::Feature", "InterpolationSurface") self.interpshape.Shape = obj.interpSurface self.interpshape.ViewObject.Transparency = 60 self.interpshape.ViewObject.ShapeColor = (1.00000, 1.00000, 0.01961) @@ -345,9 +334,7 @@ class CommandPathDressup: "Pixmap": "CAM_Dressup", "MenuText": QT_TRANSLATE_NOOP("CAM_DressupZCorrect", "Z Depth Correction"), "Accel": "", - "ToolTip": QT_TRANSLATE_NOOP( - "CAM_DressupZCorrect", "Use Probe Map to correct Z depth" - ), + "ToolTip": QT_TRANSLATE_NOOP("CAM_DressupZCorrect", "Use Probe Map to correct Z depth"), } def IsActive(self): @@ -371,9 +358,7 @@ class CommandPathDressup: ) return if selection[0].isDerivedFrom("Path::FeatureCompoundPython"): - FreeCAD.Console.PrintError( - translate("CAM_Dressup", "Please select a toolpath object") - ) + FreeCAD.Console.PrintError(translate("CAM_Dressup", "Please select a toolpath object")) return # everything ok! @@ -385,13 +370,9 @@ class CommandPathDressup: ) FreeCADGui.doCommand("Path.Dressup.Gui.ZCorrect.ObjectDressup(obj)") FreeCADGui.doCommand("obj.Base = FreeCAD.ActiveDocument." + selection[0].Name) - FreeCADGui.doCommand( - "Path.Dressup.Gui.ZCorrect.ViewProviderDressup(obj.ViewObject)" - ) + FreeCADGui.doCommand("Path.Dressup.Gui.ZCorrect.ViewProviderDressup(obj.ViewObject)") FreeCADGui.doCommand("PathScripts.PathUtils.addToJob(obj)") - FreeCADGui.doCommand( - "Gui.ActiveDocument.getObject(obj.Base.Name).Visibility = False" - ) + FreeCADGui.doCommand("Gui.ActiveDocument.getObject(obj.Base.Name).Visibility = False") FreeCADGui.doCommand("obj.ViewObject.Document.setEdit(obj.ViewObject, 0)") # FreeCAD.ActiveDocument.commitTransaction() # Final `commitTransaction()` called via TaskPanel.accept() FreeCAD.ActiveDocument.recompute() diff --git a/src/Mod/CAM/Path/Dressup/Tags.py b/src/Mod/CAM/Path/Dressup/Tags.py index f9b24ec2d2..dfab7a98eb 100644 --- a/src/Mod/CAM/Path/Dressup/Tags.py +++ b/src/Mod/CAM/Path/Dressup/Tags.py @@ -79,9 +79,7 @@ def debugMarker(vector, label, color=None, radius=0.5): obj = FreeCAD.ActiveDocument.addObject("Part::Sphere", label) obj.Label = label obj.Radius = radius - obj.Placement = FreeCAD.Placement( - vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0) - ) + obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0)) if color: obj.ViewObject.ShapeColor = color @@ -92,9 +90,7 @@ def debugCylinder(vector, r, height, label, color=None): obj.Label = label obj.Radius = r obj.Height = height - obj.Placement = FreeCAD.Placement( - vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0) - ) + obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0)) obj.ViewObject.Transparency = 90 if color: obj.ViewObject.ShapeColor = color @@ -107,9 +103,7 @@ def debugCone(vector, r1, r2, height, label, color=None): obj.Radius1 = r1 obj.Radius2 = r2 obj.Height = height - obj.Placement = FreeCAD.Placement( - vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0) - ) + obj.Placement = FreeCAD.Placement(vector, FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0)) obj.ViewObject.Transparency = 90 if color: obj.ViewObject.ShapeColor = color @@ -118,8 +112,7 @@ def debugCone(vector, r1, r2, height, label, color=None): class Tag: def __init__(self, nr, x, y, width, height, angle, radius, enabled=True): Path.Log.track( - "%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d" - % (x, y, width, height, angle, radius, enabled) + "%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d" % (x, y, width, height, angle, radius, enabled) ) self.nr = nr self.x = x @@ -190,9 +183,7 @@ class Tag: # degenerated case - no tag Path.Log.debug("Part.makeSphere(%f / 10000)" % (r1)) self.solid = Part.makeSphere(r1 / 10000) - if not Path.Geom.isRoughly( - 0, R - ): # testing is easier if the solid is not rotated + if not Path.Geom.isRoughly(0, R): # testing is easier if the solid is not rotated angle = -Path.Geom.getAngle(self.originAt(0)) * 180 / math.pi Path.Log.debug("solid.rotate(%f)" % angle) self.solid.rotate(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, 1), angle) @@ -212,9 +203,7 @@ class Tag: or type(face.Surface) == Part.Toroid ): Path.Log.track("it's a cone/cylinder, checking z") - return list( - [pt for pt in pts if pt.z >= self.bottom() and pt.z <= self.top()] - ) + return list([pt for pt in pts if pt.z >= self.bottom() and pt.z <= self.top()]) if type(face.Surface) == Part.Plane: Path.Log.track("it's a plane, checking R") c = face.Edges[0].Curve @@ -270,9 +259,7 @@ class Tag: zLast = edge.valueAt(edge.LastParameter).z zMax = self.top() if isDefinitelySmaller(zFirst, zMax) or isDefinitelySmaller(zLast, zMax): - return self.nextIntersectionClosestTo( - edge, self.solid, edge.valueAt(param) - ) + return self.nextIntersectionClosestTo(edge, self.solid, edge.valueAt(param)) return None def bbEdges(self): @@ -317,9 +304,7 @@ class MapWireToTag: self.edges = [] self.entry = i if tail: - Path.Log.debug( - "MapWireToTag(%s - %s)" % (i, tail.valueAt(tail.FirstParameter)) - ) + Path.Log.debug("MapWireToTag(%s - %s)" % (i, tail.valueAt(tail.FirstParameter))) else: Path.Log.debug("MapWireToTag(%s - )" % i) self.complete = False @@ -380,9 +365,9 @@ class MapWireToTag: p2 = e.valueAt(e.LastParameter) self.edgePoints.append(p1) self.edgePoints.append(p2) - if self.tag.solid.isInside( - p1, Path.Geom.Tolerance, False - ) or self.tag.solid.isInside(p2, Path.Geom.Tolerance, False): + if self.tag.solid.isInside(p1, Path.Geom.Tolerance, False) or self.tag.solid.isInside( + p2, Path.Geom.Tolerance, False + ): edges.remove(e) debugEdge(e, "......... X0", False) else: @@ -400,9 +385,7 @@ class MapWireToTag: # we need to add in the missing segment and collect the new entry/exit edges. if not self.entryEdges: Path.Log.debug("fill entryEdges ...") - self.realEntry = sorted( - self.edgePoints, key=lambda p: (p - self.entry).Length - )[0] + self.realEntry = sorted(self.edgePoints, key=lambda p: (p - self.entry).Length)[0] self.entryEdges = list( [e for e in edges if Path.Geom.edgeConnectsTo(e, self.realEntry)] ) @@ -411,12 +394,8 @@ class MapWireToTag: self.realEntry = None if not self.exitEdges: Path.Log.debug("fill exitEdges ...") - self.realExit = sorted( - self.edgePoints, key=lambda p: (p - self.exit).Length - )[0] - self.exitEdges = list( - [e for e in edges if Path.Geom.edgeConnectsTo(e, self.realExit)] - ) + self.realExit = sorted(self.edgePoints, key=lambda p: (p - self.exit).Length)[0] + self.exitEdges = list([e for e in edges if Path.Geom.edgeConnectsTo(e, self.realExit)]) edges.append(Part.Edge(Part.LineSegment(self.realExit, self.exit))) else: self.realExit = None @@ -485,9 +464,7 @@ class MapWireToTag: cnt = 0 for p in reversed(e.discretize(Deflection=0.01)): if not p0 is None: - outputEdges.append( - (Part.Edge(Part.LineSegment(p0, p)), True) - ) + outputEdges.append((Part.Edge(Part.LineSegment(p0, p)), True)) cnt = cnt + 1 p0 = p Path.Log.info("replaced edge with %d straight segments" % cnt) @@ -580,9 +557,7 @@ class MapWireToTag: else: if rapid: commands.append( - Path.Command( - "G0", {"X": rapid.x, "Y": rapid.y, "Z": rapid.z} - ) + Path.Command("G0", {"X": rapid.x, "Y": rapid.y, "Z": rapid.z}) ) rapid = None commands.extend( @@ -596,9 +571,7 @@ class MapWireToTag: ) ) if rapid: - commands.append( - Path.Command("G0", {"X": rapid.x, "Y": rapid.y, "Z": rapid.z}) - ) + commands.append(Path.Command("G0", {"X": rapid.x, "Y": rapid.y, "Z": rapid.z})) # rapid = None # commented out per LGTM suggestion return commands except Exception as e: @@ -618,9 +591,7 @@ class MapWireToTag: def add(self, edge): self.tail = None self.finalEdge = edge - if self.tag.solid.isInside( - edge.valueAt(edge.LastParameter), Path.Geom.Tolerance, True - ): + if self.tag.solid.isInside(edge.valueAt(edge.LastParameter), Path.Geom.Tolerance, True): Path.Log.track("solid.isInside") self.addEdge(edge) else: @@ -792,7 +763,7 @@ class PathData: tags = [] - for (i, count) in edgeDict.items(): + for i, count in edgeDict.items(): edge = self.baseWire.Edges[i] Path.Log.debug(" %d: %d" % (i, count)) # debugMarker(edge.Vertexes[0].Point, 'base', (1.0, 0.0, 0.0), 0.2) @@ -826,10 +797,7 @@ class PathData: if production or dist[0] < W: # russ4262:: `production` variable was a `True` declaration, forcing True branch to be processed always # The application of the `production` argument/variable is to appease LGTM - print( - "tag[%d/%d]: (%.2f, %.2f, %.2f)" - % (i, j, pos.x, pos.y, self.minZ) - ) + print("tag[%d/%d]: (%.2f, %.2f, %.2f)" % (i, j, pos.x, pos.y, self.minZ)) at = dist[1][0][0] tags.append(Tag(j, at.x, at.y, W, H, A, R, True)) j += 1 @@ -1092,14 +1060,10 @@ class ObjectTagDressup: vertRapid = tc.VertRapid.Value while edge or lastEdge < len(pathData.edges): - Path.Log.debug( - "------- lastEdge = %d/%d.%d/%d" % (lastEdge, lastTag, t, len(tags)) - ) + Path.Log.debug("------- lastEdge = %d/%d.%d/%d" % (lastEdge, lastTag, t, len(tags))) if not edge: edge = pathData.edges[lastEdge] - debugEdge( - edge, "======= new edge: %d/%d" % (lastEdge, len(pathData.edges)) - ) + debugEdge(edge, "======= new edge: %d/%d" % (lastEdge, len(pathData.edges))) lastEdge += 1 # sameTag = None @@ -1142,14 +1106,10 @@ class ObjectTagDressup: and not Path.Geom.isRoughly(0, v.Z) ): # The very first move is just to move to ClearanceHeight - commands.append( - Path.Command("G0", {"Z": v.Z, "F": horizRapid}) - ) + commands.append(Path.Command("G0", {"Z": v.Z, "F": horizRapid})) else: commands.append( - Path.Command( - "G0", {"X": v.X, "Y": v.Y, "Z": v.Z, "F": vertRapid} - ) + Path.Command("G0", {"X": v.X, "Y": v.Y, "Z": v.Z, "F": vertRapid}) ) else: commands.extend( @@ -1189,21 +1149,17 @@ class ObjectTagDressup: if tag.enabled: if prev: if prev.solid.common(tag.solid).Faces: - Path.Log.info( - "Tag #%d intersects with previous tag - disabling\n" % i - ) + Path.Log.info("Tag #%d intersects with previous tag - disabling\n" % i) Path.Log.debug("this tag = %d [%s]" % (i, tag.solid.BoundBox)) tag.enabled = False elif self.pathData.edges: e = self.pathData.edges[0] p0 = e.valueAt(e.FirstParameter) p1 = e.valueAt(e.LastParameter) - if tag.solid.isInside( - p0, Path.Geom.Tolerance, True - ) or tag.solid.isInside(p1, Path.Geom.Tolerance, True): - Path.Log.info( - "Tag #%d intersects with starting point - disabling\n" % i - ) + if tag.solid.isInside(p0, Path.Geom.Tolerance, True) or tag.solid.isInside( + p1, Path.Geom.Tolerance, True + ): + Path.Log.info("Tag #%d intersects with starting point - disabling\n" % i) tag.enabled = False if tag.enabled: @@ -1245,9 +1201,7 @@ class ObjectTagDressup: obj, obj.Positions, obj.Disabled ) if obj.Disabled != disabled: - Path.Log.debug( - "Updating properties.... %s vs. %s" % (obj.Disabled, disabled) - ) + Path.Log.debug("Updating properties.... %s vs. %s" % (obj.Disabled, disabled)) obj.Positions = positions obj.Disabled = disabled @@ -1259,9 +1213,7 @@ class ObjectTagDressup: try: self.processTags(obj) except Exception as e: - Path.Log.error( - "processing tags failed clearing all tags ... '%s'" % (e.args[0]) - ) + Path.Log.error("processing tags failed clearing all tags ... '%s'" % (e.args[0])) obj.Path = PathUtils.getPathWithPlacement(obj.Base) # update disabled in case there are some additional ones @@ -1282,9 +1234,7 @@ class ObjectTagDressup: for tag in self.tags: tagID += 1 if tag.enabled: - Path.Log.debug( - "x=%s, y=%s, z=%s" % (tag.x, tag.y, self.pathData.minZ) - ) + Path.Log.debug("x=%s, y=%s, z=%s" % (tag.x, tag.y, self.pathData.minZ)) # debugMarker(FreeCAD.Vector(tag.x, tag.y, self.pathData.minZ), "tag-%02d" % tagID , (1.0, 0.0, 1.0), 0.5) # if not Path.Geom.isRoughly(90, tag.angle): # debugCone(tag.originAt(self.pathData.minZ), tag.r1, tag.r2, tag.actualHeight, "tag-%02d" % tagID) @@ -1353,9 +1303,7 @@ def Create(baseObject, name="DressupTag"): Create(basePath, name='DressupTag') ... create tag dressup object for the given base path. """ if not baseObject.isDerivedFrom("Path::Feature"): - Path.Log.error( - translate("CAM_DressupTag", "The selected object is not a path") + "\n" - ) + Path.Log.error(translate("CAM_DressupTag", "The selected object is not a path") + "\n") return None if baseObject.isDerivedFrom("Path::FeatureCompoundPython"): diff --git a/src/Mod/CAM/Path/Dressup/Utils.py b/src/Mod/CAM/Path/Dressup/Utils.py index 3927f77bdf..e6492b421c 100644 --- a/src/Mod/CAM/Path/Dressup/Utils.py +++ b/src/Mod/CAM/Path/Dressup/Utils.py @@ -30,11 +30,7 @@ def selection(): import FreeCADGui sel = FreeCADGui.Selection.getSelectionEx() - if ( - len(sel) == 1 - and sel[0].Object.isDerivedFrom("Path::Feature") - and PathJob.Instances() - ): + if len(sel) == 1 and sel[0].Object.isDerivedFrom("Path::Feature") and PathJob.Instances(): return sel[0].Object return None diff --git a/src/Mod/CAM/Path/Geom.py b/src/Mod/CAM/Path/Geom.py index c915bead22..ecca7f3e98 100644 --- a/src/Mod/CAM/Path/Geom.py +++ b/src/Mod/CAM/Path/Geom.py @@ -86,7 +86,7 @@ CmdMoveRapid = ["G0", "G00"] CmdMoveStraight = ["G1", "G01"] CmdMoveCW = ["G2", "G02"] CmdMoveCCW = ["G3", "G03"] -CmdMoveDrill = ["G73", "G81", "G82", "G83","G85"] +CmdMoveDrill = ["G73", "G81", "G82", "G83", "G85"] CmdMoveArc = CmdMoveCW + CmdMoveCCW CmdMove = CmdMoveStraight + CmdMoveArc + CmdMoveDrill CmdMoveAll = CmdMove + CmdMoveRapid @@ -122,9 +122,9 @@ def edgesMatch(e0, e1, error=Tolerance): def edgeConnectsTo(edge, vector, error=Tolerance): """edgeConnectsTop(edge, vector, error=Tolerance) Returns True if edge connects to given vector.""" - return pointsCoincide( - edge.valueAt(edge.FirstParameter), vector, error - ) or pointsCoincide(edge.valueAt(edge.LastParameter), vector, error) + return pointsCoincide(edge.valueAt(edge.FirstParameter), vector, error) or pointsCoincide( + edge.valueAt(edge.LastParameter), vector, error + ) def normalizeAngle(a): @@ -287,27 +287,17 @@ def cmdsForEdge(edge, flip=False, useHelixForBSpline=True, segm=50, hSpeed=0, vS no direct Path.Command mapping and will be approximated by straight segments. segm is a factor for the segmentation of arbitrary curves not mapped to G1/2/3 commands. The higher the value the more segments will be used.""" - pt = ( - edge.valueAt(edge.LastParameter) - if not flip - else edge.valueAt(edge.FirstParameter) - ) + pt = edge.valueAt(edge.LastParameter) if not flip else edge.valueAt(edge.FirstParameter) params = {"X": pt.x, "Y": pt.y, "Z": pt.z} if type(edge.Curve) == Part.Line or type(edge.Curve) == Part.LineSegment: if hSpeed > 0 and vSpeed > 0: pt2 = ( - edge.valueAt(edge.FirstParameter) - if not flip - else edge.valueAt(edge.LastParameter) + edge.valueAt(edge.FirstParameter) if not flip else edge.valueAt(edge.LastParameter) ) params.update({"F": speedBetweenPoints(pt, pt2, hSpeed, vSpeed)}) commands = [Path.Command("G1", params)] else: - p1 = ( - edge.valueAt(edge.FirstParameter) - if not flip - else edge.valueAt(edge.LastParameter) - ) + p1 = edge.valueAt(edge.FirstParameter) if not flip else edge.valueAt(edge.LastParameter) p2 = edge.valueAt((edge.FirstParameter + edge.LastParameter) / 2) p3 = pt @@ -414,8 +404,7 @@ def edgeForCmd(cmd, startPoint): if isRoughly(d, 0, 0.005): Path.Log.debug( - "Half circle arc at: (%.2f, %.2f, %.2f)" - % (center.x, center.y, center.z) + "Half circle arc at: (%.2f, %.2f, %.2f)" % (center.x, center.y, center.z) ) # we're dealing with half a circle here angle = getAngle(A) + math.pi / 2 @@ -434,9 +423,7 @@ def edgeForCmd(cmd, startPoint): "arc: p1=(%.2f, %.2f) p2=(%.2f, %.2f) -> center=(%.2f, %.2f)" % (startPoint.x, startPoint.y, endPoint.x, endPoint.y, center.x, center.y) ) - Path.Log.debug( - "arc: A=(%.2f, %.2f) B=(%.2f, %.2f) -> d=%.2f" % (A.x, A.y, B.x, B.y, d) - ) + Path.Log.debug("arc: A=(%.2f, %.2f) B=(%.2f, %.2f) -> d=%.2f" % (A.x, A.y, B.x, B.y, d)) Path.Log.debug("arc: R=%.2f angle=%.2f" % (R, angle / math.pi)) if isRoughly(startPoint.z, endPoint.z): midPoint = center + Vector(math.cos(angle), math.sin(angle), 0) * R @@ -520,7 +507,8 @@ def wiresForPath(path, startPoint=Vector(0, 0, 0)): def arcToHelix(edge, z0, z1): """arcToHelix(edge, z0, z1) - Assuming edge is an arc it'll return a helix matching the arc starting at z0 and rising/falling to z1.""" + Assuming edge is an arc it'll return a helix matching the arc starting at z0 and rising/falling to z1. + """ p1 = edge.valueAt(edge.FirstParameter) # p2 = edge.valueAt(edge.LastParameter) @@ -626,14 +614,10 @@ def flipEdge(edge): if Part.Line == type(edge.Curve) and not edge.Vertexes: return Part.Edge( - Part.Line( - edge.valueAt(edge.LastParameter), edge.valueAt(edge.FirstParameter) - ) + Part.Line(edge.valueAt(edge.LastParameter), edge.valueAt(edge.FirstParameter)) ) elif Part.Line == type(edge.Curve) or Part.LineSegment == type(edge.Curve): - return Part.Edge( - Part.LineSegment(edge.Vertexes[-1].Point, edge.Vertexes[0].Point) - ) + return Part.Edge(Part.LineSegment(edge.Vertexes[-1].Point, edge.Vertexes[0].Point)) elif Part.Circle == type(edge.Curve): # Create an inverted circle circle = Part.Circle(edge.Curve.Center, -edge.Curve.Axis, edge.Curve.Radius) @@ -672,17 +656,13 @@ def flipEdge(edge): knots.reverse() flipped = Part.BSplineCurve() - flipped.buildFromPolesMultsKnots( - poles, mults, knots, perio, degree, weights, ratio - ) + flipped.buildFromPolesMultsKnots(poles, mults, knots, perio, degree, weights, ratio) return Part.Edge(flipped, ma + mi - edge.LastParameter, ma + mi - edge.FirstParameter) elif type(edge.Curve) == Part.OffsetCurve: return edge.reversed() - Path.Log.warning( - translate("PathGeom", "%s not supported for flipping") % type(edge.Curve) - ) + Path.Log.warning(translate("PathGeom", "%s not supported for flipping") % type(edge.Curve)) def flipWire(wire): diff --git a/src/Mod/CAM/Path/Main/Gui/Camotics.py b/src/Mod/CAM/Path/Main/Gui/Camotics.py index a29a000d77..c66fa652f0 100644 --- a/src/Mod/CAM/Path/Main/Gui/Camotics.py +++ b/src/Mod/CAM/Path/Main/Gui/Camotics.py @@ -185,9 +185,7 @@ class CamoticsSimulation(QtCore.QObject): self.SIM.set_resolution("high") bb = self.job.Stock.Shape.BoundBox - self.SIM.set_workpiece( - min=(bb.XMin, bb.YMin, bb.ZMin), max=(bb.XMax, bb.YMax, bb.ZMax) - ) + self.SIM.set_workpiece(min=(bb.XMin, bb.YMin, bb.ZMin), max=(bb.XMax, bb.YMax, bb.ZMax)) for t in self.job.Tools.Group: self.SIM.set_tool( @@ -272,9 +270,7 @@ class CamoticsSimulation(QtCore.QObject): "files": [], } - unitstring = ( - "imperial" if FreeCAD.Units.getSchema() in [2, 3, 5, 7] else "metric" - ) + unitstring = "imperial" if FreeCAD.Units.getSchema() in [2, 3, 5, 7] else "metric" camoticstemplate["units"] = unitstring camoticstemplate["resolution-mode"] = "medium" diff --git a/src/Mod/CAM/Path/Main/Gui/Fixture.py b/src/Mod/CAM/Path/Main/Gui/Fixture.py index 8f04562810..e701db08f5 100644 --- a/src/Mod/CAM/Path/Main/Gui/Fixture.py +++ b/src/Mod/CAM/Path/Main/Gui/Fixture.py @@ -151,9 +151,7 @@ class CommandPathFixture: return { "Pixmap": "CAM_Datums", "MenuText": QT_TRANSLATE_NOOP("CAM_Fixture", "Fixture"), - "ToolTip": QT_TRANSLATE_NOOP( - "CAM_Fixture", "Creates a Fixture Offset" - ), + "ToolTip": QT_TRANSLATE_NOOP("CAM_Fixture", "Creates a Fixture Offset"), } def IsActive(self): diff --git a/src/Mod/CAM/Path/Main/Gui/Inspect.py b/src/Mod/CAM/Path/Main/Gui/Inspect.py index 6adfec5d08..055f18de84 100644 --- a/src/Mod/CAM/Path/Main/Gui/Inspect.py +++ b/src/Mod/CAM/Path/Main/Gui/Inspect.py @@ -36,9 +36,7 @@ translate = FreeCAD.Qt.translate class GCodeHighlighter(QtGui.QSyntaxHighlighter): def __init__(self, parent=None): def convertcolor(c): - return QtGui.QColor( - int((c >> 24) & 0xFF), int((c >> 16) & 0xFF), int((c >> 8) & 0xFF) - ) + return QtGui.QColor(int((c >> 24) & 0xFF), int((c >> 16) & 0xFF), int((c >> 8) & 0xFF)) super(GCodeHighlighter, self).__init__(parent) p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Editor") @@ -62,25 +60,18 @@ class GCodeHighlighter(QtGui.QSyntaxHighlighter): self.highlightingRules = [] numberFormat = QtGui.QTextCharFormat() numberFormat.setForeground(colors[0]) - self.highlightingRules.append( - (QtCore.QRegularExpression("[\\-0-9\\.]"), numberFormat) - ) + self.highlightingRules.append((QtCore.QRegularExpression("[\\-0-9\\.]"), numberFormat)) keywordFormat = QtGui.QTextCharFormat() keywordFormat.setForeground(colors[1]) keywordFormat.setFontWeight(QtGui.QFont.Bold) keywordPatterns = ["\\bG[0-9]+\\b", "\\bM[0-9]+\\b"] self.highlightingRules.extend( - [ - (QtCore.QRegularExpression(pattern), keywordFormat) - for pattern in keywordPatterns - ] + [(QtCore.QRegularExpression(pattern), keywordFormat) for pattern in keywordPatterns] ) speedFormat = QtGui.QTextCharFormat() speedFormat.setFontWeight(QtGui.QFont.Bold) speedFormat.setForeground(colors[2]) - self.highlightingRules.append( - (QtCore.QRegularExpression("\\bF[0-9\\.]+\\b"), speedFormat) - ) + self.highlightingRules.append((QtCore.QRegularExpression("\\bF[0-9\\.]+\\b"), speedFormat)) def highlightBlock(self, text): @@ -108,9 +99,7 @@ class GCodeEditorDialog(QtGui.QDialog): p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/CAM") c = p.GetUnsigned("DefaultHighlightPathColor", 4286382335) - Q = QtGui.QColor( - int((c >> 24) & 0xFF), int((c >> 16) & 0xFF), int((c >> 8) & 0xFF) - ) + Q = QtGui.QColor(int((c >> 24) & 0xFF), int((c >> 16) & 0xFF), int((c >> 8) & 0xFF)) highlightcolor = ( Q.red() / 255.0, Q.green() / 255.0, @@ -118,9 +107,7 @@ class GCodeEditorDialog(QtGui.QDialog): Q.alpha() / 255.0, ) - self.selectionobj = FreeCAD.ActiveDocument.addObject( - "Path::Feature", "selection" - ) + self.selectionobj = FreeCAD.ActiveDocument.addObject("Path::Feature", "selection") self.selectionobj.ViewObject.LineWidth = 4 self.selectionobj.ViewObject.NormalColor = highlightcolor @@ -281,23 +268,19 @@ class CommandPathInspect: selection = FreeCADGui.Selection.getSelection() if len(selection) != 1: FreeCAD.Console.PrintError( - translate("CAM_Inspect", "Please select exactly one path object") - + "\n" + translate("CAM_Inspect", "Please select exactly one path object") + "\n" ) return if not (selection[0].isDerivedFrom("Path::Feature")): FreeCAD.Console.PrintError( - translate("CAM_Inspect", "Please select exactly one path object") - + "\n" + translate("CAM_Inspect", "Please select exactly one path object") + "\n" ) return # if everything is ok, execute FreeCADGui.addModule("Path.Main.Gui.Inspect") FreeCADGui.doCommand( - "Path.Main.Gui.Inspect.show(FreeCAD.ActiveDocument." - + selection[0].Name - + ")" + "Path.Main.Gui.Inspect.show(FreeCAD.ActiveDocument." + selection[0].Name + ")" ) diff --git a/src/Mod/CAM/Path/Main/Gui/Job.py b/src/Mod/CAM/Path/Main/Gui/Job.py index e25c8fc453..f9507401b6 100644 --- a/src/Mod/CAM/Path/Main/Gui/Job.py +++ b/src/Mod/CAM/Path/Main/Gui/Job.py @@ -254,9 +254,7 @@ class ViewProvider: return self.openTaskPanel("Model") if obj == self.obj.Stock: return self.openTaskPanel("Stock") - Path.Log.info( - "Expected a specific object to edit - %s not recognized" % obj.Label - ) + Path.Log.info("Expected a specific object to edit - %s not recognized" % obj.Label) return self.openTaskPanel() def uneditObject(self, obj=None): @@ -356,9 +354,7 @@ class MaterialDialog(QtWidgets.QDialog): self.setWindowTitle("Assign Material") - self.materialTree = FreeCADGui.UiLoader().createWidget( - "MatGui::MaterialTreeWidget" - ) + self.materialTree = FreeCADGui.UiLoader().createWidget("MatGui::MaterialTreeWidget") self.materialTreeWidget = MatGui.MaterialTreeWidget(self.materialTree) material_filter = Materials.MaterialFilter() @@ -440,9 +436,7 @@ class StockEdit(object): stock.ViewObject.Proxy.onEdit(_OpenCloseResourceEditor) def setLengthField(self, widget, prop): - widget.setText( - FreeCAD.Units.Quantity(prop.Value, FreeCAD.Units.Length).UserString - ) + widget.setText(FreeCAD.Units.Quantity(prop.Value, FreeCAD.Units.Length).UserString) # the following members must be overwritten by subclasses def editorFrame(self): @@ -576,17 +570,11 @@ class StockCreateBoxEdit(StockEdit): try: if self.IsStock(obj): if "length" in fields: - obj.Stock.Length = FreeCAD.Units.Quantity( - self.form.stockBoxLength.text() - ) + obj.Stock.Length = FreeCAD.Units.Quantity(self.form.stockBoxLength.text()) if "width" in fields: - obj.Stock.Width = FreeCAD.Units.Quantity( - self.form.stockBoxWidth.text() - ) + obj.Stock.Width = FreeCAD.Units.Quantity(self.form.stockBoxWidth.text()) if "height" in fields: - obj.Stock.Height = FreeCAD.Units.Quantity( - self.form.stockBoxHeight.text() - ) + obj.Stock.Height = FreeCAD.Units.Quantity(self.form.stockBoxHeight.text()) else: Path.Log.error("Stock not a box!") except Exception: @@ -602,15 +590,9 @@ class StockCreateBoxEdit(StockEdit): def setupUi(self, obj): self.setFields(obj) - self.form.stockBoxLength.textChanged.connect( - lambda: self.getFields(obj, ["length"]) - ) - self.form.stockBoxWidth.textChanged.connect( - lambda: self.getFields(obj, ["width"]) - ) - self.form.stockBoxHeight.textChanged.connect( - lambda: self.getFields(obj, ["height"]) - ) + self.form.stockBoxLength.textChanged.connect(lambda: self.getFields(obj, ["length"])) + self.form.stockBoxWidth.textChanged.connect(lambda: self.getFields(obj, ["width"])) + self.form.stockBoxHeight.textChanged.connect(lambda: self.getFields(obj, ["height"])) class StockCreateCylinderEdit(StockEdit): @@ -626,13 +608,9 @@ class StockCreateCylinderEdit(StockEdit): try: if self.IsStock(obj): if "radius" in fields: - obj.Stock.Radius = FreeCAD.Units.Quantity( - self.form.stockCylinderRadius.text() - ) + obj.Stock.Radius = FreeCAD.Units.Quantity(self.form.stockCylinderRadius.text()) if "height" in fields: - obj.Stock.Height = FreeCAD.Units.Quantity( - self.form.stockCylinderHeight.text() - ) + obj.Stock.Height = FreeCAD.Units.Quantity(self.form.stockCylinderHeight.text()) else: Path.Log.error(translate("CAM_Job", "Stock not a cylinder!")) except Exception: @@ -647,12 +625,8 @@ class StockCreateCylinderEdit(StockEdit): def setupUi(self, obj): self.setFields(obj) - self.form.stockCylinderRadius.textChanged.connect( - lambda: self.getFields(obj, ["radius"]) - ) - self.form.stockCylinderHeight.textChanged.connect( - lambda: self.getFields(obj, ["height"]) - ) + self.form.stockCylinderRadius.textChanged.connect(lambda: self.getFields(obj, ["radius"])) + self.form.stockCylinderHeight.textChanged.connect(lambda: self.getFields(obj, ["height"])) class StockFromExistingEdit(StockEdit): @@ -671,9 +645,7 @@ class StockFromExistingEdit(StockEdit): and obj.Stock.Objects[0] == stock ): if stock: - stock = PathJob.createResourceClone( - obj, stock, self.StockLabelPrefix, "Stock" - ) + stock = PathJob.createResourceClone(obj, stock, self.StockLabelPrefix, "Stock") stock.ViewObject.Visibility = True PathStock.SetupStockObject(stock, PathStock.StockType.Unknown) stock.Proxy.execute(stock) @@ -724,26 +696,18 @@ class TaskPanel: self.obj = vobj.Object self.deleteOnReject = deleteOnReject self.form = FreeCADGui.PySideUic.loadUi(":/panels/PathEdit.ui") - self.template = PathJobDlg.JobTemplateExport( - self.obj, self.form.jobBox.widget(1) - ) + self.template = PathJobDlg.JobTemplateExport(self.obj, self.form.jobBox.widget(1)) self.name = self.obj.Name vUnit = FreeCAD.Units.Quantity(1, FreeCAD.Units.Velocity).getUserPreferred()[2] self.form.toolControllerList.horizontalHeaderItem(1).setText("#") self.form.toolControllerList.horizontalHeaderItem(2).setText( - translate( - "Path", "H", "H is horizontal feed rate. Must be as short as possible" - ) + translate("Path", "H", "H is horizontal feed rate. Must be as short as possible") ) self.form.toolControllerList.horizontalHeaderItem(3).setText( - translate( - "Path", "V", "V is vertical feed rate. Must be as short as possible" - ) - ) - self.form.toolControllerList.horizontalHeader().setResizeMode( - 0, QtGui.QHeaderView.Stretch + translate("Path", "V", "V is vertical feed rate. Must be as short as possible") ) + self.form.toolControllerList.horizontalHeader().setResizeMode(0, QtGui.QHeaderView.Stretch) self.form.toolControllerList.horizontalHeaderItem(1).setToolTip( translate("Path", "Tool number") + " " ) @@ -763,9 +727,7 @@ class TaskPanel: self.form.toolControllerList.resizeColumnsToContents() currentPostProcessor = self.obj.PostProcessor - postProcessors = Path.Preferences.allEnabledPostProcessors( - ["", currentPostProcessor] - ) + postProcessors = Path.Preferences.allEnabledPostProcessors(["", currentPostProcessor]) for post in postProcessors: self.form.postProcessor.addItem(post) # update the enumeration values, just to make sure all selections are valid @@ -773,9 +735,7 @@ class TaskPanel: self.obj.PostProcessor = currentPostProcessor self.postProcessorDefaultTooltip = self.form.postProcessor.toolTip() - self.postProcessorArgsDefaultTooltip = ( - self.form.postProcessorArguments.toolTip() - ) + self.postProcessorArgsDefaultTooltip = self.form.postProcessorArguments.toolTip() # Populate the other comboboxes with enums from the job class comboToPropertyMap = [("orderBy", "OrderOutputBy")] @@ -790,12 +750,8 @@ class TaskPanel: self.stockCreateCylinder = None self.stockEdit = None - self.setupGlobal = PathSetupSheetGui.GlobalEditor( - self.obj.SetupSheet, self.form - ) - self.setupOps = PathSetupSheetGui.OpsDefaultEditor( - self.obj.SetupSheet, self.form - ) + self.setupGlobal = PathSetupSheetGui.GlobalEditor(self.obj.SetupSheet, self.form) + self.setupOps = PathSetupSheetGui.OpsDefaultEditor(self.obj.SetupSheet, self.form) def populateCombobox(self, form, enumTups, comboBoxesPropertyMap): """populateCombobox(form, enumTups, comboBoxesPropertyMap) ... populate comboboxes with translated enumerations @@ -879,25 +835,17 @@ class TaskPanel: if hasattr(self.obj.Proxy, "tooltipArgs") and self.obj.Proxy.tooltipArgs: self.form.postProcessorArguments.setToolTip(self.obj.Proxy.tooltipArgs) else: - self.form.postProcessorArguments.setToolTip( - self.postProcessorArgsDefaultTooltip - ) + self.form.postProcessorArguments.setToolTip(self.postProcessorArgsDefaultTooltip) else: self.form.postProcessor.setToolTip(self.postProcessorDefaultTooltip) - self.form.postProcessorArguments.setToolTip( - self.postProcessorArgsDefaultTooltip - ) + self.form.postProcessorArguments.setToolTip(self.postProcessorArgsDefaultTooltip) def getFields(self): """sets properties in the object to match the form""" if self.obj: self.obj.PostProcessor = str(self.form.postProcessor.currentText()) - self.obj.PostProcessorArgs = str( - self.form.postProcessorArguments.displayText() - ) - self.obj.PostProcessorOutputFile = str( - self.form.postProcessorOutputFile.text() - ) + self.obj.PostProcessorArgs = str(self.form.postProcessorArguments.displayText()) + self.obj.PostProcessorOutputFile = str(self.form.postProcessorOutputFile.text()) self.obj.Label = str(self.form.jobLabel.text()) self.obj.Description = str(self.form.jobDescription.toPlainText()) @@ -911,10 +859,7 @@ class TaskPanel: flist = [] for i in range(self.form.wcslist.count()): - if ( - self.form.wcslist.item(i).checkState() - == QtCore.Qt.CheckState.Checked - ): + if self.form.wcslist.item(i).checkState() == QtCore.Qt.CheckState.Checked: flist.append(self.form.wcslist.item(i).text()) self.obj.Fixtures = flist except Exception as e: @@ -1078,9 +1023,7 @@ class TaskPanel: self.form.operationMove.setEnabled(True) row = self.form.operationsList.currentRow() self.form.operationUp.setEnabled(row > 0) - self.form.operationDown.setEnabled( - row < self.form.operationsList.count() - 1 - ) + self.form.operationDown.setEnabled(row < self.form.operationsList.count() - 1) else: self.form.operationModify.setEnabled(False) self.form.operationMove.setEnabled(False) @@ -1128,9 +1071,7 @@ class TaskPanel: # can only delete what is selected delete = edit # ... but we want to make sure there's at least one TC left - if len(self.obj.Tools.Group) == len( - self.form.toolControllerList.selectedItems() - ): + if len(self.obj.Tools.Group) == len(self.form.toolControllerList.selectedItems()): delete = False # ... also don't want to delete any TCs that are already used if delete: @@ -1170,9 +1111,7 @@ class TaskPanel: if toolBit["path"] == tool.File: toolNum = toolBit["nr"] - tc = PathToolControllerGui.Create( - name=tool.Label, tool=tool, toolNumber=toolNum - ) + tc = PathToolControllerGui.Create(name=tool.Label, tool=tool, toolNumber=toolNum) self.obj.Proxy.addToolController(tc) FreeCAD.ActiveDocument.recompute() @@ -1204,13 +1143,9 @@ class TaskPanel: tc.SpindleSpeed = speed except Exception: pass - item.setText( - "%s%g" % ("+" if tc.SpindleDir == "Forward" else "-", tc.SpindleSpeed) - ) + item.setText("%s%g" % ("+" if tc.SpindleDir == "Forward" else "-", tc.SpindleSpeed)) elif "HorizFeed" == prop or "VertFeed" == prop: - vUnit = FreeCAD.Units.Quantity( - 1, FreeCAD.Units.Velocity - ).getUserPreferred()[2] + vUnit = FreeCAD.Units.Quantity(1, FreeCAD.Units.Velocity).getUserPreferred()[2] try: val = FreeCAD.Units.Quantity(item.text()) if FreeCAD.Units.Velocity == val.Unit: @@ -1235,9 +1170,7 @@ class TaskPanel: Path.Log.track(axis) def alignSel(sel, normal, flip=False): - Path.Log.track( - "Vector(%.2f, %.2f, %.2f)" % (normal.x, normal.y, normal.z), flip - ) + Path.Log.track("Vector(%.2f, %.2f, %.2f)" % (normal.x, normal.y, normal.z), flip) v = axis if flip: v = axis.negative() @@ -1291,12 +1224,10 @@ class TaskPanel: alignSel(sel, normal) elif "Edge" == sub.ShapeType: - normal = ( - sub.Vertexes[1].Point - sub.Vertexes[0].Point - ).normalize() - if Path.Geom.pointsCoincide( - axis, normal - ) or Path.Geom.pointsCoincide(axis, FreeCAD.Vector() - normal): + normal = (sub.Vertexes[1].Point - sub.Vertexes[0].Point).normalize() + if Path.Geom.pointsCoincide(axis, normal) or Path.Geom.pointsCoincide( + axis, FreeCAD.Vector() - normal + ): # Don't really know the orientation of an edge, so let's just flip the object # and if the user doesn't like it they can flip again alignSel(sel, normal, True) @@ -1325,9 +1256,7 @@ class TaskPanel: Path.Log.track(selObject.Label, name) feature = selObject.Shape.getElement(name) bb = feature.BoundBox - offset = FreeCAD.Vector( - axis.x * bb.XMax, axis.y * bb.YMax, axis.z * bb.ZMax - ) + offset = FreeCAD.Vector(axis.x * bb.XMax, axis.y * bb.YMax, axis.z * bb.ZMax) Path.Log.track(feature.BoundBox.ZMax, offset) p = selObject.Placement p.move(offset) @@ -1359,9 +1288,7 @@ class TaskPanel: Draft.rotate(sel.Object, angle, bb.Center, axis) else: for sel in selection: - Draft.rotate( - sel.Object, angle, sel.Object.Shape.BoundBox.Center, axis - ) + Draft.rotate(sel.Object, angle, sel.Object.Shape.BoundBox.Center, axis) def alignSetOrigin(self): (obj, by) = self.alignMoveToOrigin() @@ -1405,9 +1332,7 @@ class TaskPanel: def setupFromBaseEdit(): Path.Log.track(index, force) if force or not self.stockFromBase: - self.stockFromBase = StockFromBaseBoundBoxEdit( - self.obj, self.form, force - ) + self.stockFromBase = StockFromBaseBoundBoxEdit(self.obj, self.form, force) self.stockEdit = self.stockFromBase def setupCreateBoxEdit(): @@ -1419,17 +1344,13 @@ class TaskPanel: def setupCreateCylinderEdit(): Path.Log.track(index, force) if force or not self.stockCreateCylinder: - self.stockCreateCylinder = StockCreateCylinderEdit( - self.obj, self.form, force - ) + self.stockCreateCylinder = StockCreateCylinderEdit(self.obj, self.form, force) self.stockEdit = self.stockCreateCylinder def setupFromExisting(): Path.Log.track(index, force) if force or not self.stockFromExisting: - self.stockFromExisting = StockFromExistingEdit( - self.obj, self.form, force - ) + self.stockFromExisting = StockFromExistingEdit(self.obj, self.form, force) if self.stockFromExisting.candidates(self.obj): self.stockEdit = self.stockFromExisting return True @@ -1446,8 +1367,7 @@ class TaskPanel: setupFromExisting() else: Path.Log.error( - translate("CAM_Job", "Unsupported stock object %s") - % self.obj.Stock.Label + translate("CAM_Job", "Unsupported stock object %s") % self.obj.Stock.Label ) else: if index == StockFromBaseBoundBoxEdit.Index: @@ -1572,11 +1492,7 @@ class TaskPanel: for model, count in obsolete.items(): for i in range(count): # it seems natural to remove the last of all the base objects for a given model - base = [ - b - for b in obj.Model.Group - if proxy.baseObject(obj, b) == model - ][-1] + base = [b for b in obj.Model.Group if proxy.baseObject(obj, b) == model][-1] self.vproxy.forgetBaseVisibility(obj, base) self.obj.Proxy.removeBase(obj, base, True) # do not access any of the retired objects after this point, they don't exist anymore @@ -1620,9 +1536,7 @@ class TaskPanel: self.form.postProcessor.currentIndexChanged.connect(self.getFields) self.form.postProcessorArguments.editingFinished.connect(self.getFields) self.form.postProcessorOutputFile.editingFinished.connect(self.getFields) - self.form.postProcessorSetOutputFile.clicked.connect( - self.setPostProcessorOutputFile - ) + self.form.postProcessorSetOutputFile.clicked.connect(self.setPostProcessorOutputFile) # Workplan self.form.operationsList.itemSelectionChanged.connect(self.operationSelect) @@ -1635,9 +1549,7 @@ class TaskPanel: self.form.activeToolGroup.hide() # not supported yet # Tool controller - self.form.toolControllerList.itemSelectionChanged.connect( - self.toolControllerSelect - ) + self.form.toolControllerList.itemSelectionChanged.connect(self.toolControllerSelect) self.form.toolControllerList.itemChanged.connect(self.toolControllerChanged) self.form.toolControllerEdit.clicked.connect(self.toolControllerEdit) self.form.toolControllerDelete.clicked.connect(self.toolControllerDelete) @@ -1654,58 +1566,32 @@ class TaskPanel: self.form.stock.currentIndexChanged.connect(self.updateStockEditor) self.form.refreshStock.clicked.connect(self.refreshStock) - self.form.modelSetXAxis.clicked.connect( - lambda: self.modelSetAxis(FreeCAD.Vector(1, 0, 0)) - ) - self.form.modelSetYAxis.clicked.connect( - lambda: self.modelSetAxis(FreeCAD.Vector(0, 1, 0)) - ) - self.form.modelSetZAxis.clicked.connect( - lambda: self.modelSetAxis(FreeCAD.Vector(0, 0, 1)) - ) - self.form.modelSetX0.clicked.connect( - lambda: self.modelSet0(FreeCAD.Vector(-1, 0, 0)) - ) - self.form.modelSetY0.clicked.connect( - lambda: self.modelSet0(FreeCAD.Vector(0, -1, 0)) - ) - self.form.modelSetZ0.clicked.connect( - lambda: self.modelSet0(FreeCAD.Vector(0, 0, -1)) - ) + self.form.modelSetXAxis.clicked.connect(lambda: self.modelSetAxis(FreeCAD.Vector(1, 0, 0))) + self.form.modelSetYAxis.clicked.connect(lambda: self.modelSetAxis(FreeCAD.Vector(0, 1, 0))) + self.form.modelSetZAxis.clicked.connect(lambda: self.modelSetAxis(FreeCAD.Vector(0, 0, 1))) + self.form.modelSetX0.clicked.connect(lambda: self.modelSet0(FreeCAD.Vector(-1, 0, 0))) + self.form.modelSetY0.clicked.connect(lambda: self.modelSet0(FreeCAD.Vector(0, -1, 0))) + self.form.modelSetZ0.clicked.connect(lambda: self.modelSet0(FreeCAD.Vector(0, 0, -1))) self.form.setOrigin.clicked.connect(self.alignSetOrigin) self.form.moveToOrigin.clicked.connect(self.alignMoveToOrigin) - self.form.modelMoveLeftUp.clicked.connect( - lambda: self.modelMove(FreeCAD.Vector(-1, 1, 0)) - ) - self.form.modelMoveLeft.clicked.connect( - lambda: self.modelMove(FreeCAD.Vector(-1, 0, 0)) - ) + self.form.modelMoveLeftUp.clicked.connect(lambda: self.modelMove(FreeCAD.Vector(-1, 1, 0))) + self.form.modelMoveLeft.clicked.connect(lambda: self.modelMove(FreeCAD.Vector(-1, 0, 0))) self.form.modelMoveLeftDown.clicked.connect( lambda: self.modelMove(FreeCAD.Vector(-1, -1, 0)) ) - self.form.modelMoveUp.clicked.connect( - lambda: self.modelMove(FreeCAD.Vector(0, 1, 0)) - ) - self.form.modelMoveDown.clicked.connect( - lambda: self.modelMove(FreeCAD.Vector(0, -1, 0)) - ) + self.form.modelMoveUp.clicked.connect(lambda: self.modelMove(FreeCAD.Vector(0, 1, 0))) + self.form.modelMoveDown.clicked.connect(lambda: self.modelMove(FreeCAD.Vector(0, -1, 0))) - self.form.modelMoveRightUp.clicked.connect( - lambda: self.modelMove(FreeCAD.Vector(1, 1, 0)) - ) - self.form.modelMoveRight.clicked.connect( - lambda: self.modelMove(FreeCAD.Vector(1, 0, 0)) - ) + self.form.modelMoveRightUp.clicked.connect(lambda: self.modelMove(FreeCAD.Vector(1, 1, 0))) + self.form.modelMoveRight.clicked.connect(lambda: self.modelMove(FreeCAD.Vector(1, 0, 0))) self.form.modelMoveRightDown.clicked.connect( lambda: self.modelMove(FreeCAD.Vector(1, -1, 0)) ) - self.form.modelRotateLeft.clicked.connect( - lambda: self.modelRotate(FreeCAD.Vector(0, 0, 1)) - ) + self.form.modelRotateLeft.clicked.connect(lambda: self.modelRotate(FreeCAD.Vector(0, 0, 1))) self.form.modelRotateRight.clicked.connect( lambda: self.modelRotate(FreeCAD.Vector(0, 0, -1)) ) diff --git a/src/Mod/CAM/Path/Main/Gui/JobDlg.py b/src/Mod/CAM/Path/Main/Gui/JobDlg.py index 2e15fbd8f6..07cdc13661 100644 --- a/src/Mod/CAM/Path/Main/Gui/JobDlg.py +++ b/src/Mod/CAM/Path/Main/Gui/JobDlg.py @@ -68,13 +68,9 @@ class JobCreate: "The currently selected unit schema: \n '{}' for this document\n Does not use 'minutes' for velocity values. \n \nCNC machines require feed rate to be expressed in \nunit/minute. To ensure correct G-code: \nSelect a minute-based schema in preferences.\nFor example:\n 'Metric, Small Parts & CNC'\n 'US Customary'\n 'Imperial Decimal'", ).format(current_schema) header = translate("CAM_Job", "Warning") - msgbox = QtGui.QMessageBox( - QtGui.QMessageBox.Warning, header, msg - ) + msgbox = QtGui.QMessageBox(QtGui.QMessageBox.Warning, header, msg) - msgbox.addButton( - translate("CAM_Job", "Ok"), QtGui.QMessageBox.AcceptRole - ) + msgbox.addButton(translate("CAM_Job", "Ok"), QtGui.QMessageBox.AcceptRole) msgbox.addButton( translate("CAM_Job", "Don't Show This Anymore"), QtGui.QMessageBox.ActionRole, @@ -110,14 +106,10 @@ class JobCreate: ) jobResources = job.Model.Group + [job.Stock] else: - preSelected = Counter( - [obj.Label for obj in FreeCADGui.Selection.getSelection()] - ) + preSelected = Counter([obj.Label for obj in FreeCADGui.Selection.getSelection()]) jobResources = [] - self.candidates = sorted( - PathJob.ObjectJob.baseCandidates(), key=lambda o: o.Label - ) + self.candidates = sorted(PathJob.ObjectJob.baseCandidates(), key=lambda o: o.Label) # If there is only one possibility we might as well make sure it's selected if not preSelected and 1 == len(self.candidates): @@ -187,7 +179,9 @@ class JobCreate: self.delegate = _ItemDelegate(self, self.dialog.modelTree) self.model = QtGui.QStandardItemModel(self.dialog) - self.model.setHorizontalHeaderLabels([translate("CAM_Job","Model"), translate("CAM_Job", "Count")]) + self.model.setHorizontalHeaderLabels( + [translate("CAM_Job", "Model"), translate("CAM_Job", "Count")] + ) if self.itemsSolid.hasChildren(): self.model.appendRow(self.itemsSolid) @@ -299,9 +293,7 @@ class JobCreate: # Note that we do want to use the models (resource clones) of the # source job as base objects for the new job in order to get the # identical placement, and anything else that's been customized. - models.extend( - self.itemsJob.child(i, 0).data(self.DataObject).Model.Group - ) + models.extend(self.itemsJob.child(i, 0).data(self.DataObject).Model.Group) return models @@ -353,9 +345,7 @@ class JobTemplateExport: if job.Stock and not PathJob.isResourceClone(job, "Stock", "Stock"): stockType = PathStock.StockType.FromStock(job.Stock) if stockType == PathStock.StockType.FromBase: - seHint = translate( - "CAM_Job", "Base -/+ %.2f/%.2f %.2f/%.2f %.2f/%.2f" - ) % ( + seHint = translate("CAM_Job", "Base -/+ %.2f/%.2f %.2f/%.2f %.2f/%.2f") % ( job.Stock.ExtXneg, job.Stock.ExtXpos, job.Stock.ExtYneg, diff --git a/src/Mod/CAM/Path/Main/Gui/PreferencesJob.py b/src/Mod/CAM/Path/Main/Gui/PreferencesJob.py index 969fa3f600..6b4abdc7e5 100644 --- a/src/Mod/CAM/Path/Main/Gui/PreferencesJob.py +++ b/src/Mod/CAM/Path/Main/Gui/PreferencesJob.py @@ -41,9 +41,7 @@ class JobPreferencesPage: self.form.toolBox.setCurrentIndex(0) # Take that qt designer! self.postProcessorDefaultTooltip = self.form.defaultPostProcessor.toolTip() - self.postProcessorArgsDefaultTooltip = ( - self.form.defaultPostProcessorArgs.toolTip() - ) + self.postProcessorArgsDefaultTooltip = self.form.defaultPostProcessorArgs.toolTip() self.processor = {} def saveSettings(self): @@ -51,9 +49,7 @@ class JobPreferencesPage: jobTemplate = self.form.leDefaultJobTemplate.text() geometryTolerance = Units.Quantity(self.form.geometryTolerance.text()) curveAccuracy = Units.Quantity(self.form.curveAccuracy.text()) - Path.Preferences.setJobDefaults( - filePath, jobTemplate, geometryTolerance, curveAccuracy - ) + Path.Preferences.setJobDefaults(filePath, jobTemplate, geometryTolerance, curveAccuracy) if curveAccuracy: Path.Area.setDefaultParams(Accuracy=curveAccuracy) @@ -84,15 +80,9 @@ class JobPreferencesPage: ][self.form.stock.currentIndex()] attrs["create"] = typ if typ == PathStock.StockType.CreateBox: - attrs["length"] = FreeCAD.Units.Quantity( - self.form.stockBoxLength.text() - ).UserString - attrs["width"] = FreeCAD.Units.Quantity( - self.form.stockBoxWidth.text() - ).UserString - attrs["height"] = FreeCAD.Units.Quantity( - self.form.stockBoxHeight.text() - ).UserString + attrs["length"] = FreeCAD.Units.Quantity(self.form.stockBoxLength.text()).UserString + attrs["width"] = FreeCAD.Units.Quantity(self.form.stockBoxWidth.text()).UserString + attrs["height"] = FreeCAD.Units.Quantity(self.form.stockBoxHeight.text()).UserString if typ == PathStock.StockType.CreateCylinder: attrs["radius"] = FreeCAD.Units.Quantity( self.form.stockCylinderRadius.text() @@ -101,24 +91,12 @@ class JobPreferencesPage: self.form.stockCylinderHeight.text() ).UserString if typ == PathStock.StockType.FromBase: - attrs["xneg"] = FreeCAD.Units.Quantity( - self.form.stockExtXneg.text() - ).UserString - attrs["xpos"] = FreeCAD.Units.Quantity( - self.form.stockExtXpos.text() - ).UserString - attrs["yneg"] = FreeCAD.Units.Quantity( - self.form.stockExtYneg.text() - ).UserString - attrs["ypos"] = FreeCAD.Units.Quantity( - self.form.stockExtYpos.text() - ).UserString - attrs["zneg"] = FreeCAD.Units.Quantity( - self.form.stockExtZneg.text() - ).UserString - attrs["zpos"] = FreeCAD.Units.Quantity( - self.form.stockExtZpos.text() - ).UserString + attrs["xneg"] = FreeCAD.Units.Quantity(self.form.stockExtXneg.text()).UserString + attrs["xpos"] = FreeCAD.Units.Quantity(self.form.stockExtXpos.text()).UserString + attrs["yneg"] = FreeCAD.Units.Quantity(self.form.stockExtYneg.text()).UserString + attrs["ypos"] = FreeCAD.Units.Quantity(self.form.stockExtYpos.text()).UserString + attrs["zneg"] = FreeCAD.Units.Quantity(self.form.stockExtZneg.text()).UserString + attrs["zpos"] = FreeCAD.Units.Quantity(self.form.stockExtZpos.text()).UserString if self.form.stockPlacementGroup.isChecked(): angle = FreeCAD.Units.Quantity(self.form.stockAngle.text()).Value axis = FreeCAD.Vector( @@ -131,15 +109,9 @@ class JobPreferencesPage: attrs["rotY"] = rot.Q[1] attrs["rotZ"] = rot.Q[2] attrs["rotW"] = rot.Q[3] - attrs["posX"] = FreeCAD.Units.Quantity( - self.form.stockPositionX.text() - ).Value - attrs["posY"] = FreeCAD.Units.Quantity( - self.form.stockPositionY.text() - ).Value - attrs["posZ"] = FreeCAD.Units.Quantity( - self.form.stockPositionZ.text() - ).Value + attrs["posX"] = FreeCAD.Units.Quantity(self.form.stockPositionX.text()).Value + attrs["posY"] = FreeCAD.Units.Quantity(self.form.stockPositionY.text()).Value + attrs["posZ"] = FreeCAD.Units.Quantity(self.form.stockPositionZ.text()).Value Path.Preferences.setDefaultStockTemplate(json.dumps(attrs)) else: Path.Preferences.setDefaultStockTemplate("") @@ -194,35 +166,23 @@ class JobPreferencesPage: | QtCore.Qt.ItemFlag.ItemIsUserCheckable ) self.form.postProcessorList.addItem(item) - self.verifyAndUpdateDefaultPostProcessorWith( - Path.Preferences.defaultPostProcessor() - ) + self.verifyAndUpdateDefaultPostProcessorWith(Path.Preferences.defaultPostProcessor()) - self.form.defaultPostProcessorArgs.setText( - Path.Preferences.defaultPostProcessorArgs() - ) + self.form.defaultPostProcessorArgs.setText(Path.Preferences.defaultPostProcessorArgs()) - geomTol = Units.Quantity( - Path.Preferences.defaultGeometryTolerance(), Units.Length - ) + geomTol = Units.Quantity(Path.Preferences.defaultGeometryTolerance(), Units.Length) self.form.geometryTolerance.setText(geomTol.UserString) self.form.curveAccuracy.setText( - Units.Quantity( - Path.Preferences.defaultLibAreaCurveAccuracy(), Units.Length - ).UserString + Units.Quantity(Path.Preferences.defaultLibAreaCurveAccuracy(), Units.Length).UserString ) self.form.leOutputFile.setText(Path.Preferences.defaultOutputFile()) - self.selectComboEntry( - self.form.cboOutputPolicy, Path.Preferences.defaultOutputPolicy() - ) + self.selectComboEntry(self.form.cboOutputPolicy, Path.Preferences.defaultOutputPolicy()) self.form.tbDefaultFilePath.clicked.connect(self.browseDefaultFilePath) self.form.tbDefaultJobTemplate.clicked.connect(self.browseDefaultJobTemplate) self.form.postProcessorList.itemEntered.connect(self.setProcessorListTooltip) - self.form.postProcessorList.itemChanged.connect( - self.verifyAndUpdateDefaultPostProcessor - ) + self.form.postProcessorList.itemChanged.connect(self.verifyAndUpdateDefaultPostProcessor) self.form.defaultPostProcessor.currentIndexChanged.connect( self.updateDefaultPostProcessorToolTip ) @@ -324,9 +284,7 @@ class JobPreferencesPage: self.form.stockCreateCylinder.hide() def loadToolSettings(self): - self.form.toolsAbsolutePaths.setChecked( - Path.Preferences.toolsStoreAbsolutePaths() - ) + self.form.toolsAbsolutePaths.setChecked(Path.Preferences.toolsStoreAbsolutePaths()) def getPostProcessor(self, name): if not name in self.processor: @@ -355,14 +313,10 @@ class JobPreferencesPage: if processor.tooltipArgs: self.form.defaultPostProcessorArgs.setToolTip(processor.tooltipArgs) else: - self.form.defaultPostProcessorArgs.setToolTip( - self.postProcessorArgsDefaultTooltip - ) + self.form.defaultPostProcessorArgs.setToolTip(self.postProcessorArgsDefaultTooltip) else: self.form.defaultPostProcessor.setToolTip(self.postProcessorDefaultTooltip) - self.form.defaultPostProcessorArgs.setToolTip( - self.postProcessorArgsDefaultTooltip - ) + self.form.defaultPostProcessorArgs.setToolTip(self.postProcessorArgsDefaultTooltip) def bestGuessForFilePath(self): path = self.form.leDefaultFilePath.text() diff --git a/src/Mod/CAM/Path/Main/Gui/SanityCmd.py b/src/Mod/CAM/Path/Main/Gui/SanityCmd.py index 469cc44a39..f5c79b9a14 100644 --- a/src/Mod/CAM/Path/Main/Gui/SanityCmd.py +++ b/src/Mod/CAM/Path/Main/Gui/SanityCmd.py @@ -50,13 +50,9 @@ class CommandCAMSanity: def GetResources(self): return { "Pixmap": "CAM_Sanity", - "MenuText": QT_TRANSLATE_NOOP( - "CAM_Sanity", "Check the CAM job for common errors" - ), + "MenuText": QT_TRANSLATE_NOOP("CAM_Sanity", "Check the CAM job for common errors"), "Accel": "P, S", - "ToolTip": QT_TRANSLATE_NOOP( - "CAM_Sanity", "Check the CAM job for common errors" - ), + "ToolTip": QT_TRANSLATE_NOOP("CAM_Sanity", "Check the CAM job for common errors"), } def IsActive(self): @@ -67,7 +63,6 @@ class CommandCAMSanity: FreeCADGui.addIconPath(":/icons") obj = FreeCADGui.Selection.getSelectionEx()[0].Object - # Ask the user for a filename to save the report to file_location = QFileDialog.getSaveFileName( @@ -85,11 +80,9 @@ class CommandCAMSanity: return with open(file_location, "w") as fp: - fp.write(html) + fp.write(html) - FreeCAD.Console.PrintMessage( - "Sanity check report written to: {}\n".format(file_location) - ) + FreeCAD.Console.PrintMessage("Sanity check report written to: {}\n".format(file_location)) webbrowser.open_new_tab(file_location) diff --git a/src/Mod/CAM/Path/Main/Gui/Simulator.py b/src/Mod/CAM/Path/Main/Gui/Simulator.py index 0e4b53cf43..ea683745f9 100644 --- a/src/Mod/CAM/Path/Main/Gui/Simulator.py +++ b/src/Mod/CAM/Path/Main/Gui/Simulator.py @@ -83,9 +83,7 @@ class PathSimulation: def UpdateProgress(self): if self.numCommands > 0: - self.taskForm.form.progressBar.setValue( - self.iprogress * 100 / self.numCommands - ) + self.taskForm.form.progressBar.setValue(self.iprogress * 100 / self.numCommands) def Activate(self): self.initdone = False @@ -124,9 +122,7 @@ class PathSimulation: guiSelection = FreeCADGui.Selection.getSelectionEx() if guiSelection: # Identify job selected by user sel = guiSelection[0] - if hasattr(sel.Object, "Proxy") and isinstance( - sel.Object.Proxy, PathJob.ObjectJob - ): + if hasattr(sel.Object, "Proxy") and isinstance(sel.Object.Proxy, PathJob.ObjectJob): jobName = sel.Object.Name FreeCADGui.Selection.clearSelection() @@ -193,9 +189,7 @@ class PathSimulation: if not self.cutTool.Shape.isValid() or self.cutTool.Shape.isNull(): self.EndSimulation() raise RuntimeError( - "Path Simulation: Error in tool geometry - {}".format( - self.tool.Name - ) + "Path Simulation: Error in tool geometry - {}".format(self.tool.Name) ) self.cutTool.ViewObject.show() @@ -212,9 +206,7 @@ class PathSimulation: self.skipStep = False self.initialPos = Vector(0, 0, self.job.Stock.Shape.BoundBox.ZMax) # Add cut tool - self.cutTool = FreeCAD.ActiveDocument.addObject( - "Part::FeaturePython", "CutTool" - ) + self.cutTool = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "CutTool") self.cutTool.ViewObject.Proxy = 0 self.cutTool.ViewObject.hide() @@ -240,9 +232,7 @@ class PathSimulation: # Add cut path solid for debug if self.debug: - self.cutSolid = FreeCAD.ActiveDocument.addObject( - "Part::FeaturePython", "CutDebug" - ) + self.cutSolid = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "CutDebug") self.cutSolid.ViewObject.Proxy = 0 self.cutSolid.ViewObject.hide() @@ -270,9 +260,7 @@ class PathSimulation: if self.skipStep: self.curpos = self.RapidMove(cmd, self.curpos) else: - (pathSolid, self.curpos) = self.GetPathSolid( - self.tool, cmd, self.curpos - ) + (pathSolid, self.curpos) = self.GetPathSolid(self.tool, cmd, self.curpos) if cmd.Name in ["G80"]: self.firstDrill = True @@ -363,15 +351,9 @@ class PathSimulation: if self.firstDrill: extendcommands.append(Path.Command("G0", {"Z": cmd.r})) self.firstDrill = False - extendcommands.append( - Path.Command("G0", {"X": cmd.x, "Y": cmd.y, "Z": cmd.r}) - ) - extendcommands.append( - Path.Command("G1", {"X": cmd.x, "Y": cmd.y, "Z": cmd.z}) - ) - extendcommands.append( - Path.Command("G1", {"X": cmd.x, "Y": cmd.y, "Z": cmd.r}) - ) + extendcommands.append(Path.Command("G0", {"X": cmd.x, "Y": cmd.y, "Z": cmd.r})) + extendcommands.append(Path.Command("G1", {"X": cmd.x, "Y": cmd.y, "Z": cmd.z})) + extendcommands.append(Path.Command("G1", {"X": cmd.x, "Y": cmd.y, "Z": cmd.r})) for ecmd in extendcommands: self.curpos = self.voxSim.ApplyCommand(self.curpos, ecmd) if not self.disableAnim: @@ -630,9 +612,7 @@ class CommandPathSimulate: "Pixmap": "CAM_Simulator", "MenuText": QtCore.QT_TRANSLATE_NOOP("CAM_Simulator", "CAM Simulator"), "Accel": "P, M", - "ToolTip": QtCore.QT_TRANSLATE_NOOP( - "CAM_Simulator", "Simulate G-code on stock" - ), + "ToolTip": QtCore.QT_TRANSLATE_NOOP("CAM_Simulator", "Simulate G-code on stock"), } def IsActive(self): diff --git a/src/Mod/CAM/Path/Main/Gui/SimulatorGL.py b/src/Mod/CAM/Path/Main/Gui/SimulatorGL.py index be36a4e5af..7e878de93e 100644 --- a/src/Mod/CAM/Path/Main/Gui/SimulatorGL.py +++ b/src/Mod/CAM/Path/Main/Gui/SimulatorGL.py @@ -30,7 +30,7 @@ import FreeCAD import Path.Base.Util as PathUtil import Path.Dressup.Utils as PathDressup import Path.Main.Job as PathJob -from PathScripts import PathUtils +from PathScripts import PathUtils import CAMSimulator from FreeCAD import Vector, Placement, Rotation @@ -49,48 +49,45 @@ if FreeCAD.GuiUp: _filePath = os.path.dirname(os.path.abspath(__file__)) + def IsSame(x, y): - """ Check if two floats are the same within an epsilon - """ + """Check if two floats are the same within an epsilon""" return abs(x - y) < 0.0001 + def RadiusAt(edge, p): - """ Find the tool radius within a point on its circumference - """ + """Find the tool radius within a point on its circumference""" x = edge.valueAt(p).x y = edge.valueAt(p).y return math.sqrt(x * x + y * y) class CAMSimTaskUi: - """ Handles the simulator task panel - """ + """Handles the simulator task panel""" + def __init__(self, parent): # this will create a Qt widget from our ui file self.form = FreeCADGui.PySideUic.loadUi(":/panels/TaskCAMSimulator.ui") self.parent = parent def getStandardButtons(self, *_args): - """ Task panel needs only Close button - """ + """Task panel needs only Close button""" return QDialogButtonBox.Close def reject(self): - """ User Pressed the Close button - """ + """User Pressed the Close button""" self.parent.cancel() FreeCADGui.Control.closeDialog() def TSError(msg): - """ Display error message - """ + """Display error message""" QtGui.QMessageBox.information(None, "Path Simulation", msg) class CAMSimulation: - """ Handles and prepares CAM jobs for simulation - """ + """Handles and prepares CAM jobs for simulation""" + def __init__(self): self.debug = False self.stdrot = FreeCAD.Rotation(Vector(0, 0, 1), 0) @@ -114,12 +111,11 @@ class CAMSimulation: self.baseShape = None def Connect(self, but, sig): - """ Connect task panel buttons """ + """Connect task panel buttons""" QtCore.QObject.connect(but, QtCore.SIGNAL("clicked()"), sig) def FindClosestEdge(self, edges, px, pz): - """ Convert tool shape to tool profile needed by GL simulator - """ + """Convert tool shape to tool profile needed by GL simulator""" for edge in edges: p1 = edge.FirstParameter p2 = edge.LastParameter @@ -140,8 +136,7 @@ class CAMSimulation: return None, 0.0, 0.0 def FindTopMostEdge(self, edges): - """ Examine tool solid edges and find the top most one - """ + """Examine tool solid edges and find the top most one""" maxz = -99999999.0 topedge = None top_p1 = 0.0 @@ -164,11 +159,11 @@ class CAMSimulation: return topedge, top_p1, top_p2 def GetToolProfile(self, tool, resolution): - """ Get the edge profile of a tool solid. Basically locating the - side edge that OCC creates on any revolved object + """Get the edge profile of a tool solid. Basically locating the + side edge that OCC creates on any revolved object """ originalPlacement = tool.Placement - tool.Placement = Placement(Vector(0,0,0), Rotation(Vector(0,0,1),0), Vector(0,0,0)) + tool.Placement = Placement(Vector(0, 0, 0), Rotation(Vector(0, 0, 1), 0), Vector(0, 0, 0)) shape = tool.Shape tool.Placement = originalPlacement sideEdgeList = [] @@ -217,8 +212,7 @@ class CAMSimulation: return profile def Activate(self): - """ Invoke the simulator task panel - """ + """Invoke the simulator task panel""" self.initdone = False self.taskForm = CAMSimTaskUi(self) form = self.taskForm.form @@ -238,8 +232,7 @@ class CAMSimulation: # self.SetupSimulation() def _populateJobSelection(self, form): - """ Make Job selection combobox - """ + """Make Job selection combobox""" setJobIdx = 0 jobName = "" jIdx = 0 @@ -251,9 +244,7 @@ class CAMSimulation: guiSelection = FreeCADGui.Selection.getSelectionEx() if guiSelection: # Identify job selected by user sel = guiSelection[0] - if hasattr(sel.Object, "Proxy") and isinstance( - sel.Object.Proxy, PathJob.ObjectJob - ): + if hasattr(sel.Object, "Proxy") and isinstance(sel.Object.Proxy, PathJob.ObjectJob): jobName = sel.Object.Name FreeCADGui.Selection.clearSelection() @@ -275,8 +266,7 @@ class CAMSimulation: form.comboJobs.setCurrentIndex(0) def SetupSimulation(self): - """ Prepare all selected job operations for simulation - """ + """Prepare all selected job operations for simulation""" form = self.taskForm.form self.activeOps = [] self.numCommands = 0 @@ -291,8 +281,7 @@ class CAMSimulation: self.busy = False def onJobChange(self): - """ When a new job is selected from the drop-down, update job operation list - """ + """When a new job is selected from the drop-down, update job operation list""" form = self.taskForm.form j = self.jobs[form.comboJobs.currentIndex()] self.job = j @@ -311,8 +300,7 @@ class CAMSimulation: self.baseShape = None def onAccuracyBarChange(self): - """ Update simulation quality - """ + """Update simulation quality""" form = self.taskForm.form self.quality = form.sliderAccuracy.value() qualText = QtCore.QT_TRANSLATE_NOOP("CAM_Simulator", "High") @@ -323,8 +311,7 @@ class CAMSimulation: form.labelAccuracy.setText(qualText) def onOperationItemChange(self, _item): - """ Check if at least one operation is selected to enable the Play button - """ + """Check if at least one operation is selected to enable the Play button""" playvalid = False form = self.taskForm.form for i in range(form.listOperations.count()): @@ -334,8 +321,7 @@ class CAMSimulation: form.toolButtonPlay.setEnabled(playvalid) def SimPlay(self): - """ Activate the simulation - """ + """Activate the simulation""" self.SetupSimulation() self.millSim.ResetSimulation() for op in self.activeOps: @@ -351,28 +337,23 @@ class CAMSimulation: self.millSim.SetBaseShape(self.baseShape, 1) def cancel(self): - """ Cancel the simulation - """ + """Cancel the simulation""" class CommandCAMSimulate: - """ FreeCAD invoke simulation task panel command - """ + """FreeCAD invoke simulation task panel command""" + def GetResources(self): - """ Command info - """ + """Command info""" return { "Pixmap": "CAM_SimulatorGL", "MenuText": QtCore.QT_TRANSLATE_NOOP("CAM_Simulator", "New CAM Simulator"), "Accel": "P, N", - "ToolTip": QtCore.QT_TRANSLATE_NOOP( - "CAM_Simulator", "Simulate G-code on stock" - ), + "ToolTip": QtCore.QT_TRANSLATE_NOOP("CAM_Simulator", "Simulate G-code on stock"), } def IsActive(self): - """ Command is active if at least one CAM job exists - """ + """Command is active if at least one CAM job exists""" if FreeCAD.ActiveDocument is not None: for o in FreeCAD.ActiveDocument.Objects: if o.Name[:3] == "Job": @@ -380,8 +361,7 @@ class CommandCAMSimulate: return False def Activated(self): - """ Activate the simulation - """ + """Activate the simulation""" CamSimulation = CAMSimulation() CamSimulation.Activate() diff --git a/src/Mod/CAM/Path/Main/Job.py b/src/Mod/CAM/Path/Main/Job.py index 830cfabe6c..5dd6c86fc6 100644 --- a/src/Mod/CAM/Path/Main/Job.py +++ b/src/Mod/CAM/Path/Main/Job.py @@ -112,9 +112,7 @@ class ObjectJob: "App::PropertyFile", "PostProcessorOutputFile", "Output", - QT_TRANSLATE_NOOP( - "App::Property", "The G-code output file for this project" - ), + QT_TRANSLATE_NOOP("App::Property", "The G-code output file for this project"), ) obj.addProperty( "App::PropertyEnumeration", @@ -197,25 +195,19 @@ class ObjectJob: "App::PropertyBool", "SplitOutput", "Output", - QT_TRANSLATE_NOOP( - "App::Property", "Split output into multiple G-code files" - ), + QT_TRANSLATE_NOOP("App::Property", "Split output into multiple G-code files"), ) obj.addProperty( "App::PropertyEnumeration", "OrderOutputBy", "WCS", - QT_TRANSLATE_NOOP( - "App::Property", "If multiple WCS, order the output this way" - ), + QT_TRANSLATE_NOOP("App::Property", "If multiple WCS, order the output this way"), ) obj.addProperty( "App::PropertyStringList", "Fixtures", "WCS", - QT_TRANSLATE_NOOP( - "App::Property", "The Work Coordinate Systems for the Job" - ), + QT_TRANSLATE_NOOP("App::Property", "The Work Coordinate Systems for the Job"), ) obj.Fixtures = ["G54"] @@ -309,9 +301,7 @@ class ObjectJob: if obj.SetupSheet.ViewObject: import Path.Base.Gui.IconViewProvider - Path.Base.Gui.IconViewProvider.Attach( - obj.SetupSheet.ViewObject, "SetupSheet" - ) + Path.Base.Gui.IconViewProvider.Attach(obj.SetupSheet.ViewObject, "SetupSheet") obj.SetupSheet.Label = "SetupSheet" self.setupSheet = obj.SetupSheet.Proxy @@ -324,31 +314,23 @@ class ObjectJob: "App::PropertyLink", "Model", "Base", - QT_TRANSLATE_NOOP( - "App::Property", "The base objects for all operations" - ), + QT_TRANSLATE_NOOP("App::Property", "The base objects for all operations"), ) addModels = True elif obj.Model is None: addModels = True if addModels: - model = FreeCAD.ActiveDocument.addObject( - "App::DocumentObjectGroup", "Model" - ) + model = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", "Model") if model.ViewObject: model.ViewObject.Visibility = False if models: - model.addObjects( - [createModelResourceClone(obj, base) for base in models] - ) + model.addObjects([createModelResourceClone(obj, base) for base in models]) obj.Model = model obj.Model.Label = "Model" if hasattr(obj, "Base"): - Path.Log.info( - "Converting Job.Base to new Job.Model for {}".format(obj.Label) - ) + Path.Log.info("Converting Job.Base to new Job.Model for {}".format(obj.Label)) obj.Model.addObject(obj.Base) obj.Base = None obj.removeProperty("Base") @@ -369,9 +351,7 @@ class ObjectJob: addTable = True if addTable: - toolTable = FreeCAD.ActiveDocument.addObject( - "App::DocumentObjectGroup", "Tools" - ) + toolTable = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", "Tools") toolTable.Label = "Tools" if toolTable.ViewObject: toolTable.ViewObject.Visibility = False @@ -408,9 +388,7 @@ class ObjectJob: if getattr(obj, "Operations", None): # the first to tear down are the ops, they depend on other resources - Path.Log.debug( - "taking down ops: %s" % [o.Name for o in self.allOperations()] - ) + Path.Log.debug("taking down ops: %s" % [o.Name for o in self.allOperations()]) while obj.Operations.Group: op = obj.Operations.Group[0] if ( @@ -469,9 +447,7 @@ class ObjectJob: except Exception: name = obj.Operations.Name label = obj.Operations.Label - ops = FreeCAD.ActiveDocument.addObject( - "Path::FeatureCompoundPython", "Operations" - ) + ops = FreeCAD.ActiveDocument.addObject("Path::FeatureCompoundPython", "Operations") ops.ViewObject.Proxy = 0 ops.Group = obj.Operations.Group obj.Operations.Group = [] @@ -509,9 +485,7 @@ class ObjectJob: "App::PropertyStringList", "Fixtures", "WCS", - QT_TRANSLATE_NOOP( - "App::Property", "The Work Coordinate Systems for the Job" - ), + QT_TRANSLATE_NOOP("App::Property", "The Work Coordinate Systems for the Job"), ) obj.Fixtures = ["G54"] @@ -520,9 +494,7 @@ class ObjectJob: "App::PropertyEnumeration", "OrderOutputBy", "WCS", - QT_TRANSLATE_NOOP( - "App::Property", "If multiple WCS, order the output this way" - ), + QT_TRANSLATE_NOOP("App::Property", "If multiple WCS, order the output this way"), ) obj.OrderOutputBy = ["Fixture", "Tool", "Operation"] @@ -531,9 +503,7 @@ class ObjectJob: "App::PropertyBool", "SplitOutput", "Output", - QT_TRANSLATE_NOOP( - "App::Property", "Split output into multiple G-code files" - ), + QT_TRANSLATE_NOOP("App::Property", "Split output into multiple G-code files"), ) obj.SplitOutput = False @@ -588,9 +558,7 @@ class ObjectJob: self.setupSheet.setFromTemplate(attrs[JobTemplate.SetupSheet]) if attrs.get(JobTemplate.GeometryTolerance): - obj.GeometryTolerance = float( - attrs.get(JobTemplate.GeometryTolerance) - ) + obj.GeometryTolerance = float(attrs.get(JobTemplate.GeometryTolerance)) if attrs.get(JobTemplate.PostProcessor): obj.PostProcessor = attrs.get(JobTemplate.PostProcessor) if attrs.get(JobTemplate.PostProcessorArgs): @@ -598,9 +566,7 @@ class ObjectJob: else: obj.PostProcessorArgs = "" if attrs.get(JobTemplate.PostProcessorOutputFile): - obj.PostProcessorOutputFile = attrs.get( - JobTemplate.PostProcessorOutputFile - ) + obj.PostProcessorOutputFile = attrs.get(JobTemplate.PostProcessorOutputFile) if attrs.get(JobTemplate.Description): obj.Description = attrs.get(JobTemplate.Description) @@ -612,14 +578,10 @@ class ObjectJob: else: Path.Log.debug(f"skipping TC {tc['name']}") if attrs.get(JobTemplate.Stock): - obj.Stock = PathStock.CreateFromTemplate( - obj, attrs.get(JobTemplate.Stock) - ) + obj.Stock = PathStock.CreateFromTemplate(obj, attrs.get(JobTemplate.Stock)) if attrs.get(JobTemplate.Fixtures): - obj.Fixtures = [ - x for y in attrs.get(JobTemplate.Fixtures) for x in y - ] + obj.Fixtures = [x for y in attrs.get(JobTemplate.Fixtures) for x in y] if attrs.get(JobTemplate.OrderOutputBy): obj.OrderOutputBy = attrs.get(JobTemplate.OrderOutputBy) @@ -632,9 +594,7 @@ class ObjectJob: obj.Tools.Group = tcs else: Path.Log.error( - "Unsupported PathJob template version {}".format( - attrs.get(JobTemplate.Version) - ) + "Unsupported PathJob template version {}".format(attrs.get(JobTemplate.Version)) ) if not tcs: @@ -694,9 +654,7 @@ class ObjectJob: # Convert the formatted time from HH:MM:SS to just seconds opCycleTime = sum( x * int(t) - for x, t in zip( - [1, 60, 3600], reversed(formattedCycleTime.split(":")) - ) + for x, t in zip([1, 60, 3600], reversed(formattedCycleTime.split(":"))) ) except Exception: continue @@ -733,9 +691,7 @@ class ObjectJob: def addToolController(self, tc): group = self.obj.Tools.Group - Path.Log.debug( - "addToolController(%s): %s" % (tc.Label, [t.Label for t in group]) - ) + Path.Log.debug("addToolController(%s): %s" % (tc.Label, [t.Label for t in group])) if tc.Name not in [str(t.Name) for t in group]: tc.setExpression( "VertRapid", @@ -770,9 +726,7 @@ class ObjectJob: for sub in op.Group: collectBaseOps(sub) - if getattr(self.obj, "Operations", None) and getattr( - self.obj.Operations, "Group", None - ): + if getattr(self.obj, "Operations", None) and getattr(self.obj.Operations, "Group", None): for op in self.obj.Operations.Group: collectBaseOps(op) diff --git a/src/Mod/CAM/Path/Main/Sanity/HTMLTemplate.py b/src/Mod/CAM/Path/Main/Sanity/HTMLTemplate.py index f5837ec138..bfddab0009 100644 --- a/src/Mod/CAM/Path/Main/Sanity/HTMLTemplate.py +++ b/src/Mod/CAM/Path/Main/Sanity/HTMLTemplate.py @@ -20,6 +20,7 @@ # * * # *************************************************************************** from string import Template + """ This module contains the HTML template for the CAM Sanity report. """ diff --git a/src/Mod/CAM/Path/Main/Sanity/Sanity.py b/src/Mod/CAM/Path/Main/Sanity/Sanity.py index 7749be2ddc..974ab774da 100644 --- a/src/Mod/CAM/Path/Main/Sanity/Sanity.py +++ b/src/Mod/CAM/Path/Main/Sanity/Sanity.py @@ -64,15 +64,11 @@ class CAMSanity: raise ValueError( translate( "CAM_Sanity", - "output location {} doesn't exist".format( - os.path.dirname(output_file) - ), + "output location {} doesn't exist".format(os.path.dirname(output_file)), ) ) - self.image_builder = ImageBuilder.ImageBuilderFactory.get_image_builder( - self.filelocation - ) + self.image_builder = ImageBuilder.ImageBuilderFactory.get_image_builder(self.filelocation) self.data = self.summarize() def summarize(self): @@ -93,11 +89,7 @@ class CAMSanity: return data def squawk(self, operator, note, date=datetime.now(), squawkType="NOTE"): - squawkType = ( - squawkType - if squawkType in ("NOTE", "WARNING", "CAUTION", "TIP") - else "NOTE" - ) + squawkType = squawkType if squawkType in ("NOTE", "WARNING", "CAUTION", "TIP") else "NOTE" if squawkType == "TIP": squawk_icon = "Sanity_Bulb" @@ -225,12 +217,8 @@ class CAMSanity: ) else: if os.path.isfile(obj.LastPostProcessOutput): - data["filesize"] = str( - os.path.getsize(obj.LastPostProcessOutput) / 1000 - ) - data["linecount"] = str( - sum(1 for line in open(obj.LastPostProcessOutput)) - ) + data["filesize"] = str(os.path.getsize(obj.LastPostProcessOutput) / 1000) + data["linecount"] = str(sum(1 for line in open(obj.LastPostProcessOutput))) else: data["filesize"] = str(0.0) data["linecount"] = str(0) @@ -321,15 +309,9 @@ class CAMSanity: } bb = obj.Stock.Shape.BoundBox - data["xLen"] = FreeCAD.Units.Quantity( - bb.XLength, FreeCAD.Units.Length - ).UserString - data["yLen"] = FreeCAD.Units.Quantity( - bb.YLength, FreeCAD.Units.Length - ).UserString - data["zLen"] = FreeCAD.Units.Quantity( - bb.ZLength, FreeCAD.Units.Length - ).UserString + data["xLen"] = FreeCAD.Units.Quantity(bb.XLength, FreeCAD.Units.Length).UserString + data["yLen"] = FreeCAD.Units.Quantity(bb.YLength, FreeCAD.Units.Length).UserString + data["zLen"] = FreeCAD.Units.Quantity(bb.ZLength, FreeCAD.Units.Length).UserString data["material"] = "Not Specified" if hasattr(obj.Stock, "ShapeMaterial"): @@ -391,9 +373,9 @@ class CAMSanity: data["squawkData"].append( self.squawk( "CAMSanity", - translate( - "CAM_Sanity", "Tool number {} used by multiple tools" - ).format(TC.ToolNumber), + translate("CAM_Sanity", "Tool number {} used by multiple tools").format( + TC.ToolNumber + ), squawkType="CAUTION", ) ) @@ -414,9 +396,9 @@ class CAMSanity: data["squawkData"].append( self.squawk( "CAMSanity", - translate( - "CAM_Sanity", "Toolbit Shape for TC: {} not found" - ).format(TC.ToolNumber), + translate("CAM_Sanity", "Toolbit Shape for TC: {} not found").format( + TC.ToolNumber + ), squawkType="WARNING", ) ) @@ -434,9 +416,9 @@ class CAMSanity: data["squawkData"].append( self.squawk( "CAMSanity", - translate( - "CAM_Sanity", "Tool Controller '{}' has no feedrate" - ).format(TC.Label), + translate("CAM_Sanity", "Tool Controller '{}' has no feedrate").format( + TC.Label + ), squawkType="WARNING", ) ) @@ -446,9 +428,9 @@ class CAMSanity: data["squawkData"].append( self.squawk( "CAMSanity", - translate( - "CAM_Sanity", "Tool Controller '{}' has no spindlespeed" - ).format(TC.Label), + translate("CAM_Sanity", "Tool Controller '{}' has no spindlespeed").format( + TC.Label + ), squawkType="WARNING", ) ) @@ -472,9 +454,9 @@ class CAMSanity: data["squawkData"].append( self.squawk( "CAMSanity", - translate( - "CAM_Sanity", "Tool Controller '{}' is not used" - ).format(TC.Label), + translate("CAM_Sanity", "Tool Controller '{}' is not used").format( + TC.Label + ), squawkType="WARNING", ) ) @@ -487,9 +469,7 @@ class CAMSanity: # Convert an exception to its string representation return str(obj) # You might need to handle more types depending on your needs - return str( - obj - ) # Fallback to convert any other non-serializable types to string + return str(obj) # Fallback to convert any other non-serializable types to string def get_output_report(self): Path.Log.debug("get_output_url") diff --git a/src/Mod/CAM/Path/Main/Stock.py b/src/Mod/CAM/Path/Main/Stock.py index bc2a4850d5..939512abeb 100644 --- a/src/Mod/CAM/Path/Main/Stock.py +++ b/src/Mod/CAM/Path/Main/Stock.py @@ -86,9 +86,7 @@ def shapeBoundBox(obj): bb = bb.united(b) return bb if obj: - Path.Log.error( - translate("PathStock", "Invalid base object %s - no shape found") % obj.Name - ) + Path.Log.error(translate("PathStock", "Invalid base object %s - no shape found") % obj.Name) return None @@ -114,9 +112,7 @@ class StockFromBase(Stock): "App::PropertyLink", "Base", "Base", - QT_TRANSLATE_NOOP( - "App::Property", "The base object this stock is derived from" - ), + QT_TRANSLATE_NOOP("App::Property", "The base object this stock is derived from"), ) obj.addProperty( "App::PropertyDistance", @@ -204,19 +200,13 @@ class StockFromBase(Stock): return None def execute(self, obj): - bb = ( - shapeBoundBox(obj.Base.Group) - if obj.Base and hasattr(obj.Base, "Group") - else None - ) + bb = shapeBoundBox(obj.Base.Group) if obj.Base and hasattr(obj.Base, "Group") else None Path.Log.track(obj.Label, bb) # Sometimes, when the Base changes it's temporarily not assigned when # Stock.execute is triggered - it'll be set correctly the next time around. if bb: - self.origin = FreeCAD.Vector( - -obj.ExtXneg.Value, -obj.ExtYneg.Value, -obj.ExtZneg.Value - ) + self.origin = FreeCAD.Vector(-obj.ExtXneg.Value, -obj.ExtYneg.Value, -obj.ExtZneg.Value) self.length = bb.XLength + obj.ExtXneg.Value + obj.ExtXpos.Value self.width = bb.YLength + obj.ExtYneg.Value + obj.ExtYpos.Value @@ -433,16 +423,14 @@ def CreateCylinder(job, radius=None, height=None, placement=None): obj.Height = height elif base: bb = shapeBoundBox(base.Group) - obj.Radius = math.sqrt(bb.XLength ** 2 + bb.YLength ** 2) / 2.0 + obj.Radius = math.sqrt(bb.XLength**2 + bb.YLength**2) / 2.0 obj.Height = max(bb.ZLength, 1) if placement: obj.Placement = placement elif base: bb = shapeBoundBox(base.Group) - origin = FreeCAD.Vector( - (bb.XMin + bb.XMax) / 2, (bb.YMin + bb.YMax) / 2, bb.ZMin - ) + origin = FreeCAD.Vector((bb.XMin + bb.XMax) / 2, (bb.YMin + bb.YMax) / 2, bb.ZMin) obj.Placement = FreeCAD.Placement(origin, FreeCAD.Vector(), 0) SetupStockObject(obj, StockType.CreateCylinder) @@ -508,9 +496,7 @@ def CreateFromTemplate(job, template): and rotW is not None ): pos = FreeCAD.Vector(float(posX), float(posY), float(posZ)) - rot = FreeCAD.Rotation( - float(rotX), float(rotY), float(rotZ), float(rotW) - ) + rot = FreeCAD.Rotation(float(rotX), float(rotY), float(rotZ), float(rotW)) placement = FreeCAD.Placement(pos, rot) elif ( posX is not None @@ -584,8 +570,7 @@ def CreateFromTemplate(job, template): ) else: Path.Log.track( - " take placement (%s) and extent (%s) from model" - % (placement, extent) + " take placement (%s) and extent (%s) from model" % (placement, extent) ) return CreateBox(job, extent, placement) @@ -603,15 +588,13 @@ def CreateFromTemplate(job, template): return CreateCylinder(job, radius, height, placement) Path.Log.error( - translate("PathStock", "Unsupported stock type named {}").format( - stockType - ) + translate("PathStock", "Unsupported stock type named {}").format(stockType) ) else: Path.Log.error( - translate( - "PathStock", "Unsupported PathStock template version {}" - ).format(template.get("version")) + translate("PathStock", "Unsupported PathStock template version {}").format( + template.get("version") + ) ) return None diff --git a/src/Mod/CAM/Path/Op/Adaptive.py b/src/Mod/CAM/Path/Op/Adaptive.py index 98c12c48be..ade9b250ba 100644 --- a/src/Mod/CAM/Path/Op/Adaptive.py +++ b/src/Mod/CAM/Path/Op/Adaptive.py @@ -43,9 +43,7 @@ from lazy_loader.lazy_loader import LazyLoader Part = LazyLoader("Part", globals(), "Part") # TechDraw = LazyLoader('TechDraw', globals(), 'TechDraw') -FeatureExtensions = LazyLoader( - "Path.Op.FeatureExtension", globals(), "Path.Op.FeatureExtension" -) +FeatureExtensions = LazyLoader("Path.Op.FeatureExtension", globals(), "Path.Op.FeatureExtension") DraftGeomUtils = LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils") @@ -127,9 +125,7 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): for region in adaptiveResults: p1 = region["HelixCenterPoint"] p2 = region["StartPoint"] - r = math.sqrt( - (p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]) - ) + r = math.sqrt((p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1])) if r > helixRadius: helixRadius = r @@ -211,15 +207,11 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): region["HelixCenterPoint"][1] + r * math.sin(offsetFi), ] - op.commandlist.append( - Path.Command("(Helix to depth: %f)" % passEndDepth) - ) + op.commandlist.append(Path.Command("(Helix to depth: %f)" % passEndDepth)) if obj.UseHelixArcs is False: # rapid move to start point - op.commandlist.append( - Path.Command("G0", {"Z": obj.ClearanceHeight.Value}) - ) + op.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value})) op.commandlist.append( Path.Command( "G0", @@ -258,19 +250,11 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): if obj.HelixConeAngle == 0: while fi < maxfi: - x = region["HelixCenterPoint"][0] + r * math.cos( - fi + offsetFi - ) - y = region["HelixCenterPoint"][1] + r * math.sin( - fi + offsetFi - ) - z = passStartDepth - fi / maxfi * ( - passStartDepth - passEndDepth - ) + x = region["HelixCenterPoint"][0] + r * math.cos(fi + offsetFi) + y = region["HelixCenterPoint"][1] + r * math.sin(fi + offsetFi) + z = passStartDepth - fi / maxfi * (passStartDepth - passEndDepth) op.commandlist.append( - Path.Command( - "G1", {"X": x, "Y": y, "Z": z, "F": op.vertFeed} - ) + Path.Command("G1", {"X": x, "Y": y, "Z": z, "F": op.vertFeed}) ) # lx = x # ly = y @@ -279,17 +263,11 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): # one more circle at target depth to make sure center is cleared maxfi = maxfi + 2 * math.pi while fi < maxfi: - x = region["HelixCenterPoint"][0] + r * math.cos( - fi + offsetFi - ) - y = region["HelixCenterPoint"][1] + r * math.sin( - fi + offsetFi - ) + x = region["HelixCenterPoint"][0] + r * math.cos(fi + offsetFi) + y = region["HelixCenterPoint"][1] + r * math.sin(fi + offsetFi) z = passEndDepth op.commandlist.append( - Path.Command( - "G1", {"X": x, "Y": y, "Z": z, "F": op.horizFeed} - ) + Path.Command("G1", {"X": x, "Y": y, "Z": z, "F": op.horizFeed}) ) # lx = x # ly = y @@ -306,9 +284,7 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): # Calculate everything helix_height = passStartDepth - passEndDepth - r_extra = helix_height * math.tan( - math.radians(obj.HelixConeAngle) - ) + r_extra = helix_height * math.tan(math.radians(obj.HelixConeAngle)) HelixTopRadius = helixRadius + r_extra helix_full_height = HelixTopRadius * ( math.cos(math.radians(obj.HelixConeAngle)) @@ -354,16 +330,8 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): # Calculate some stuff for arcs at bottom p["X"] = p["X"] + region["HelixCenterPoint"][0] p["Y"] = p["Y"] + region["HelixCenterPoint"][1] - x_m = ( - region["HelixCenterPoint"][0] - - p["X"] - + region["HelixCenterPoint"][0] - ) - y_m = ( - region["HelixCenterPoint"][1] - - p["Y"] - + region["HelixCenterPoint"][1] - ) + x_m = region["HelixCenterPoint"][0] - p["X"] + region["HelixCenterPoint"][0] + y_m = region["HelixCenterPoint"][1] - p["Y"] + region["HelixCenterPoint"][1] i_off = (x_m - p["X"]) / 2 j_off = (y_m - p["Y"]) / 2 @@ -403,9 +371,7 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): ] # rapid move to start point - op.commandlist.append( - Path.Command("G0", {"Z": obj.ClearanceHeight.Value}) - ) + op.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value})) op.commandlist.append( Path.Command( "G0", @@ -549,9 +515,7 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): else: # no helix entry # rapid move to clearance height - op.commandlist.append( - Path.Command("G0", {"Z": obj.ClearanceHeight.Value}) - ) + op.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value})) op.commandlist.append( Path.Command( "G0", @@ -592,9 +556,7 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter): if motionType == area.AdaptiveMotionType.Cutting: z = passEndDepth if z != lz: - op.commandlist.append( - Path.Command("G1", {"Z": z, "F": op.vertFeed}) - ) + op.commandlist.append(Path.Command("G1", {"Z": z, "F": op.vertFeed})) op.commandlist.append( Path.Command("G1", {"X": x, "Y": y, "F": op.horizFeed}) @@ -754,9 +716,7 @@ def Execute(op, obj): if FreeCAD.GuiUp: for ( path - ) in ( - tpaths - ): # path[0] contains the MotionType, #path[1] contains list of points + ) in tpaths: # path[0] contains the MotionType, #path[1] contains list of points if path[0] == area.AdaptiveMotionType.Cutting: sceneDrawPath(path[1], (0, 0, 1)) @@ -805,9 +765,7 @@ def Execute(op, obj): obj.AdaptiveInputState = inputStateObject else: - Path.Log.info( - "*** Processing cancelled (after: %f sec).\n\n" % (time.time() - start) - ) + Path.Log.info("*** Processing cancelled (after: %f sec).\n\n" % (time.time() - start)) finally: if FreeCAD.GuiUp: diff --git a/src/Mod/CAM/Path/Op/Area.py b/src/Mod/CAM/Path/Op/Area.py index 559f454248..1b4e4aee1b 100644 --- a/src/Mod/CAM/Path/Op/Area.py +++ b/src/Mod/CAM/Path/Op/Area.py @@ -109,18 +109,12 @@ class ObjectOp(PathOp.ObjectOp): The default implementation returns the job's Base.Shape""" if job: if job.Stock: - Path.Log.debug( - "job=%s base=%s shape=%s" % (job, job.Stock, job.Stock.Shape) - ) + Path.Log.debug("job=%s base=%s shape=%s" % (job, job.Stock, job.Stock.Shape)) return job.Stock.Shape else: - Path.Log.warning( - translate("PathAreaOp", "job %s has no Base.") % job.Label - ) + Path.Log.warning(translate("PathAreaOp", "job %s has no Base.") % job.Label) else: - Path.Log.warning( - translate("PathAreaOp", "no job for operation %s found.") % obj.Label - ) + Path.Log.warning(translate("PathAreaOp", "no job for operation %s found.") % obj.Label) return None def areaOpOnChanged(self, obj, prop): @@ -203,9 +197,7 @@ class ObjectOp(PathOp.ObjectOp): ) ) Path.Log.debug( - "Default Depths are Start: {}, and Final: {}".format( - startDepth, finalDepth - ) + "Default Depths are Start: {}, and Final: {}".format(startDepth, finalDepth) ) self.areaOpSetDefaultValues(obj, job) @@ -223,9 +215,7 @@ class ObjectOp(PathOp.ObjectOp): area.add(baseobject) areaParams = self.areaOpAreaParams(obj, isHole) - areaParams["SectionTolerance"] = ( - FreeCAD.Base.Precision.confusion() * 10 - ) # basically 1e-06 + areaParams["SectionTolerance"] = FreeCAD.Base.Precision.confusion() * 10 # basically 1e-06 heights = [i for i in self.depthparams] Path.Log.debug("depths: {}".format(heights)) @@ -234,15 +224,11 @@ class ObjectOp(PathOp.ObjectOp): Path.Log.debug("Area with params: {}".format(area.getParams())) - sections = area.makeSections( - mode=0, project=self.areaOpUseProjection(obj), heights=heights - ) + sections = area.makeSections(mode=0, project=self.areaOpUseProjection(obj), heights=heights) Path.Log.debug("sections = %s" % sections) # Rest machining - self.sectionShapes = self.sectionShapes + [ - section.toTopoShape() for section in sections - ] + self.sectionShapes = self.sectionShapes + [section.toTopoShape() for section in sections] if hasattr(obj, "UseRestMachining") and obj.UseRestMachining: restSections = [] for section in sections: @@ -250,11 +236,7 @@ class ObjectOp(PathOp.ObjectOp): z = bbox.ZMin sectionClearedAreas = [] for op in self.job.Operations.Group: - if self in [ - x.Proxy - for x in [op] + op.OutListRecursive - if hasattr(x, "Proxy") - ]: + if self in [x.Proxy for x in [op] + op.OutListRecursive if hasattr(x, "Proxy")]: break if hasattr(op, "Active") and op.Active and op.Path: tool = ( @@ -264,9 +246,7 @@ class ObjectOp(PathOp.ObjectOp): ) diameter = tool.Diameter.getValueAs("mm") dz = ( - 0 - if not hasattr(tool, "TipAngle") - else -PathUtils.drillTipLength(tool) + 0 if not hasattr(tool, "TipAngle") else -PathUtils.drillTipLength(tool) ) # for drills, dz translates to the full width part of the tool sectionClearedAreas.append( section.getClearedArea( @@ -314,9 +294,7 @@ class ObjectOp(PathOp.ObjectOp): elif PathOp.FeatureStartPoint & self.opFeatures(obj) and obj.UseStartPoint: pathParams["start"] = obj.StartPoint - obj.PathParams = str( - {key: value for key, value in pathParams.items() if key != "shapes"} - ) + obj.PathParams = str({key: value for key, value in pathParams.items() if key != "shapes"}) Path.Log.debug("Path with params: {}".format(obj.PathParams)) (pp, end_vector) = Path.fromShapes(**pathParams) @@ -331,9 +309,7 @@ class ObjectOp(PathOp.ObjectOp): areaParams["Thicken"] = True areaParams["ToolRadius"] = self.radius - self.radius * 0.005 area.setParams(**areaParams) - sec = area.makeSections(mode=0, project=False, heights=heights)[ - -1 - ].getShape() + sec = area.makeSections(mode=0, project=False, heights=heights)[-1].getShape() simobj = sec.extrude(FreeCAD.Vector(0, 0, baseobject.BoundBox.ZMax)) return pp, simobj @@ -411,9 +387,7 @@ class ObjectOp(PathOp.ObjectOp): self.leadIn = 2.0 # Initiate depthparams and calculate operation heights for operation - self.depthparams = self._customDepthParams( - obj, obj.StartDepth.Value, obj.FinalDepth.Value - ) + self.depthparams = self._customDepthParams(obj, obj.StartDepth.Value, obj.FinalDepth.Value) # Set start point if PathOp.FeatureStartPoint & self.opFeatures(obj) and obj.UseStartPoint: @@ -439,9 +413,7 @@ class ObjectOp(PathOp.ObjectOp): shp = Part.makeCompound(s[0]) else: shp = s[0] - locations.append( - {"x": shp.BoundBox.XMax, "y": shp.BoundBox.YMax, "shape": s} - ) + locations.append({"x": shp.BoundBox.XMax, "y": shp.BoundBox.YMax, "shape": s}) locations = PathUtils.sort_locations(locations, ["x", "y"]) @@ -454,22 +426,15 @@ class ObjectOp(PathOp.ObjectOp): if sub == "OpenEdge": profileEdgesIsOpen = True - if ( - PathOp.FeatureStartPoint & self.opFeatures(obj) - and obj.UseStartPoint - ): + if PathOp.FeatureStartPoint & self.opFeatures(obj) and obj.UseStartPoint: osp = obj.StartPoint self.commandlist.append( - Path.Command( - "G0", {"X": osp.x, "Y": osp.y, "F": self.horizRapid} - ) + Path.Command("G0", {"X": osp.x, "Y": osp.y, "F": self.horizRapid}) ) try: if profileEdgesIsOpen: - (pp, sim) = self._buildProfileOpenEdges( - obj, shape, isHole, start, getsim - ) + (pp, sim) = self._buildProfileOpenEdges(obj, shape, isHole, start, getsim) else: (pp, sim) = self._buildPathArea(obj, shape, isHole, start, getsim) except Exception as e: @@ -491,9 +456,7 @@ class ObjectOp(PathOp.ObjectOp): ): self.endVector[2] = obj.ClearanceHeight.Value self.commandlist.append( - Path.Command( - "G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid} - ) + Path.Command("G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid}) ) Path.Log.debug("obj.Name: " + str(obj.Name) + "\n\n") diff --git a/src/Mod/CAM/Path/Op/Base.py b/src/Mod/CAM/Path/Op/Base.py index 64f7a824e0..25bdb9afd6 100644 --- a/src/Mod/CAM/Path/Op/Base.py +++ b/src/Mod/CAM/Path/Op/Base.py @@ -121,9 +121,7 @@ class ObjectOp(object): "App::PropertyDistance", "OpStartDepth", "Op Values", - QT_TRANSLATE_NOOP( - "App::Property", "Holds the calculated value for the StartDepth" - ), + QT_TRANSLATE_NOOP("App::Property", "Holds the calculated value for the StartDepth"), ) obj.setEditorMode("OpStartDepth", 1) # read-only if "final" in values: @@ -131,9 +129,7 @@ class ObjectOp(object): "App::PropertyDistance", "OpFinalDepth", "Op Values", - QT_TRANSLATE_NOOP( - "App::Property", "Holds the calculated value for the FinalDepth" - ), + QT_TRANSLATE_NOOP("App::Property", "Holds the calculated value for the FinalDepth"), ) obj.setEditorMode("OpFinalDepth", 1) # read-only if "tooldia" in values: @@ -175,9 +171,7 @@ class ObjectOp(object): "App::PropertyString", "Comment", "Path", - QT_TRANSLATE_NOOP( - "App::Property", "An optional comment for this Operation" - ), + QT_TRANSLATE_NOOP("App::Property", "An optional comment for this Operation"), ) obj.addProperty( "App::PropertyString", @@ -231,17 +225,13 @@ class ObjectOp(object): "App::PropertyDistance", "StartDepth", "Depth", - QT_TRANSLATE_NOOP( - "App::Property", "Starting Depth of Tool- first cut depth in Z" - ), + QT_TRANSLATE_NOOP("App::Property", "Starting Depth of Tool- first cut depth in Z"), ) obj.addProperty( "App::PropertyDistance", "FinalDepth", "Depth", - QT_TRANSLATE_NOOP( - "App::Property", "Final Depth of Tool- lowest value in Z" - ), + QT_TRANSLATE_NOOP("App::Property", "Final Depth of Tool- lowest value in Z"), ) if FeatureNoFinalDepth & features: obj.setEditorMode("FinalDepth", 2) # hide @@ -274,9 +264,7 @@ class ObjectOp(object): "App::PropertyDistance", "FinishDepth", "Depth", - QT_TRANSLATE_NOOP( - "App::Property", "Maximum material removed on final pass." - ), + QT_TRANSLATE_NOOP("App::Property", "Maximum material removed on final pass."), ) if FeatureHeights & features: @@ -293,9 +281,7 @@ class ObjectOp(object): "App::PropertyDistance", "SafeHeight", "Depth", - QT_TRANSLATE_NOOP( - "App::Property", "Rapid Safety Height between locations." - ), + QT_TRANSLATE_NOOP("App::Property", "Rapid Safety Height between locations."), ) if FeatureStartPoint & features: @@ -309,9 +295,7 @@ class ObjectOp(object): "App::PropertyBool", "UseStartPoint", "Start Point", - QT_TRANSLATE_NOOP( - "App::Property", "Make True, if specifying a Start Point" - ), + QT_TRANSLATE_NOOP("App::Property", "Make True, if specifying a Start Point"), ) if FeatureDiameters & features: @@ -319,17 +303,13 @@ class ObjectOp(object): "App::PropertyDistance", "MinDiameter", "Diameter", - QT_TRANSLATE_NOOP( - "App::Property", "Lower limit of the turning diameter" - ), + QT_TRANSLATE_NOOP("App::Property", "Lower limit of the turning diameter"), ) obj.addProperty( "App::PropertyDistance", "MaxDiameter", "Diameter", - QT_TRANSLATE_NOOP( - "App::Property", "Upper limit of the turning diameter." - ), + QT_TRANSLATE_NOOP("App::Property", "Upper limit of the turning diameter."), ) # members being set later @@ -428,8 +408,7 @@ class ObjectOp(object): oldvalue = str(obj.CoolantMode) if hasattr(obj, "CoolantMode") else "None" if ( hasattr(obj, "CoolantMode") - and not obj.getTypeIdOfProperty("CoolantMode") - == "App::PropertyEnumeration" + and not obj.getTypeIdOfProperty("CoolantMode") == "App::PropertyEnumeration" ): obj.removeProperty("CoolantMode") @@ -438,9 +417,7 @@ class ObjectOp(object): "App::PropertyEnumeration", "CoolantMode", "Path", - QT_TRANSLATE_NOOP( - "App::Property", "Coolant option for this operation" - ), + QT_TRANSLATE_NOOP("App::Property", "Coolant option for this operation"), ) for n in self.opPropertyEnumerations(): if n[0] == "CoolantMode": @@ -576,9 +553,7 @@ class ObjectOp(object): if FeatureTool & features: if 1 < len(job.Operations.Group): - obj.ToolController = PathUtil.toolControllerForOp( - job.Operations.Group[-2] - ) + obj.ToolController = PathUtil.toolControllerForOp(job.Operations.Group[-2]) else: obj.ToolController = PathUtils.findToolController(obj, self) if not obj.ToolController: @@ -591,15 +566,11 @@ class ObjectOp(object): obj.CoolantMode = job.SetupSheet.CoolantMode if FeatureDepths & features: - if self.applyExpression( - obj, "StartDepth", job.SetupSheet.StartDepthExpression - ): + if self.applyExpression(obj, "StartDepth", job.SetupSheet.StartDepthExpression): obj.OpStartDepth = 1.0 else: obj.StartDepth = 1.0 - if self.applyExpression( - obj, "FinalDepth", job.SetupSheet.FinalDepthExpression - ): + if self.applyExpression(obj, "FinalDepth", job.SetupSheet.FinalDepthExpression): obj.OpFinalDepth = 0.0 else: obj.FinalDepth = 0.0 @@ -607,16 +578,12 @@ class ObjectOp(object): obj.StartDepth = 1.0 if FeatureStepDown & features: - if not self.applyExpression( - obj, "StepDown", job.SetupSheet.StepDownExpression - ): + if not self.applyExpression(obj, "StepDown", job.SetupSheet.StepDownExpression): obj.StepDown = "1 mm" if FeatureHeights & features: if job.SetupSheet.SafeHeightExpression: - if not self.applyExpression( - obj, "SafeHeight", job.SetupSheet.SafeHeightExpression - ): + if not self.applyExpression(obj, "SafeHeight", job.SetupSheet.SafeHeightExpression): obj.SafeHeight = "3 mm" if job.SetupSheet.ClearanceHeightExpression: if not self.applyExpression( @@ -646,8 +613,7 @@ class ObjectOp(object): if not job.Model.Group: if not ignoreErrors: Path.Log.error( - translate("CAM", "Parent job %s doesn't have a base object") - % job.Label + translate("CAM", "Parent job %s doesn't have a base object") % job.Label ) return False self.job = job @@ -715,9 +681,7 @@ class ObjectOp(object): zmin = obj.OpFinalDepth.Value def minZmax(z): - if hasattr(obj, "StepDown") and not Path.Geom.isRoughly( - obj.StepDown.Value, 0 - ): + if hasattr(obj, "StepDown") and not Path.Geom.isRoughly(obj.StepDown.Value, 0): return z + obj.StepDown.Value else: return z + 1 @@ -740,13 +704,11 @@ class ObjectOp(object): """sanitizeBase(obj) ... check if Base is valid and clear on errors.""" if hasattr(obj, "Base"): try: - for (o, sublist) in obj.Base: + for o, sublist in obj.Base: for sub in sublist: o.Shape.getElement(sub) except Part.OCCError: - Path.Log.error( - "{} - stale base geometry detected - clearing.".format(obj.Label) - ) + Path.Log.error("{} - stale base geometry detected - clearing.".format(obj.Label)) obj.Base = [] return True return False @@ -827,9 +789,7 @@ class ObjectOp(object): if self.commandlist and (FeatureHeights & self.opFeatures(obj)): # Let's finish by rapid to clearance...just for safety - self.commandlist.append( - Path.Command("G0", {"Z": obj.ClearanceHeight.Value}) - ) + self.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value})) path = Path.Path(self.commandlist) obj.Path = path @@ -850,9 +810,7 @@ class ObjectOp(object): hRapidrate = tc.HorizRapid.Value vRapidrate = tc.VertRapid.Value - if ( - hFeedrate == 0 or vFeedrate == 0 - ) and not Path.Preferences.suppressAllSpeedsWarning(): + if (hFeedrate == 0 or vFeedrate == 0) and not Path.Preferences.suppressAllSpeedsWarning(): Path.Log.warning( translate( "CAM", @@ -899,10 +857,7 @@ class ObjectOp(object): for p, el in baselist: if p == base and sub in el: Path.Log.notice( - ( - translate("CAM", "Base object %s.%s already in the list") - + "\n" - ) + (translate("CAM", "Base object %s.%s already in the list") + "\n") % (base.Label, sub) ) return diff --git a/src/Mod/CAM/Path/Op/CircularHoleBase.py b/src/Mod/CAM/Path/Op/CircularHoleBase.py index d01fa66d7e..2cdce169c5 100644 --- a/src/Mod/CAM/Path/Op/CircularHoleBase.py +++ b/src/Mod/CAM/Path/Op/CircularHoleBase.py @@ -100,10 +100,8 @@ class ObjectOp(PathOp.ObjectOp): for i in range(len(shape.Edges)): if ( type(shape.Edges[i].Curve) == Part.Circle - and shape.Edges[i].Curve.Radius * 2 - < shape.BoundBox.XLength * 1.1 - and shape.Edges[i].Curve.Radius * 2 - > shape.BoundBox.XLength * 0.9 + and shape.Edges[i].Curve.Radius * 2 < shape.BoundBox.XLength * 1.1 + and shape.Edges[i].Curve.Radius * 2 > shape.BoundBox.XLength * 0.9 ): return shape.Edges[i].Curve.Radius * 2 @@ -135,9 +133,7 @@ class ObjectOp(PathOp.ObjectOp): if shape.ShapeType == "Face": if hasattr(shape.Surface, "Center"): - return FreeCAD.Vector( - shape.Surface.Center.x, shape.Surface.Center.y, 0 - ) + return FreeCAD.Vector(shape.Surface.Center.x, shape.Surface.Center.y, 0) if len(shape.Edges) == 1 and type(shape.Edges[0].Curve) == Part.Circle: return shape.Edges[0].Curve.Center except Part.OCCError as e: @@ -213,9 +209,7 @@ class ObjectOp(PathOp.ObjectOp): features = [] for base in self.model: features.extend( - Drillable.getDrillableTargets( - base, ToolDiameter=tooldiameter, vector=matchvector - ) + Drillable.getDrillableTargets(base, ToolDiameter=tooldiameter, vector=matchvector) ) obj.Base = features obj.Disabled = [] diff --git a/src/Mod/CAM/Path/Op/Custom.py b/src/Mod/CAM/Path/Op/Custom.py index 0f3d0ae547..5b409c5153 100644 --- a/src/Mod/CAM/Path/Op/Custom.py +++ b/src/Mod/CAM/Path/Op/Custom.py @@ -174,8 +174,7 @@ class ObjectCustom(PathOp.ObjectOp): # could not determine the path if not gcode_file: Path.Log.error( - translate("PathCustom", "Custom file %s could not be found.") - % obj.GcodeFile + translate("PathCustom", "Custom file %s could not be found.") % obj.GcodeFile ) with open(gcode_file) as fd: @@ -184,9 +183,7 @@ class ObjectCustom(PathOp.ObjectOp): newcommand = Path.Command(str(l)) self.commandlist.append(newcommand) except ValueError: - Path.Log.warning( - translate("PathCustom", "Invalid G-code line: %s") % l - ) + Path.Log.warning(translate("PathCustom", "Invalid G-code line: %s") % l) continue self.commandlist.append(Path.Command("(End Custom)")) diff --git a/src/Mod/CAM/Path/Op/Deburr.py b/src/Mod/CAM/Path/Op/Deburr.py index 14bf268915..1123a4ae5b 100644 --- a/src/Mod/CAM/Path/Op/Deburr.py +++ b/src/Mod/CAM/Path/Op/Deburr.py @@ -166,7 +166,6 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): @classmethod def propertyEnumerations(self, dataType="data"): - """opPropertyEnumerations(dataType="data")... return property enumeration lists of specified dataType. Args: dataType = 'data', 'raw', 'translated' @@ -290,34 +289,15 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): break else: # Arc - if ( - edge.Vertexes[0].Point.z - == edge.Vertexes[1].Point.z - ): + if edge.Vertexes[0].Point.z == edge.Vertexes[1].Point.z: # Arc vertexes are on same layer l1 = math.sqrt( - ( - edge.Vertexes[0].Point.x - - edge.Curve.Center.x - ) - ** 2 - + ( - edge.Vertexes[0].Point.y - - edge.Curve.Center.y - ) - ** 2 + (edge.Vertexes[0].Point.x - edge.Curve.Center.x) ** 2 + + (edge.Vertexes[0].Point.y - edge.Curve.Center.y) ** 2 ) l2 = math.sqrt( - ( - edge.Vertexes[1].Point.x - - edge.Curve.Center.x - ) - ** 2 - + ( - edge.Vertexes[1].Point.y - - edge.Curve.Center.y - ) - ** 2 + (edge.Vertexes[1].Point.x - edge.Curve.Center.x) ** 2 + + (edge.Vertexes[1].Point.y - edge.Curve.Center.y) ** 2 ) # New center @@ -329,30 +309,16 @@ class ObjectDeburr(PathEngraveBase.ObjectOp): # Calculate angles based on x-axis (0 - PI/2) start_angle = math.acos( - ( - edge.Vertexes[0].Point.x - - edge.Curve.Center.x - ) - / l1 + (edge.Vertexes[0].Point.x - edge.Curve.Center.x) / l1 ) end_angle = math.acos( - ( - edge.Vertexes[1].Point.x - - edge.Curve.Center.x - ) - / l2 + (edge.Vertexes[1].Point.x - edge.Curve.Center.x) / l2 ) # Angles are based on x-axis (Mirrored on x-axis) -> negative y value means negative angle - if ( - edge.Vertexes[0].Point.y - < edge.Curve.Center.y - ): + if edge.Vertexes[0].Point.y < edge.Curve.Center.y: start_angle *= -1 - if ( - edge.Vertexes[1].Point.y - < edge.Curve.Center.y - ): + if edge.Vertexes[1].Point.y < edge.Curve.Center.y: end_angle *= -1 # Create new arc diff --git a/src/Mod/CAM/Path/Op/Drilling.py b/src/Mod/CAM/Path/Op/Drilling.py index 7d864a127d..ae17156cba 100644 --- a/src/Mod/CAM/Path/Op/Drilling.py +++ b/src/Mod/CAM/Path/Op/Drilling.py @@ -22,7 +22,6 @@ # *************************************************************************** - import FreeCAD import Part import Path @@ -92,9 +91,7 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp): def circularHoleFeatures(self, obj): """circularHoleFeatures(obj) ... drilling works on anything, turn on all Base geometries and Locations.""" - return ( - PathOp.FeatureBaseGeometry | PathOp.FeatureLocations | PathOp.FeatureCoolant - ) + return PathOp.FeatureBaseGeometry | PathOp.FeatureLocations | PathOp.FeatureCoolant def onDocumentRestored(self, obj): if not hasattr(obj, "chipBreakEnabled"): @@ -107,10 +104,10 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp): if not hasattr(obj, "feedRetractEnabled"): obj.addProperty( - "App::PropertyBool", "feedRetractEnabled", "Drill", - QT_TRANSLATE_NOOP( - "App::Property", - "Use G85 boring cycle with feed out") + "App::PropertyBool", + "feedRetractEnabled", + "Drill", + QT_TRANSLATE_NOOP("App::Property", "Use G85 boring cycle with feed out"), ) def initCircularHoleOperation(self, obj): @@ -162,7 +159,8 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp): "RetractMode", "Drill", QT_TRANSLATE_NOOP( - "App::Property", "Controls tool retract height between holes in same op, Default=G98: safety height" + "App::Property", + "Controls tool retract height between holes in same op, Default=G98: safety height", ), ) obj.addProperty( @@ -181,16 +179,19 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp): QT_TRANSLATE_NOOP("App::Property", "How far the drilling depth is extended"), ) obj.addProperty( - "App::PropertyBool", "KeepToolDown", "Drill", + "App::PropertyBool", + "KeepToolDown", + "Drill", QT_TRANSLATE_NOOP( "App::Property", - "Apply G99 retraction: only retract to RetractHeight between holes in this operation") + "Apply G99 retraction: only retract to RetractHeight between holes in this operation", + ), ) obj.addProperty( - "App::PropertyBool", "feedRetractEnabled", "Drill", - QT_TRANSLATE_NOOP( - "App::Property", - "Use G85 boring cycle with feed out") + "App::PropertyBool", + "feedRetractEnabled", + "Drill", + QT_TRANSLATE_NOOP("App::Property", "Use G85 boring cycle with feed out"), ) for n in self.propertyEnumerations(): @@ -219,10 +220,13 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp): if not hasattr(obj, "KeepToolDown"): obj.addProperty( - "App::PropertyBool", "KeepToolDown", "Drill", + "App::PropertyBool", + "KeepToolDown", + "Drill", QT_TRANSLATE_NOOP( "App::Property", - "Apply G99 retraction: only retract to RetractHeight between holes in this operation") + "Apply G99 retraction: only retract to RetractHeight between holes in this operation", + ), ) if not hasattr(obj, "RetractMode"): @@ -232,7 +236,7 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp): "Drill", QT_TRANSLATE_NOOP( "App::Property", - "Controls tool retract height between holes in same op, Default=G98: safety height" + "Controls tool retract height between holes in same op, Default=G98: safety height", ), ) # ensure new enums exist in old class @@ -240,8 +244,10 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp): setattr(obj, n[0], n[1]) # http://linuxcnc.org/docs/html/gcode/g-code.html#gcode:g98-g99 - if obj.KeepToolDown: obj.RetractMode = "G99" - else: obj.RetractMode = "G98" + if obj.KeepToolDown: + obj.RetractMode = "G99" + else: + obj.RetractMode = "G98" self.commandlist.append(Path.Command(obj.RetractMode)) holes = PathUtils.sort_locations(holes, ["x", "y"]) @@ -290,7 +296,7 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp): repeat, obj.RetractHeight.Value, chipBreak=chipBreak, - feedRetract=obj.feedRetractEnabled + feedRetract=obj.feedRetractEnabled, ) except ValueError as e: # any targets that fail the generator are ignored @@ -317,9 +323,7 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp): if hasattr(job.SetupSheet, "RetractHeight"): obj.RetractHeight = job.SetupSheet.RetractHeight - elif self.applyExpression( - obj, "RetractHeight", "StartDepth+SetupSheet.SafeHeightOffset" - ): + elif self.applyExpression(obj, "RetractHeight", "StartDepth+SetupSheet.SafeHeightOffset"): if not job: obj.RetractHeight = 10 else: diff --git a/src/Mod/CAM/Path/Op/Engrave.py b/src/Mod/CAM/Path/Op/Engrave.py index 5ae2c571b5..af0e534883 100644 --- a/src/Mod/CAM/Path/Op/Engrave.py +++ b/src/Mod/CAM/Path/Op/Engrave.py @@ -66,9 +66,7 @@ class ObjectEngrave(PathEngraveBase.ObjectOp): "App::PropertyLinkList", "BaseShapes", "Path", - QT_TRANSLATE_NOOP( - "App::Property", "Additional base objects to be engraved" - ), + QT_TRANSLATE_NOOP("App::Property", "Additional base objects to be engraved"), ) obj.setEditorMode("BaseShapes", 2) # hide if not hasattr(obj, "BaseObject"): @@ -76,9 +74,7 @@ class ObjectEngrave(PathEngraveBase.ObjectOp): "App::PropertyLink", "BaseObject", "Path", - QT_TRANSLATE_NOOP( - "App::Property", "Additional base objects to be engraved" - ), + QT_TRANSLATE_NOOP("App::Property", "Additional base objects to be engraved"), ) obj.setEditorMode("BaseObject", 2) # hide @@ -88,9 +84,7 @@ class ObjectEngrave(PathEngraveBase.ObjectOp): "App::PropertyInteger", "StartVertex", "Path", - QT_TRANSLATE_NOOP( - "App::Property", "The vertex index to start the toolpath from" - ), + QT_TRANSLATE_NOOP("App::Property", "The vertex index to start the toolpath from"), ) self.setupAdditionalProperties(obj) @@ -145,16 +139,12 @@ class ObjectEngrave(PathEngraveBase.ObjectOp): shapeWires = shape.Wires Path.Log.debug("jobshape has {} edges".format(len(shape.Edges))) self.commandlist.append( - Path.Command( - "G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid} - ) + Path.Command("G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid}) ) self.buildpathocc(obj, shapeWires, self.getZValues(obj)) wires.extend(shapeWires) self.wires = wires - Path.Log.debug( - "processing {} jobshapes -> {} wires".format(len(jobshapes), len(wires)) - ) + Path.Log.debug("processing {} jobshapes -> {} wires".format(len(jobshapes), len(wires))) # the last command is a move to clearance, which is automatically added by PathOp if self.commandlist: self.commandlist.pop() diff --git a/src/Mod/CAM/Path/Op/EngraveBase.py b/src/Mod/CAM/Path/Op/EngraveBase.py index 2f1c9b2131..1c4248695a 100644 --- a/src/Mod/CAM/Path/Op/EngraveBase.py +++ b/src/Mod/CAM/Path/Op/EngraveBase.py @@ -98,9 +98,7 @@ class ObjectOp(PathOp.ObjectOp): edges = edges[start_idx:] + edges[:start_idx] for edge in edges: Path.Log.debug( - "points: {} -> {}".format( - edge.Vertexes[0].Point, edge.Vertexes[-1].Point - ) + "points: {} -> {}".format(edge.Vertexes[0].Point, edge.Vertexes[-1].Point) ) Path.Log.debug( "valueat {} -> {}".format( @@ -120,14 +118,10 @@ class ObjectOp(PathOp.ObjectOp): ) ) self.commandlist.append( - Path.Command( - "G0", {"X": last.x, "Y": last.y, "F": self.horizRapid} - ) + Path.Command("G0", {"X": last.x, "Y": last.y, "F": self.horizRapid}) ) self.commandlist.append( - Path.Command( - "G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid} - ) + Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid}) ) self.appendCommand( Path.Command("G1", {"X": last.x, "Y": last.y, "Z": last.z}), @@ -137,9 +131,7 @@ class ObjectOp(PathOp.ObjectOp): ) first = False - if Path.Geom.pointsCoincide( - last, edge.valueAt(edge.FirstParameter) - ): + if Path.Geom.pointsCoincide(last, edge.valueAt(edge.FirstParameter)): # if Path.Geom.pointsCoincide(last, edge.Vertexes[0].Point): for cmd in Path.Geom.cmdsForEdge(edge): self.appendCommand(cmd, z, relZ, self.horizFeed) @@ -149,9 +141,7 @@ class ObjectOp(PathOp.ObjectOp): self.appendCommand(cmd, z, relZ, self.horizFeed) last = edge.Vertexes[0].Point self.commandlist.append( - Path.Command( - "G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid} - ) + Path.Command("G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid}) ) def appendCommand(self, cmd, z, relZ, feed): diff --git a/src/Mod/CAM/Path/Op/FeatureExtension.py b/src/Mod/CAM/Path/Op/FeatureExtension.py index 7664db36ab..cd7df2342e 100644 --- a/src/Mod/CAM/Path/Op/FeatureExtension.py +++ b/src/Mod/CAM/Path/Op/FeatureExtension.py @@ -145,7 +145,8 @@ def createExtension(obj, extObj, extFeature, extSub): def readObjExtensionFeature(obj): """readObjExtensionFeature(obj)... - Return three item string tuples (base name, feature, subfeature) extracted from obj.ExtensionFeature""" + Return three item string tuples (base name, feature, subfeature) extracted from obj.ExtensionFeature + """ extensions = [] for extObj, features in obj.ExtensionFeature: @@ -218,8 +219,7 @@ class Extension(object): def __init__(self, op, obj, feature, sub, length, direction): Path.Log.debug( - "Extension(%s, %s, %s, %.2f, %s" - % (obj.Label, feature, sub, length, direction) + "Extension(%s, %s, %s, %.2f, %s" % (obj.Label, feature, sub, length, direction) ) self.op = op self.obj = obj @@ -247,14 +247,10 @@ class Extension(object): e2.translate(off) e2 = Path.Geom.flipEdge(e2) e1 = Part.Edge( - Part.LineSegment( - e0.valueAt(e0.LastParameter), e2.valueAt(e2.FirstParameter) - ) + Part.LineSegment(e0.valueAt(e0.LastParameter), e2.valueAt(e2.FirstParameter)) ) e3 = Part.Edge( - Part.LineSegment( - e2.valueAt(e2.LastParameter), e0.valueAt(e0.FirstParameter) - ) + Part.LineSegment(e2.valueAt(e2.LastParameter), e0.valueAt(e0.FirstParameter)) ) wire = Part.Wire([e0, e1, e2, e3]) self.wire = wire @@ -411,9 +407,7 @@ class Extension(object): else: Path.Log.debug("else is NOT Part.Circle") - Path.Log.track( - self.feature, self.sub, type(edge.Curve), endPoints(edge) - ) + Path.Log.track(self.feature, self.sub, type(edge.Curve), endPoints(edge)) direction = self._getDirection(sub) if direction is None: return None @@ -517,9 +511,7 @@ def SetupProperties(): # Extend outline face generation function -def getExtendOutlineFace( - base_shape, face, extension, remHoles=False, offset_tolerance=1e-4 -): +def getExtendOutlineFace(base_shape, face, extension, remHoles=False, offset_tolerance=1e-4): """getExtendOutlineFace(obj, base_shape, face, extension, remHoles) ... Creates an extended face for the pocket, taking into consideration lateral collision with the greater base shape. @@ -605,9 +597,7 @@ def getWaterlineFace(base_shape, face): final_depth=baseBB.ZMin, user_depths=None, ) - env = PathUtils.getEnvelope( - partshape=base_shape, subshape=None, depthparams=depthparams - ) + env = PathUtils.getEnvelope(partshape=base_shape, subshape=None, depthparams=depthparams) # Get top face(s) of envelope at face height rawList = list() for f in env.Faces: @@ -615,9 +605,7 @@ def getWaterlineFace(base_shape, face): rawList.append(f) # make compound and extrude downward rawComp = Part.makeCompound(rawList) - rawCompExtNeg = rawComp.extrude( - FreeCAD.Vector(0.0, 0.0, baseBB.ZMin - faceHeight - 1.0) - ) + rawCompExtNeg = rawComp.extrude(FreeCAD.Vector(0.0, 0.0, baseBB.ZMin - faceHeight - 1.0)) # Cut off bottom of base shape at face height topSolid = base_shape.cut(rawCompExtNeg) diff --git a/src/Mod/CAM/Path/Op/Gui/Adaptive.py b/src/Mod/CAM/Path/Op/Gui/Adaptive.py index 42941b33f7..a9ae651faa 100644 --- a/src/Mod/CAM/Path/Op/Gui/Adaptive.py +++ b/src/Mod/CAM/Path/Op/Gui/Adaptive.py @@ -44,18 +44,12 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): return form def initPage(self, obj): - self.form.LiftDistance.setProperty( - "unit", obj.LiftDistance.getUserPreferred()[2] - ) + self.form.LiftDistance.setProperty("unit", obj.LiftDistance.getUserPreferred()[2]) self.form.HelixDiameterLimit.setProperty( "unit", obj.HelixDiameterLimit.getUserPreferred()[2] ) - self.form.KeepToolDownRatio.setProperty( - "unit", obj.KeepToolDownRatio.getUserPreferred()[2] - ) - self.form.StockToLeave.setProperty( - "unit", obj.StockToLeave.getUserPreferred()[2] - ) + self.form.KeepToolDownRatio.setProperty("unit", obj.KeepToolDownRatio.getUserPreferred()[2]) + self.form.StockToLeave.setProperty("unit", obj.StockToLeave.getUserPreferred()[2]) def getSignalsForUpdate(self, obj): """getSignalsForUpdate(obj) ... return list of signals for updating obj""" @@ -92,16 +86,12 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): FreeCAD.Units.Quantity(obj.HelixConeAngle, FreeCAD.Units.Angle).UserString ) - self.form.HelixDiameterLimit.setProperty( - "rawValue", obj.HelixDiameterLimit.Value - ) + self.form.HelixDiameterLimit.setProperty("rawValue", obj.HelixDiameterLimit.Value) self.form.LiftDistance.setProperty("rawValue", obj.LiftDistance.Value) if hasattr(obj, "KeepToolDownRatio"): - self.form.KeepToolDownRatio.setProperty( - "rawValue", obj.KeepToolDownRatio.Value - ) + self.form.KeepToolDownRatio.setProperty("rawValue", obj.KeepToolDownRatio.Value) # self.form.KeepToolDownRatio.setValue(obj.KeepToolDownRatio) if hasattr(obj, "StockToLeave"): @@ -131,15 +121,11 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): obj.Tolerance = 1.0 * self.form.Tolerance.value() / 100.0 PathGuiUtil.updateInputField(obj, "HelixAngle", self.form.HelixAngle) PathGuiUtil.updateInputField(obj, "HelixConeAngle", self.form.HelixConeAngle) - PathGuiUtil.updateInputField( - obj, "HelixDiameterLimit", self.form.HelixDiameterLimit - ) + PathGuiUtil.updateInputField(obj, "HelixDiameterLimit", self.form.HelixDiameterLimit) PathGuiUtil.updateInputField(obj, "LiftDistance", self.form.LiftDistance) if hasattr(obj, "KeepToolDownRatio"): - PathGuiUtil.updateInputField( - obj, "KeepToolDownRatio", self.form.KeepToolDownRatio - ) + PathGuiUtil.updateInputField(obj, "KeepToolDownRatio", self.form.KeepToolDownRatio) if hasattr(obj, "StockToLeave"): PathGuiUtil.updateInputField(obj, "StockToLeave", self.form.StockToLeave) @@ -161,9 +147,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): def taskPanelBaseLocationPage(self, obj, features): if not hasattr(self, "extensionsPanel"): - self.extensionsPanel = PathFeatureExtensionsGui.TaskPanelExtensionPage( - obj, features - ) + self.extensionsPanel = PathFeatureExtensionsGui.TaskPanelExtensionPage(obj, features) return self.extensionsPanel diff --git a/src/Mod/CAM/Path/Op/Gui/Array.py b/src/Mod/CAM/Path/Op/Gui/Array.py index a4b62f36ab..8bbd026730 100644 --- a/src/Mod/CAM/Path/Op/Gui/Array.py +++ b/src/Mod/CAM/Path/Op/Gui/Array.py @@ -93,9 +93,7 @@ class ObjectArray: "App::PropertyVector", "Centre", "Path", - QT_TRANSLATE_NOOP( - "App::Property", "The centre of rotation in Polar pattern" - ), + QT_TRANSLATE_NOOP("App::Property", "The centre of rotation in Polar pattern"), ) obj.addProperty( "App::PropertyBool", @@ -137,9 +135,7 @@ class ObjectArray: "App::PropertyBool", "Active", "Path", - QT_TRANSLATE_NOOP( - "PathOp", "Make False, to prevent operation from generating code" - ), + QT_TRANSLATE_NOOP("PathOp", "Make False, to prevent operation from generating code"), ) obj.Active = True @@ -170,9 +166,7 @@ class ObjectArray: "App::PropertyInteger", "JitterSeed", "Path", - QtCore.QT_TRANSLATE_NOOP( - "App::Property", "Seed value for jitter randomness" - ), + QtCore.QT_TRANSLATE_NOOP("App::Property", "Seed value for jitter randomness"), ) obj.JitterSeed = 0 @@ -293,15 +287,9 @@ class PathArray: if self.jitterPercent == 0: pass elif random.randint(0, 100) < self.jitterPercent: - pos.x = pos.x + random.uniform( - -self.jitterMagnitude.x, self.jitterMagnitude.x - ) - pos.y = pos.y + random.uniform( - -self.jitterMagnitude.y, self.jitterMagnitude.y - ) - pos.z = pos.z + random.uniform( - -self.jitterMagnitude.z, self.jitterMagnitude.z - ) + pos.x = pos.x + random.uniform(-self.jitterMagnitude.x, self.jitterMagnitude.x) + pos.y = pos.y + random.uniform(-self.jitterMagnitude.y, self.jitterMagnitude.y) + pos.z = pos.z + random.uniform(-self.jitterMagnitude.z, self.jitterMagnitude.z) return pos # Public method @@ -349,7 +337,9 @@ class PathArray: for b in base: pl = FreeCAD.Placement() pl.move(pos) - np = Path.Path([cm.transform(pl) for cm in PathUtils.getPathWithPlacement(b).Commands]) + np = Path.Path( + [cm.transform(pl) for cm in PathUtils.getPathWithPlacement(b).Commands] + ) output += np.toGCode() elif self.arrayType == "Linear2D": @@ -376,7 +366,10 @@ class PathArray: if not (i == 0 and j == 0): pl.move(pos) np = Path.Path( - [cm.transform(pl) for cm in PathUtils.getPathWithPlacement(b).Commands] + [ + cm.transform(pl) + for cm in PathUtils.getPathWithPlacement(b).Commands + ] ) output += np.toGCode() else: @@ -402,7 +395,10 @@ class PathArray: if not (i == 0 and j == 0): pl.move(pos) np = Path.Path( - [cm.transform(pl) for cm in PathUtils.getPathWithPlacement(b).Commands] + [ + cm.transform(pl) + for cm in PathUtils.getPathWithPlacement(b).Commands + ] ) output += np.toGCode() # Eif @@ -450,15 +446,12 @@ class CommandPathArray: return { "Pixmap": "CAM_Array", "MenuText": QT_TRANSLATE_NOOP("CAM_Array", "Array"), - "ToolTip": QT_TRANSLATE_NOOP( - "CAM_Array", "Creates an array from selected toolpath(s)" - ), + "ToolTip": QT_TRANSLATE_NOOP("CAM_Array", "Creates an array from selected toolpath(s)"), } def IsActive(self): selections = [ - sel.isDerivedFrom("Path::Feature") - for sel in FreeCADGui.Selection.getSelection() + sel.isDerivedFrom("Path::Feature") for sel in FreeCADGui.Selection.getSelection() ] return selections and all(selections) @@ -470,9 +463,7 @@ class CommandPathArray: for sel in selection: if not (sel.isDerivedFrom("Path::Feature")): FreeCAD.Console.PrintError( - translate( - "CAM_Array", "Arrays can be created only from toolpath operations." - ) + translate("CAM_Array", "Arrays can be created only from toolpath operations.") + "\n" ) return diff --git a/src/Mod/CAM/Path/Op/Gui/Base.py b/src/Mod/CAM/Path/Op/Gui/Base.py index 2e82e3908e..8203eaefc1 100644 --- a/src/Mod/CAM/Path/Op/Gui/Base.py +++ b/src/Mod/CAM/Path/Op/Gui/Base.py @@ -266,7 +266,8 @@ class TaskPanelPage(object): def pageRegisterSignalHandlers(self): """pageRegisterSignalHandlers() .. internal callback. Registers a callback for all signals returned by getSignalsForUpdate(obj). - Do not overwrite, implement getSignalsForUpdate(obj) and/or registerSignalHandlers(obj) instead.""" + Do not overwrite, implement getSignalsForUpdate(obj) and/or registerSignalHandlers(obj) instead. + """ for signal in self.getSignalsForUpdate(self.obj): signal.connect(self.pageGetFields) self.registerSignalHandlers(self.obj) @@ -446,9 +447,7 @@ class TaskPanelPage(object): if parent and hasattr(parent, "featurePages"): for page in parent.featurePages: if hasattr(page, "panelTitle"): - if page.panelTitle == panelTitle and hasattr( - page, "updateVisibility" - ): + if page.panelTitle == panelTitle and hasattr(page, "updateVisibility"): page.updateVisibility() break @@ -557,20 +556,11 @@ class TaskPanelBaseGeometryPage(TaskPanelPage): return False sel = selection[0] if sel.HasSubObjects: - if ( - not self.supportsVertexes() - and selection[0].SubObjects[0].ShapeType == "Vertex" - ): + if not self.supportsVertexes() and selection[0].SubObjects[0].ShapeType == "Vertex": return False - if ( - not self.supportsEdges() - and selection[0].SubObjects[0].ShapeType == "Edge" - ): + if not self.supportsEdges() and selection[0].SubObjects[0].ShapeType == "Edge": return False - if ( - not self.supportsFaces() - and selection[0].SubObjects[0].ShapeType == "Face" - ): + if not self.supportsFaces() and selection[0].SubObjects[0].ShapeType == "Face": return False else: if not self.supportsPanels() or "Panel" not in sel.Object.Name: @@ -688,13 +678,9 @@ class TaskPanelBaseLocationPage(TaskPanelPage): def getForm(self): self.formLoc = FreeCADGui.PySideUic.loadUi(":/panels/PageBaseLocationEdit.ui") if QtCore.qVersion()[0] == "4": - self.formLoc.baseList.horizontalHeader().setResizeMode( - QtGui.QHeaderView.Stretch - ) + self.formLoc.baseList.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch) else: - self.formLoc.baseList.horizontalHeader().setSectionResizeMode( - QtGui.QHeaderView.Stretch - ) + self.formLoc.baseList.horizontalHeader().setSectionResizeMode(QtGui.QHeaderView.Stretch) self.getPoint = PathGetPoint.TaskPanel(self.formLoc.addRemoveEdit) return self.formLoc @@ -768,12 +754,8 @@ class TaskPanelBaseLocationPage(TaskPanelPage): def editLocationAt(self, point, obj): if point: - self.formLoc.baseList.item(self.editRow, 0).setData( - self.DataLocation, point.x - ) - self.formLoc.baseList.item(self.editRow, 1).setData( - self.DataLocation, point.y - ) + self.formLoc.baseList.item(self.editRow, 0).setData(self.DataLocation, point.x) + self.formLoc.baseList.item(self.editRow, 1).setData(self.DataLocation, point.y) self.updateLocations() FreeCAD.ActiveDocument.recompute() @@ -813,9 +795,7 @@ class TaskPanelHeightsPage(TaskPanelPage): return FreeCADGui.PySideUic.loadUi(":/panels/PageHeightsEdit.ui") def initPage(self, obj): - self.safeHeight = PathGuiUtil.QuantitySpinBox( - self.form.safeHeight, obj, "SafeHeight" - ) + self.safeHeight = PathGuiUtil.QuantitySpinBox(self.form.safeHeight, obj, "SafeHeight") self.clearanceHeight = PathGuiUtil.QuantitySpinBox( self.form.clearanceHeight, obj, "ClearanceHeight" ) @@ -865,15 +845,11 @@ class TaskPanelDepthsPage(TaskPanelPage): def haveFinalDepth(self): return ( - PathOp.FeatureDepths & self.features - and not PathOp.FeatureNoFinalDepth & self.features + PathOp.FeatureDepths & self.features and not PathOp.FeatureNoFinalDepth & self.features ) def haveFinishDepth(self): - return ( - PathOp.FeatureDepths & self.features - and PathOp.FeatureFinishDepth & self.features - ) + return PathOp.FeatureDepths & self.features and PathOp.FeatureFinishDepth & self.features def haveStepDown(self): return PathOp.FeatureStepDown & self.features @@ -881,18 +857,14 @@ class TaskPanelDepthsPage(TaskPanelPage): def initPage(self, obj): if self.haveStartDepth(): - self.startDepth = PathGuiUtil.QuantitySpinBox( - self.form.startDepth, obj, "StartDepth" - ) + self.startDepth = PathGuiUtil.QuantitySpinBox(self.form.startDepth, obj, "StartDepth") else: self.form.startDepth.hide() self.form.startDepthLabel.hide() self.form.startDepthSet.hide() if self.haveFinalDepth(): - self.finalDepth = PathGuiUtil.QuantitySpinBox( - self.form.finalDepth, obj, "FinalDepth" - ) + self.finalDepth = PathGuiUtil.QuantitySpinBox(self.form.finalDepth, obj, "FinalDepth") else: if self.haveStartDepth(): self.form.finalDepth.setEnabled(False) @@ -908,9 +880,7 @@ class TaskPanelDepthsPage(TaskPanelPage): self.form.finalDepthSet.hide() if self.haveStepDown(): - self.stepDown = PathGuiUtil.QuantitySpinBox( - self.form.stepDown, obj, "StepDown" - ) + self.stepDown = PathGuiUtil.QuantitySpinBox(self.form.stepDown, obj, "StepDown") else: self.form.stepDown.hide() self.form.stepDownLabel.hide() @@ -1021,12 +991,8 @@ class TaskPanelDiametersPage(TaskPanelPage): return FreeCADGui.PySideUic.loadUi(":/panels/PageDiametersEdit.ui") def initPage(self, obj): - self.minDiameter = PathGuiUtil.QuantitySpinBox( - self.form.minDiameter, obj, "MinDiameter" - ) - self.maxDiameter = PathGuiUtil.QuantitySpinBox( - self.form.maxDiameter, obj, "MaxDiameter" - ) + self.minDiameter = PathGuiUtil.QuantitySpinBox(self.form.minDiameter, obj, "MinDiameter") + self.maxDiameter = PathGuiUtil.QuantitySpinBox(self.form.maxDiameter, obj, "MaxDiameter") def getTitle(self, obj): return translate("PathOp", "Diameters") @@ -1085,17 +1051,13 @@ class TaskPanel(object): if PathOp.FeatureBaseGeometry & features: if hasattr(opPage, "taskPanelBaseGeometryPage"): - self.featurePages.append( - opPage.taskPanelBaseGeometryPage(obj, features) - ) + self.featurePages.append(opPage.taskPanelBaseGeometryPage(obj, features)) else: self.featurePages.append(TaskPanelBaseGeometryPage(obj, features)) if PathOp.FeatureLocations & features: if hasattr(opPage, "taskPanelBaseLocationPage"): - self.featurePages.append( - opPage.taskPanelBaseLocationPage(obj, features) - ) + self.featurePages.append(opPage.taskPanelBaseLocationPage(obj, features)) else: self.featurePages.append(TaskPanelBaseLocationPage(obj, features)) @@ -1193,9 +1155,7 @@ class TaskPanel(object): self.preCleanup() FreeCAD.ActiveDocument.abortTransaction() if self.deleteOnReject: - FreeCAD.ActiveDocument.openTransaction( - translate("PathOp", "Uncreate AreaOp Operation") - ) + FreeCAD.ActiveDocument.openTransaction(translate("PathOp", "Uncreate AreaOp Operation")) try: PathUtil.clearExpressionEngine(self.obj) FreeCAD.ActiveDocument.removeObject(self.obj.Name) @@ -1266,19 +1226,14 @@ class TaskPanel(object): def getStandardButtons(self): """getStandardButtons() ... returns the Buttons for the task panel.""" return ( - QtGui.QDialogButtonBox.Ok - | QtGui.QDialogButtonBox.Apply - | QtGui.QDialogButtonBox.Cancel + QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Cancel ) def setupUi(self): """setupUi() ... internal function to initialise all pages.""" Path.Log.track(self.deleteOnReject) - if ( - self.deleteOnReject - and PathOp.FeatureBaseGeometry & self.obj.Proxy.opFeatures(self.obj) - ): + if self.deleteOnReject and PathOp.FeatureBaseGeometry & self.obj.Proxy.opFeatures(self.obj): sel = FreeCADGui.Selection.getSelectionEx() for page in self.featurePages: if getattr(page, "InitBase", True) and hasattr(page, "addBase"): @@ -1286,7 +1241,7 @@ class TaskPanel(object): page.addBaseGeometry(sel) # Update properties based upon expressions in case expression value has changed - for (prp, expr) in self.obj.ExpressionEngine: + for prp, expr in self.obj.ExpressionEngine: val = FreeCAD.Units.Quantity(self.obj.evalExpression(expr)) value = val.Value if hasattr(val, "Value") else val prop = getattr(self.obj, prp) @@ -1375,16 +1330,12 @@ def Create(res): obj.ViewObject.Document.setEdit(obj.ViewObject, 0) return obj except PathUtils.PathNoTCExistsException: - msg = translate( - "PathOp", "No suitable tool controller found.\nAborting op creation" - ) + msg = translate("PathOp", "No suitable tool controller found.\nAborting op creation") diag = QtGui.QMessageBox(QtGui.QMessageBox.Warning, "Error", msg) diag.setWindowModality(QtCore.Qt.ApplicationModal) diag.exec_() except PathOp.PathNoTCException: - Path.Log.warning( - translate("PathOp", "No tool controller, aborting op creation") - ) + Path.Log.warning(translate("PathOp", "No tool controller, aborting op creation")) FreeCAD.ActiveDocument.abortTransaction() FreeCAD.ActiveDocument.recompute() @@ -1423,9 +1374,7 @@ class CommandPathOp: class CommandResources: """POD class to hold command specific resources.""" - def __init__( - self, name, objFactory, opPageClass, pixmap, menuText, accelKey, toolTip - ): + def __init__(self, name, objFactory, opPageClass, pixmap, menuText, accelKey, toolTip): self.name = name self.objFactory = objFactory self.opPageClass = opPageClass @@ -1436,9 +1385,7 @@ class CommandResources: self.job = None -def SetupOperation( - name, objFactory, opPageClass, pixmap, menuText, toolTip, setupProperties=None -): +def SetupOperation(name, objFactory, opPageClass, pixmap, menuText, toolTip, setupProperties=None): """SetupOperation(name, objFactory, opPageClass, pixmap, menuText, toolTip, setupProperties=None) Creates an instance of CommandPathOp with the given parameters and registers the command with FreeCAD. When activated it creates a model with proxy (by invoking objFactory), assigns a view provider to it @@ -1447,9 +1394,7 @@ def SetupOperation( It is not expected to be called manually. """ - res = CommandResources( - name, objFactory, opPageClass, pixmap, menuText, None, toolTip - ) + res = CommandResources(name, objFactory, opPageClass, pixmap, menuText, None, toolTip) command = CommandPathOp(res) FreeCADGui.addCommand("CAM_%s" % name.replace(" ", "_"), command) diff --git a/src/Mod/CAM/Path/Op/Gui/CircularHoleBase.py b/src/Mod/CAM/Path/Op/Gui/CircularHoleBase.py index d4992cf31b..9493cdcd64 100644 --- a/src/Mod/CAM/Path/Op/Gui/CircularHoleBase.py +++ b/src/Mod/CAM/Path/Op/Gui/CircularHoleBase.py @@ -67,7 +67,7 @@ class TaskPanelHoleGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): self.form.baseList.blockSignals(True) self.form.baseList.clearContents() self.form.baseList.setRowCount(0) - for (base, subs) in obj.Base: + for base, subs in obj.Base: for sub in subs: self.form.baseList.insertRow(self.form.baseList.rowCount()) @@ -118,9 +118,7 @@ class TaskPanelHoleGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): def deleteBase(self): """deleteBase() ... callback for push button""" Path.Log.track() - selected = [ - self.form.baseList.row(item) for item in self.form.baseList.selectedItems() - ] + selected = [self.form.baseList.row(item) for item in self.form.baseList.selectedItems()] self.form.baseList.blockSignals(True) for row in sorted(list(set(selected)), key=lambda row: -row): self.form.baseList.removeRow(row) diff --git a/src/Mod/CAM/Path/Op/Gui/Comment.py b/src/Mod/CAM/Path/Op/Gui/Comment.py index 160c7d22d9..796589b7d6 100644 --- a/src/Mod/CAM/Path/Op/Gui/Comment.py +++ b/src/Mod/CAM/Path/Op/Gui/Comment.py @@ -101,9 +101,7 @@ class CommandPathComment: return { "Pixmap": "CAM_Comment", "MenuText": QT_TRANSLATE_NOOP("CAM_Comment", "Comment"), - "ToolTip": QT_TRANSLATE_NOOP( - "CAM_Comment", "Add a Comment to your CNC program" - ), + "ToolTip": QT_TRANSLATE_NOOP("CAM_Comment", "Add a Comment to your CNC program"), } def IsActive(self): diff --git a/src/Mod/CAM/Path/Op/Gui/Copy.py b/src/Mod/CAM/Path/Op/Gui/Copy.py index 6d0016d1d8..bdde0dcd20 100644 --- a/src/Mod/CAM/Path/Op/Gui/Copy.py +++ b/src/Mod/CAM/Path/Op/Gui/Copy.py @@ -91,9 +91,7 @@ class CommandPathCopy: return { "Pixmap": "CAM_Copy", "MenuText": QT_TRANSLATE_NOOP("CAM_Copy", "Copy"), - "ToolTip": QT_TRANSLATE_NOOP( - "CAM_Copy", "Creates a linked copy of another toolpath" - ), + "ToolTip": QT_TRANSLATE_NOOP("CAM_Copy", "Creates a linked copy of another toolpath"), } def IsActive(self): diff --git a/src/Mod/CAM/Path/Op/Gui/Deburr.py b/src/Mod/CAM/Path/Op/Gui/Deburr.py index 35bb6868b0..7ec917ae11 100644 --- a/src/Mod/CAM/Path/Op/Gui/Deburr.py +++ b/src/Mod/CAM/Path/Op/Gui/Deburr.py @@ -70,9 +70,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): return form def initPage(self, obj): - self.opImagePath = "{}Mod/CAM/Images/Ops/{}".format( - FreeCAD.getHomePath(), "chamfer.svg" - ) + self.opImagePath = "{}Mod/CAM/Images/Ops/{}".format(FreeCAD.getHomePath(), "chamfer.svg") self.opImage = QtGui.QPixmap(self.opImagePath) self.form.opImage.setPixmap(self.opImage) iconMiter = QtGui.QIcon(":/icons/edge-join-miter-not.svg") @@ -101,9 +99,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): FreeCAD.Units.Quantity(obj.Width.Value, FreeCAD.Units.Length).UserString ) self.form.value_h.setText( - FreeCAD.Units.Quantity( - obj.ExtraDepth.Value, FreeCAD.Units.Length - ).UserString + FreeCAD.Units.Quantity(obj.ExtraDepth.Value, FreeCAD.Units.Length).UserString ) self.setupToolController(obj, self.form.toolController) self.setupCoolant(obj, self.form.coolantController) @@ -143,9 +139,7 @@ Command = PathOpGui.SetupOperation( TaskPanelOpPage, "CAM_Deburr", QT_TRANSLATE_NOOP("CAM_Deburr", "Deburr"), - QT_TRANSLATE_NOOP( - "CAM_Deburr", "Creates a Deburr toolpath along Edges or around Faces" - ), + QT_TRANSLATE_NOOP("CAM_Deburr", "Creates a Deburr toolpath along Edges or around Faces"), PathDeburr.SetupProperties, ) diff --git a/src/Mod/CAM/Path/Op/Gui/Drilling.py b/src/Mod/CAM/Path/Op/Gui/Drilling.py index aba21c970b..55940ef298 100644 --- a/src/Mod/CAM/Path/Op/Gui/Drilling.py +++ b/src/Mod/CAM/Path/Op/Gui/Drilling.py @@ -48,15 +48,11 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): """Controller for the drilling operation's page""" def initPage(self, obj): - self.peckDepthSpinBox = PathGuiUtil.QuantitySpinBox( - self.form.peckDepth, obj, "PeckDepth" - ) + self.peckDepthSpinBox = PathGuiUtil.QuantitySpinBox(self.form.peckDepth, obj, "PeckDepth") self.peckRetractSpinBox = PathGuiUtil.QuantitySpinBox( self.form.peckRetractHeight, obj, "RetractHeight" ) - self.dwellTimeSpinBox = PathGuiUtil.QuantitySpinBox( - self.form.dwellTime, obj, "DwellTime" - ) + self.dwellTimeSpinBox = PathGuiUtil.QuantitySpinBox(self.form.dwellTime, obj, "DwellTime") self.form.chipBreakEnabled.setEnabled(False) def registerSignalHandlers(self, obj): @@ -143,9 +139,16 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): Path.Log.track() self.updateQuantitySpinBoxes() - if not hasattr(obj,"KeepToolDown"): - obj.addProperty("App::PropertyBool", "KeepToolDown", "Drill", - QtCore.QT_TRANSLATE_NOOP("App::Property", "Apply G99 retraction: only retract to RetractHeight between holes in this operation")) + if not hasattr(obj, "KeepToolDown"): + obj.addProperty( + "App::PropertyBool", + "KeepToolDown", + "Drill", + QtCore.QT_TRANSLATE_NOOP( + "App::Property", + "Apply G99 retraction: only retract to RetractHeight between holes in this operation", + ), + ) if obj.KeepToolDown: self.form.KeepToolDownEnabled.setCheckState(QtCore.Qt.Checked) diff --git a/src/Mod/CAM/Path/Op/Gui/Engrave.py b/src/Mod/CAM/Path/Op/Gui/Engrave.py index af779ed604..32707d03d7 100644 --- a/src/Mod/CAM/Path/Op/Gui/Engrave.py +++ b/src/Mod/CAM/Path/Op/Gui/Engrave.py @@ -71,10 +71,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): base = job.Proxy.resourceClone(job, sel.Object) if not base: Path.Log.notice( - ( - translate("CAM", "%s is not a Base Model object of the job %s") - + "\n" - ) + (translate("CAM", "%s is not a Base Model object of the job %s") + "\n") % (sel.Object.Label, job.Label) ) continue @@ -124,9 +121,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): sub = item.data(self.super().DataObjectSub) if not sub: shapes.append(obj) - Path.Log.debug( - "Setting new base shapes: %s -> %s" % (self.obj.BaseShapes, shapes) - ) + Path.Log.debug("Setting new base shapes: %s -> %s" % (self.obj.BaseShapes, shapes)) self.obj.BaseShapes = shapes return self.super().updateBase() diff --git a/src/Mod/CAM/Path/Op/Gui/FeatureExtension.py b/src/Mod/CAM/Path/Op/Gui/FeatureExtension.py index 75cb156ad0..12132e2876 100644 --- a/src/Mod/CAM/Path/Op/Gui/FeatureExtension.py +++ b/src/Mod/CAM/Path/Op/Gui/FeatureExtension.py @@ -311,9 +311,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): self._enableExtensions() # Recalculate extensions def createItemForBaseModel(self, base, sub, edges, extensions): - Path.Log.track( - base.Label, sub, "+", len(edges), len(base.Shape.getElement(sub).Edges) - ) + Path.Log.track(base.Label, sub, "+", len(edges), len(base.Shape.getElement(sub).Edges)) # Path.Log.debug("createItemForBaseModel() label: {}, sub: {}, {}, edgeCnt: {}, subEdges: {}".format(base.Label, sub, '+', len(edges), len(base.Shape.getElement(sub).Edges))) extendCorners = self.form.extendCorners.isChecked() @@ -349,7 +347,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): subEdges = subShape.Edges for edge in subEdges: - for (e, label) in edges: + for e, label in edges: if edge.isSame(e): ext1 = self._cachedExtension(self.obj, base, sub, label) if ext1.isValid(): @@ -362,16 +360,12 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): def edgesMatchShape(e0, e1): flipped = Path.Geom.flipEdge(e1) if flipped: - return Path.Geom.edgesMatch(e0, e1) or Path.Geom.edgesMatch( - e0, flipped - ) + return Path.Geom.edgesMatch(e0, e1) or Path.Geom.edgesMatch(e0, flipped) else: return Path.Geom.edgesMatch(e0, e1) self.extensionEdges = extensionEdges - Path.Log.debug( - "extensionEdges.values(): {}".format(extensionEdges.values()) - ) + Path.Log.debug("extensionEdges.values(): {}".format(extensionEdges.values())) for edgeList in Part.sortEdges( list(extensionEdges) ): # Identify connected edges that form wires @@ -447,10 +441,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): if self.enabled: for base in self.obj.Base: show = False - edges = [ - (edge, "Edge%d" % (i + 1)) - for i, edge in enumerate(base[0].Shape.Edges) - ] + edges = [(edge, "Edge%d" % (i + 1)) for i, edge in enumerate(base[0].Shape.Edges)] baseItem = QtGui.QStandardItem() baseItem.setData(base[0].Label, QtCore.Qt.EditRole) baseItem.setSelectable(False) @@ -531,9 +522,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): def setSelectionVisuals(item, ext): if selectItem(item, ext): - self.selectionModel.select( - item.index(), QtCore.QItemSelectionModel.Select - ) + self.selectionModel.select(item.index(), QtCore.QItemSelectionModel.Select) selected = self.selectionModel.isSelected(item.index()) if selected: @@ -652,9 +641,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): if parent and hasattr(parent, "featurePages"): for page in parent.featurePages: if hasattr(page, "panelTitle"): - if page.panelTitle == "Operation" and hasattr( - page.form, "useOutline" - ): + if page.panelTitle == "Operation" and hasattr(page.form, "useOutline"): Path.Log.debug("Found useOutline checkbox") self.useOutlineCheckbox = page.form.useOutline if page.form.useOutline.isChecked(): diff --git a/src/Mod/CAM/Path/Op/Gui/Helix.py b/src/Mod/CAM/Path/Op/Gui/Helix.py index 55ba808e21..99edc2f321 100644 --- a/src/Mod/CAM/Path/Op/Gui/Helix.py +++ b/src/Mod/CAM/Path/Op/Gui/Helix.py @@ -85,9 +85,7 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): self.setupCoolant(obj, self.form.coolantController) self.form.extraOffset.setText( - FreeCAD.Units.Quantity( - obj.OffsetExtra.Value, FreeCAD.Units.Length - ).UserString + FreeCAD.Units.Quantity(obj.OffsetExtra.Value, FreeCAD.Units.Length).UserString ) def getSignalsForUpdate(self, obj): @@ -110,9 +108,7 @@ Command = PathOpGui.SetupOperation( TaskPanelOpPage, "CAM_Helix", QT_TRANSLATE_NOOP("CAM_Helix", "Helix"), - QT_TRANSLATE_NOOP( - "CAM_Helix", "Creates a Helical toolpath from the features of a base object" - ), + QT_TRANSLATE_NOOP("CAM_Helix", "Creates a Helical toolpath from the features of a base object"), PathHelix.SetupProperties, ) diff --git a/src/Mod/CAM/Path/Op/Gui/MillFace.py b/src/Mod/CAM/Path/Op/Gui/MillFace.py index 011525d8e6..72ac381441 100644 --- a/src/Mod/CAM/Path/Op/Gui/MillFace.py +++ b/src/Mod/CAM/Path/Op/Gui/MillFace.py @@ -56,9 +56,7 @@ class TaskPanelOpPage(PathPocketBaseGui.TaskPanelOpPage): ] enumTups = PathMillFace.ObjectFace.propertyEnumerations(dataType="raw") - enumTups.update( - PathPocketShape.ObjectPocket.pocketPropertyEnumerations(dataType="raw") - ) + enumTups.update(PathPocketShape.ObjectPocket.pocketPropertyEnumerations(dataType="raw")) self.populateCombobox(form, enumTups, comboToPropertyMap) return form @@ -74,9 +72,7 @@ Command = PathOpGui.SetupOperation( TaskPanelOpPage, "CAM_Face", QT_TRANSLATE_NOOP("CAM_MillFace", "Face"), - QT_TRANSLATE_NOOP( - "CAM_MillFace", "Create a Facing Operation from a model or face" - ), + QT_TRANSLATE_NOOP("CAM_MillFace", "Create a Facing Operation from a model or face"), PathMillFace.SetupProperties, ) diff --git a/src/Mod/CAM/Path/Op/Gui/Pocket.py b/src/Mod/CAM/Path/Op/Gui/Pocket.py index 18ba4750cc..41ca6ea428 100644 --- a/src/Mod/CAM/Path/Op/Gui/Pocket.py +++ b/src/Mod/CAM/Path/Op/Gui/Pocket.py @@ -55,9 +55,7 @@ Command = PathOpGui.SetupOperation( TaskPanelOpPage, "CAM_3DPocket", QT_TRANSLATE_NOOP("CAM_Pocket3D", "3D Pocket"), - QT_TRANSLATE_NOOP( - "CAM_Pocket3D", "Creates a 3D Pocket toolpath from a face or faces" - ), + QT_TRANSLATE_NOOP("CAM_Pocket3D", "Creates a 3D Pocket toolpath from a face or faces"), PathPocket.SetupProperties, ) diff --git a/src/Mod/CAM/Path/Op/Gui/PocketBase.py b/src/Mod/CAM/Path/Op/Gui/PocketBase.py index f83fc8dbc2..5c1a5c8dc3 100644 --- a/src/Mod/CAM/Path/Op/Gui/PocketBase.py +++ b/src/Mod/CAM/Path/Op/Gui/PocketBase.py @@ -93,7 +93,6 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): if not (FeatureRestMachining & self.pocketFeatures()): form.useRestMachining.hide() - return form def updateMinTravel(self, obj, setModel=True): @@ -148,9 +147,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): """setFields(obj) ... transfers obj's property values to UI""" self.form.stepOverPercent.setValue(obj.StepOver) self.form.extraOffset.setText( - FreeCAD.Units.Quantity( - obj.ExtraOffset.Value, FreeCAD.Units.Length - ).UserString + FreeCAD.Units.Quantity(obj.ExtraOffset.Value, FreeCAD.Units.Length).UserString ) self.form.useStartPoint.setChecked(obj.UseStartPoint) self.form.useRestMachining.setChecked(obj.UseRestMachining) diff --git a/src/Mod/CAM/Path/Op/Gui/PocketShape.py b/src/Mod/CAM/Path/Op/Gui/PocketShape.py index 25cdd4327a..01338e6654 100644 --- a/src/Mod/CAM/Path/Op/Gui/PocketShape.py +++ b/src/Mod/CAM/Path/Op/Gui/PocketShape.py @@ -52,13 +52,15 @@ class TaskPanelOpPage(PathPocketBaseGui.TaskPanelOpPage): def pocketFeatures(self): """pocketFeatures() ... return FeaturePocket (see PathPocketBaseGui)""" - return PathPocketBaseGui.FeaturePocket | PathPocketBaseGui.FeatureOutline | PathPocketBaseGui.FeatureRestMachining + return ( + PathPocketBaseGui.FeaturePocket + | PathPocketBaseGui.FeatureOutline + | PathPocketBaseGui.FeatureRestMachining + ) def taskPanelBaseLocationPage(self, obj, features): if not hasattr(self, "extensionsPanel"): - self.extensionsPanel = PathFeatureExtensionsGui.TaskPanelExtensionPage( - obj, features - ) + self.extensionsPanel = PathFeatureExtensionsGui.TaskPanelExtensionPage(obj, features) return self.extensionsPanel @@ -68,9 +70,7 @@ Command = PathOpGui.SetupOperation( TaskPanelOpPage, "CAM_Pocket", QT_TRANSLATE_NOOP("CAM_Pocket_Shape", "Pocket Shape"), - QT_TRANSLATE_NOOP( - "CAM_Pocket_Shape", "Creates a pocket toolpath from a face or faces" - ), + QT_TRANSLATE_NOOP("CAM_Pocket_Shape", "Creates a pocket toolpath from a face or faces"), PathPocketShape.SetupProperties, ) diff --git a/src/Mod/CAM/Path/Op/Gui/Profile.py b/src/Mod/CAM/Path/Op/Gui/Profile.py index b161bbcde1..a9ce036787 100644 --- a/src/Mod/CAM/Path/Op/Gui/Profile.py +++ b/src/Mod/CAM/Path/Op/Gui/Profile.py @@ -98,9 +98,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): self.selectInComboBox(obj.Side, self.form.cutSide) self.selectInComboBox(obj.Direction, self.form.direction) self.form.extraOffset.setText( - FreeCAD.Units.Quantity( - obj.OffsetExtra.Value, FreeCAD.Units.Length - ).UserString + FreeCAD.Units.Quantity(obj.OffsetExtra.Value, FreeCAD.Units.Length).UserString ) self.form.useCompensation.setChecked(obj.UseComp) @@ -135,7 +133,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): objBase = self.obj.Base if objBase.__len__() > 0: - for (base, subsList) in objBase: + for base, subsList in objBase: for sub in subsList: if sub[:4] == "Face": hasFace = True @@ -163,9 +161,7 @@ Command = PathOpGui.SetupOperation( TaskPanelOpPage, "CAM_Profile", QT_TRANSLATE_NOOP("CAM_Profile", "Profile"), - QT_TRANSLATE_NOOP( - "CAM_Profile", "Profile entire model, selected face(s) or selected edge(s)" - ), + QT_TRANSLATE_NOOP("CAM_Profile", "Profile entire model, selected face(s) or selected edge(s)"), PathProfile.SetupProperties, ) diff --git a/src/Mod/CAM/Path/Op/Gui/SimpleCopy.py b/src/Mod/CAM/Path/Op/Gui/SimpleCopy.py index 52727795be..9f6fb9a4a8 100644 --- a/src/Mod/CAM/Path/Op/Gui/SimpleCopy.py +++ b/src/Mod/CAM/Path/Op/Gui/SimpleCopy.py @@ -55,30 +55,22 @@ class CommandPathSimpleCopy: selection = FreeCADGui.Selection.getSelection() if len(selection) != 1: FreeCAD.Console.PrintError( - translate("CAM_SimpleCopy", "Please select exactly one toolpath object") - + "\n" + translate("CAM_SimpleCopy", "Please select exactly one toolpath object") + "\n" ) return if not (selection[0].isDerivedFrom("Path::Feature")): FreeCAD.Console.PrintError( - translate("CAM_SimpleCopy", "Please select exactly one toolpath object") - + "\n" + translate("CAM_SimpleCopy", "Please select exactly one toolpath object") + "\n" ) return FreeCAD.ActiveDocument.openTransaction("Simple Copy") - FreeCADGui.doCommand( - "srcobj = FreeCADGui.Selection.getSelectionEx()[0].Object\n" - ) + FreeCADGui.doCommand("srcobj = FreeCADGui.Selection.getSelectionEx()[0].Object\n") FreeCADGui.addModule("PathScripts.PathUtils") - FreeCADGui.doCommand( - "srcpath = PathScripts.PathUtils.getPathWithPlacement(srcobj)\n" - ) + FreeCADGui.doCommand("srcpath = PathScripts.PathUtils.getPathWithPlacement(srcobj)\n") FreeCADGui.addModule("Path.Op.Custom") - FreeCADGui.doCommand( - 'obj = Path.Op.Custom.Create("' + selection[0].Name + '_SimpleCopy")' - ) + FreeCADGui.doCommand('obj = Path.Op.Custom.Create("' + selection[0].Name + '_SimpleCopy")') FreeCADGui.doCommand("obj.ViewObject.Proxy = 0") FreeCADGui.doCommand("obj.Gcode = [c.toGCode() for c in srcpath.Commands]") FreeCADGui.doCommand("PathScripts.PathUtils.addToJob(obj)") diff --git a/src/Mod/CAM/Path/Op/Gui/Slot.py b/src/Mod/CAM/Path/Op/Gui/Slot.py index f5c4a493fe..5118097400 100644 --- a/src/Mod/CAM/Path/Op/Gui/Slot.py +++ b/src/Mod/CAM/Path/Op/Gui/Slot.py @@ -125,9 +125,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): val = self.propEnums["LayerMode"][self.form.layerMode.currentIndex()][1] obj.LayerMode = val - val = self.propEnums["PathOrientation"][ - self.form.pathOrientation.currentIndex() - ][1] + val = self.propEnums["PathOrientation"][self.form.pathOrientation.currentIndex()][1] obj.PathOrientation = val obj.ReverseDirection = self.form.reverseDirection.isChecked() @@ -186,16 +184,12 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): # Show Reference1 and customize options within self.form.geo1Reference.show() self.form.geo1Reference_label.show() - self.form.geo1Reference_label.setText( - "Start Reference: {}".format(n1) - ) + self.form.geo1Reference_label.setText("Start Reference: {}".format(n1)) self.customizeReference_1(n1) # Show Reference2 and customize options within self.form.geo2Reference.show() self.form.geo2Reference_label.show() - self.form.geo2Reference_label.setText( - "End Reference: {}".format(n2) - ) + self.form.geo2Reference_label.setText("End Reference: {}".format(n2)) self.customizeReference_2(n2) else: self.form.pathOrientation_label.hide() diff --git a/src/Mod/CAM/Path/Op/Gui/Stop.py b/src/Mod/CAM/Path/Op/Gui/Stop.py index 6133672fbf..fa887eff4a 100644 --- a/src/Mod/CAM/Path/Op/Gui/Stop.py +++ b/src/Mod/CAM/Path/Op/Gui/Stop.py @@ -37,9 +37,7 @@ class Stop: "App::PropertyEnumeration", "Stop", "Path", - QT_TRANSLATE_NOOP( - "App::Property", "Add Optional or Mandatory Stop to the program" - ), + QT_TRANSLATE_NOOP("App::Property", "Add Optional or Mandatory Stop to the program"), ) obj.Stop = ["Optional", "Mandatory"] obj.Proxy = self @@ -121,9 +119,7 @@ class CommandPathStop: return False def Activated(self): - FreeCAD.ActiveDocument.openTransaction( - "Add Optional or Mandatory Stop to the program" - ) + FreeCAD.ActiveDocument.openTransaction("Add Optional or Mandatory Stop to the program") FreeCADGui.addModule("Path.Op.Gui.Stop") snippet = """ import Path diff --git a/src/Mod/CAM/Path/Op/Gui/Surface.py b/src/Mod/CAM/Path/Op/Gui/Surface.py index d7c513c7cc..b1103a0a98 100644 --- a/src/Mod/CAM/Path/Op/Gui/Surface.py +++ b/src/Mod/CAM/Path/Op/Gui/Surface.py @@ -136,13 +136,8 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): if obj.OptimizeLinearPaths != self.form.optimizeEnabled.isChecked(): obj.OptimizeLinearPaths = self.form.optimizeEnabled.isChecked() - if ( - obj.OptimizeStepOverTransitions - != self.form.optimizeStepOverTransitions.isChecked() - ): - obj.OptimizeStepOverTransitions = ( - self.form.optimizeStepOverTransitions.isChecked() - ) + if obj.OptimizeStepOverTransitions != self.form.optimizeStepOverTransitions.isChecked(): + obj.OptimizeStepOverTransitions = self.form.optimizeStepOverTransitions.isChecked() def setFields(self, obj): """setFields(obj) ... transfers obj's property values to UI""" @@ -169,26 +164,18 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): self.form.avoidLastX_Faces.setValue(obj.AvoidLastX_Faces) self.form.boundBoxExtraOffsetX.setText( - FreeCAD.Units.Quantity( - obj.DropCutterExtraOffset.x, FreeCAD.Units.Length - ).UserString + FreeCAD.Units.Quantity(obj.DropCutterExtraOffset.x, FreeCAD.Units.Length).UserString ) self.form.boundBoxExtraOffsetY.setText( - FreeCAD.Units.Quantity( - obj.DropCutterExtraOffset.y, FreeCAD.Units.Length - ).UserString + FreeCAD.Units.Quantity(obj.DropCutterExtraOffset.y, FreeCAD.Units.Length).UserString ) self.selectInComboBox(obj.DropCutterDir, self.form.dropCutterDirSelect) self.form.depthOffset.setText( - FreeCAD.Units.Quantity( - obj.DepthOffset.Value, FreeCAD.Units.Length - ).UserString + FreeCAD.Units.Quantity(obj.DepthOffset.Value, FreeCAD.Units.Length).UserString ) self.form.stepOver.setValue(obj.StepOver) self.form.sampleInterval.setText( - FreeCAD.Units.Quantity( - obj.SampleInterval.Value, FreeCAD.Units.Length - ).UserString + FreeCAD.Units.Quantity(obj.SampleInterval.Value, FreeCAD.Units.Length).UserString ) if obj.UseStartPoint: @@ -280,9 +267,7 @@ Command = PathOpGui.SetupOperation( TaskPanelOpPage, "CAM_3DSurface", QtCore.QT_TRANSLATE_NOOP("CAM_Surface", "3D Surface"), - QtCore.QT_TRANSLATE_NOOP( - "CAM_Surface", "Create a 3D Surface Operation from a model" - ), + QtCore.QT_TRANSLATE_NOOP("CAM_Surface", "Create a 3D Surface Operation from a model"), PathSurface.SetupProperties, ) diff --git a/src/Mod/CAM/Path/Op/Gui/ThreadMilling.py b/src/Mod/CAM/Path/Op/Gui/ThreadMilling.py index 9f99e72e05..5f019d90e4 100644 --- a/src/Mod/CAM/Path/Op/Gui/ThreadMilling.py +++ b/src/Mod/CAM/Path/Op/Gui/ThreadMilling.py @@ -55,9 +55,7 @@ def fillThreads(form, dataFile, defaultSelect): select = form.threadName.currentText() Path.Log.debug("select = '{}'".format(select)) form.threadName.clear() - with open( - "{}Mod/CAM/Data/Threads/{}".format(FreeCAD.getHomePath(), dataFile) - ) as fp: + with open("{}Mod/CAM/Data/Threads/{}".format(FreeCAD.getHomePath(), dataFile)) as fp: reader = csv.DictReader(fp) for row in reader: form.threadName.addItem(row["name"], row) @@ -73,12 +71,8 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): """Controller for the thread milling operation's page""" def initPage(self, obj): - self.majorDia = PathGuiUtil.QuantitySpinBox( - self.form.threadMajor, obj, "MajorDiameter" - ) - self.minorDia = PathGuiUtil.QuantitySpinBox( - self.form.threadMinor, obj, "MinorDiameter" - ) + self.majorDia = PathGuiUtil.QuantitySpinBox(self.form.threadMajor, obj, "MajorDiameter") + self.minorDia = PathGuiUtil.QuantitySpinBox(self.form.threadMinor, obj, "MinorDiameter") self.pitch = PathGuiUtil.QuantitySpinBox(self.form.threadPitch, obj, "Pitch") def getForm(self): @@ -89,9 +83,7 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): ("threadType", "ThreadType"), ("opDirection", "Direction"), ] - enumTups = PathThreadMilling.ObjectThreadMilling.propertyEnumerations( - dataType="raw" - ) + enumTups = PathThreadMilling.ObjectThreadMilling.propertyEnumerations(dataType="raw") self.populateCombobox(form, enumTups, comboToPropertyMap) return form @@ -157,22 +149,16 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): ] def _isThreadImperial(self): - return ( - self.form.threadType.currentData() in PathThreadMilling.ThreadTypesImperial - ) + return self.form.threadType.currentData() in PathThreadMilling.ThreadTypesImperial def _isThreadMetric(self): return self.form.threadType.currentData() in PathThreadMilling.ThreadTypesMetric def _isThreadInternal(self): - return ( - self.form.threadType.currentData() in PathThreadMilling.ThreadTypesInternal - ) + return self.form.threadType.currentData() in PathThreadMilling.ThreadTypesInternal def _isThreadExternal(self): - return ( - self.form.threadType.currentData() in PathThreadMilling.ThreadTypesExternal - ) + return self.form.threadType.currentData() in PathThreadMilling.ThreadTypesExternal def _updateFromThreadType(self): diff --git a/src/Mod/CAM/Path/Op/Gui/Vcarve.py b/src/Mod/CAM/Path/Op/Gui/Vcarve.py index 662f32d774..8d8a2c93f5 100644 --- a/src/Mod/CAM/Path/Op/Gui/Vcarve.py +++ b/src/Mod/CAM/Path/Op/Gui/Vcarve.py @@ -63,17 +63,12 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): base = job.Proxy.resourceClone(job, sel.Object) if not base: Path.Log.notice( - ( - translate("CAM", "%s is not a Base Model object of the job %s") - + "\n" - ) + (translate("CAM", "%s is not a Base Model object of the job %s") + "\n") % (sel.Object.Label, job.Label) ) continue if base in shapes: - Path.Log.notice( - "Base shape %s already in the list".format(sel.Object.Label) - ) + Path.Log.notice("Base shape %s already in the list".format(sel.Object.Label)) continue if base.isDerivedFrom("Part::Part2DObject"): if sel.HasSubObjects: @@ -117,9 +112,7 @@ class TaskPanelBaseGeometryPage(PathOpGui.TaskPanelBaseGeometryPage): sub = item.data(self.super().DataObjectSub) if not sub: shapes.append(obj) - Path.Log.debug( - "Setting new base shapes: %s -> %s" % (self.obj.BaseShapes, shapes) - ) + Path.Log.debug("Setting new base shapes: %s -> %s" % (self.obj.BaseShapes, shapes)) self.obj.BaseShapes = shapes return self.super().updateBase() diff --git a/src/Mod/CAM/Path/Op/Gui/Waterline.py b/src/Mod/CAM/Path/Op/Gui/Waterline.py index 61526ecbc0..23347f8a4c 100644 --- a/src/Mod/CAM/Path/Op/Gui/Waterline.py +++ b/src/Mod/CAM/Path/Op/Gui/Waterline.py @@ -81,9 +81,7 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): if obj.CutPattern != str(self.form.cutPattern.currentData()): obj.CutPattern = str(self.form.cutPattern.currentData()) - PathGuiUtil.updateInputField( - obj, "BoundaryAdjustment", self.form.boundaryAdjustment - ) + PathGuiUtil.updateInputField(obj, "BoundaryAdjustment", self.form.boundaryAdjustment) if obj.StepOver != self.form.stepOver.value(): obj.StepOver = self.form.stepOver.value() @@ -102,15 +100,11 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage): self.selectInComboBox(obj.LayerMode, self.form.layerMode) self.selectInComboBox(obj.CutPattern, self.form.cutPattern) self.form.boundaryAdjustment.setText( - FreeCAD.Units.Quantity( - obj.BoundaryAdjustment.Value, FreeCAD.Units.Length - ).UserString + FreeCAD.Units.Quantity(obj.BoundaryAdjustment.Value, FreeCAD.Units.Length).UserString ) self.form.stepOver.setValue(obj.StepOver) self.form.sampleInterval.setText( - FreeCAD.Units.Quantity( - obj.SampleInterval.Value, FreeCAD.Units.Length - ).UserString + FreeCAD.Units.Quantity(obj.SampleInterval.Value, FreeCAD.Units.Length).UserString ) if obj.OptimizeLinearPaths: diff --git a/src/Mod/CAM/Path/Op/Helix.py b/src/Mod/CAM/Path/Op/Helix.py index dbc1cdc0e5..7df87e70c4 100644 --- a/src/Mod/CAM/Path/Op/Helix.py +++ b/src/Mod/CAM/Path/Op/Helix.py @@ -93,9 +93,7 @@ class ObjectHelix(PathCircularHoleBase.ObjectOp): def circularHoleFeatures(self, obj): """circularHoleFeatures(obj) ... enable features supported by Helix.""" - return ( - PathOp.FeatureStepDown | PathOp.FeatureBaseEdges | PathOp.FeatureBaseFaces - ) + return PathOp.FeatureStepDown | PathOp.FeatureBaseEdges | PathOp.FeatureBaseFaces def initCircularHoleOperation(self, obj): """initCircularHoleOperation(obj) ... create helix specific properties.""" @@ -113,9 +111,7 @@ class ObjectHelix(PathCircularHoleBase.ObjectOp): "App::PropertyEnumeration", "StartSide", "Helix Drill", - QT_TRANSLATE_NOOP( - "App::Property", "Start cutting from the inside or outside" - ), + QT_TRANSLATE_NOOP("App::Property", "Start cutting from the inside or outside"), ) obj.addProperty( @@ -177,9 +173,7 @@ class ObjectHelix(PathCircularHoleBase.ObjectOp): holes = sort_locations(holes, ["x", "y"]) tool = obj.ToolController.Tool - tooldiamter = ( - tool.Diameter.Value if hasattr(tool.Diameter, "Value") else tool.Diameter - ) + tooldiamter = tool.Diameter.Value if hasattr(tool.Diameter, "Value") else tool.Diameter args = { "edge": None, @@ -199,9 +193,7 @@ class ObjectHelix(PathCircularHoleBase.ObjectOp): args["edge"] = Part.makeLine(startPoint, endPoint) # move to starting position - self.commandlist.append( - Path.Command("G0", {"Z": obj.ClearanceHeight.Value}) - ) + self.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value})) self.commandlist.append( Path.Command( "G0", @@ -213,9 +205,7 @@ class ObjectHelix(PathCircularHoleBase.ObjectOp): ) ) self.commandlist.append( - Path.Command( - "G0", {"X": startPoint.x, "Y": startPoint.y, "Z": startPoint.z} - ) + Path.Command("G0", {"X": startPoint.x, "Y": startPoint.y, "Z": startPoint.z}) ) results = helix.generate(**args) diff --git a/src/Mod/CAM/Path/Op/MillFace.py b/src/Mod/CAM/Path/Op/MillFace.py index 5925d1960c..d89929bb4b 100644 --- a/src/Mod/CAM/Path/Op/MillFace.py +++ b/src/Mod/CAM/Path/Op/MillFace.py @@ -108,9 +108,7 @@ class ObjectFace(PathPocketBase.ObjectPocket): "App::PropertyBool", "ExcludeRaisedAreas", "Face", - QT_TRANSLATE_NOOP( - "App::Property", "Exclude milling raised areas inside the face." - ), + QT_TRANSLATE_NOOP("App::Property", "Exclude milling raised areas inside the face."), ) for n in self.propertyEnumerations(): @@ -174,9 +172,7 @@ class ObjectFace(PathPocketBase.ObjectPocket): # Limit to one model base per operation if oneBase[0] is not b[0]: oneBase[1] = False - if numpy.isclose( - abs(shape.normalAt(0, 0).z), 1 - ): # horizontal face + if numpy.isclose(abs(shape.normalAt(0, 0).z), 1): # horizontal face # Analyze internal closed wires to determine if raised or a recess for wire in shape.Wires[1:]: if obj.ExcludeRaisedAreas: @@ -187,17 +183,13 @@ class ObjectFace(PathPocketBase.ObjectPocket): holes.append((b[0].Shape, wire)) else: Path.Log.warning( - 'The base subobject, "{0}," is not a face. Ignoring "{0}."'.format( - sub - ) + 'The base subobject, "{0}," is not a face. Ignoring "{0}."'.format(sub) ) if obj.ExcludeRaisedAreas and len(holes) > 0: for shape, wire in holes: f = Part.makeFace(wire, "Part::FaceMakerSimple") - env = PathUtils.getEnvelope( - shape, subshape=f, depthparams=self.depthparams - ) + env = PathUtils.getEnvelope(shape, subshape=f, depthparams=self.depthparams) holeEnvs.append(env) holeShape = Part.makeCompound(holeEnvs) @@ -233,9 +225,7 @@ class ObjectFace(PathPocketBase.ObjectPocket): ) env = PathUtils.getEnvelope(partshape=bbperim, depthparams=self.depthparams) if obj.ExcludeRaisedAreas and oneBase[1]: - includedFaces = self.getAllIncludedFaces( - oneBase[0], env, faceZ=minHeight - ) + includedFaces = self.getAllIncludedFaces(oneBase[0], env, faceZ=minHeight) if len(includedFaces) > 0: includedShape = Part.makeCompound(includedFaces) includedEnv = PathUtils.getEnvelope( @@ -249,13 +239,9 @@ class ObjectFace(PathPocketBase.ObjectPocket): env = stock if obj.ExcludeRaisedAreas and oneBase[1]: - includedFaces = self.getAllIncludedFaces( - oneBase[0], stock, faceZ=minHeight - ) + includedFaces = self.getAllIncludedFaces(oneBase[0], stock, faceZ=minHeight) if len(includedFaces) > 0: - stockEnv = PathUtils.getEnvelope( - partshape=stock, depthparams=self.depthparams - ) + stockEnv = PathUtils.getEnvelope(partshape=stock, depthparams=self.depthparams) includedShape = Part.makeCompound(includedFaces) includedEnv = PathUtils.getEnvelope( oneBase[0].Shape, @@ -269,16 +255,10 @@ class ObjectFace(PathPocketBase.ObjectPocket): ofstShape = PathUtils.getOffsetArea( planeshape, self.radius * 1.25, plane=planeshape ) - ofstShape.translate( - FreeCAD.Vector(0.0, 0.0, psZMin - ofstShape.BoundBox.ZMin) - ) - env = PathUtils.getEnvelope( - partshape=ofstShape, depthparams=self.depthparams - ) + ofstShape.translate(FreeCAD.Vector(0.0, 0.0, psZMin - ofstShape.BoundBox.ZMin)) + env = PathUtils.getEnvelope(partshape=ofstShape, depthparams=self.depthparams) else: - env = PathUtils.getEnvelope( - partshape=planeshape, depthparams=self.depthparams - ) + env = PathUtils.getEnvelope(partshape=planeshape, depthparams=self.depthparams) elif obj.BoundaryShape == "Face Region": baseShape = planeshape # oneBase[0].Shape psZMin = planeshape.BoundBox.ZMin @@ -286,17 +266,13 @@ class ObjectFace(PathPocketBase.ObjectPocket): if obj.ClearEdges: ofst = self.tool.Diameter * 0.51 ofstShape = PathUtils.getOffsetArea(planeshape, ofst, plane=planeshape) - ofstShape.translate( - FreeCAD.Vector(0.0, 0.0, psZMin - ofstShape.BoundBox.ZMin) - ) + ofstShape.translate(FreeCAD.Vector(0.0, 0.0, psZMin - ofstShape.BoundBox.ZMin)) # Calculate custom depth params for removal shape envelope, with start and final depth buffers custDepthparams = self._customDepthParams( obj, obj.StartDepth.Value + 0.2, obj.FinalDepth.Value - 0.1 ) # only an envelope - ofstShapeEnv = PathUtils.getEnvelope( - partshape=ofstShape, depthparams=custDepthparams - ) + ofstShapeEnv = PathUtils.getEnvelope(partshape=ofstShape, depthparams=custDepthparams) if obj.ExcludeRaisedAreas: env = ofstShapeEnv.cut(baseShape) env.translate( @@ -307,9 +283,7 @@ class ObjectFace(PathPocketBase.ObjectPocket): if holeShape: Path.Log.debug("Processing holes and face ...") - holeEnv = PathUtils.getEnvelope( - partshape=holeShape, depthparams=self.depthparams - ) + holeEnv = PathUtils.getEnvelope(partshape=holeShape, depthparams=self.depthparams) newEnv = env.cut(holeEnv) tup = newEnv, False, "pathMillFace" else: @@ -359,7 +333,8 @@ class ObjectFace(PathPocketBase.ObjectPocket): def getAllIncludedFaces(self, base, env, faceZ): """getAllIncludedFaces(base, env, faceZ)... - Return all `base` faces extending above `faceZ` whose boundboxes overlap with the `env` boundbox.""" + Return all `base` faces extending above `faceZ` whose boundboxes overlap with the `env` boundbox. + """ included = [] eXMin = env.BoundBox.XMin diff --git a/src/Mod/CAM/Path/Op/Pocket.py b/src/Mod/CAM/Path/Op/Pocket.py index a961f53ffb..6bfa54176f 100644 --- a/src/Mod/CAM/Path/Op/Pocket.py +++ b/src/Mod/CAM/Path/Op/Pocket.py @@ -178,10 +178,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): if len(Faces) == 0: allSubsFaceType = False - if ( - allSubsFaceType is True - and obj.HandleMultipleFeatures == "Collectively" - ): + if allSubsFaceType is True and obj.HandleMultipleFeatures == "Collectively": (fzmin, fzmax) = self.getMinMaxOfFaces(Faces) if obj.FinalDepth.Value < fzmin: Path.Log.warning( @@ -191,10 +188,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): ) ) - if ( - obj.AdaptivePocketStart is True - or obj.AdaptivePocketFinish is True - ): + if obj.AdaptivePocketStart is True or obj.AdaptivePocketFinish is True: pocketTup = self.calculateAdaptivePocket(obj, base, subObjTups) if pocketTup is not False: obj.removalshape = pocketTup[0] @@ -205,12 +199,8 @@ class ObjectPocket(PathPocketBase.ObjectPocket): base[0].Shape, subshape=shape, depthparams=self.depthparams ) rawRemovalShape = env.cut(base[0].Shape) - faceExtrusions = [ - f.extrude(FreeCAD.Vector(0.0, 0.0, 1.0)) for f in Faces - ] - obj.removalshape = _identifyRemovalSolids( - rawRemovalShape, faceExtrusions - ) + faceExtrusions = [f.extrude(FreeCAD.Vector(0.0, 0.0, 1.0)) for f in Faces] + obj.removalshape = _identifyRemovalSolids(rawRemovalShape, faceExtrusions) removalshapes.append( (obj.removalshape, False, "3DPocket") ) # (shape, isHole, detail) @@ -227,9 +217,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): ) rawRemovalShape = env.cut(base[0].Shape) faceExtrusions = [shape.extrude(FreeCAD.Vector(0.0, 0.0, 1.0))] - obj.removalshape = _identifyRemovalSolids( - rawRemovalShape, faceExtrusions - ) + obj.removalshape = _identifyRemovalSolids(rawRemovalShape, faceExtrusions) removalshapes.append((obj.removalshape, False, "3DPocket")) else: # process the job base object as a whole @@ -253,9 +241,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): removalSolids = [ s for s in rawRemovalShape.Solids - if Path.Geom.isRoughly( - s.BoundBox.ZMax, rawRemovalShape.BoundBox.ZMax - ) + if Path.Geom.isRoughly(s.BoundBox.ZMax, rawRemovalShape.BoundBox.ZMax) ] # Fuse multiple solids @@ -300,7 +286,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): isHighFacePlanar = True isLowFacePlanar = True - for (sub, face) in subObjTups: + for sub, face in subObjTups: Faces.append(face) # identify max and min face heights for top loop @@ -317,7 +303,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): allEdges = [] makeHighFace = 0 tryNonPlanar = False - for (sub, face, ei) in high: + for sub, face, ei in high: allEdges.append(face.Edges[ei]) (hzmin, hzmax) = self.getMinMaxOfFaces(allEdges) @@ -344,9 +330,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): except Exception as eee: Path.Log.warning(eee) Path.Log.error( - translate( - "CAM", "The non-planar adaptive start is also unavailable." - ) + translate("CAM", "The non-planar adaptive start is also unavailable.") + "(1)" ) isHighFacePlanar = False @@ -363,10 +347,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): if makeHighFace == 2: mx = hzmax + obj.StepDown.Value mn = hzmin - obj.StepDown.Value - if ( - highFace.Shape.BoundBox.ZMax > mx - or highFace.Shape.BoundBox.ZMin < mn - ): + if highFace.Shape.BoundBox.ZMax > mx or highFace.Shape.BoundBox.ZMin < mn: Path.Log.warning( "ZMaxDiff: {}; ZMinDiff: {}".format( highFace.Shape.BoundBox.ZMax - mx, @@ -374,9 +355,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): ) ) Path.Log.error( - translate( - "CAM", "The non-planar adaptive start is also unavailable." - ) + translate("CAM", "The non-planar adaptive start is also unavailable.") + "(2)" ) isHighFacePlanar = False @@ -387,7 +366,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): if len(low) > 0 and obj.AdaptivePocketFinish is True: # attempt planar face with bottom edges of pocket allEdges = [] - for (sub, face, ei) in low: + for sub, face, ei in low: allEdges.append(face.Edges[ei]) # (lzmin, lzmax) = self.getMinMaxOfFaces(allEdges) @@ -430,9 +409,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): user_depths=None, ) shape = Part.makeCompound(Faces) - env = PathUtils.getEnvelope( - base[0].Shape, subshape=shape, depthparams=depthparams - ) + env = PathUtils.getEnvelope(base[0].Shape, subshape=shape, depthparams=depthparams) cuts.append(env.cut(base[0].Shape)) # Might need to change to .cut(job.Stock.Shape) if pocket has no bottom @@ -524,7 +501,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): return int(sub.replace("Face", "")) - 1 # get CenterOfMass for each face and add to sumCenterOfMass for average calculation - for (sub, face) in subObjTups: + for sub, face in subObjTups: # for (bsNm, fIdx, eIdx, vIdx) in bfevList: # face = FreeCAD.ActiveDocument.getObject(bsNm).Shape.Faces[fIdx] subCnt += 1 @@ -538,13 +515,9 @@ class ObjectPocket(PathPocketBase.ObjectPocket): avgCom.z = sumCom.z / subCnt # calculate vector (mag, direct) for each face from avgCom - for (sub, face, com) in comList: - adjCom = com.sub( - avgCom - ) # effectively treats avgCom as origin for each face. - mag = math.sqrt( - adjCom.x**2 + adjCom.y**2 - ) # adjCom.Length without Z values + for sub, face, com in comList: + adjCom = com.sub(avgCom) # effectively treats avgCom as origin for each face. + mag = math.sqrt(adjCom.x**2 + adjCom.y**2) # adjCom.Length without Z values drctn = 0.0 # Determine direction of vector if adjCom.x > 0.0: @@ -572,7 +545,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): sortList = sorted(vectList, key=getDrctn) # remove magnitute and direction values - for (sub, face, mag, drctn) in sortList: + for sub, face, mag, drctn in sortList: newList.append((sub, face)) # Rotate list items so highest face is first @@ -604,7 +577,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): touchingCleaned = {} # Prepare dictionary for edges in shared - for (sub, face) in subObjTups: + for sub, face in subObjTups: touching[sub] = [] # prepare list of indexes as proxies for subObjTups items @@ -633,9 +606,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): edg2 = face2.Edges[ei2] if edg1.isSame(edg2) is True: Path.Log.debug( - "{}.Edges[{}] connects at {}.Edges[{}]".format( - sub1, ei1, sub2, ei2 - ) + "{}.Edges[{}] connects at {}.Edges[{}]".format(sub1, ei1, sub2, ei2) ) shared.append((sub1, face1, ei1)) touching[sub1].append(ei1) @@ -659,7 +630,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): low = [] holding = [] - for (sub, face) in subObjTups: + for sub, face in subObjTups: holding = [] for ei in range(0, len(face.Edges)): if ei not in touching[sub]: @@ -780,7 +751,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): (sub2, face2, ei2) = holding[h2] # Cycle through attachments for connection to existing - for (g, t) in attachments: + for g, t in attachments: h1 = grps[g][t] (sub1, face1, ei1) = holding[h1] @@ -893,9 +864,7 @@ def _extrudeBaseDown(base): allExtrusions = list() zMin = base.Shape.BoundBox.ZMin bbFace = Path.Geom.makeBoundBoxFace(base.Shape.BoundBox, offset=5.0) - bbFace.translate( - FreeCAD.Vector(0.0, 0.0, float(int(base.Shape.BoundBox.ZMin - 5.0))) - ) + bbFace.translate(FreeCAD.Vector(0.0, 0.0, float(int(base.Shape.BoundBox.ZMin - 5.0)))) direction = FreeCAD.Vector(0.0, 0.0, -1.0) # Make projections of each non-vertical face and extrude it diff --git a/src/Mod/CAM/Path/Op/PocketBase.py b/src/Mod/CAM/Path/Op/PocketBase.py index 681cdcd936..36cad37b6c 100644 --- a/src/Mod/CAM/Path/Op/PocketBase.py +++ b/src/Mod/CAM/Path/Op/PocketBase.py @@ -90,11 +90,7 @@ class ObjectPocket(PathAreaOp.ObjectOp): def areaOpFeatures(self, obj): """areaOpFeatures(obj) ... Pockets have a FinishDepth and work on Faces""" - return ( - PathOp.FeatureBaseFaces - | PathOp.FeatureFinishDepth - | self.pocketOpFeatures(obj) - ) + return PathOp.FeatureBaseFaces | PathOp.FeatureFinishDepth | self.pocketOpFeatures(obj) def pocketOpFeatures(self, obj): return 0 @@ -177,9 +173,7 @@ class ObjectPocket(PathAreaOp.ObjectOp): "App::PropertyBool", "KeepToolDown", "Pocket", - QT_TRANSLATE_NOOP( - "App::Property", "Attempts to avoid unnecessary retractions." - ), + QT_TRANSLATE_NOOP("App::Property", "Attempts to avoid unnecessary retractions."), ) obj.addProperty( "App::PropertyPercent", diff --git a/src/Mod/CAM/Path/Op/PocketShape.py b/src/Mod/CAM/Path/Op/PocketShape.py index d95d521c37..8e4156f4bf 100644 --- a/src/Mod/CAM/Path/Op/PocketShape.py +++ b/src/Mod/CAM/Path/Op/PocketShape.py @@ -34,9 +34,7 @@ Part = LazyLoader("Part", globals(), "Part") TechDraw = LazyLoader("TechDraw", globals(), "TechDraw") math = LazyLoader("math", globals(), "math") PathUtils = LazyLoader("PathScripts.PathUtils", globals(), "PathScripts.PathUtils") -FeatureExtensions = LazyLoader( - "Path.Op.FeatureExtension", globals(), "Path.Op.FeatureExtension" -) +FeatureExtensions = LazyLoader("Path.Op.FeatureExtension", globals(), "Path.Op.FeatureExtension") __title__ = "CAM Pocket Shape Operation" @@ -65,9 +63,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): "App::PropertyBool", "UseOutline", "Pocket", - QT_TRANSLATE_NOOP( - "App::Property", "Uses the outline of the base geometry." - ), + QT_TRANSLATE_NOOP("App::Property", "Uses the outline of the base geometry."), ) FeatureExtensions.initialize_properties(obj) @@ -105,14 +101,12 @@ class ObjectPocket(PathPocketBase.ObjectPocket): Path.Log.debug("base items exist. Processing...") self.horiz = [] self.vert = [] - for (base, subList) in obj.Base: + for base, subList in obj.Base: for sub in subList: if "Face" in sub: if sub not in avoidFeatures and not self.clasifySub(base, sub): Path.Log.error( - "Pocket does not support shape {}.{}".format( - base.Label, sub - ) + "Pocket does not support shape {}.{}".format(base.Label, sub) ) # Convert horizontal faces to use outline only if requested @@ -158,26 +152,19 @@ class ObjectPocket(PathPocketBase.ObjectPocket): buffer = self.job.GeometryTolerance.Value / 10.0 for h in self.horizontal: h.translate( - FreeCAD.Vector( - 0.0, 0.0, obj.FinalDepth.Value - h.BoundBox.ZMin - buffer - ) + FreeCAD.Vector(0.0, 0.0, obj.FinalDepth.Value - h.BoundBox.ZMin - buffer) ) # extrude all faces up to StartDepth plus buffer and those are the removal shapes - extent = FreeCAD.Vector( - 0, 0, obj.StartDepth.Value - obj.FinalDepth.Value + buffer - ) + extent = FreeCAD.Vector(0, 0, obj.StartDepth.Value - obj.FinalDepth.Value + buffer) self.removalshapes = [ - (face.removeSplitter().extrude(extent), False) - for face in self.horizontal + (face.removeSplitter().extrude(extent), False) for face in self.horizontal ] else: # process the job base object as a whole Path.Log.debug("processing the whole job base object") self.outlines = [ - Part.Face( - TechDraw.findShapeOutline(base.Shape, 1, FreeCAD.Vector(0, 0, 1)) - ) + Part.Face(TechDraw.findShapeOutline(base.Shape, 1, FreeCAD.Vector(0, 0, 1))) for base in self.model ] stockBB = self.stock.Shape.BoundBox @@ -232,9 +219,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): else: return False - elif type(face.Surface) == Part.Cylinder and Path.Geom.isVertical( - face.Surface.Axis - ): + elif type(face.Surface) == Part.Cylinder and Path.Geom.isVertical(face.Surface.Axis): Path.Log.debug("type() == Part.Cylinder") # vertical cylinder wall if any(e.isClosed() for e in face.Edges): @@ -242,9 +227,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): # complete cylinder circle = Part.makeCircle(face.Surface.Radius, face.Surface.Center) disk = Part.Face(Part.Wire(circle)) - disk.translate( - FreeCAD.Vector(0, 0, face.BoundBox.ZMin - disk.BoundBox.ZMin) - ) + disk.translate(FreeCAD.Vector(0, 0, face.BoundBox.ZMin - disk.BoundBox.ZMin)) self.horiz.append(disk) return True @@ -274,9 +257,7 @@ class ObjectPocket(PathPocketBase.ObjectPocket): def SetupProperties(): setup = PathPocketBase.SetupProperties() # Add properties from PocketBase module - setup.extend( - FeatureExtensions.SetupProperties() - ) # Add properties from Extensions Feature + setup.extend(FeatureExtensions.SetupProperties()) # Add properties from Extensions Feature # Add properties initialized here in PocketShape setup.append("UseOutline") diff --git a/src/Mod/CAM/Path/Op/Probe.py b/src/Mod/CAM/Path/Op/Probe.py index 05536327ff..4c894e2986 100644 --- a/src/Mod/CAM/Path/Op/Probe.py +++ b/src/Mod/CAM/Path/Op/Probe.py @@ -64,17 +64,13 @@ class ObjectProbing(PathOp.ObjectOp): "App::PropertyInteger", "PointCountX", "Probe", - QT_TRANSLATE_NOOP( - "App::Property", "Number of points to probe in X direction" - ), + QT_TRANSLATE_NOOP("App::Property", "Number of points to probe in X direction"), ) obj.addProperty( "App::PropertyInteger", "PointCountY", "Probe", - QT_TRANSLATE_NOOP( - "App::Property", "Number of points to probe in Y direction" - ), + QT_TRANSLATE_NOOP("App::Property", "Number of points to probe in Y direction"), ) obj.addProperty( "App::PropertyFile", @@ -142,6 +138,7 @@ class ObjectProbing(PathOp.ObjectOp): Path.Log.track(tool.Label, support) return support + def SetupProperties(): setup = ["Xoffset", "Yoffset", "PointCountX", "PointCountY", "OutputFileName"] return setup diff --git a/src/Mod/CAM/Path/Op/Profile.py b/src/Mod/CAM/Path/Op/Profile.py index d4f122d367..80d356af63 100644 --- a/src/Mod/CAM/Path/Op/Profile.py +++ b/src/Mod/CAM/Path/Op/Profile.py @@ -43,9 +43,7 @@ translate = FreeCAD.Qt.translate __title__ = "CAM Profile Operation" __author__ = "sliptonic (Brad Collette)" __url__ = "https://www.freecad.org" -__doc__ = ( - "Create a profile toolpath based on entire model, selected faces or selected edges." -) +__doc__ = "Create a profile toolpath based on entire model, selected faces or selected edges." __contributors__ = "Schildkroet" if False: @@ -74,7 +72,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): """initAreaOpProperties(obj) ... create operation specific properties""" self.addNewProps = [] - for (propertytype, propertyname, grp, tt) in self.areaOpProperties(): + for propertytype, propertyname, grp, tt in self.areaOpProperties(): if not hasattr(obj, propertyname): obj.addProperty(propertytype, propertyname, grp, tt) self.addNewProps.append(propertyname) @@ -146,9 +144,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): "App::PropertyBool", "processHoles", "Profile", - QT_TRANSLATE_NOOP( - "App::Property", "Profile holes as well as the outline" - ), + QT_TRANSLATE_NOOP("App::Property", "Profile holes as well as the outline"), ), ( "App::PropertyBool", @@ -180,7 +176,6 @@ class ObjectProfile(PathAreaOp.ObjectOp): @classmethod def areaOpPropertyEnumerations(self, dataType="data"): - """opPropertyEnumerations(dataType="data")... return property enumeration lists of specified dataType. Args: dataType = 'data', 'raw', 'translated' @@ -400,9 +395,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): self.useComp = True self.ofstRadius = self.radius + self.offsetExtra self.commandlist.append( - Path.Command( - "(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")" - ) + Path.Command("(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")") ) else: self.useComp = False @@ -423,7 +416,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): elif ( remainingObjBaseFeatures and len(remainingObjBaseFeatures) > 0 ): # Process remaining features after edges processed above. - for (base, subsList) in remainingObjBaseFeatures: + for base, subsList in remainingObjBaseFeatures: holes = [] faces = [] faceDepths = [] @@ -433,9 +426,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): # only process faces here if isinstance(shape, Part.Face): faces.append(shape) - if numpy.isclose( - abs(shape.normalAt(0, 0).z), 1 - ): # horizontal face + if numpy.isclose(abs(shape.normalAt(0, 0).z), 1): # horizontal face Path.Log.debug(abs(shape.normalAt(0, 0).z)) for wire in shape.Wires: if wire.hashCode() == shape.OuterWire.hashCode(): @@ -485,9 +476,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): ) except Exception as ee: # PathUtils.getEnvelope() failed to return an object. - msg = translate( - "PathProfile", "Unable to create path for face(s)." - ) + msg = translate("PathProfile", "Unable to create path for face(s).") Path.Log.error(msg + "\n{}".format(ee)) cont = False @@ -500,9 +489,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): for shape in faces: custDepthparams = self.depthparams self._addDebugObject("Indiv_Shp", shape) - shapeEnv = PathUtils.getEnvelope( - shape, depthparams=custDepthparams - ) + shapeEnv = PathUtils.getEnvelope(shape, depthparams=custDepthparams) if shapeEnv: self._addDebugObject("IndivCutShapeEnv", shapeEnv) tup = shapeEnv, False, "pathProfile" @@ -582,14 +569,10 @@ class ObjectProfile(PathAreaOp.ObjectOp): # f = Part.makeFace(wire, 'Part::FaceMakerSimple') # if planar error, Comment out previous line, uncomment the next two - (origWire, flatWire) = self._flattenWire( - obj, wire, obj.FinalDepth.Value - ) + (origWire, flatWire) = self._flattenWire(obj, wire, obj.FinalDepth.Value) f = flatWire.Wires[0] if f: - shapeEnv = PathUtils.getEnvelope( - Part.Face(f), depthparams=self.depthparams - ) + shapeEnv = PathUtils.getEnvelope(Part.Face(f), depthparams=self.depthparams) if shapeEnv: tup = shapeEnv, False, "pathProfile" shapes.append(tup) @@ -614,13 +597,9 @@ class ObjectProfile(PathAreaOp.ObjectOp): for po in passOffsets: self.ofstRadius = po - cutShp = self._getCutAreaCrossSection( - obj, base, origWire, flatWire - ) + cutShp = self._getCutAreaCrossSection(obj, base, origWire, flatWire) if cutShp: - cutWireObjs = self._extractPathWire( - obj, base, flatWire, cutShp - ) + cutWireObjs = self._extractPathWire(obj, base, flatWire, cutShp) if cutWireObjs: for cW in cutWireObjs: @@ -673,9 +652,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): Path.Log.debug("_getCutAreaCrossSection()") # FCAD = FreeCAD.ActiveDocument tolerance = self.JOB.GeometryTolerance.Value - toolDiam = ( - 2 * self.radius - ) # self.radius defined in PathAreaOp or PathProfileBase modules + toolDiam = 2 * self.radius # self.radius defined in PathAreaOp or PathProfileBase modules minBfr = toolDiam * 1.25 bbBfr = (self.ofstRadius * 2) * 1.25 if bbBfr < minBfr: @@ -709,9 +686,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): # Obtain beginning point perpendicular points if blen > 0.1: - bcp = begE.valueAt( - begE.getParameterByLength(0.1) - ) # point returned 0.1 mm along edge + bcp = begE.valueAt(begE.getParameterByLength(0.1)) # point returned 0.1 mm along edge else: bcp = FreeCAD.Vector(begE.Vertexes[1].X, begE.Vertexes[1].Y, fdv) if elen > 0.1: @@ -722,9 +697,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): ecp = FreeCAD.Vector(endE.Vertexes[1].X, endE.Vertexes[1].Y, fdv) # Create intersection tags for determining which side of wire to cut - (begInt, begExt, iTAG, eTAG) = self._makeIntersectionTags( - useWire, numOrigEdges, fdv - ) + (begInt, begExt, iTAG, eTAG) = self._makeIntersectionTags(useWire, numOrigEdges, fdv) if not begInt or not begExt: return False self.iTAG = iTAG @@ -745,15 +718,9 @@ class ObjectProfile(PathAreaOp.ObjectOp): bbZMin = cutArea.BoundBox.ZMin for f in range(0, len(cutArea.Faces)): FcBB = cutArea.Faces[f].BoundBox - if ( - abs(FcBB.ZMax - bbZMax) < tolerance - and abs(FcBB.ZMin - bbZMax) < tolerance - ): + if abs(FcBB.ZMax - bbZMax) < tolerance and abs(FcBB.ZMin - bbZMax) < tolerance: topFc.append(f) - if ( - abs(FcBB.ZMax - bbZMin) < tolerance - and abs(FcBB.ZMin - bbZMin) < tolerance - ): + if abs(FcBB.ZMax - bbZMin) < tolerance and abs(FcBB.ZMin - bbZMin) < tolerance: botFc.append(f) if len(topFc) == 0: Path.Log.error("Failed to identify top faces of cut area.") @@ -848,9 +815,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): # verify that wire chosen is not inside the physical model if wi > 0: # and isInterior is False: - Path.Log.debug( - "Multiple wires in cut area. First choice is not 0. Testing." - ) + Path.Log.debug("Multiple wires in cut area. First choice is not 0. Testing.") testArea = fcShp.cut(base.Shape) isReady = self._checkTagIntersection(iTAG, eTAG, self.cutSide, testArea) @@ -864,9 +829,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): workShp = pfcShp.cut(fcShp) if testArea.Area < minArea: - Path.Log.debug( - "offset area is less than minArea of {}.".format(minArea) - ) + Path.Log.debug("offset area is less than minArea of {}.".format(minArea)) Path.Log.debug("Using wire index {}.".format(wi - 1)) pWire = Part.Wire(Part.__sortEdges__(workShp.Wires[wi - 1].Edges)) pfcShp = Part.Face(pWire) @@ -910,9 +873,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): subLoops = [] rtnWIRES = [] osWrIdxs = [] - subDistFactor = ( - 1.0 # Raise to include sub wires at greater distance from original - ) + subDistFactor = 1.0 # Raise to include sub wires at greater distance from original fdv = obj.FinalDepth.Value wire = flatWire lstVrtIdx = len(wire.Vertexes) - 1 @@ -970,9 +931,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): if w0 != w1: Path.Log.warning( - "Offset wire endpoint indexes are not equal - w0, w1: {}, {}".format( - w0, w1 - ) + "Offset wire endpoint indexes are not equal - w0, w1: {}, {}".format(w0, w1) ) # Debugging @@ -1054,9 +1013,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): if isHole is False: offset = 0 - offset - return PathUtils.getOffsetArea( - fcShape, offset, plane=fcShape, tolerance=tolerance - ) + return PathUtils.getOffsetArea(fcShape, offset, plane=fcShape, tolerance=tolerance) def _findNearestVertex(self, shape, point): Path.Log.debug("_findNearestVertex()") @@ -1265,9 +1222,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): E = useWire.Edges[e] LE = E.Length if LE > (self.radius * 2): - nt = math.ceil( - LE / (tagRad * math.pi) - ) # (tagRad * 2 * math.pi) is circumference + nt = math.ceil(LE / (tagRad * math.pi)) # (tagRad * 2 * math.pi) is circumference else: nt = 4 # desired + 1 mid = LE / nt @@ -1324,9 +1279,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): cutFactor = ( cutterRad / 2.1 ) / lenToMid # = 2 is tangent to wire; > 2 allows tag to overlap wire; < 2 pulls tag away from wire - perpE = FreeCAD.Vector(-1 * toMid.y, toMid.x, 0.0).multiply( - -1 * cutFactor - ) # exterior tag + perpE = FreeCAD.Vector(-1 * toMid.y, toMid.x, 0.0).multiply(-1 * cutFactor) # exterior tag extPnt = pb.add(toMid.add(perpE)) # make exterior tag @@ -1335,9 +1288,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): extTag = Part.Face(ecw) # make interior tag - perpI = FreeCAD.Vector(-1 * toMid.y, toMid.x, 0.0).multiply( - cutFactor - ) # interior tag + perpI = FreeCAD.Vector(-1 * toMid.y, toMid.x, 0.0).multiply(cutFactor) # interior tag intPnt = pb.add(toMid.add(perpI)) iCntr = intPnt.add(FreeCAD.Vector(0, 0, depth)) icw = Part.Wire(Part.makeCircle((cutterRad / 2), iCntr).Edges[0]) @@ -1396,20 +1347,12 @@ class ObjectProfile(PathAreaOp.ObjectOp): # positive dist in _makePerp2DVector() is CCW rotation p1 = E if sType == "BEG": - p2 = self._makePerp2DVector( - C, E, -1 * (shrt + abs(self.offsetExtra)) - ) # left, shrt + p2 = self._makePerp2DVector(C, E, -1 * (shrt + abs(self.offsetExtra))) # left, shrt p3 = self._makePerp2DVector(p1, p2, shrt + abs(self.offsetExtra)) - p4 = self._makePerp2DVector( - p2, p3, (med + abs(self.offsetExtra)) - ) # FIRST POINT - p5 = self._makePerp2DVector( - p3, p4, shrt + abs(self.offsetExtra) - ) # E1 SECOND + p4 = self._makePerp2DVector(p2, p3, (med + abs(self.offsetExtra))) # FIRST POINT + p5 = self._makePerp2DVector(p3, p4, shrt + abs(self.offsetExtra)) # E1 SECOND elif sType == "END": - p2 = self._makePerp2DVector( - C, E, (shrt + abs(self.offsetExtra)) - ) # left, shrt + p2 = self._makePerp2DVector(C, E, (shrt + abs(self.offsetExtra))) # left, shrt p3 = self._makePerp2DVector(p1, p2, -1 * (shrt + abs(self.offsetExtra))) p4 = self._makePerp2DVector( p2, p3, -1 * (med + abs(self.offsetExtra)) @@ -1463,9 +1406,7 @@ class ObjectProfile(PathAreaOp.ObjectOp): # Method to add temporary debug object def _addDebugObject(self, objName, objShape): if self.isDebug: - newDocObj = FreeCAD.ActiveDocument.addObject( - "Part::Feature", "tmp_" + objName - ) + newDocObj = FreeCAD.ActiveDocument.addObject("Part::Feature", "tmp_" + objName) newDocObj.Shape = objShape newDocObj.purgeTouched() self.tmpGrp.addObject(newDocObj) diff --git a/src/Mod/CAM/Path/Op/Slot.py b/src/Mod/CAM/Path/Op/Slot.py index feecdd8d90..d4fd14fa21 100644 --- a/src/Mod/CAM/Path/Op/Slot.py +++ b/src/Mod/CAM/Path/Op/Slot.py @@ -88,7 +88,7 @@ class ObjectSlot(PathOp.ObjectOp): Path.Log.track() self.addNewProps = list() - for (prtyp, nm, grp, tt) in self.opPropertyDefinitions(): + for prtyp, nm, grp, tt in self.opPropertyDefinitions(): if not hasattr(obj, nm): obj.addProperty(prtyp, nm, grp, tt) self.addNewProps.append(nm) @@ -231,9 +231,7 @@ class ObjectSlot(PathOp.ObjectOp): "App::PropertyBool", "UseStartPoint", "Start Point", - QtCore.QT_TRANSLATE_NOOP( - "App::Property", "Make True, if specifying a Start Point" - ), + QtCore.QT_TRANSLATE_NOOP("App::Property", "Make True, if specifying a Start Point"), ), ] @@ -335,9 +333,7 @@ class ObjectSlot(PathOp.ObjectOp): subCnt = len(subsList) if subCnt == 1: # Adjust available enumerations - ENUMS["Reference1"] = self._makeReference1Enumerations( - subsList[0], True - ) + ENUMS["Reference1"] = self._makeReference1Enumerations(subsList[0], True) elif subCnt == 2: # Adjust available enumerations ENUMS["Reference1"] = self._makeReference1Enumerations(subsList[0]) @@ -538,9 +534,7 @@ class ObjectSlot(PathOp.ObjectOp): self.commandlist.append(Path.Command("N ({})".format(obj.Label), {})) self.commandlist.append(Path.Command("N (Tool type: {})".format(toolType), {})) self.commandlist.append( - Path.Command( - "N (Compensated Tool Path. Diameter: {})".format(tool.Diameter), {} - ) + Path.Command("N (Compensated Tool Path. Diameter: {})".format(tool.Diameter), {}) ) self.commandlist.append(Path.Command("N ({})".format(output), {})) self.commandlist.append( @@ -578,9 +572,7 @@ class ObjectSlot(PathOp.ObjectOp): CMDS.extend(cmds) # Save gcode produced - CMDS.append( - Path.Command("G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid}) - ) + CMDS.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid})) self.commandlist.extend(CMDS) # ###### CLOSING COMMANDS FOR OPERATION ###### @@ -609,14 +601,18 @@ class ObjectSlot(PathOp.ObjectOp): p1 = obj.CustomPoint1 p2 = obj.CustomPoint2 if p1 == p2: - msg = translate("CAM_Slot", "Custom points are identical. No slot path will be generated") + msg = translate( + "CAM_Slot", "Custom points are identical. No slot path will be generated" + ) FreeCAD.Console.PrintUserWarning(msg + "\n") return False elif p1.z == p2.z: pnts = (p1, p2) featureCount = 2 else: - msg = translate("CAM_Slot", "Custom points not at same Z height. No slot path will be generated") + msg = translate( + "CAM_Slot", "Custom points not at same Z height. No slot path will be generated" + ) FreeCAD.Console.PrintUserWarning(msg + "\n") return False else: @@ -659,17 +655,13 @@ class ObjectSlot(PathOp.ObjectOp): """This method finishes an Arc Slot operation. It returns the gcode for the slot operation.""" Path.Log.debug("arc center: {}".format(self.arcCenter)) - self._addDebugObject( - Part.makeLine(self.arcCenter, self.arcMidPnt), "CentToMidPnt" - ) + self._addDebugObject(Part.makeLine(self.arcCenter, self.arcMidPnt), "CentToMidPnt") # Path.Log.debug('Pre-offset points are:\np1 = {}\np2 = {}'.format(p1, p2)) if obj.ExtendRadius.Value != 0: # verify offset does not force radius < 0 newRadius = self.arcRadius + obj.ExtendRadius.Value - Path.Log.debug( - "arc radius: {}; offset radius: {}".format(self.arcRadius, newRadius) - ) + Path.Log.debug("arc radius: {}; offset radius: {}".format(self.arcRadius, newRadius)) if newRadius <= 0: msg = translate( "CAM_Slot", @@ -690,9 +682,7 @@ class ObjectSlot(PathOp.ObjectOp): if self.isArc == 1: # Complete circle if obj.ExtendPathStart.Value != 0 or obj.ExtendPathEnd.Value != 0: - msg = translate( - "CAM_Slot", "No path extensions available for full circles." - ) + msg = translate("CAM_Slot", "No path extensions available for full circles.") FreeCAD.Console.PrintWarning(msg + "\n") else: # Arc segment @@ -742,9 +732,7 @@ class ObjectSlot(PathOp.ObjectOp): cmds = list() (st_pt, end_pt, arcCmd) = POINTS # cmds.append(Path.Command('N (Tool type: {})'.format(toolType), {})) - cmds.append( - Path.Command("G0", {"X": st_pt.x, "Y": st_pt.y, "F": self.horizRapid}) - ) + cmds.append(Path.Command("G0", {"X": st_pt.x, "Y": st_pt.y, "F": self.horizRapid})) cmds.append(Path.Command("G1", {"Z": depth, "F": self.vertFeed})) vtc = self.arcCenter.sub(st_pt) # vector to center cmds.append( @@ -768,9 +756,7 @@ class ObjectSlot(PathOp.ObjectOp): for depth in self.depthParams: CMDS.extend(arcPass(PATHS[path_index], depth)) CMDS.append( - Path.Command( - "G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid} - ) + Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid}) ) elif obj.CutPattern == "ZigZag": i = 0 @@ -781,9 +767,7 @@ class ObjectSlot(PathOp.ObjectOp): CMDS.extend(arcPass(PATHS[not path_index], depth)) i += 1 # Raise to SafeHeight when finished - CMDS.append( - Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid}) - ) + CMDS.append(Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid})) if self.isDebug: Path.Log.debug("G-code arc command is: {}".format(PATHS[path_index][2])) @@ -808,16 +792,10 @@ class ObjectSlot(PathOp.ObjectOp): if perpZero: (p1, p2) = pnts initPerpDist = p1.sub(p2).Length - pnts = self._makePerpendicular( - p1, p2, initPerpDist - ) # 10.0 offset below + pnts = self._makePerpendicular(p1, p2, initPerpDist) # 10.0 offset below else: # Modify path points if user selected two parallel edges - if ( - featureCnt == 2 - and self.shapeType1 == "Edge" - and self.shapeType2 == "Edge" - ): + if featureCnt == 2 and self.shapeType1 == "Edge" and self.shapeType2 == "Edge": if self.featureDetails[0] == "arc" and self.featureDetails[1] == "arc": perpZero = False elif self._isParallel(self.dYdX1, self.dYdX2): @@ -826,14 +804,10 @@ class ObjectSlot(PathOp.ObjectOp): edg1_len = self.shape1.Length edg2_len = self.shape2.Length set_length = max(edg1_len, edg2_len) - pnts = self._makePerpendicular( - p1, p2, 10.0 + set_length - ) # 10.0 offset below + pnts = self._makePerpendicular(p1, p2, 10.0 + set_length) # 10.0 offset below if edg1_len != edg2_len: msg = obj.Label + " " - msg += translate( - "CAM_Slot", "Verify slot path start and end points." - ) + msg += translate("CAM_Slot", "Verify slot path start and end points.") FreeCAD.Console.PrintWarning(msg + "\n") else: perpZero = False @@ -883,9 +857,7 @@ class ObjectSlot(PathOp.ObjectOp): def linePass(p1, p2, depth): cmds = list() # cmds.append(Path.Command('N (Tool type: {})'.format(toolType), {})) - cmds.append( - Path.Command("G0", {"X": p1.x, "Y": p1.y, "F": self.horizRapid}) - ) + cmds.append(Path.Command("G0", {"X": p1.x, "Y": p1.y, "F": self.horizRapid})) cmds.append(Path.Command("G1", {"Z": depth, "F": self.vertFeed})) cmds.append(Path.Command("G1", {"X": p2.x, "Y": p2.y, "F": self.horizFeed})) return cmds @@ -893,42 +865,26 @@ class ObjectSlot(PathOp.ObjectOp): # CMDS.append(Path.Command('N (Tool type: {})'.format(toolType), {})) if obj.LayerMode == "Single-pass": CMDS.extend(linePass(p1, p2, obj.FinalDepth.Value)) - CMDS.append( - Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid}) - ) + CMDS.append(Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid})) else: if obj.CutPattern == "Line": for dep in self.depthParams: CMDS.extend(linePass(p1, p2, dep)) CMDS.append( - Path.Command( - "G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid} - ) + Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid}) ) elif obj.CutPattern == "ZigZag": - CMDS.append( - Path.Command("G0", {"X": p1.x, "Y": p1.y, "F": self.horizRapid}) - ) + CMDS.append(Path.Command("G0", {"X": p1.x, "Y": p1.y, "F": self.horizRapid})) i = 0 for dep in self.depthParams: if i % 2.0 == 0: # even CMDS.append(Path.Command("G1", {"Z": dep, "F": self.vertFeed})) - CMDS.append( - Path.Command( - "G1", {"X": p2.x, "Y": p2.y, "F": self.horizFeed} - ) - ) + CMDS.append(Path.Command("G1", {"X": p2.x, "Y": p2.y, "F": self.horizFeed})) else: # odd CMDS.append(Path.Command("G1", {"Z": dep, "F": self.vertFeed})) - CMDS.append( - Path.Command( - "G1", {"X": p1.x, "Y": p1.y, "F": self.horizFeed} - ) - ) + CMDS.append(Path.Command("G1", {"X": p1.x, "Y": p1.y, "F": self.horizFeed})) i += 1 - CMDS.append( - Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid}) - ) + CMDS.append(Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid})) return CMDS @@ -1008,9 +964,7 @@ class ObjectSlot(PathOp.ObjectOp): # Reject triangular faces if len(shape.Edges) < 4: - msg = translate( - "CAM_Slot", "A single selected face must have four edges minimum." - ) + msg = translate("CAM_Slot", "A single selected face must have four edges minimum.") FreeCAD.Console.PrintError(msg + "\n") return False @@ -1060,10 +1014,8 @@ class ObjectSlot(PathOp.ObjectOp): if self.isDebug: Path.Log.debug(" -pairCnt: {}".format(pairCnt)) - for (a, b) in parallel_edge_pairs: - Path.Log.debug( - " -pair: {}, {}".format(round(a.Length, 4), round(b.Length, 4)) - ) + for a, b in parallel_edge_pairs: + Path.Log.debug(" -pair: {}, {}".format(round(a.Length, 4), round(b.Length, 4))) Path.Log.debug(" -parallel_edge_flags: {}".format(parallel_edge_flags)) if pairCnt == 0: @@ -1401,9 +1353,7 @@ class ObjectSlot(PathOp.ObjectOp): norm = shape.normalAt(0.0, 0.0) # FreeCAD.Console.PrintMessage('{} normal {}.\n'.format(sub, norm)) if norm.z != 0: - msg = translate( - "CAM_Slot", "The selected face is not oriented vertically:" - ) + msg = translate("CAM_Slot", "The selected face is not oriented vertically:") FreeCAD.Console.PrintError(msg + " {}.\n".format(sub)) return False @@ -1478,7 +1428,9 @@ class ObjectSlot(PathOp.ObjectOp): beginRadians = self._getVectorAngle(p1.sub(self.arcCenter)) if begExt < 0: - beginRadians += 0 # negative Ext shortens slot so chord endpoint is slot start point + beginRadians += ( + 0 # negative Ext shortens slot so chord endpoint is slot start point + ) else: beginRadians -= ( 2 * ExtRadians @@ -1759,9 +1711,7 @@ class ObjectSlot(PathOp.ObjectOp): face = Part.Face(wires[0]) if face.Area > 0: face.translate( - FreeCAD.Vector( - 0.0, 0.0, shape.BoundBox.ZMin - face.BoundBox.ZMin - ) + FreeCAD.Vector(0.0, 0.0, shape.BoundBox.ZMin - face.BoundBox.ZMin) ) return ("Face", face) return ("Wire", wires[0]) @@ -1915,9 +1865,7 @@ class ObjectSlot(PathOp.ObjectOp): newRadius = arcRadius - rad # Path.Log.debug('arcRadius, newRadius: {}, {}'.format(arcRadius, newRadius)) if newRadius <= 0: - msg = translate( - "CAM_Slot", "Current offset value produces negative radius." - ) + msg = translate("CAM_Slot", "Current offset value produces negative radius.") FreeCAD.Console.PrintError(msg + "\n") return False else: @@ -1929,9 +1877,7 @@ class ObjectSlot(PathOp.ObjectOp): newRadius = arcRadius + rad # Path.Log.debug('arcRadius, newRadius: {}, {}'.format(arcRadius, newRadius)) if newRadius <= 0: - msg = translate( - "CAM_Slot", "Current offset value produces negative radius." - ) + msg = translate("CAM_Slot", "Current offset value produces negative radius.") FreeCAD.Console.PrintError(msg + "\n") return False else: diff --git a/src/Mod/CAM/Path/Op/Surface.py b/src/Mod/CAM/Path/Op/Surface.py index a5c314c897..d61e17f4a4 100644 --- a/src/Mod/CAM/Path/Op/Surface.py +++ b/src/Mod/CAM/Path/Op/Surface.py @@ -38,9 +38,7 @@ try: except ImportError: import opencamlib as ocl except ImportError: - msg = translate( - "PathSurface", "This operation requires OpenCamLib to be installed." - ) + msg = translate("PathSurface", "This operation requires OpenCamLib to be installed.") FreeCAD.Console.PrintError(msg + "\n") raise ImportError # import sys @@ -102,7 +100,7 @@ class ObjectSurface(PathOp.ObjectOp): """initOpProperties(obj) ... create operation specific properties""" self.addNewProps = [] - for (prtyp, nm, grp, tt) in self.opPropertyDefinitions(): + for prtyp, nm, grp, tt in self.opPropertyDefinitions(): if not hasattr(obj, nm): obj.addProperty(prtyp, nm, grp, tt) self.addNewProps.append(nm) @@ -148,9 +146,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyFloat", "CutterTilt", "Rotation", - QT_TRANSLATE_NOOP( - "App::Property", "Stop index(angle) for rotational scan" - ), + QT_TRANSLATE_NOOP("App::Property", "Stop index(angle) for rotational scan"), ), ( "App::PropertyEnumeration", @@ -173,25 +169,19 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyEnumeration", "RotationAxis", "Rotation", - QT_TRANSLATE_NOOP( - "App::Property", "The model will be rotated around this axis." - ), + QT_TRANSLATE_NOOP("App::Property", "The model will be rotated around this axis."), ), ( "App::PropertyFloat", "StartIndex", "Rotation", - QT_TRANSLATE_NOOP( - "App::Property", "Start index(angle) for rotational scan" - ), + QT_TRANSLATE_NOOP("App::Property", "Start index(angle) for rotational scan"), ), ( "App::PropertyFloat", "StopIndex", "Rotation", - QT_TRANSLATE_NOOP( - "App::Property", "Stop index(angle) for rotational scan" - ), + QT_TRANSLATE_NOOP("App::Property", "Stop index(angle) for rotational scan"), ), ( "App::PropertyEnumeration", @@ -329,9 +319,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyVectorDistance", "PatternCenterCustom", "Clearing Options", - QT_TRANSLATE_NOOP( - "App::Property", "Set the start point for the cut pattern." - ), + QT_TRANSLATE_NOOP("App::Property", "Set the start point for the cut pattern."), ), ( "App::PropertyEnumeration", @@ -346,9 +334,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyEnumeration", "ProfileEdges", "Clearing Options", - QT_TRANSLATE_NOOP( - "App::Property", "Profile the edges of the selection." - ), + QT_TRANSLATE_NOOP("App::Property", "Profile the edges of the selection."), ), ( "App::PropertyDistance", @@ -426,9 +412,7 @@ class ObjectSurface(PathOp.ObjectOp): "App::PropertyBool", "UseStartPoint", "Start Point", - QT_TRANSLATE_NOOP( - "App::Property", "Make True, if specifying a Start Point" - ), + QT_TRANSLATE_NOOP("App::Property", "Make True, if specifying a Start Point"), ), ] @@ -557,9 +541,7 @@ class ObjectSurface(PathOp.ObjectOp): defaults["LinearDeflection"] = job.GeometryTolerance.Value / 4 if warn: msg = translate("PathSurface", "The GeometryTolerance for this Job is 0.0.") - msg += translate( - "PathSurface", "Initializing LinearDeflection to 0.001 mm." - ) + msg += translate("PathSurface", "Initializing LinearDeflection to 0.001 mm.") FreeCAD.Console.PrintWarning(msg + "\n") return defaults @@ -822,22 +804,14 @@ class ObjectSurface(PathOp.ObjectOp): if obj.Comment != "": self.commandlist.append(Path.Command("N ({})".format(str(obj.Comment)), {})) self.commandlist.append(Path.Command("N ({})".format(obj.Label), {})) + self.commandlist.append(Path.Command("N (Tool type: {})".format(oclTool.toolType), {})) self.commandlist.append( - Path.Command("N (Tool type: {})".format(oclTool.toolType), {}) + Path.Command("N (Compensated Tool Path. Diameter: {})".format(oclTool.diameter), {}) ) self.commandlist.append( - Path.Command( - "N (Compensated Tool Path. Diameter: {})".format(oclTool.diameter), {} - ) - ) - self.commandlist.append( - Path.Command( - "N (Sample interval: {})".format(str(obj.SampleInterval.Value)), {} - ) - ) - self.commandlist.append( - Path.Command("N (Step over %: {})".format(str(obj.StepOver)), {}) + Path.Command("N (Sample interval: {})".format(str(obj.SampleInterval.Value)), {}) ) + self.commandlist.append(Path.Command("N (Step over %: {})".format(str(obj.StepOver)), {})) self.commandlist.append(Path.Command("N ({})".format(output), {})) self.commandlist.append( Path.Command("G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid}) @@ -866,9 +840,7 @@ class ObjectSurface(PathOp.ObjectOp): if FCAD.getObject(tempGroupName + "001"): for to in FCAD.getObject(tempGroupName + "001").Group: FCAD.removeObject(to.Name) - FCAD.removeObject( - tempGroupName + "001" - ) # remove temp directory if already exists + FCAD.removeObject(tempGroupName + "001") # remove temp directory if already exists tempGroup = FCAD.addObject("App::DocumentObjectGroup", tempGroupName) tempGroupName = tempGroup.Name self.tempGroup = tempGroup @@ -895,9 +867,7 @@ class ObjectSurface(PathOp.ObjectOp): if FreeCAD.GuiUp: for model in JOB.Model.Group: mNm = model.Name - modelVisibility.append( - FreeCADGui.ActiveDocument.getObject(mNm).Visibility - ) + modelVisibility.append(FreeCADGui.ActiveDocument.getObject(mNm).Visibility) # Setup STL, model type, and bound box containers for each model in Job for model in JOB.Model.Group: @@ -938,16 +908,10 @@ class ObjectSurface(PathOp.ObjectOp): PathSurfaceSupport._prepareModelSTLs(self, JOB, obj, idx, ocl) if FACES[idx]: - Path.Log.debug( - "Working on Model.Group[{}]: {}".format(idx, model.Label) - ) + Path.Log.debug("Working on Model.Group[{}]: {}".format(idx, model.Label)) if idx > 0: # Raise to clearance between models - CMDS.append( - Path.Command( - "N (Transition to base: {}.)".format(model.Label) - ) - ) + CMDS.append(Path.Command("N (Transition to base: {}.)".format(model.Label))) CMDS.append( Path.Command( "G0", @@ -959,9 +923,7 @@ class ObjectSurface(PathOp.ObjectOp): self, JOB, obj, idx, FACES[idx], VOIDS[idx], ocl ) # Process model/faces - OCL objects must be ready - CMDS.extend( - self._processCutAreas(JOB, obj, idx, FACES[idx], VOIDS[idx]) - ) + CMDS.extend(self._processCutAreas(JOB, obj, idx, FACES[idx], VOIDS[idx])) else: Path.Log.debug("No data for model base: {}".format(model.Label)) @@ -1171,9 +1133,7 @@ class ObjectSurface(PathOp.ObjectOp): if obj.CutPattern == "Offset": useGeom = self._offsetFacesToPointData(obj, pathGeom, profile=False) if useGeom is False: - msg = translate( - "PathSurface", "No clearing path geometry returned." - ) + msg = translate("PathSurface", "No clearing path geometry returned.") Path.Log.error(msg) return [] geoScan = [self._planarPerformOclScan(obj, pdc, useGeom, True)] @@ -1209,13 +1169,9 @@ class ObjectSurface(PathOp.ObjectOp): # Process OCL scan data if obj.LayerMode == "Single-pass": - final.extend( - self._planarDropCutSingle(JOB, obj, pdc, safePDC, depthparams, SCANDATA) - ) + final.extend(self._planarDropCutSingle(JOB, obj, pdc, safePDC, depthparams, SCANDATA)) elif obj.LayerMode == "Multi-pass": - final.extend( - self._planarDropCutMulti(JOB, obj, pdc, safePDC, depthparams, SCANDATA) - ) + final.extend(self._planarDropCutMulti(JOB, obj, pdc, safePDC, depthparams, SCANDATA)) # If cut pattern is `Circular`, restore initial OLP value if obj.CutPattern in ["Circular", "CircularZigZag"]: @@ -1223,9 +1179,7 @@ class ObjectSurface(PathOp.ObjectOp): # Raise to safe height between individual faces. if obj.HandleMultipleFeatures == "Individually": - final.insert( - 0, Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid}) - ) + final.insert(0, Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid})) return final @@ -1290,9 +1244,7 @@ class ObjectSurface(PathOp.ObjectOp): PNTSET = PathSurfaceSupport.pathGeomToLinesPointSet(self, obj, pathGeom) elif obj.CutPattern == "ZigZag": # PNTSET = PathSurfaceSupport.pathGeomToZigzagPointSet(obj, pathGeom, self.CutClimb, self.toolDiam, self.closedGap, self.gaps) - PNTSET = PathSurfaceSupport.pathGeomToZigzagPointSet( - self, obj, pathGeom - ) + PNTSET = PathSurfaceSupport.pathGeomToZigzagPointSet(self, obj, pathGeom) elif obj.CutPattern == "Spiral": PNTSET = PathSurfaceSupport.pathGeomToSpiralPointSet(obj, pathGeom) @@ -1332,9 +1284,7 @@ class ObjectSurface(PathOp.ObjectOp): erFlg = True else: if aTyp == "L": - scan.append( - FreeCAD.Vector(scan[0].x, scan[0].y, scan[0].z) - ) + scan.append(FreeCAD.Vector(scan[0].x, scan[0].y, scan[0].z)) stpOvr.append(scan) if erFlg is False: SCANS.append(stpOvr) @@ -1396,9 +1346,7 @@ class ObjectSurface(PathOp.ObjectOp): # Send cutter to x,y position of first point on first line first = SCANDATA[0][0][0] # [step][item][point] - GCODE.append( - Path.Command("G0", {"X": first.x, "Y": first.y, "F": self.horizRapid}) - ) + GCODE.append(Path.Command("G0", {"X": first.x, "Y": first.y, "F": self.horizRapid})) # Cycle through step-over sections (line segments or arcs) odd = True @@ -1417,9 +1365,7 @@ class ObjectSurface(PathOp.ObjectOp): odd = False else: odd = True - cmds.extend( - self._stepTransitionCmds(obj, lstStpEnd, first, safePDC, tolrnc) - ) + cmds.extend(self._stepTransitionCmds(obj, lstStpEnd, first, safePDC, tolrnc)) # Override default `OptimizeLinearPaths` behavior to allow # `ProfileEdges` optimization if so == peIdx or peIdx == -1: @@ -1432,9 +1378,7 @@ class ObjectSurface(PathOp.ObjectOp): if prt == "BRK": nxtStart = PRTS[i + 1][0] cmds.append(Path.Command("N (Break)", {})) - cmds.extend( - self._stepTransitionCmds(obj, last, nxtStart, safePDC, tolrnc) - ) + cmds.extend(self._stepTransitionCmds(obj, last, nxtStart, safePDC, tolrnc)) else: cmds.append(Path.Command("N (part {}.)".format(i + 1), {})) last = prt[lenPrt - 1] @@ -1445,9 +1389,7 @@ class ObjectSurface(PathOp.ObjectOp): and obj.CircularUseG2G3 is True and lenPrt > 2 ): - (rtnVal, gcode) = self._arcsToG2G3( - prt, lenPrt, odd, gDIR, tolrnc - ) + (rtnVal, gcode) = self._arcsToG2G3(prt, lenPrt, odd, gDIR, tolrnc) if rtnVal: cmds.extend(gcode) else: @@ -1468,16 +1410,12 @@ class ObjectSurface(PathOp.ObjectOp): def _planarSinglepassProcess(self, obj, points): if obj.OptimizeLinearPaths: - points = PathUtils.simplify3dLine( - points, tolerance=obj.LinearDeflection.Value - ) + points = PathUtils.simplify3dLine(points, tolerance=obj.LinearDeflection.Value) # Begin processing ocl points list into gcode commands = [] for pnt in points: commands.append( - Path.Command( - "G1", {"X": pnt.x, "Y": pnt.y, "Z": pnt.z, "F": self.horizFeed} - ) + Path.Command("G1", {"X": pnt.x, "Y": pnt.y, "Z": pnt.z, "F": self.horizFeed}) ) return commands @@ -1534,9 +1472,7 @@ class ObjectSurface(PathOp.ObjectOp): LMAX.append(prt) brkFlg = False else: - (PTS, lMax) = self._planarMultipassPreProcess( - obj, prt, prevDepth, lyrDep - ) + (PTS, lMax) = self._planarMultipassPreProcess(obj, prt, prevDepth, lyrDep) if len(PTS) > 0: ADJPRTS.append(PTS) soHasPnts = True @@ -1567,9 +1503,7 @@ class ObjectSurface(PathOp.ObjectOp): if prvStpLast is None: prvStpLast = lastPrvStpLast transCmds.extend( - self._stepTransitionCmds( - obj, prvStpLast, first, safePDC, tolrnc - ) + self._stepTransitionCmds(obj, prvStpLast, first, safePDC, tolrnc) ) # Override default `OptimizeLinearPaths` behavior to allow `ProfileEdges` optimization @@ -1586,19 +1520,13 @@ class ObjectSurface(PathOp.ObjectOp): prtsCmds.append(Path.Command("N (--Break)", {})) else: # Transition straight up to Safe Height if no more parts - nxtStart = FreeCAD.Vector( - last.x, last.y, obj.SafeHeight.Value - ) + nxtStart = FreeCAD.Vector(last.x, last.y, obj.SafeHeight.Value) prtsCmds.extend( - self._stepTransitionCmds( - obj, last, nxtStart, safePDC, tolrnc - ) + self._stepTransitionCmds(obj, last, nxtStart, safePDC, tolrnc) ) else: segCmds = False - prtsCmds.append( - Path.Command("N (part {})".format(i + 1), {}) - ) + prtsCmds.append(Path.Command("N (part {})".format(i + 1), {})) last = prt[lenPrt - 1] if so == peIdx or peIdx == -1: segCmds = self._planarSinglepassProcess(obj, prt) @@ -1607,9 +1535,7 @@ class ObjectSurface(PathOp.ObjectOp): and obj.CircularUseG2G3 is True and lenPrt > 2 ): - (rtnVal, gcode) = self._arcsToG2G3( - prt, lenPrt, odd, gDIR, tolrnc - ) + (rtnVal, gcode) = self._arcsToG2G3(prt, lenPrt, odd, gDIR, tolrnc) if rtnVal is True: segCmds = gcode else: @@ -1637,14 +1563,10 @@ class ObjectSurface(PathOp.ObjectOp): stpOvrCmds.extend(transCmds) stpOvrCmds.append(Path.Command("N (Begin step {}.)".format(so), {})) stpOvrCmds.append( - Path.Command( - "G0", {"X": first.x, "Y": first.y, "F": self.horizRapid} - ) + Path.Command("G0", {"X": first.x, "Y": first.y, "F": self.horizRapid}) ) stpOvrCmds.extend(prtsCmds) - stpOvrCmds.append( - Path.Command("N (End of step {}.)".format(so), {}) - ) + stpOvrCmds.append(Path.Command("N (End of step {}.)".format(so), {})) # Layer transition at first active step over in current layer if actvSteps == 1: @@ -1652,14 +1574,10 @@ class ObjectSurface(PathOp.ObjectOp): if lyr > 0: LYR.append(Path.Command("N (Layer transition)", {})) LYR.append( - Path.Command( - "G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid} - ) + Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid}) ) LYR.append( - Path.Command( - "G0", {"X": first.x, "Y": first.y, "F": self.horizRapid} - ) + Path.Command("G0", {"X": first.x, "Y": first.y, "F": self.horizRapid}) ) if stepHasCmds is True: @@ -1768,17 +1686,13 @@ class ObjectSurface(PathOp.ObjectOp): if onHold is False: onHold = True output.append(Path.Command("N (Start hold)", {})) - output.append( - Path.Command("G0", {"Z": clrScnLn, "F": self.vertRapid}) - ) + output.append(Path.Command("G0", {"Z": clrScnLn, "F": self.vertRapid})) else: if onHold is True: onHold = False output.append(Path.Command("N (End hold)", {})) output.append( - Path.Command( - "G0", {"X": pnt.x, "Y": pnt.y, "F": self.horizRapid} - ) + Path.Command("G0", {"X": pnt.x, "Y": pnt.y, "F": self.horizRapid}) ) # Process point @@ -1841,9 +1755,7 @@ class ObjectSurface(PathOp.ObjectOp): # Try to keep cutting for short distances. if xyDistanceSqrd <= maxXYDistanceSqrd: # Try to keep cutting, following the model shape - (transLine, minZ, maxZ) = self._getTransitionLine( - safePDC, p1, p2, obj - ) + (transLine, minZ, maxZ) = self._getTransitionLine(safePDC, p1, p2, obj) # For now, only optimize moderate deviations in Z direction, and # no dropping below the min of p1 and p2, primarily for multi # layer path safety. @@ -1884,9 +1796,7 @@ class ObjectSurface(PathOp.ObjectOp): # Create raise, shift, and optional lower commands if height is not False: cmds.append(Path.Command("G0", {"Z": height, "F": self.vertRapid})) - cmds.append( - Path.Command("G0", {"X": p2.x, "Y": p2.y, "F": self.horizRapid}) - ) + cmds.append(Path.Command("G0", {"X": p2.x, "Y": p2.y, "F": self.horizRapid})) if rtpd is not False: # ReturnToPreviousDepth cmds.append(Path.Command("G0", {"Z": rtpd, "F": self.vertRapid})) @@ -1945,9 +1855,7 @@ class ObjectSurface(PathOp.ObjectOp): ) ) cmds.append( - Path.Command( - "G1", {"X": xyz.x, "Y": xyz.y, "Z": xyz.z, "F": self.horizFeed} - ) + Path.Command("G1", {"X": xyz.x, "Y": xyz.y, "Z": xyz.z, "F": self.horizFeed}) ) ijk = self.tmpCOM - xyz # vector from start to center rst = strtPnt # end point @@ -2047,9 +1955,7 @@ class ObjectSurface(PathOp.ObjectOp): # Main rotational scan functions def _processRotationalOp(self, JOB, obj, mdlIdx, compoundFaces=None): - Path.Log.debug( - "_processRotationalOp(self, JOB, obj, mdlIdx, compoundFaces=None)" - ) + Path.Log.debug("_processRotationalOp(self, JOB, obj, mdlIdx, compoundFaces=None)") base = JOB.Model.Group[mdlIdx] bb = self.boundBoxes[mdlIdx] @@ -2134,18 +2040,14 @@ class ObjectSurface(PathOp.ObjectOp): numPnts = len( scanLines[0] ) # Number of points per line along axis, at obj.SampleInterval.Value spacing - for ( - line - ) in scanLines: # extract circular set(ring) of points from scan lines + for line in scanLines: # extract circular set(ring) of points from scan lines if len(line) != numPnts: Path.Log.debug("Error: line lengths not equal") return rngs for num in range(0, numPnts): rngs.append([1.1]) # Initiate new ring - for ( - line - ) in scanLines: # extract circular set(ring) of points from scan lines + for line in scanLines: # extract circular set(ring) of points from scan lines rngs[num].append(line[num]) rngs[num].pop(0) return rngs @@ -2279,23 +2181,17 @@ class ObjectSurface(PathOp.ObjectOp): scanLines.reverse() # Begin gcode operation with raising cutter to safe height - commands.append( - Path.Command("G0", {"Z": self.clearHeight, "F": self.vertRapid}) - ) + commands.append(Path.Command("G0", {"Z": self.clearHeight, "F": self.vertRapid})) # Convert rotational scans into gcode rings = linesToPointRings(scanLines) rNum = 0 for rng in rings: - rSTG = self._rotationalScanToGcode( - obj, rng, rNum, prevDepth, layDep, advances - ) + rSTG = self._rotationalScanToGcode(obj, rng, rNum, prevDepth, layDep, advances) commands.extend(rSTG) if arc != 360.0: clrZ = self.layerEndzMax + self.SafeHeightOffset - commands.append( - Path.Command("G0", {"Z": clrZ, "F": self.vertRapid}) - ) + commands.append(Path.Command("G0", {"Z": clrZ, "F": self.vertRapid})) rNum += 1 # Eol @@ -2314,9 +2210,7 @@ class ObjectSurface(PathOp.ObjectOp): return commands - def _indexedDropCutScan( - self, obj, stl, advances, xmin, ymin, xmax, ymax, layDep, sample - ): + def _indexedDropCutScan(self, obj, stl, advances, xmin, ymin, xmax, ymax, layDep, sample): cutterOfst = 0.0 iCnt = 0 Lines = [] @@ -2381,10 +2275,7 @@ class ObjectSurface(PathOp.ObjectOp): # Convert list of OCL objects to list of Vectors for faster access and Apply depth offset if obj.DepthOffset.Value != 0.0: Lines.append( - [ - FreeCAD.Vector(p.x, p.y, p.z + obj.DepthOffset.Value) - for p in result - ] + [FreeCAD.Vector(p.x, p.y, p.z + obj.DepthOffset.Value) for p in result] ) else: Lines.append([FreeCAD.Vector(p.x, p.y, p.z) for p in result]) @@ -2429,13 +2320,9 @@ class ObjectSurface(PathOp.ObjectOp): clrZ = pnt.z + 2.0 output.append(Path.Command("G1", {"Z": clrZ, "F": self.vertRapid})) else: - output.append( - Path.Command("G0", {"Z": self.clearHeight, "F": self.vertRapid}) - ) + output.append(Path.Command("G0", {"Z": self.clearHeight, "F": self.vertRapid})) - output.append( - Path.Command("G0", {"X": pnt.x, "Y": pnt.y, "F": self.horizRapid}) - ) + output.append(Path.Command("G0", {"X": pnt.x, "Y": pnt.y, "F": self.horizRapid})) output.append(Path.Command("G1", {"Z": pnt.z, "F": self.vertFeed})) for i in range(0, lenCLP): @@ -2481,9 +2368,7 @@ class ObjectSurface(PathOp.ObjectOp): if holdStop is True: # Send hold and current points to zMax += 2.0 - for cmd in self.holdStopCmds( - obj, zMax, prvDep, pnt, "Hold Stop: in-line" - ): + for cmd in self.holdStopCmds(obj, zMax, prvDep, pnt, "Hold Stop: in-line"): output.append(cmd) # reset necessary hold related settings zMax = prvDep @@ -2503,9 +2388,7 @@ class ObjectSurface(PathOp.ObjectOp): # Rotate point data prev = pnt pnt = nxt - output.append( - Path.Command("N (End index angle " + str(round(idxAng, 4)) + ")", {}) - ) + output.append(Path.Command("N (End index angle " + str(round(idxAng, 4)) + ")", {})) # Save layer end point for use in transitioning to next layer self.layerEndPnt = pnt @@ -2541,9 +2424,7 @@ class ObjectSurface(PathOp.ObjectOp): clrZ = pnt.z + 5.0 output.append(Path.Command("G1", {"Z": clrZ, "F": self.vertRapid})) else: - output.append( - Path.Command("G1", {"Z": self.clearHeight, "F": self.vertRapid}) - ) + output.append(Path.Command("G1", {"Z": self.clearHeight, "F": self.vertRapid})) output.append(Path.Command("G0", {axisOfRot: ang, "F": self.axialFeed})) output.append(Path.Command("G1", {"X": pnt.x, "Y": pnt.y, "F": self.axialFeed})) @@ -2584,9 +2465,7 @@ class ObjectSurface(PathOp.ObjectOp): """holdStopCmds(obj, zMax, pd, p2, txt) ... Gcode commands to be executed at beginning of hold.""" cmds = [] msg = "N (" + txt + ")" - cmds.append( - Path.Command(msg, {}) - ) # Raise cutter rapid to zMax in line of travel + cmds.append(Path.Command(msg, {})) # Raise cutter rapid to zMax in line of travel cmds.append( Path.Command("G0", {"Z": zMax, "F": self.vertRapid}) ) # Raise cutter rapid to zMax in line of travel @@ -2725,9 +2604,7 @@ class ObjectSurface(PathOp.ObjectOp): p1xy, p2xy = ((p1.x, p1.y), (p2.x, p2.y)) pdcLine = self._planarDropCutScan(pdc, p1xy, p2xy) if obj.OptimizeLinearPaths: - pdcLine = PathUtils.simplify3dLine( - pdcLine, tolerance=obj.LinearDeflection.Value - ) + pdcLine = PathUtils.simplify3dLine(pdcLine, tolerance=obj.LinearDeflection.Value) zs = [obj.z for obj in pdcLine] # PDC z values are based on the model, and do not take into account # any remaining stock / multi layer paths. Adjust raw PDC z values to diff --git a/src/Mod/CAM/Path/Op/SurfaceSupport.py b/src/Mod/CAM/Path/Op/SurfaceSupport.py index 581d09e2d7..77d153168d 100644 --- a/src/Mod/CAM/Path/Op/SurfaceSupport.py +++ b/src/Mod/CAM/Path/Op/SurfaceSupport.py @@ -90,9 +90,7 @@ class PathGeometryGenerator: if shape.BoundBox.ZMin != 0.0: shape.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - shape.BoundBox.ZMin)) if shape.BoundBox.ZLength > 1.0e-8: - msg = translate( - "PathSurfaceSupport", "Shape appears to not be horizontal planar." - ) + msg = translate("PathSurfaceSupport", "Shape appears to not be horizontal planar.") msg += " ZMax == {} mm.\n".format(shape.BoundBox.ZMax) FreeCAD.Console.PrintWarning(msg) else: @@ -111,18 +109,12 @@ class PathGeometryGenerator: areaF = F.Area totArea += areaF fCnt += 1 - zeroCOM = zeroCOM.add( - FreeCAD.Vector(comF.x, comF.y, 0.0).multiply(areaF) - ) + zeroCOM = zeroCOM.add(FreeCAD.Vector(comF.x, comF.y, 0.0).multiply(areaF)) if fCnt == 0: - msg = translate( - "PathSurfaceSupport", "Cannot calculate the Center Of Mass." - ) + msg = translate("PathSurfaceSupport", "Cannot calculate the Center Of Mass.") msg += ( " " - + translate( - "PathSurfaceSupport", "Using Center of Boundbox instead." - ) + + translate("PathSurfaceSupport", "Using Center of Boundbox instead.") + "\n" ) FreeCAD.Console.PrintError(msg) @@ -189,9 +181,7 @@ class PathGeometryGenerator: FreeCAD.Vector(0, 0, 1), self.obj.CutPatternAngle ) bbC = self.shape.BoundBox.Center - geomShape.Placement.Base = FreeCAD.Vector( - bbC.x, bbC.y, 0.0 - geomShape.BoundBox.ZMin - ) + geomShape.Placement.Base = FreeCAD.Vector(bbC.x, bbC.y, 0.0 - geomShape.BoundBox.ZMin) if self.debugObjectsGroup: F = FreeCAD.ActiveDocument.addObject("Part::Feature", "tmpGeometrySet") @@ -243,9 +233,7 @@ class PathGeometryGenerator: def _Line(self): GeoSet = [] - centRot = FreeCAD.Vector( - 0.0, 0.0, 0.0 - ) # Bottom left corner of face/selection/model + centRot = FreeCAD.Vector(0.0, 0.0, 0.0) # Bottom left corner of face/selection/model # Create end points for set of lines to intersect with cross-section face pntTuples = [] @@ -259,7 +247,7 @@ class PathGeometryGenerator: pntTuples.append((p1, p2)) # Convert end points to lines - for (p1, p2) in pntTuples: + for p1, p2 in pntTuples: line = Part.makeLine(p1, p2) GeoSet.append(line) @@ -283,9 +271,7 @@ class PathGeometryGenerator: # Set tool properties and calculate cutout cutOut = self.cutOut / twoPi - segLen = ( - self.obj.SampleInterval.Value - ) # CutterDiameter / 10.0 # SampleInterval.Value + segLen = self.obj.SampleInterval.Value # CutterDiameter / 10.0 # SampleInterval.Value stepAng = segLen / ((loopCnt + 1) * self.cutOut) # math.pi / 18.0 # 10 degrees stopRadians = maxDist / cutOut @@ -298,9 +284,7 @@ class PathGeometryGenerator: while draw: radAng = sumRadians + stepAng p1 = lastPoint - p2 = getPoint( - move, cutOut, radAng - ) # cutOut is 'b' in the equation r = b * radAng + p2 = getPoint(move, cutOut, radAng) # cutOut is 'b' in the equation r = b * radAng sumRadians += stepAng # Increment sumRadians loopRadians += stepAng # Increment loopRadians if loopRadians > twoPi: @@ -327,9 +311,7 @@ class PathGeometryGenerator: while draw: radAng = sumRadians + stepAng p1 = lastPoint - p2 = getPoint( - move, cutOut, radAng - ) # cutOut is 'b' in the equation r = b * radAng + p2 = getPoint(move, cutOut, radAng) # cutOut is 'b' in the equation r = b * radAng sumRadians += stepAng # Increment sumRadians loopRadians += stepAng # Increment loopRadians if loopRadians > twoPi: @@ -365,9 +347,7 @@ class PathGeometryGenerator: cent = self.shape.BoundBox.Center cntrPnt = FreeCAD.Vector(cent.x, cent.y, 0.0) elif centerAt == "XminYmin": - cntrPnt = FreeCAD.Vector( - self.shape.BoundBox.XMin, self.shape.BoundBox.YMin, 0.0 - ) + cntrPnt = FreeCAD.Vector(self.shape.BoundBox.XMin, self.shape.BoundBox.YMin, 0.0) elif centerAt == "Custom": cntrPnt = FreeCAD.Vector( self.obj.PatternCenterCustom.x, self.obj.PatternCenterCustom.y, 0.0 @@ -507,9 +487,7 @@ class ProcessSelectedFaces: ) + "\n" ) - self.msgNoFaces += ( - " " + translate("PathSurfaceSupport", "Ignoring selected faces.") + "\n" - ) + self.msgNoFaces += " " + translate("PathSurfaceSupport", "Ignoring selected faces.") + "\n" self.JOB = JOB self.obj = obj self.profileEdges = "None" @@ -579,9 +557,7 @@ class ProcessSelectedFaces: # Cycle through each base model, processing faces for each for m in range(0, lenGRP): base = GRP[m] - (mFS, mVS, mPS) = self._preProcessFacesAndVoids( - base, FACES[m], VOIDS[m] - ) + (mFS, mVS, mPS) = self._preProcessFacesAndVoids(base, FACES[m], VOIDS[m]) fShapes[m] = mFS vShapes[m] = mVS self.profileShapes[m] = mPS @@ -625,9 +601,7 @@ class ProcessSelectedFaces: if fcShp: Path.Log.debug("vShapes[{}]: {}".format(m, vShapes[m])) if vShapes[m]: - Path.Log.debug( - " -Cutting void from base profile shape." - ) + Path.Log.debug(" -Cutting void from base profile shape.") adjPS = prflShp.cut(vShapes[m][0]) self.profileShapes[m] = [adjPS] else: @@ -637,9 +611,7 @@ class ProcessSelectedFaces: Path.Log.debug(" -Saving base profile shape.") self.profileShapes[m] = [prflShp] Path.Log.debug( - "self.profileShapes[{}]: {}".format( - m, self.profileShapes[m] - ) + "self.profileShapes[{}]: {}".format(m, self.profileShapes[m]) ) # Efor @@ -677,7 +649,7 @@ class ProcessSelectedFaces: hasVoid = False # Separate selected faces into (base, face) tuples and flag model(s) for STL creation - for (bs, SBS) in self.obj.Base: + for bs, SBS in self.obj.Base: for sb in SBS: # Flag model for STL creation mdlIdx = None @@ -747,9 +719,7 @@ class ProcessSelectedFaces: if cont: if self.showDebugObjects: - T = FreeCAD.ActiveDocument.addObject( - "Part::Feature", "tmpCollectiveShape" - ) + T = FreeCAD.ActiveDocument.addObject("Part::Feature", "tmpCollectiveShape") T.Shape = cfsL T.purgeTouched() self.tempGroup.addObject(T) @@ -779,16 +749,14 @@ class ProcessSelectedFaces: C.purgeTouched() self.tempGroup.addObject(C) ofstVal = self._calculateOffsetValue(isHole=True) - intOfstShp = PathUtils.getOffsetArea( - casL, ofstVal, plane=self.wpc - ) + intOfstShp = PathUtils.getOffsetArea(casL, ofstVal, plane=self.wpc) mIFS.append(intOfstShp) mFS = [faceOfstShp] # Eif elif self.obj.HandleMultipleFeatures == "Individually": - for (fcshp, fcIdx) in FCS: + for fcshp, fcIdx in FCS: cont = True fNum = fcIdx + 1 outerFace = False @@ -800,15 +768,11 @@ class ProcessSelectedFaces: ifL = [] # avoid shape list if outerFace: - Path.Log.debug( - "Attempting to create offset face of Face{}".format(fNum) - ) + Path.Log.debug("Attempting to create offset face of Face{}".format(fNum)) if self.profileEdges != "None": ofstVal = self._calculateOffsetValue(isHole) - psOfst = PathUtils.getOffsetArea( - outerFace, ofstVal, plane=self.wpc - ) + psOfst = PathUtils.getOffsetArea(outerFace, ofstVal, plane=self.wpc) if psOfst: if mPS is False: mPS = [] @@ -835,9 +799,7 @@ class ProcessSelectedFaces: casL = Part.makeCompound(ifL) ofstVal = self._calculateOffsetValue(isHole=True) - intOfstShp = PathUtils.getOffsetArea( - casL, ofstVal, plane=self.wpc - ) + intOfstShp = PathUtils.getOffsetArea(casL, ofstVal, plane=self.wpc) mIFS.append(intOfstShp) # faceOfstShp = faceOfstShp.cut(intOfstShp) @@ -874,18 +836,14 @@ class ProcessSelectedFaces: avoid = Part.makeCompound(outFCS) if self.showDebugObjects: - P = FreeCAD.ActiveDocument.addObject( - "Part::Feature", "tmpVoidEnvelope" - ) + P = FreeCAD.ActiveDocument.addObject("Part::Feature", "tmpVoidEnvelope") P.Shape = avoid P.purgeTouched() self.tempGroup.addObject(P) if cont: if self.showDebugObjects: - P = FreeCAD.ActiveDocument.addObject( - "Part::Feature", "tmpVoidCompound" - ) + P = FreeCAD.ActiveDocument.addObject("Part::Feature", "tmpVoidCompound") P.Shape = avoid P.purgeTouched() self.tempGroup.addObject(P) @@ -964,9 +922,7 @@ class ProcessSelectedFaces: if cont: ofstVal = self._calculateOffsetValue(isHole) - faceOffsetShape = PathUtils.getOffsetArea( - csFaceShape, ofstVal, plane=self.wpc - ) + faceOffsetShape = PathUtils.getOffsetArea(csFaceShape, ofstVal, plane=self.wpc) if faceOffsetShape is False: Path.Log.debug("getOffsetArea() failed for entire base.") else: @@ -983,9 +939,7 @@ class ProcessSelectedFaces: # We need to offset by at least our linear tessellation deflection # (default GeometryTolerance / 4) to avoid false retracts at the # boundaries. - tolrnc = max( - self.JOB.GeometryTolerance.Value / 10.0, self.obj.LinearDeflection.Value - ) + tolrnc = max(self.JOB.GeometryTolerance.Value / 10.0, self.obj.LinearDeflection.Value) if isVoid is False: if isHole is True: @@ -1040,9 +994,7 @@ class ProcessSelectedFaces: internalFaces = Part.makeCompound(internalFaces) return ([outlineShape], [internalFaces]) except Exception as e: - Path.Log.warning( - "getOffsetArea failed: {}; Using FindUnifiedRegions.".format(e) - ) + Path.Log.warning("getOffsetArea failed: {}; Using FindUnifiedRegions.".format(e)) # Use face-unifying class FUR = FindUnifiedRegions(shapeAndIndexTuples, tolerance) if self.showDebugObjects: @@ -1178,9 +1130,7 @@ def getShapeEnvelope(shape): dep_par = PathUtils.depth_params(maxz + 5.0, maxz + 3.0, maxz, stpDwn, 0.0, minz) try: - env = PathUtils.getEnvelope( - partshape=shape, depthparams=dep_par - ) # Produces .Shape + env = PathUtils.getEnvelope(partshape=shape, depthparams=dep_par) # Produces .Shape except Exception as ee: FreeCAD.Console.PrintError("PathUtils.getEnvelope() failed.\n" + str(ee) + "\n") return False @@ -1235,9 +1185,7 @@ def _makeSafeSTL(self, JOB, obj, mdlIdx, faceShapes, voidShapes, ocl): zmin = mBB.ZMin zmax = mBB.ZMin + extFwd stpDwn = (zmax - zmin) / 4.0 - dep_par = PathUtils.depth_params( - zmax + 5.0, zmax + 3.0, zmax, stpDwn, 0.0, zmin - ) + dep_par = PathUtils.depth_params(zmax + 5.0, zmax + 3.0, zmax, stpDwn, 0.0, zmin) try: envBB = PathUtils.getEnvelope( @@ -1313,9 +1261,7 @@ def _makeSTL(model, obj, ocl, model_type=None): else: shape = model vertices, facet_indices = shape.tessellate(obj.LinearDeflection.Value) - facets = ( - (vertices[f[0]], vertices[f[1]], vertices[f[2]]) for f in facet_indices - ) + facets = ((vertices[f[0]], vertices[f[1]], vertices[f[2]]) for f in facet_indices) stl = ocl.STLSurf() for tri in facets: v1, v2, v3 = tri @@ -1331,7 +1277,8 @@ def _makeSTL(model, obj, ocl, model_type=None): # Functions to convert path geometry into line/arc segments for OCL input or directly to g-code def pathGeomToLinesPointSet(self, obj, compGeoShp): """pathGeomToLinesPointSet(self, obj, compGeoShp)... - Convert a compound set of sequential line segments to directionally-oriented collinear groupings.""" + Convert a compound set of sequential line segments to directionally-oriented collinear groupings. + """ Path.Log.debug("pathGeomToLinesPointSet()") # Extract intersection line segments for return value as [] LINES = [] @@ -1394,9 +1341,7 @@ def pathGeomToLinesPointSet(self, obj, compGeoShp): ( vA, vB, - ) = ( - inLine.pop() - ) # pop off previous line segment for combining with current + ) = inLine.pop() # pop off previous line segment for combining with current tup = (vA, tup[1]) self.closedGap = True else: @@ -1498,9 +1443,7 @@ def pathGeomToZigzagPointSet(self, obj, compGeoShp): ( vA, vB, - ) = ( - inLine.pop() - ) # pop off previous line segment for combining with current + ) = inLine.pop() # pop off previous line segment for combining with current if dirFlg == 1: tup = (vA, tup[1]) else: @@ -1676,14 +1619,10 @@ def pathGeomToCircularPointSet(self, obj, compGeoShp): # space = obj.SampleInterval.Value / 10.0 # space = 0.000001 - space = ( - self.toolDiam * 0.005 - ) # If too small, OCL will fail to scan the loop + space = self.toolDiam * 0.005 # If too small, OCL will fail to scan the loop # p1 = FreeCAD.Vector(v1.X, v1.Y, v1.Z) - p1 = FreeCAD.Vector( - v1.X, v1.Y, 0.0 - ) # z=0.0 for waterline; z=v1.Z for 3D Surface + p1 = FreeCAD.Vector(v1.X, v1.Y, 0.0) # z=0.0 for waterline; z=v1.Z for 3D Surface rad = p1.sub(self.tmpCOM).Length spcRadRatio = space / rad if spcRadRatio < 1.0: @@ -1775,9 +1714,7 @@ def pathGeomToCircularPointSet(self, obj, compGeoShp): vA, vB, vC, - ) = ( - PRTS.pop() - ) # pop off previous arc segment for combining with current + ) = PRTS.pop() # pop off previous arc segment for combining with current arc = (vA, arc[1], vC) self.closedGap = True else: @@ -1828,9 +1765,7 @@ def pathGeomToSpiralPointSet(obj, compGeoShp): tup = ((p1.x, p1.y), (p2.x, p2.y)) inLine.append(tup) - for ei in range( - start, ec - ): # Skipped first edge, started with second edge above as edg1 + for ei in range(start, ec): # Skipped first edge, started with second edge above as edg1 edg = compGeoShp.Edges[ei] # Get edge for vertexes sp = FreeCAD.Vector( edg.Vertexes[0].X, edg.Vertexes[0].Y, 0.0 @@ -1857,7 +1792,8 @@ def pathGeomToSpiralPointSet(obj, compGeoShp): def pathGeomToOffsetPointSet(obj, compGeoShp): """pathGeomToOffsetPointSet(obj, compGeoShp)... - Convert a compound set of 3D profile segmented wires to 2D segments, applying linear optimization.""" + Convert a compound set of 3D profile segmented wires to 2D segments, applying linear optimization. + """ Path.Log.debug("pathGeomToOffsetPointSet()") LINES = [] @@ -1936,7 +1872,7 @@ class FindUnifiedRegions: self.tempGroup.addObject(S) def _extractTopFaces(self): - for (F, fcIdx) in self.FACES: # format is tuple (faceShape, faceIndex_on_base) + for F, fcIdx in self.FACES: # format is tuple (faceShape, faceIndex_on_base) cont = True fNum = fcIdx + 1 # Extrude face @@ -1989,9 +1925,7 @@ class FindUnifiedRegions: tfBB_Area = tfBB.XLength * tfBB.YLength # self._showShape(topFace, 'topFaceAlt_2_{}'.format(fNum)) if tfBB_Area < (fBB_Area * 0.9): - msg = "Failed to extract processing region for Face {}\n".format( - fNum - ) + msg = "Failed to extract processing region for Face {}\n".format(fNum) FreeCAD.Console.PrintError(msg) cont = False # Eif @@ -2003,7 +1937,7 @@ class FindUnifiedRegions: def _fuseTopFaces(self): (one, baseFcIdx) = self.topFaces.pop(0) base = one - for (face, fcIdx) in self.topFaces: + for face, fcIdx in self.topFaces: base = base.fuse(face) self.topFaces.insert(0, (one, baseFcIdx)) self.fusedFaces = base @@ -2263,7 +2197,7 @@ class FindUnifiedRegions: Path.Log.debug("_identifyInternalFeatures()") remList = [] - for (top, fcIdx) in self.topFaces: + for top, fcIdx in self.topFaces: big = Part.Face(top.OuterWire) for s in range(0, len(self.REGIONS)): if s not in remList: @@ -2435,7 +2369,7 @@ class FindUnifiedRegions: if self.noSharedEdges: Path.Log.debug("No shared edges by length detected.") allTopFaces = [] - for (topFace, fcIdx) in self.topFaces: + for topFace, fcIdx in self.topFaces: allTopFaces.append(topFace) # Identify internal features lenWrs = len(topFace.Wires) @@ -2504,9 +2438,7 @@ class OCL_Tool: self.toolType = self.tool.ShapeName # Indicates ToolBit tool self.toolMode = "ToolBit" if self.toolType: - Path.Log.debug( - "OCL_Tool tool mode, type: {}, {}".format(self.toolMode, self.toolType) - ) + Path.Log.debug("OCL_Tool tool mode, type: {}, {}".format(self.toolMode, self.toolType)) """ #### FreeCAD Legacy tool shape properties per tool type @@ -2648,9 +2580,7 @@ class OCL_Tool: if hasattr(self.tool, "Diameter"): self.diameter = float(self.tool.Diameter) else: - msg = translate( - "PathSurfaceSupport", "Diameter dimension missing from ToolBit shape." - ) + msg = translate("PathSurfaceSupport", "Diameter dimension missing from ToolBit shape.") FreeCAD.Console.PrintError(msg + "\n") return False if hasattr(self.tool, "LengthOffset"): @@ -2677,9 +2607,7 @@ class OCL_Tool: # OCL -> CylCutter::CylCutter(diameter, length) if self.diameter == -1.0 or self.cutEdgeHeight == -1.0: return - self.oclTool = self.ocl.CylCutter( - self.diameter, self.cutEdgeHeight + self.lengthOffset - ) + self.oclTool = self.ocl.CylCutter(self.diameter, self.cutEdgeHeight + self.lengthOffset) def _oclBallCutter(self): # Standard Ball End Mill @@ -2689,19 +2617,13 @@ class OCL_Tool: self.tiltCutter = True if self.cutEdgeHeight == 0: self.cutEdgeHeight = self.diameter / 2 - self.oclTool = self.ocl.BallCutter( - self.diameter, self.cutEdgeHeight + self.lengthOffset - ) + self.oclTool = self.ocl.BallCutter(self.diameter, self.cutEdgeHeight + self.lengthOffset) def _oclBullCutter(self): # Standard Bull Nose cutter # Reference: https://www.fine-tools.com/halbstabfraeser.html # OCL -> BullCutter::BullCutter(diameter, minor radius, length) - if ( - self.diameter == -1.0 - or self.flatRadius == -1.0 - or self.cutEdgeHeight == -1.0 - ): + if self.diameter == -1.0 or self.flatRadius == -1.0 or self.cutEdgeHeight == -1.0: return self.oclTool = self.ocl.BullCutter( self.diameter, @@ -2712,15 +2634,9 @@ class OCL_Tool: def _oclConeCutter(self): # Engraver or V-bit cutter # OCL -> ConeCutter::ConeCutter(diameter, angle, length) - if ( - self.diameter == -1.0 - or self.cutEdgeAngle == -1.0 - or self.cutEdgeHeight == -1.0 - ): + if self.diameter == -1.0 or self.cutEdgeAngle == -1.0 or self.cutEdgeHeight == -1.0: return - self.oclTool = self.ocl.ConeCutter( - self.diameter, self.cutEdgeAngle / 2, self.lengthOffset - ) + self.oclTool = self.ocl.ConeCutter(self.diameter, self.cutEdgeAngle / 2, self.lengthOffset) def _setToolMethod(self): toolMap = dict() @@ -2755,9 +2671,7 @@ class OCL_Tool: self._setToolMethod() if self.toolMethod == "None": - err = translate( - "PathSurface", "Failed to map selected tool to an OCL tool type." - ) + err = translate("PathSurface", "Failed to map selected tool to an OCL tool type.") FreeCAD.Console.PrintError(err + "\n") return False else: @@ -2769,9 +2683,7 @@ class OCL_Tool: return self.oclTool # Set error messages - err = translate( - "PathSurface", "Failed to translate active tool to OCL tool type." - ) + err = translate("PathSurface", "Failed to translate active tool to OCL tool type.") FreeCAD.Console.PrintError(err + "\n") return False @@ -2791,6 +2703,7 @@ class OCL_Tool: # Eclass + # Support functions def makeExtendedBoundBox(wBB, bbBfr, zDep): Path.Log.debug("makeExtendedBoundBox()") diff --git a/src/Mod/CAM/Path/Op/ThreadMilling.py b/src/Mod/CAM/Path/Op/ThreadMilling.py index e8b80da194..16a6fc2810 100644 --- a/src/Mod/CAM/Path/Op/ThreadMilling.py +++ b/src/Mod/CAM/Path/Op/ThreadMilling.py @@ -338,9 +338,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): "App::PropertyString", "ThreadName", "Thread", - QT_TRANSLATE_NOOP( - "App::Property", "Defines which standard thread was chosen" - ), + QT_TRANSLATE_NOOP("App::Property", "Defines which standard thread was chosen"), ) obj.addProperty( "App::PropertyLength", @@ -358,9 +356,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): "App::PropertyLength", "Pitch", "Thread", - QT_TRANSLATE_NOOP( - "App::Property", "Set thread's pitch - used for metric threads" - ), + QT_TRANSLATE_NOOP("App::Property", "Set thread's pitch - used for metric threads"), ) obj.addProperty( "App::PropertyInteger", @@ -384,9 +380,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): "App::PropertyInteger", "Passes", "Operation", - QT_TRANSLATE_NOOP( - "App::Property", "Set how many passes are used to cut the thread" - ), + QT_TRANSLATE_NOOP("App::Property", "Set how many passes are used to cut the thread"), ) obj.addProperty( "App::PropertyEnumeration", @@ -407,9 +401,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): "App::PropertyLink", "ClearanceOp", "Operation", - QT_TRANSLATE_NOOP( - "App::Property", "Operation to clear the inside of the thread" - ), + QT_TRANSLATE_NOOP("App::Property", "Operation to clear the inside of the thread"), ) for n in self.propertyEnumerations(): @@ -431,9 +423,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): Path.Log.track(obj.Label, loc, gcode, zStart, zFinal, pitch) elevator = elevatorRadius(obj, loc, _isThreadInternal(obj), self.tool) - move2clearance = Path.Command( - "G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid} - ) + move2clearance = Path.Command("G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid}) self.commandlist.append(move2clearance) start = None diff --git a/src/Mod/CAM/Path/Op/Util.py b/src/Mod/CAM/Path/Op/Util.py index 790cbf907a..f1b1f57eb9 100644 --- a/src/Mod/CAM/Path/Op/Util.py +++ b/src/Mod/CAM/Path/Op/Util.py @@ -93,10 +93,7 @@ def debugWire(label, w): if not PrintWireDebug: return print("#%s wire >>>>>>>>>>>>>>>>>>>>>>>>" % label) - print( - "grp = FreeCAD.ActiveDocument.addObject('App::DocumentObjectGroup', '%s')" - % label - ) + print("grp = FreeCAD.ActiveDocument.addObject('App::DocumentObjectGroup', '%s')" % label) for i, e in enumerate(w.Edges): edge = "%s_e%d" % (label, i) debugEdge("%s = " % edge, e) @@ -136,7 +133,8 @@ def _orientEdges(inEdges): def _isWireClockwise(w): """_isWireClockwise(w) ... return True if wire is oriented clockwise. - Assumes the edges of w are already properly oriented - for generic access use isWireClockwise(w).""" + Assumes the edges of w are already properly oriented - for generic access use isWireClockwise(w). + """ # handle wires consisting of a single circle or 2 edges where one is an arc. # in both cases, because the edges are expected to be oriented correctly, the orientation can be # determined by looking at (one of) the circle curves. @@ -165,7 +163,8 @@ def orientWire(w, forward=True): """orientWire(w, forward=True) ... orients given wire in a specific direction. If forward = True (the default) the wire is oriented clockwise, looking down the negative Z axis. If forward = False the wire is oriented counter clockwise. - If forward = None the orientation is determined by the order in which the edges appear in the wire.""" + If forward = None the orientation is determined by the order in which the edges appear in the wire. + """ Path.Log.debug("orienting forward: {}: {} edges".format(forward, len(w.Edges))) wire = Part.Wire(_orientEdges(w.Edges)) if forward is not None: @@ -191,9 +190,7 @@ def offsetWire(wire, base, offset, forward, Side=None): # https://www.freecad.org/wiki/Part%20Offset2D # it's easy to construct them manually though z = -1 if forward else 1 - new_edge = Part.makeCircle( - curve.Radius + offset, curve.Center, FreeCAD.Vector(0, 0, z) - ) + new_edge = Part.makeCircle(curve.Radius + offset, curve.Center, FreeCAD.Vector(0, 0, z)) if base.isInside(new_edge.Vertexes[0].Point, offset / 2, True): if offset > curve.Radius or Path.Geom.isRoughly(offset, curve.Radius): # offsetting a hole by its own radius (or more) makes the hole vanish @@ -246,17 +243,13 @@ def offsetWire(wire, base, offset, forward, Side=None): # Create new arc if curve.AngleXU > 0: edge = Part.ArcOfCircle( - Part.Circle( - curve.Center, FreeCAD.Vector(0, 0, 1), curve.Radius + offset - ), + Part.Circle(curve.Center, FreeCAD.Vector(0, 0, 1), curve.Radius + offset), start_angle, end_angle, ).toShape() else: edge = Part.ArcOfCircle( - Part.Circle( - curve.Center, FreeCAD.Vector(0, 0, 1), curve.Radius - offset - ), + Part.Circle(curve.Center, FreeCAD.Vector(0, 0, 1), curve.Radius - offset), start_angle, end_angle, ).toShape() @@ -341,9 +334,7 @@ def offsetWire(wire, base, offset, forward, Side=None): p0 = edge.firstVertex().Point p1 = edge.lastVertex().Point for p in insideEndpoints: - if Path.Geom.pointsCoincide(p, p0, 0.01) or Path.Geom.pointsCoincide( - p, p1, 0.01 - ): + if Path.Geom.pointsCoincide(p, p0, 0.01) or Path.Geom.pointsCoincide(p, p1, 0.01): return True return False diff --git a/src/Mod/CAM/Path/Op/Vcarve.py b/src/Mod/CAM/Path/Op/Vcarve.py index d797dd71a1..98f0c2fcbf 100644 --- a/src/Mod/CAM/Path/Op/Vcarve.py +++ b/src/Mod/CAM/Path/Op/Vcarve.py @@ -280,9 +280,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): "App::PropertyLinkList", "BaseShapes", "Path", - QT_TRANSLATE_NOOP( - "App::Property", "Additional base objects to be engraved" - ), + QT_TRANSLATE_NOOP("App::Property", "Additional base objects to be engraved"), ) obj.setEditorMode("BaseShapes", 2) # hide @@ -316,9 +314,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): "App::PropertyFloat", "Discretize", "Path", - QT_TRANSLATE_NOOP( - "App::Property", "The deflection value for discretizing arcs" - ), + QT_TRANSLATE_NOOP("App::Property", "The deflection value for discretizing arcs"), ) obj.addProperty( "App::PropertyFloat", @@ -371,9 +367,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): dist = ptv[-1].distanceToPoint(ptv[0]) if dist < FreeCAD.Base.Precision.confusion(): Path.Log.debug( - "Removing bad carve point: {} from polygon origin".format( - dist - ) + "Removing bad carve point: {} from polygon origin".format(dist) ) del ptv[-1] ptv.append(ptv[0]) @@ -399,9 +393,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): vd.colorExterior(EXTERIOR1) vd.colorExterior( EXTERIOR2, - lambda v: not f.isInside( - v.toPoint(f.BoundBox.ZMin), obj.Tolerance, True - ), + lambda v: not f.isInside(v.toPoint(f.BoundBox.ZMin), obj.Tolerance, True), ) vd.colorColinear(COLINEAR, obj.Colinear) vd.colorTwins(TWIN) @@ -470,9 +462,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): path.append(Path.Command("G0 Z{}".format(obj.SafeHeight.Value))) path.append( Path.Command( - "G0 X{} Y{} Z{}".format( - newPosition.x, newPosition.y, obj.SafeHeight.Value - ) + "G0 X{} Y{} Z{}".format(newPosition.x, newPosition.y, obj.SafeHeight.Value) ) ) @@ -480,9 +470,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): vSpeed = obj.ToolController.VertFeed.Value path.append( Path.Command( - "G1 X{} Y{} Z{} F{}".format( - newPosition.x, newPosition.y, newPosition.z, vSpeed - ) + "G1 X{} Y{} Z{} F{}".format(newPosition.x, newPosition.y, newPosition.z, vSpeed) ) ) for e in wire: @@ -508,9 +496,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): _maximumUsableDepth = _get_maximumUsableDepth(wires, geom) if _maximumUsableDepth is not None: maximumUsableDepth = _maximumUsableDepth - Path.Log.debug( - f"Maximum usable depth for current face: {maximumUsableDepth}" - ) + Path.Log.debug(f"Maximum usable depth for current face: {maximumUsableDepth}") # first pass cutWires(wires, pathlist, obj.OptimizeMovements) @@ -551,9 +537,7 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): if obj.ToolController.Tool.CuttingEdgeAngle >= 180.0: Path.Log.info( - translate( - "CAM_Vcarve", "Engraver cutting edge angle must be < 180 degrees." - ) + translate("CAM_Vcarve", "Engraver cutting edge angle must be < 180 degrees.") ) return @@ -571,9 +555,9 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): if not faces: for model in self.model: - if model.isDerivedFrom( - "Sketcher::SketchObject" - ) or model.isDerivedFrom("Part::Part2DObject"): + if model.isDerivedFrom("Sketcher::SketchObject") or model.isDerivedFrom( + "Part::Part2DObject" + ): faces.extend(model.Shape.Faces) if faces: @@ -621,14 +605,10 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): """Debug function to display calculated voronoi edges""" if not getattr(self, "voronoiDebugCache", None): - Path.Log.error( - "debugVoronoi: empty debug cache. Recompute VCarve operation first" - ) + Path.Log.error("debugVoronoi: empty debug cache. Recompute VCarve operation first") return - vPart = FreeCAD.activeDocument().addObject( - "App::Part", f"{obj.Name}-VoronoiDebug" - ) + vPart = FreeCAD.activeDocument().addObject("App::Part", f"{obj.Name}-VoronoiDebug") wiresToShow = [] diff --git a/src/Mod/CAM/Path/Op/Waterline.py b/src/Mod/CAM/Path/Op/Waterline.py index ff779367e4..5714565d85 100644 --- a/src/Mod/CAM/Path/Op/Waterline.py +++ b/src/Mod/CAM/Path/Op/Waterline.py @@ -38,9 +38,7 @@ try: except ImportError: import opencamlib as ocl except ImportError: - msg = translate( - "path_waterline", "This operation requires OpenCamLib to be installed." - ) + msg = translate("path_waterline", "This operation requires OpenCamLib to be installed.") FreeCAD.Console.PrintError(msg + "\n") raise ImportError @@ -172,7 +170,7 @@ class ObjectWaterline(PathOp.ObjectOp): """initOpProperties(obj) ... create operation specific properties""" self.addNewProps = list() - for (prtyp, nm, grp, tt) in self.opPropertyDefinitions(): + for prtyp, nm, grp, tt in self.opPropertyDefinitions(): if not hasattr(obj, nm): obj.addProperty(prtyp, nm, grp, tt) self.addNewProps.append(nm) @@ -358,9 +356,7 @@ class ObjectWaterline(PathOp.ObjectOp): "App::PropertyDistance", "IgnoreOuterAbove", "Clearing Options", - QT_TRANSLATE_NOOP( - "App::Property", "Ignore outer waterlines above this height." - ), + QT_TRANSLATE_NOOP("App::Property", "Ignore outer waterlines above this height."), ), ( "App::PropertyEnumeration", @@ -375,9 +371,7 @@ class ObjectWaterline(PathOp.ObjectOp): "App::PropertyVectorDistance", "PatternCenterCustom", "Clearing Options", - QT_TRANSLATE_NOOP( - "App::Property", "Set the start point for the cut pattern." - ), + QT_TRANSLATE_NOOP("App::Property", "Set the start point for the cut pattern."), ), ( "App::PropertyEnumeration", @@ -455,9 +449,7 @@ class ObjectWaterline(PathOp.ObjectOp): "App::PropertyBool", "UseStartPoint", "Start Point", - QT_TRANSLATE_NOOP( - "App::Property", "Make True, if specifying a Start Point" - ), + QT_TRANSLATE_NOOP("App::Property", "Make True, if specifying a Start Point"), ), ] @@ -503,12 +495,8 @@ class ObjectWaterline(PathOp.ObjectOp): warn = False defaults["LinearDeflection"] = job.GeometryTolerance.Value if warn: - msg = translate( - "PathWaterline", "The GeometryTolerance for this Job is 0.0." - ) - msg += translate( - "PathWaterline", "Initializing LinearDeflection to 0.0001 mm." - ) + msg = translate("PathWaterline", "The GeometryTolerance for this Job is 0.0.") + msg += translate("PathWaterline", "Initializing LinearDeflection to 0.0001 mm.") FreeCAD.Console.PrintWarning(msg + "\n") return defaults @@ -661,16 +649,12 @@ class ObjectWaterline(PathOp.ObjectOp): if obj.CutPatternAngle < -360.0: obj.CutPatternAngle = 0.0 Path.Log.error( - translate( - "PathWaterline", "Cut pattern angle limits are +-360 degrees." - ) + translate("PathWaterline", "Cut pattern angle limits are +-360 degrees.") ) if obj.CutPatternAngle >= 360.0: obj.CutPatternAngle = 0.0 Path.Log.error( - translate( - "PathWaterline", "Cut pattern angle limits are +- 360 degrees." - ) + translate("PathWaterline", "Cut pattern angle limits are +- 360 degrees.") ) # Limit StepOver to natural number percentage @@ -807,22 +791,14 @@ class ObjectWaterline(PathOp.ObjectOp): if obj.Comment != "": self.commandlist.append(Path.Command("N ({})".format(str(obj.Comment)), {})) self.commandlist.append(Path.Command("N ({})".format(obj.Label), {})) + self.commandlist.append(Path.Command("N (Tool type: {})".format(oclTool.toolType), {})) self.commandlist.append( - Path.Command("N (Tool type: {})".format(oclTool.toolType), {}) + Path.Command("N (Compensated Tool Path. Diameter: {})".format(oclTool.diameter), {}) ) self.commandlist.append( - Path.Command( - "N (Compensated Tool Path. Diameter: {})".format(oclTool.diameter), {} - ) - ) - self.commandlist.append( - Path.Command( - "N (Sample interval: {})".format(str(obj.SampleInterval.Value)), {} - ) - ) - self.commandlist.append( - Path.Command("N (Step over %: {})".format(str(obj.StepOver)), {}) + Path.Command("N (Sample interval: {})".format(str(obj.SampleInterval.Value)), {}) ) + self.commandlist.append(Path.Command("N (Step over %: {})".format(str(obj.StepOver)), {})) self.commandlist.append(Path.Command("N ({})".format(output), {})) self.commandlist.append( Path.Command("G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid}) @@ -851,9 +827,7 @@ class ObjectWaterline(PathOp.ObjectOp): if FCAD.getObject(tempGroupName + "001"): for to in FCAD.getObject(tempGroupName + "001").Group: FCAD.removeObject(to.Name) - FCAD.removeObject( - tempGroupName + "001" - ) # remove temp directory if already exists + FCAD.removeObject(tempGroupName + "001") # remove temp directory if already exists tempGroup = FCAD.addObject("App::DocumentObjectGroup", tempGroupName) tempGroupName = tempGroup.Name self.tempGroup = tempGroup @@ -896,9 +870,7 @@ class ObjectWaterline(PathOp.ObjectOp): if FreeCAD.GuiUp: for m in range(0, len(JOB.Model.Group)): mNm = JOB.Model.Group[m].Name - modelVisibility.append( - FreeCADGui.ActiveDocument.getObject(mNm).Visibility - ) + modelVisibility.append(FreeCADGui.ActiveDocument.getObject(mNm).Visibility) # Setup STL, model type, and bound box containers for each model in Job for m in range(0, len(JOB.Model.Group)): @@ -941,35 +913,23 @@ class ObjectWaterline(PathOp.ObjectOp): Mdl = JOB.Model.Group[m] if FACES[m] is False: - Path.Log.error( - "No data for model base: {}".format(JOB.Model.Group[m].Label) - ) + Path.Log.error("No data for model base: {}".format(JOB.Model.Group[m].Label)) else: if m > 0: # Raise to clearance between models - CMDS.append( - Path.Command( - "N (Transition to base: {}.)".format(Mdl.Label) - ) - ) + CMDS.append(Path.Command("N (Transition to base: {}.)".format(Mdl.Label))) CMDS.append( Path.Command( "G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid}, ) ) - Path.Log.info( - "Working on Model.Group[{}]: {}".format(m, Mdl.Label) - ) + Path.Log.info("Working on Model.Group[{}]: {}".format(m, Mdl.Label)) # make stock-model-voidShapes STL model for avoidance detection on transitions if obj.Algorithm == "OCL Dropcutter": - PathSurfaceSupport._makeSafeSTL( - self, JOB, obj, m, FACES[m], VOIDS[m], ocl - ) + PathSurfaceSupport._makeSafeSTL(self, JOB, obj, m, FACES[m], VOIDS[m], ocl) # Process model/faces - OCL objects must be ready - CMDS.extend( - self._processWaterlineAreas(JOB, obj, m, FACES[m], VOIDS[m]) - ) + CMDS.extend(self._processWaterlineAreas(JOB, obj, m, FACES[m], VOIDS[m])) # Save gcode produced self.commandlist.extend(CMDS) @@ -1062,9 +1022,7 @@ class ObjectWaterline(PathOp.ObjectOp): else: COMP = ADD - final.append( - Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid}) - ) + final.append(Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid})) if obj.Algorithm == "OCL Dropcutter": final.extend( self._oclWaterlineOp(JOB, obj, mdlIdx, COMP) @@ -1090,9 +1048,7 @@ class ObjectWaterline(PathOp.ObjectOp): else: COMP = ADD - final.append( - Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid}) - ) + final.append(Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid})) if obj.Algorithm == "OCL Dropcutter": final.extend( self._oclWaterlineOp(JOB, obj, mdlIdx, COMP) @@ -1184,9 +1140,7 @@ class ObjectWaterline(PathOp.ObjectOp): # Create raise, shift, and optional lower commands if height is not False: cmds.append(Path.Command("G0", {"Z": height, "F": self.vertRapid})) - cmds.append( - Path.Command(horizGC, {"X": first.x, "Y": first.y, "F": hSpeed}) - ) + cmds.append(Path.Command(horizGC, {"X": first.x, "Y": first.y, "F": hSpeed})) if rtpd is not False: # ReturnToPreviousDepth cmds.append(Path.Command("G0", {"Z": rtpd, "F": self.vertRapid})) @@ -1310,9 +1264,7 @@ class ObjectWaterline(PathOp.ObjectOp): cmds = self._getWaterline(obj, scanLines, layDep, lyr, lenSL, pntsPerLine) commands.extend(cmds) lyr += 1 - Path.Log.debug( - "--All layer scans combined took " + str(time.time() - layTime) + " s" - ) + Path.Log.debug("--All layer scans combined took " + str(time.time() - layTime) + " s") return commands def _waterlineDropCutScan(self, stl, smplInt, xmin, xmax, ymin, fd, numScanLines): @@ -1429,9 +1381,7 @@ class ObjectWaterline(PathOp.ObjectOp): TM[lin + 1][pt] = 1 # square the corner cont = False - if ( - cont is True and TM[lin + 1][pt + 1] == 1 - ): # forward right == 1 + if cont is True and TM[lin + 1][pt + 1] == 1: # forward right == 1 if TM[lin][pt + 1] == 2: # right == 2 TM[lin + 1][pt] = 1 # square the corner cont = True @@ -1631,16 +1581,12 @@ class ObjectWaterline(PathOp.ObjectOp): + ". Stopped following loop." ) break - nxt = self._findNextWlPoint( - lC, pC, cur[0], cur[1], prv[0], prv[1] - ) # get next point + nxt = self._findNextWlPoint(lC, pC, cur[0], cur[1], prv[0], prv[1]) # get next point loop.append(oclScan[nxt[0] - 1][nxt[1] - 1]) # add it to loop point list self.topoMap[nxt[0]][nxt[1]] = nxt[2] # Mute the point, if not Y stem if nxt[0] == L and nxt[1] == P: # check if loop complete follow = False - elif ( - nxt[0] == cur[0] and nxt[1] == cur[1] - ): # check if line cannot be detected + elif nxt[0] == cur[0] and nxt[1] == cur[1]: # check if line cannot be detected follow = False prv = cur cur = nxt @@ -1695,12 +1641,8 @@ class ObjectWaterline(PathOp.ObjectOp): pnt = FreeCAD.Vector(loop[0].x, loop[0].y, layDep) # Position cutter to begin loop - output.append( - Path.Command("G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid}) - ) - output.append( - Path.Command("G0", {"X": pnt.x, "Y": pnt.y, "F": self.horizRapid}) - ) + output.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid})) + output.append(Path.Command("G0", {"X": pnt.x, "Y": pnt.y, "F": self.horizRapid})) output.append(Path.Command("G1", {"Z": pnt.z, "F": self.vertFeed})) lenCLP = len(loop) @@ -1712,9 +1654,7 @@ class ObjectWaterline(PathOp.ObjectOp): nxt.y = loop[i + 1].y nxt.z = layDep - output.append( - Path.Command("G1", {"X": pnt.x, "Y": pnt.y, "F": self.horizFeed}) - ) + output.append(Path.Command("G1", {"X": pnt.x, "Y": pnt.y, "F": self.horizFeed})) # Rotate point data pnt = nxt @@ -1756,9 +1696,7 @@ class ObjectWaterline(PathOp.ObjectOp): # safePDC = self._planarGetPDC(safeSTL, depthparams[lenDP - 1], obj.SampleInterval.Value, self.cutter) buffer = self.cutter.getDiameter() * 10.0 - borderFace = Part.Face( - self._makeExtendedBoundBox(JOB.Stock.Shape.BoundBox, buffer, 0.0) - ) + borderFace = Part.Face(self._makeExtendedBoundBox(JOB.Stock.Shape.BoundBox, buffer, 0.0)) # Get correct boundbox if obj.BoundBox == "Stock": @@ -1772,9 +1710,7 @@ class ObjectWaterline(PathOp.ObjectOp): self.showDebugObject(trimFace, "TrimFace") # Cycle through layer depths - CUTAREAS = self._getCutAreas( - base.Shape, depthparams, bbFace, trimFace, borderFace - ) + CUTAREAS = self._getCutAreas(base.Shape, depthparams, bbFace, trimFace, borderFace) if not CUTAREAS: Path.Log.error("No cross-section cut areas identified.") return commands @@ -1807,12 +1743,8 @@ class ObjectWaterline(PathOp.ObjectOp): self.showDebugObject(activeArea, "ActiveArea_{}".format(caCnt)) ofstArea = PathUtils.getOffsetArea(activeArea, ofst, self.wpc) if not ofstArea: - data = FreeCAD.Units.Quantity( - csHght, FreeCAD.Units.Length - ).UserString - Path.Log.debug( - "No offset area returned for cut area depth at {}.".format(data) - ) + data = FreeCAD.Units.Quantity(csHght, FreeCAD.Units.Length).UserString + Path.Log.debug("No offset area returned for cut area depth at {}.".format(data)) cont = False if cont: @@ -1824,12 +1756,8 @@ class ObjectWaterline(PathOp.ObjectOp): self.showDebugObject(clearArea, "ClearArea_{}".format(caCnt)) else: cont = False - data = FreeCAD.Units.Quantity( - csHght, FreeCAD.Units.Length - ).UserString - Path.Log.error( - "Could not determine solid faces at {}.".format(data) - ) + data = FreeCAD.Units.Quantity(csHght, FreeCAD.Units.Length).UserString + Path.Log.error("Could not determine solid faces at {}.".format(data)) else: clearArea = activeArea @@ -1838,16 +1766,12 @@ class ObjectWaterline(PathOp.ObjectOp): Path.Log.debug("... Clearning area at {}.".format(data)) # Make waterline path for current CUTAREA depth (csHght) commands.extend(self._wiresToWaterlinePath(obj, clearArea, csHght)) - clearArea.translate( - FreeCAD.Vector(0.0, 0.0, 0.0 - clearArea.BoundBox.ZMin) - ) + clearArea.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - clearArea.BoundBox.ZMin)) lastClearArea = clearArea lastCsHght = csHght # Clear layer as needed - (clrLyr, clearLastLayer) = self._clearLayer( - obj, ca, lastCA, clearLastLayer - ) + (clrLyr, clearLastLayer) = self._clearLayer(obj, ca, lastCA, clearLastLayer) if clrLyr == "Offset": commands.extend(self._makeOffsetLayerPaths(obj, clearArea, csHght)) elif clrLyr: @@ -1855,22 +1779,16 @@ class ObjectWaterline(PathOp.ObjectOp): if clearLastLayer is False: cutPattern = obj.ClearLastLayer commands.extend( - self._makeCutPatternLayerPaths( - JOB, obj, clearArea, csHght, cutPattern - ) + self._makeCutPatternLayerPaths(JOB, obj, clearArea, csHght, cutPattern) ) # Efor if clearLastLayer and obj.ClearLastLayer != "Off": Path.Log.debug("... Clearning last layer") (clrLyr, cLL) = self._clearLayer(obj, 1, 1, False) - lastClearArea.translate( - FreeCAD.Vector(0.0, 0.0, 0.0 - lastClearArea.BoundBox.ZMin) - ) + lastClearArea.translate(FreeCAD.Vector(0.0, 0.0, 0.0 - lastClearArea.BoundBox.ZMin)) if clrLyr == "Offset": - commands.extend( - self._makeOffsetLayerPaths(obj, lastClearArea, lastCsHght) - ) + commands.extend(self._makeOffsetLayerPaths(obj, lastClearArea, lastCsHght)) elif clrLyr: commands.extend( self._makeCutPatternLayerPaths( @@ -1915,9 +1833,7 @@ class ObjectWaterline(PathOp.ObjectOp): allPrevComp ) # cut out higher layers to avoid cutting recessed areas allPrevComp = allPrevComp.fuse(compAdjFaces) - cutArea.translate( - FreeCAD.Vector(0.0, 0.0, csHght - cutArea.BoundBox.ZMin) - ) + cutArea.translate(FreeCAD.Vector(0.0, 0.0, csHght - cutArea.BoundBox.ZMin)) CUTAREAS.append(cutArea) isFirst = False else: @@ -1934,12 +1850,8 @@ class ObjectWaterline(PathOp.ObjectOp): commands = list() # Translate path geometry to layer height - ofstPlnrShp.translate( - FreeCAD.Vector(0.0, 0.0, csHght - ofstPlnrShp.BoundBox.ZMin) - ) - self.showDebugObject( - ofstPlnrShp, "WaterlinePathArea_{}".format(round(csHght, 2)) - ) + ofstPlnrShp.translate(FreeCAD.Vector(0.0, 0.0, csHght - ofstPlnrShp.BoundBox.ZMin)) + self.showDebugObject(ofstPlnrShp, "WaterlinePathArea_{}".format(round(csHght, 2))) commands.append(Path.Command("N (Cut Area {}.)".format(round(csHght, 2)))) start = 1 @@ -1957,9 +1869,7 @@ class ObjectWaterline(PathOp.ObjectOp): commands.append(Path.Command("N (Wire {}.)".format(w))) (cmds, endVect) = self._wireToPath(obj, wire, startVect) commands.extend(cmds) - commands.append( - Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid}) - ) + commands.append(Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid})) return commands @@ -1982,9 +1892,7 @@ class ObjectWaterline(PathOp.ObjectOp): if not pathGeom: Path.Log.warning("No path geometry generated.") return commands - pathGeom.translate( - FreeCAD.Vector(0.0, 0.0, csHght - pathGeom.BoundBox.ZMin) - ) + pathGeom.translate(FreeCAD.Vector(0.0, 0.0, csHght - pathGeom.BoundBox.ZMin)) self.showDebugObject(pathGeom, "PathGeom_{}".format(round(csHght, 2))) @@ -1993,14 +1901,10 @@ class ObjectWaterline(PathOp.ObjectOp): pntSet = PathSurfaceSupport.pathGeomToLinesPointSet(self, obj, pathGeom) elif cutPattern == "ZigZag": # pntSet = PathSurfaceSupport.pathGeomToZigzagPointSet(obj, pathGeom, self.CutClimb, self.toolDiam, self.closedGap, self.gaps) - pntSet = PathSurfaceSupport.pathGeomToZigzagPointSet( - self, obj, pathGeom - ) + pntSet = PathSurfaceSupport.pathGeomToZigzagPointSet(self, obj, pathGeom) elif cutPattern in ["Circular", "CircularZigZag"]: # pntSet = PathSurfaceSupport.pathGeomToCircularPointSet(obj, pathGeom, self.CutClimb, self.toolDiam, self.closedGap, self.gaps, self.tmpCOM) - pntSet = PathSurfaceSupport.pathGeomToCircularPointSet( - self, obj, pathGeom - ) + pntSet = PathSurfaceSupport.pathGeomToCircularPointSet(self, obj, pathGeom) elif cutPattern == "Spiral": pntSet = PathSurfaceSupport.pathGeomToSpiralPointSet(obj, pathGeom) @@ -2028,9 +1932,7 @@ class ObjectWaterline(PathOp.ObjectOp): if cnt == 0: ofst = 0.0 - self.cutOut cnt += 1 - Path.Log.debug( - " -Offset path count: {} at height: {}".format(cnt, round(csHght, 2)) - ) + Path.Log.debug(" -Offset path count: {} at height: {}".format(cnt, round(csHght, 2))) return cmds @@ -2049,9 +1951,7 @@ class ObjectWaterline(PathOp.ObjectOp): # Send cutter to x,y position of first point on first line first = stpOVRS[0][0][0] # [step][item][point] - GCODE.append( - Path.Command("G0", {"X": first.x, "Y": first.y, "F": self.horizRapid}) - ) + GCODE.append(Path.Command("G0", {"X": first.x, "Y": first.y, "F": self.horizRapid})) # Cycle through step-over sections (line segments or arcs) odd = True @@ -2074,9 +1974,7 @@ class ObjectWaterline(PathOp.ObjectOp): minTrnsHght = obj.SafeHeight.Value # cmds.append(Path.Command('N (Transition: last, first: {}, {}: minSTH: {})'.format(lstStpEnd, first, minTrnsHght), {})) cmds.extend( - self._stepTransitionCmds( - obj, cutPattern, lstStpEnd, first, minTrnsHght, tolrnc - ) + self._stepTransitionCmds(obj, cutPattern, lstStpEnd, first, minTrnsHght, tolrnc) ) # Cycle through current step-over parts @@ -2088,9 +1986,7 @@ class ObjectWaterline(PathOp.ObjectOp): # minSTH = self._getMinSafeTravelHeight(safePDC, last, nxtStart) # Check safe travel height against fullSTL minSTH = obj.SafeHeight.Value cmds.append(Path.Command("N (Break)", {})) - cmds.extend( - self._breakCmds(obj, cutPattern, last, nxtStart, minSTH, tolrnc) - ) + cmds.extend(self._breakCmds(obj, cutPattern, last, nxtStart, minSTH, tolrnc)) else: cmds.append(Path.Command("N (part {}.)".format(i + 1), {})) if cutPattern in ["Line", "ZigZag", "Spiral"]: @@ -2107,9 +2003,7 @@ class ObjectWaterline(PathOp.ObjectOp): ) ) cmds.append( - Path.Command( - "G1", {"X": last.x, "Y": last.y, "F": self.horizFeed} - ) + Path.Command("G1", {"X": last.x, "Y": last.y, "F": self.horizFeed}) ) elif cutPattern in ["Circular", "CircularZigZag"]: # isCircle = True if lenPRTS == 1 else False @@ -2127,9 +2021,7 @@ class ObjectWaterline(PathOp.ObjectOp): # Efor # Raise to safe height after clearing - GCODE.append( - Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid}) - ) + GCODE.append(Path.Command("G0", {"Z": obj.SafeHeight.Value, "F": self.vertRapid})) return GCODE @@ -2327,9 +2219,7 @@ class ObjectWaterline(PathOp.ObjectOp): ) ) cmds.append( - Path.Command( - "G1", {"X": endPnt.x, "Y": endPnt.y, "Z": endPnt.z, "F": self.horizFeed} - ) + Path.Command("G1", {"X": endPnt.x, "Y": endPnt.y, "Z": endPnt.z, "F": self.horizFeed}) ) return cmds diff --git a/src/Mod/CAM/Path/Post/Command.py b/src/Mod/CAM/Path/Post/Command.py index 2a0d2b6b65..9fa9be28c1 100644 --- a/src/Mod/CAM/Path/Post/Command.py +++ b/src/Mod/CAM/Path/Post/Command.py @@ -54,9 +54,7 @@ def _resolve_post_processor_name(job): elif Path.Preferences.defaultPostProcessor(): valid_name = Path.Preferences.defaultPostProcessor() elif FreeCAD.GuiUp: - valid_name = ( - DlgSelectPostProcessor().exec_() - ) # Ensure DlgSelectPostProcessor is defined + valid_name = DlgSelectPostProcessor().exec_() # Ensure DlgSelectPostProcessor is defined else: valid_name = None @@ -75,9 +73,7 @@ class DlgSelectPostProcessor: firstItem = None for post in Path.Preferences.allEnabledPostProcessors(): item = QtGui.QListWidgetItem(post) - item.setFlags( - QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsEnabled - ) + item.setFlags(QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsEnabled) self.dialog.lwPostProcessor.addItem(item) if not firstItem: firstItem = item @@ -137,7 +133,8 @@ class CommandPathPost: Path.Log.debug(filename) with open(filename, "w") as f: f.write(gcode) - else: return + else: + return elif policy == "Append Unique ID on conflict": while os.path.isfile(filename): @@ -158,7 +155,8 @@ class CommandPathPost: Path.Log.debug(filename) with open(filename, "w") as f: f.write(gcode) - else: return + else: + return else: with open(filename, "w") as f: f.write(gcode) @@ -185,9 +183,7 @@ class CommandPathPost: return # get a postprocessor - postprocessor = PostProcessorFactory.get_post_processor( - self.candidate, postprocessor_name - ) + postprocessor = PostProcessorFactory.get_post_processor(self.candidate, postprocessor_name) post_data = postprocessor.export() if not post_data: diff --git a/src/Mod/CAM/Path/Post/Processor.py b/src/Mod/CAM/Path/Post/Processor.py index ee68ab48ea..073315ba6c 100644 --- a/src/Mod/CAM/Path/Post/Processor.py +++ b/src/Mod/CAM/Path/Post/Processor.py @@ -147,8 +147,7 @@ class PostProcessor: c2 = Path.Command( "G0 Z" + str( - job.Stock.Shape.BoundBox.ZMax - + job.SetupSheet.ClearanceHeightOffset.Value + job.Stock.Shape.BoundBox.ZMax + job.SetupSheet.ClearanceHeightOffset.Value ) ) fobj.Path.addCommands(c2) @@ -278,9 +277,7 @@ class PostProcessor: return postlist Path.Log.track() - finalpostlist = [ - ("allitems", [item for slist in postlist for item in slist[1]]) - ] + finalpostlist = [("allitems", [item for slist in postlist for item in slist[1]])] Path.Log.debug(f"Postlist: {postlist}") return finalpostlist @@ -289,9 +286,7 @@ class WrapperPost(PostProcessor): """Wrapper class for old post processors that are scripts.""" def __init__(self, job, script_path, *args, **kwargs): - super().__init__( - job, tooltip=None, tooltipargs=None, units=None, *args, **kwargs - ) + super().__init__(job, tooltip=None, tooltipargs=None, units=None, *args, **kwargs) self.script_path = script_path Path.Log.debug(f"WrapperPost.__init__({script_path})") self.load_script() @@ -299,9 +294,7 @@ class WrapperPost(PostProcessor): def load_script(self): # Dynamically load the script as a module try: - spec = importlib.util.spec_from_file_location( - "script_module", self.script_path - ) + spec = importlib.util.spec_from_file_location("script_module", self.script_path) self.script_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(self.script_module) except Exception as e: @@ -311,9 +304,7 @@ class WrapperPost(PostProcessor): raise AttributeError("The script does not have an 'export' function.") # Set properties based on attributes of the module - self._units = ( - "Metric" if getattr(self.script_module, "UNITS", "G21") == "G21" else "Inch" - ) + self._units = "Metric" if getattr(self.script_module, "UNITS", "G21") == "G21" else "Inch" self._tooltip = getattr(self.script_module, "TOOLTIP", "No tooltip provided") self._tooltipargs = getattr(self.script_module, "TOOLTIP_ARGS", []) diff --git a/src/Mod/CAM/Path/Post/Utils.py b/src/Mod/CAM/Path/Post/Utils.py index f7c4cb7d7a..bd6740fac8 100644 --- a/src/Mod/CAM/Path/Post/Utils.py +++ b/src/Mod/CAM/Path/Post/Utils.py @@ -70,9 +70,7 @@ class FilenameGenerator: validFilenameSubstitutions = ["j", "d", "T", "t", "W", "O", "S"] if self.job.PostProcessorOutputFile: - candidateOutputPath, candidateFilename = os.path.split( - self.job.PostProcessorOutputFile - ) + candidateOutputPath, candidateFilename = os.path.split(self.job.PostProcessorOutputFile) if candidateOutputPath: outputpath = candidateOutputPath @@ -91,7 +89,9 @@ class FilenameGenerator: outputpath, _ = os.path.split(FreeCAD.ActiveDocument.getFileName()) if not outputpath: - outputpath = os.getcwd() ## TODO: This should be avoided as it gives the Freecad executable's path in some systems (e.g. Windows) + outputpath = ( + os.getcwd() + ) ## TODO: This should be avoided as it gives the Freecad executable's path in some systems (e.g. Windows) if not ext: ext = ".nc" @@ -102,8 +102,7 @@ class FilenameGenerator: if match not in validPathSubstitutions: outputpath = outputpath.replace(f"%{match}", "") FreeCAD.Console.PrintWarning( - "Invalid substitution strings will be ignored in output path: %s\n" - % match + "Invalid substitution strings will be ignored in output path: %s\n" % match ) for match in re.findall("%(.)", filename): @@ -111,8 +110,7 @@ class FilenameGenerator: if match not in validFilenameSubstitutions: filename = filename.replace(f"%{match}", "") FreeCAD.Console.PrintWarning( - "Invalid substitution strings will be ignored in file path: %s\n" - % match + "Invalid substitution strings will be ignored in file path: %s\n" % match ) Path.Log.debug(f"outputpath: {outputpath} filename: {filename} ext: {ext}") @@ -166,9 +164,7 @@ class FilenameGenerator: subpart = f"-{self.subpartname}" if self.subpartname else "" sequence = ( - f"-{self.sequencenumber}" - if not explicit_sequence and self.sequencenumber - else "" + f"-{self.sequencenumber}" if not explicit_sequence and self.sequencenumber else "" ) filename = f"{temp_filename}{subpart}{sequence}{self.extension}" full_path = os.path.join(self.qualified_path, filename) @@ -188,16 +184,13 @@ class GCodeHighlighter(QtGui.QSyntaxHighlighter): keywordPatterns = ["\\bG[0-9]+\\b", "\\bM[0-9]+\\b"] self.highlightingRules = [ - (QtCore.QRegularExpression(pattern), keywordFormat) - for pattern in keywordPatterns + (QtCore.QRegularExpression(pattern), keywordFormat) for pattern in keywordPatterns ] speedFormat = QtGui.QTextCharFormat() speedFormat.setFontWeight(QtGui.QFont.Bold) speedFormat.setForeground(QtCore.Qt.green) - self.highlightingRules.append( - (QtCore.QRegularExpression("\\bF[0-9\\.]+\\b"), speedFormat) - ) + self.highlightingRules.append((QtCore.QRegularExpression("\\bF[0-9\\.]+\\b"), speedFormat)) def highlightBlock(self, text): for pattern, hlFormat in self.highlightingRules: @@ -316,9 +309,7 @@ def editor(gcode): FreeCAD.Console.PrintMessage( translate( "Path", - "GCode size too big ({} o), disabling syntax highlighter.".format( - gcodeSize - ), + "GCode size too big ({} o), disabling syntax highlighter.".format(gcodeSize), ) ) result = dia.exec_() diff --git a/src/Mod/CAM/Path/Post/UtilsArguments.py b/src/Mod/CAM/Path/Post/UtilsArguments.py index 12633f471d..3952b9d187 100644 --- a/src/Mod/CAM/Path/Post/UtilsArguments.py +++ b/src/Mod/CAM/Path/Post/UtilsArguments.py @@ -316,9 +316,7 @@ def init_shared_arguments( help_message = "Time to wait (in seconds) after M3, M4 (default = 0.0)" else: help_message = argparse.SUPPRESS - shared.add_argument( - "--wait-for-spindle", type=float, default=0.0, help=help_message - ) + shared.add_argument("--wait-for-spindle", type=float, default=0.0, help=help_message) return parser @@ -706,9 +704,7 @@ def process_shared_arguments( values["RETURN_TO"] = [int(v) for v in args.return_to.split(",")] if len(values["RETURN_TO"]) != 3: values["RETURN_TO"] = None - print( - "--return-to coordinates must be specified as ,,, ignoring" - ) + print("--return-to coordinates must be specified as ,,, ignoring") if args.show_editor: values["SHOW_EDITOR"] = True if args.no_show_editor: diff --git a/src/Mod/CAM/Path/Post/UtilsExport.py b/src/Mod/CAM/Path/Post/UtilsExport.py index ac753130ac..a9529c80b1 100644 --- a/src/Mod/CAM/Path/Post/UtilsExport.py +++ b/src/Mod/CAM/Path/Post/UtilsExport.py @@ -52,11 +52,7 @@ def check_canned_cycles(values: Values) -> None: def determine_coolant_mode(obj) -> str: """Determine the coolant mode.""" - if ( - hasattr(obj, "CoolantMode") - or hasattr(obj, "Base") - and hasattr(obj.Base, "CoolantMode") - ): + if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): if hasattr(obj, "CoolantMode"): return obj.CoolantMode return obj.Base.CoolantMode @@ -70,9 +66,7 @@ def output_coolant_off(values: Values, gcode: Gcode, coolant_mode: str) -> None: if values["ENABLE_COOLANT"] and coolant_mode != "None": if values["OUTPUT_COMMENTS"]: - comment = PostUtilsParse.create_comment( - values, f"Coolant Off: {coolant_mode}" - ) + comment = PostUtilsParse.create_comment(values, f"Coolant Off: {coolant_mode}") gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}{nl}") gcode.append(f"{PostUtilsParse.linenumber(values)}M9{nl}") @@ -84,9 +78,7 @@ def output_coolant_on(values: Values, gcode: Gcode, coolant_mode: str) -> None: if values["ENABLE_COOLANT"]: if values["OUTPUT_COMMENTS"] and coolant_mode != "None": - comment = PostUtilsParse.create_comment( - values, f"Coolant On: {coolant_mode}" - ) + comment = PostUtilsParse.create_comment(values, f"Coolant On: {coolant_mode}") gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}{nl}") if coolant_mode == "Flood": gcode.append(f"{PostUtilsParse.linenumber(values)}M8{nl}") @@ -128,9 +120,7 @@ def output_header(values: Values, gcode: Gcode) -> None: cam_file = "" comment = PostUtilsParse.create_comment(values, f"Cam File: {cam_file}") gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}{nl}") - comment = PostUtilsParse.create_comment( - values, f"Output Time: {str(datetime.datetime.now())}" - ) + comment = PostUtilsParse.create_comment(values, f"Output Time: {str(datetime.datetime.now())}") gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}{nl}") @@ -201,9 +191,7 @@ def output_preop(values: Values, gcode: Gcode, obj) -> None: if values["OUTPUT_COMMENTS"]: if values["SHOW_OPERATION_LABELS"]: - comment = PostUtilsParse.create_comment( - values, f"Begin operation: {obj.Label}" - ) + comment = PostUtilsParse.create_comment(values, f"Begin operation: {obj.Label}") else: comment = PostUtilsParse.create_comment(values, "Begin operation") gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}{nl}") @@ -270,12 +258,8 @@ def output_tool_list(values: Values, gcode: Gcode, objectslist) -> None: if values["OUTPUT_COMMENTS"] and values["LIST_TOOLS_IN_PREAMBLE"]: for item in objectslist: - if hasattr(item, "Proxy") and isinstance( - item.Proxy, PathToolController.ToolController - ): - comment = PostUtilsParse.create_comment( - values, f"T{item.ToolNumber}={item.Name}" - ) + if hasattr(item, "Proxy") and isinstance(item.Proxy, PathToolController.ToolController): + comment = PostUtilsParse.create_comment(values, f"T{item.ToolNumber}={item.Name}") gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}{nl}") diff --git a/src/Mod/CAM/Path/Post/UtilsParse.py b/src/Mod/CAM/Path/Post/UtilsParse.py index b267874e75..5a7518ebb1 100644 --- a/src/Mod/CAM/Path/Post/UtilsParse.py +++ b/src/Mod/CAM/Path/Post/UtilsParse.py @@ -78,10 +78,7 @@ def check_for_drill_translate( comment: str nl: str = "\n" - if ( - values["TRANSLATE_DRILL_CYCLES"] - and command in values["DRILL_CYCLES_TO_TRANSLATE"] - ): + if values["TRANSLATE_DRILL_CYCLES"] and command in values["DRILL_CYCLES_TO_TRANSLATE"]: if values["OUTPUT_COMMENTS"]: # Comment the original command comment = create_comment( values, @@ -111,9 +108,7 @@ def check_for_drill_translate( return False -def check_for_machine_specific_commands( - values: Values, gcode: Gcode, command: str -) -> None: +def check_for_machine_specific_commands(values: Values, gcode: Gcode, command: str) -> None: """Check for comments containing machine-specific commands.""" m: object nl: str = "\n" @@ -162,9 +157,7 @@ def check_for_suppressed_commands( return False -def check_for_tlo( - values: Values, gcode: Gcode, command: str, params: PathParameters -) -> None: +def check_for_tlo(values: Values, gcode: Gcode, command: str, params: PathParameters) -> None: """Output a tool length command if USE_TLO is True.""" nl: str = "\n" @@ -356,9 +349,7 @@ def determine_adaptive_op(values: Values, pathobj) -> Tuple[bool, float, float]: if hasattr(tc, "VertRapid") and tc.VertRapid > 0: opVertRapid = Units.Quantity(tc.VertRapid, Units.Velocity) else: - FreeCAD.Console.PrintWarning( - f"Tool Controller Vertical Rapid Values are unset{nl}" - ) + FreeCAD.Console.PrintWarning(f"Tool Controller Vertical Rapid Values are unset{nl}") return (adaptiveOp, opHorizRapid, opVertRapid) @@ -428,9 +419,7 @@ def drill_translate( if motion_z > retract_z: # NIST GCODE 3.5.16.1 Preliminary and In-Between Motion says G0 to retract_z # Here use G1 since retract height may be below surface ! - cmd = format_command_line( - values, ["G1", f"Z{format_for_axis(values, retract_z)}"] - ) + cmd = format_command_line(values, ["G1", f"Z{format_for_axis(values, retract_z)}"]) gcode.append(f"{linenumber(values)}{cmd}{F_feedrate}") # drill moves @@ -512,9 +501,7 @@ def init_parameter_functions(parameter_functions: Dict[str, ParameterFunction]) "Z": default_axis_parameter, # "$" is used by LinuxCNC (and others?) to designate which spindle } - for ( - parameter - ) in default_parameter_functions: # pylint: disable=consider-using-dict-items + for parameter in default_parameter_functions: # pylint: disable=consider-using-dict-items parameter_functions[parameter] = default_parameter_functions[parameter] @@ -587,9 +574,7 @@ def output_G73_G83_drill_moves( gcode.append(f"{linenumber(values)}{G0_retract_z}") last_stop_z = next_stop_z else: - cmd = format_command_line( - values, ["G1", f"Z{format_for_axis(values, drill_z)}"] - ) + cmd = format_command_line(values, ["G1", f"Z{format_for_axis(values, drill_z)}"]) gcode.append(f"{linenumber(values)}{cmd}{F_feedrate}") gcode.append(f"{linenumber(values)}{G0_retract_z}") break @@ -652,9 +637,7 @@ def parse_a_path(values: Values, gcode: Gcode, pathobj) -> None: parameter: str parameter_value: str - current_location.update( - Path.Command("G0", {"X": -1, "Y": -1, "Z": -1, "F": 0.0}).Parameters - ) + current_location.update(Path.Command("G0", {"X": -1, "Y": -1, "Z": -1, "F": 0.0}).Parameters) adaptive_op_variables = determine_adaptive_op(values, pathobj) for c in pathobj.Path.Commands: @@ -667,9 +650,7 @@ def parse_a_path(values: Values, gcode: Gcode, pathobj) -> None: continue if values["COMMENT_SYMBOL"] != "(" and len(command) > 2: command = create_comment(values, command[1:-1]) - cmd = check_for_an_adaptive_op( - values, command, command_line, adaptive_op_variables - ) + cmd = check_for_an_adaptive_op(values, command, command_line, adaptive_op_variables) if cmd: command = cmd # Add the command name to the command line @@ -691,9 +672,7 @@ def parse_a_path(values: Values, gcode: Gcode, pathobj) -> None: if parameter_value: command_line.append(f"{parameter}{parameter_value}") - set_adaptive_op_speed( - values, command, command_line, c.Parameters, adaptive_op_variables - ) + set_adaptive_op_speed(values, command, command_line, c.Parameters, adaptive_op_variables) # Remember the current command lastcommand = command # Remember the current location @@ -724,9 +703,7 @@ def parse_a_path(values: Values, gcode: Gcode, pathobj) -> None: command_line = [] # Add a line number to the front and a newline to the end of the command line if command_line: - gcode += ( - f"{linenumber(values)}{format_command_line(values, command_line)}{nl}" - ) + gcode += f"{linenumber(values)}{format_command_line(values, command_line)}{nl}" check_for_tlo(values, gcode, command, c.Parameters) check_for_machine_specific_commands(values, gcode, command) diff --git a/src/Mod/CAM/Path/Post/scripts/KineticNCBeamicon2_post.py b/src/Mod/CAM/Path/Post/scripts/KineticNCBeamicon2_post.py index ec721a6716..5a3378ec6e 100644 --- a/src/Mod/CAM/Path/Post/scripts/KineticNCBeamicon2_post.py +++ b/src/Mod/CAM/Path/Post/scripts/KineticNCBeamicon2_post.py @@ -58,20 +58,14 @@ now = datetime.datetime.now() parser = argparse.ArgumentParser(prog="linuxcnc", add_help=False) parser.add_argument("--no-header", action="store_true", help="suppress header output") -parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" -) -parser.add_argument( - "--line-numbers", action="store_true", help="prefix with line numbers" -) +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") parser.add_argument( "--no-show-editor", action="store_true", help="don't pop up editor before writing output", ) -parser.add_argument( - "--precision", default="3", help="number of digits of precision, default=3" -) +parser.add_argument("--precision", default="3", help="number of digits of precision, default=3") parser.add_argument( "--preamble", help='set commands to be issued before the first command, default="G17\nG90"', @@ -88,9 +82,7 @@ parser.add_argument( action="store_true", help="Output the Same G-command Name USE NonModal Mode", ) -parser.add_argument( - "--axis-modal", action="store_true", help="Output the Same Axis Value Mode" -) +parser.add_argument("--axis-modal", action="store_true", help="Output the Same Axis Value Mode") TOOLTIP_ARGS = parser.format_help() @@ -100,9 +92,7 @@ OUTPUT_HEADER = True OUTPUT_LINE_NUMBERS = False SHOW_EDITOR = True MODAL = False # if true commands are suppressed if the same as previous line. -OUTPUT_DOUBLES = ( - True # if false duplicate axis values are suppressed if the same as previous line. -) +OUTPUT_DOUBLES = True # if false duplicate axis values are suppressed if the same as previous line. COMMAND_SPACE = " " LINENR = 100 # line number starting value @@ -139,8 +129,6 @@ TOOL_CHANGE = """M05 M09""" - - def processArguments(argstring): global OUTPUT_HEADER global OUTPUT_COMMENTS @@ -198,9 +186,7 @@ def export(objectslist, filename, argstring): for obj in objectslist: if not hasattr(obj, "Path"): print( - "the object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "the object " + obj.Name + " is not a path. Please select only path and Compounds." ) return None @@ -368,9 +354,7 @@ def parse(pathobj): "G0", "G00", ]: # linuxcnc doesn't use rapid speeds - speed = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + speed = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) if speed.getValueAs(UNIT_SPEED_FORMAT) > 0.0: outstring.append( param @@ -397,14 +381,9 @@ def parse(pathobj): ): continue else: - pos = Units.Quantity( - c.Parameters[param], FreeCAD.Units.Length - ) + pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outstring.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) # store the latest command diff --git a/src/Mod/CAM/Path/Post/scripts/centroid_post.py b/src/Mod/CAM/Path/Post/scripts/centroid_post.py index a22f663500..9047c8f22f 100644 --- a/src/Mod/CAM/Path/Post/scripts/centroid_post.py +++ b/src/Mod/CAM/Path/Post/scripts/centroid_post.py @@ -127,9 +127,6 @@ POST_OPERATION = """""" TOOL_CHANGE = """""" - - - def processArguments(argstring): global OUTPUT_HEADER global OUTPUT_COMMENTS @@ -303,9 +300,7 @@ def parse(pathobj): "G0", "G00", ]: # centroid doesn't use rapid speeds - speed = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + speed = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) commandlist.append( param + format( @@ -317,8 +312,7 @@ def parse(pathobj): commandlist.append(param + str(int(c.Parameters["H"]))) elif param == "S": commandlist.append( - param - + PostUtils.fmt(c.Parameters["S"], SPINDLE_DECIMALS, "G21") + param + PostUtils.fmt(c.Parameters["S"], SPINDLE_DECIMALS, "G21") ) elif param == "T": commandlist.append(param + str(int(c.Parameters["T"]))) diff --git a/src/Mod/CAM/Path/Post/scripts/comparams_post.py b/src/Mod/CAM/Path/Post/scripts/comparams_post.py index 95d78cbfea..64b646fbb5 100644 --- a/src/Mod/CAM/Path/Post/scripts/comparams_post.py +++ b/src/Mod/CAM/Path/Post/scripts/comparams_post.py @@ -25,7 +25,9 @@ import Path import Path.Post.Utils as PostUtils import PathScripts.PathUtils as PathUtils -TOOLTIP = """Example Post, using Path.Commands instead of Path.toGCode strings for Path G-code output.""" +TOOLTIP = ( + """Example Post, using Path.Commands instead of Path.toGCode strings for Path G-code output.""" +) SHOW_EDITOR = True diff --git a/src/Mod/CAM/Path/Post/scripts/dumper_post.py b/src/Mod/CAM/Path/Post/scripts/dumper_post.py index 4f4209ce31..d42012ec77 100644 --- a/src/Mod/CAM/Path/Post/scripts/dumper_post.py +++ b/src/Mod/CAM/Path/Post/scripts/dumper_post.py @@ -37,8 +37,6 @@ now = datetime.datetime.now() SHOW_EDITOR = True - - def export(objectslist, filename, argstring): "called when freecad exports a list of objects" @@ -54,9 +52,7 @@ def export(objectslist, filename, argstring): if not hasattr(obj, "Path"): print( - "the object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "the object " + obj.Name + " is not a path. Please select only path and Compounds." ) return print("postprocessing...") @@ -87,9 +83,7 @@ def parse(pathobj): return out else: # parsing simple path - if not hasattr( - pathobj, "Path" - ): # groups might contain non-path things like stock. + if not hasattr(pathobj, "Path"): # groups might contain non-path things like stock. return out out += "(Path: " + pathobj.Label + ")\n" diff --git a/src/Mod/CAM/Path/Post/scripts/dxf_post.py b/src/Mod/CAM/Path/Post/scripts/dxf_post.py index 24d3b8cae9..cd24dc4dc8 100644 --- a/src/Mod/CAM/Path/Post/scripts/dxf_post.py +++ b/src/Mod/CAM/Path/Post/scripts/dxf_post.py @@ -59,9 +59,6 @@ else: Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) - - - def processArguments(argstring): pass # global OUTPUT_HEADER diff --git a/src/Mod/CAM/Path/Post/scripts/dynapath_4060_post.py b/src/Mod/CAM/Path/Post/scripts/dynapath_4060_post.py index 17b7fb8805..781135bae6 100644 --- a/src/Mod/CAM/Path/Post/scripts/dynapath_4060_post.py +++ b/src/Mod/CAM/Path/Post/scripts/dynapath_4060_post.py @@ -49,20 +49,14 @@ delta_4060_post.export(object,"/path/to/file.ncc","") parser = argparse.ArgumentParser(prog="delta_4060", add_help=False) parser.add_argument("--no-header", action="store_true", help="suppress header output") -parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" -) -parser.add_argument( - "--line-numbers", action="store_true", help="prefix with line numbers" -) +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") parser.add_argument( "--no-show-editor", action="store_true", help="don't pop up editor before writing output", ) -parser.add_argument( - "--precision", default="3", help="number of digits of precision, default=3" -) +parser.add_argument("--precision", default="3", help="number of digits of precision, default=3") parser.add_argument( "--preamble", help='set commands to be issued before the first command, default="G17\nG90\nG80\nG40"', @@ -95,9 +89,7 @@ OUTPUT_HEADER = True OUTPUT_LINE_NUMBERS = False SHOW_EDITOR = True MODAL = False # if true commands are suppressed if the same as previous line. -OUTPUT_DOUBLES = ( - True # if false duplicate axis values are suppressed if the same as previous line. -) +OUTPUT_DOUBLES = True # if false duplicate axis values are suppressed if the same as previous line. COMMAND_SPACE = "" LINENR = 0 # Line number starting value. DWELL_TIME = 1 # Number of seconds to allow spindle to come up to speed. @@ -153,8 +145,6 @@ M30 clearanceHeight = None - - def processArguments(argstring): global OUTPUT_HEADER global OUTPUT_COMMENTS @@ -215,9 +205,7 @@ def export(objectslist, filename, argstring): for obj in objectslist: if not hasattr(obj, "Path"): print( - "the object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "the object " + obj.Name + " is not a path. Please select only path and Compounds." ) return None @@ -259,12 +247,7 @@ def export(objectslist, filename, argstring): # do the pre_op. Inserts "(T)" in comment to signify textfield. if OUTPUT_COMMENTS: - gcode += ( - linenumber() - + "(T)" - + str.upper("begin operation: " + obj.Label) - + "$\n" - ) + gcode += linenumber() + "(T)" + str.upper("begin operation: " + obj.Label) + "$\n" gcode += ( linenumber() + "(T)" @@ -275,11 +258,7 @@ def export(objectslist, filename, argstring): # get coolant mode coolantMode = "None" - if ( - hasattr(obj, "CoolantMode") - or hasattr(obj, "Base") - and hasattr(obj.Base, "CoolantMode") - ): + if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): if hasattr(obj, "CoolantMode"): coolantMode = obj.CoolantMode else: @@ -288,12 +267,7 @@ def export(objectslist, filename, argstring): # turn coolant on if required if OUTPUT_COMMENTS: if not coolantMode == "None": - gcode += ( - linenumber() - + "(T)" - + str.upper("Coolant On:" + coolantMode) - + "$\n" - ) + gcode += linenumber() + "(T)" + str.upper("Coolant On:" + coolantMode) + "$\n" if coolantMode == "Flood": gcode += linenumber() + "M8" + "\n" if coolantMode == "Mist": @@ -304,22 +278,12 @@ def export(objectslist, filename, argstring): # do the post_op if OUTPUT_COMMENTS: - gcode += ( - linenumber() - + "(T)" - + str.upper("finish operation: " + obj.Label) - + "$\n" - ) + gcode += linenumber() + "(T)" + str.upper("finish operation: " + obj.Label) + "$\n" # turn coolant off if required if not coolantMode == "None": if OUTPUT_COMMENTS: - gcode += ( - linenumber() - + "(T)" - + str.upper("Coolant Off:" + coolantMode) - + "$\n" - ) + gcode += linenumber() + "(T)" + str.upper("Coolant Off:" + coolantMode) + "$\n" gcode += linenumber() + "M9" + "\n" # do the post_amble @@ -408,9 +372,7 @@ def parse(pathobj): if hasattr(pathobj, "Group"): # We have a compound or project. if OUTPUT_COMMENTS: - out += ( - linenumber() + "(T)" + str.upper("compound: " + pathobj.Label) + "$\n" - ) + out += linenumber() + "(T)" + str.upper("compound: " + pathobj.Label) + "$\n" for p in pathobj.Group: out += parse(p) return out @@ -448,9 +410,7 @@ def parse(pathobj): if param == "F" and ( currLocation[param] != c.Parameters[param] or OUTPUT_DOUBLES ): - speed = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + speed = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) if speed.getValueAs(UNIT_SPEED_FORMAT) > 0.0: outstring.append( param @@ -463,8 +423,7 @@ def parse(pathobj): # This fixes an error thrown by Dynapath due to missing and # required XYZ move after Tool change. elif param == "Z" and ( - c.Parameters["Z"] == clearanceHeight - and c.Parameters["Z"] != lastZ + c.Parameters["Z"] == clearanceHeight and c.Parameters["Z"] != lastZ ): x = 0 y = 0 @@ -475,24 +434,16 @@ def parse(pathobj): + "Y" + PostUtils.fmt(y, PRECISION, UNITS), ) - outstring.append( - param + PostUtils.fmt(c.Parameters["Z"], PRECISION, UNITS) - ) + outstring.append(param + PostUtils.fmt(c.Parameters["Z"], PRECISION, UNITS)) elif param == "X" and (command in QCYCLE_RANGE): pos = Units.Quantity(c.Parameters["X"], FreeCAD.Units.Length) outstring.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) elif param == "Y" and (command in QCYCLE_RANGE): pos = Units.Quantity(c.Parameters["Y"], FreeCAD.Units.Length) outstring.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) # Remove X and Y between QCYCLE's since we already included them. # This is needed to prevent Path of inserting additional XY codes between @@ -534,32 +485,21 @@ def parse(pathobj): elif param == "Q": pos = Units.Quantity(c.Parameters["Q"], FreeCAD.Units.Length) outstring.append( - "K" - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + "K" + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) # Following inserts a 2nd reference plane in all canned cycles (dynapath). # This provides the ability to manually go in and bump up the "O" offset in # order to avoid obstacles. The "O" overrides "R", so set them both equal if you # don't need the 2nd reference plane. elif (param == "R") and ((command in QCYCLE_RANGE)): - pos = Units.Quantity( - pathobj.ClearanceHeight.Value, FreeCAD.Units.Length - ) + pos = Units.Quantity(pathobj.ClearanceHeight.Value, FreeCAD.Units.Length) outstring.insert( 6, - "O" - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ), + "O" + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string), ) # Insert "O" param for 2nd reference plane (Clearance Height) pos = Units.Quantity(c.Parameters["R"], FreeCAD.Units.Length) outstring.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) # First Reference plan (Safe Height) elif param == "P": outstring.append( @@ -573,14 +513,9 @@ def parse(pathobj): ): continue else: - pos = Units.Quantity( - c.Parameters[param], FreeCAD.Units.Length - ) + pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outstring.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) # save the last X, Y values if "X" in c.Parameters: diff --git a/src/Mod/CAM/Path/Post/scripts/dynapath_post.py b/src/Mod/CAM/Path/Post/scripts/dynapath_post.py index af1ae96f62..2e801c5723 100644 --- a/src/Mod/CAM/Path/Post/scripts/dynapath_post.py +++ b/src/Mod/CAM/Path/Post/scripts/dynapath_post.py @@ -76,20 +76,14 @@ dynapath_post.export(object,"/path/to/file.ncc","") parser = argparse.ArgumentParser(prog="dynapath_post", add_help=False) parser.add_argument("--no-header", action="store_true", help="suppress header output") -parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" -) -parser.add_argument( - "--line-numbers", action="store_true", help="prefix with line numbers" -) +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") parser.add_argument( "--no-show-editor", action="store_true", help="don't pop up editor before writing output", ) -parser.add_argument( - "--precision", default="3", help="number of digits of precision, default=3" -) +parser.add_argument("--precision", default="3", help="number of digits of precision, default=3") parser.add_argument( "--preamble", help='set commands to be issued before the first command, default="G17\nG90\nG80\nG40"', @@ -154,9 +148,6 @@ POST_OPERATION = """""" TOOL_CHANGE = """""" - - - def processArguments(argstring): global OUTPUT_HEADER global OUTPUT_COMMENTS @@ -210,9 +201,7 @@ def export(objectslist, filename, argstring): for obj in objectslist: if not hasattr(obj, "Path"): print( - "the object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "the object " + obj.Name + " is not a path. Please select only path and Compounds." ) return @@ -317,9 +306,7 @@ def parse(pathobj): return out else: # parsing simple path - if not hasattr( - pathobj, "Path" - ): # groups might contain non-path things like stock. + if not hasattr(pathobj, "Path"): # groups might contain non-path things like stock. return out if OUTPUT_COMMENTS: @@ -338,9 +325,7 @@ def parse(pathobj): for param in params: if param in c.Parameters: if param == "F": - speed = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + speed = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) if speed.getValueAs(UNIT_SPEED_FORMAT) > 0.0: outstring.append( param @@ -350,20 +335,13 @@ def parse(pathobj): ) ) elif param == "S": - outstring.append( - param + format(c.Parameters[param], precision_string) - ) + outstring.append(param + format(c.Parameters[param], precision_string)) elif param == "T": - outstring.append( - param + format(c.Parameters["T"], precision_string) - ) + outstring.append(param + format(c.Parameters["T"], precision_string)) else: pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outstring.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) # store the latest command diff --git a/src/Mod/CAM/Path/Post/scripts/estlcam_post.py b/src/Mod/CAM/Path/Post/scripts/estlcam_post.py index 5a5339891d..de508aaa16 100644 --- a/src/Mod/CAM/Path/Post/scripts/estlcam_post.py +++ b/src/Mod/CAM/Path/Post/scripts/estlcam_post.py @@ -61,7 +61,7 @@ OUTPUT_HEADER = True # default output header in output gCode file OUTPUT_LINE_NUMBERS = False # default doesn't output line numbers in output gCode file OUTPUT_TOOL_CHANGE = True # default output tool change -TOOL_CHANGE_USE_ALTCMD = False # default doesn't use alternative command for tool change +TOOL_CHANGE_USE_ALTCMD = False # default doesn't use alternative command for tool change SHOW_EDITOR = True # default show the resulting file dialog output in GUI PRECISION = 3 # Default precision for metric @@ -83,14 +83,18 @@ POSTAMBLE = """M5 LINENR = 100 # line number starting value LINEINCR = 10 # line number increment -DRILL_RETRACT_MODE = "G98" # Default value of drill retractations (CURRENT_Z) other possible value is G99 +DRILL_RETRACT_MODE = ( + "G98" # Default value of drill retractations (CURRENT_Z) other possible value is G99 +) MOTION_MODE = "G90" # only G90 for absolute moves UNITS = "G21" # G21 for metric, G20 for us standard UNIT_FORMAT = "mm" UNIT_SPEED_FORMAT = "mm/min" -TOOL_CHANGE_ALTERNATIVE_CMD = "M0" # alternative Tool Change command, only if TOOL_CHANGE_USE_ALTCMD is true +TOOL_CHANGE_ALTERNATIVE_CMD = ( + "M0" # alternative Tool Change command, only if TOOL_CHANGE_USE_ALTCMD is true +) TOOL_CHANGE = """M5 """ # Tool Change commands will be inserted before a tool change @@ -100,13 +104,9 @@ TOOL_CHANGE = """M5 # Parser arguments list & definition parser = argparse.ArgumentParser(prog="estlcam", add_help=False) -parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" -) +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") parser.add_argument("--no-header", action="store_true", help="suppress header output") -parser.add_argument( - "--line-numbers", action="store_true", help="prefix with line numbers" -) +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") parser.add_argument( "--no-show-editor", action="store_true", @@ -114,21 +114,15 @@ parser.add_argument( ) parser.add_argument( "--preamble", - help='set commands to be issued before the first command', + help="set commands to be issued before the first command", ) parser.add_argument( "--postamble", - help='set commands to be issued after the last command', -) -parser.add_argument( - "--precision", default="3", help="number of digits of precision, default=3" -) -parser.add_argument( - "--inches", action="store_true", help="convert output for US imperial mode" -) -parser.add_argument( - "--no-tool-change", action="store_true", help="comment out tool changes" + help="set commands to be issued after the last command", ) +parser.add_argument("--precision", default="3", help="number of digits of precision, default=3") +parser.add_argument("--inches", action="store_true", help="convert output for US imperial mode") +parser.add_argument("--no-tool-change", action="store_true", help="comment out tool changes") parser.add_argument( "--tool-change-use-altcmd", action="store_true", help="use alternative command for tool change" ) @@ -157,6 +151,7 @@ CURRENT_X = 0 CURRENT_Y = 0 CURRENT_Z = 0 + def processArguments(argstring): global OUTPUT_HEADER @@ -259,9 +254,7 @@ def export(objectslist, filename, argstring): # print("*"*70 + "\n") if not hasattr(obj, "Path"): print( - "The object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "The object " + obj.Name + " is not a path. Please select only path and Compounds." ) return @@ -281,11 +274,7 @@ def export(objectslist, filename, argstring): # get coolant mode coolantMode = "None" - if ( - hasattr(obj, "CoolantMode") - or hasattr(obj, "Base") - and hasattr(obj.Base, "CoolantMode") - ): + if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): if hasattr(obj, "CoolantMode"): coolantMode = obj.CoolantMode else: @@ -318,7 +307,6 @@ def export(objectslist, filename, argstring): if coolantMode == "Mist": gcode += linenumber() + "M11" + "\n" - # do the post_amble if OUTPUT_COMMENTS: gcode += linenumber() + "(Begin postamble)\n" @@ -406,9 +394,7 @@ def parse(pathobj): return out else: # parsing simple path - if not hasattr( - pathobj, "Path" - ): # groups might contain non-path things like stock. + if not hasattr(pathobj, "Path"): # groups might contain non-path things like stock. return out if OUTPUT_COMMENTS: @@ -425,9 +411,7 @@ def parse(pathobj): if param in c.Parameters: if param == "F": if command not in RAPID_MOVES: - speed = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + speed = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) if speed.getValueAs(UNIT_SPEED_FORMAT) > 0.0: outstring.append( param @@ -441,16 +425,11 @@ def parse(pathobj): elif param in ["D", "P", "L"]: outstring.append(param + str(c.Parameters[param])) elif param in ["A", "B", "C"]: - outstring.append( - param + format(c.Parameters[param], precision_string) - ) + outstring.append(param + format(c.Parameters[param], precision_string)) else: # [X, Y, Z, U, V, W, I, J, K, R, Q] (Conversion eventuelle mm/inches) pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outstring.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) # store the latest command @@ -491,7 +470,6 @@ def parse(pathobj): for line in TOOL_CHANGE.splitlines(True): out += linenumber() + line - if command == "message": if OUTPUT_COMMENTS is False: out = [] @@ -571,9 +549,7 @@ def drill_translate(outstring, cmd, params): "G0 Z" + format(float(RETRACT_Z.getValueAs(UNIT_FORMAT)), strFormat) + "\n" ) strF_Feedrate = ( - " F" - + format(float(drill_feedrate.getValueAs(UNIT_SPEED_FORMAT)), ".2f") - + "\n" + " F" + format(float(drill_feedrate.getValueAs(UNIT_SPEED_FORMAT)), ".2f") + "\n" ) print(strF_Feedrate) @@ -631,9 +607,7 @@ def drill_translate(outstring, cmd, params): trBuff += ( linenumber() + "G1 Z" - + format( - float(next_Stop_Z.getValueAs(UNIT_FORMAT)), strFormat - ) + + format(float(next_Stop_Z.getValueAs(UNIT_FORMAT)), strFormat) + strF_Feedrate ) trBuff += linenumber() + strG0_RETRACT_Z diff --git a/src/Mod/CAM/Path/Post/scripts/example_post.py b/src/Mod/CAM/Path/Post/scripts/example_post.py index 6cd2f27950..618973a0e3 100644 --- a/src/Mod/CAM/Path/Post/scripts/example_post.py +++ b/src/Mod/CAM/Path/Post/scripts/example_post.py @@ -35,8 +35,6 @@ to GCode. now = datetime.datetime.now() - - def export(objectslist, filename, argstring): "called when freecad exports a list of objects" if len(objectslist) > 1: diff --git a/src/Mod/CAM/Path/Post/scripts/example_pre.py b/src/Mod/CAM/Path/Post/scripts/example_pre.py index 8373effa0c..5845c1635a 100644 --- a/src/Mod/CAM/Path/Post/scripts/example_pre.py +++ b/src/Mod/CAM/Path/Post/scripts/example_pre.py @@ -45,9 +45,6 @@ if LEVEL == Path.Log.Level.DEBUG: Path.Log.trackModule(Path.Log.thisModule()) - - - def open(filename): "called when freecad opens a file." Path.Log.track(filename) diff --git a/src/Mod/CAM/Path/Post/scripts/fablin_post.py b/src/Mod/CAM/Path/Post/scripts/fablin_post.py index 64ee445fac..42aba6ea8c 100644 --- a/src/Mod/CAM/Path/Post/scripts/fablin_post.py +++ b/src/Mod/CAM/Path/Post/scripts/fablin_post.py @@ -91,9 +91,6 @@ POST_OPERATION = """""" TOOL_CHANGE = """""" - - - def processArguments(argstring): global OUTPUT_HEADER global OUTPUT_COMMENTS @@ -130,9 +127,7 @@ def export(objectslist, filename, argstring): for obj in objectslist: if not hasattr(obj, "Path"): print( - "the object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "the object " + obj.Name + " is not a path. Please select only path and Compounds." ) return @@ -245,9 +240,7 @@ def parse(pathobj): return out else: # parsing simple path - if not hasattr( - pathobj, "Path" - ): # groups might contain non-path things like stock. + if not hasattr(pathobj, "Path"): # groups might contain non-path things like stock. return out if OUTPUT_COMMENTS: diff --git a/src/Mod/CAM/Path/Post/scripts/fangling_post.py b/src/Mod/CAM/Path/Post/scripts/fangling_post.py index 05b4782d2d..618f15de0e 100644 --- a/src/Mod/CAM/Path/Post/scripts/fangling_post.py +++ b/src/Mod/CAM/Path/Post/scripts/fangling_post.py @@ -36,12 +36,13 @@ import Path import argparse import datetime import shlex -#from PathScripts import PostUtils + +# from PathScripts import PostUtils import Path.Post.Utils as PostUtils from PathScripts import PathUtils from builtins import open as pyopen -TOOLTIP = ''' +TOOLTIP = """ This is a postprocessor file for the Path workbench. It is used to take a pseudo-G-code fragment outputted by a Path object, and output real G-code suitable for FangLing plasma cutters. @@ -51,22 +52,35 @@ via python scripts with: import FangLing_post FangLing_post.export(object,"/path/to/file.ncc","") -''' +""" now = datetime.datetime.now() -parser = argparse.ArgumentParser(prog='FangLing', add_help=False) -parser.add_argument('--no-header', action='store_true', help='suppress header output') -parser.add_argument('--no-comments', action='store_true', help='suppress comment output') -parser.add_argument('--line-numbers', action='store_true', help='prefix with line numbers') -parser.add_argument('--no-show-editor', action='store_true', help='don\'t pop up editor before writing output') -parser.add_argument('--precision', default='3', help='number of digits of precision, default=3') -parser.add_argument('--preamble', help='set commands to be issued before the first command, default="G17\nG90"') -parser.add_argument('--postamble', help='set commands to be issued after the last command, default="M5\nG17 G90\nM2"') -parser.add_argument('--inches', action='store_true', help='Convert output for US imperial mode (G20)') -parser.add_argument('--modal', action='store_true', help='Output the Same G-command Name USE NonModal Mode') -parser.add_argument('--axis-modal', action='store_true', help='Output the Same Axis Value Mode') -parser.add_argument('--no-tlo', action='store_true', help='suppress tool length offset (G43) following tool changes') +parser = argparse.ArgumentParser(prog="FangLing", add_help=False) +parser.add_argument("--no-header", action="store_true", help="suppress header output") +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") +parser.add_argument( + "--no-show-editor", action="store_true", help="don't pop up editor before writing output" +) +parser.add_argument("--precision", default="3", help="number of digits of precision, default=3") +parser.add_argument( + "--preamble", help='set commands to be issued before the first command, default="G17\nG90"' +) +parser.add_argument( + "--postamble", + help='set commands to be issued after the last command, default="M5\nG17 G90\nM2"', +) +parser.add_argument( + "--inches", action="store_true", help="Convert output for US imperial mode (G20)" +) +parser.add_argument( + "--modal", action="store_true", help="Output the Same G-command Name USE NonModal Mode" +) +parser.add_argument("--axis-modal", action="store_true", help="Output the Same Axis Value Mode") +parser.add_argument( + "--no-tlo", action="store_true", help="suppress tool length offset (G43) following tool changes" +) TOOLTIP_ARGS = parser.format_help() @@ -76,43 +90,41 @@ OUTPUT_HEADER = True OUTPUT_LINE_NUMBERS = False SHOW_EDITOR = True MODAL = False # if true commands are suppressed if the same as previous line. -USE_TLO = False # if true G43 will be output following tool changes +USE_TLO = False # if true G43 will be output following tool changes OUTPUT_DOUBLES = True # if false duplicate axis values are suppressed if the same as previous line. COMMAND_SPACE = " " LINENR = 100 # line number starting value # These globals will be reflected in the Machine configuration of the project UNITS = "G21" # G21 for metric, G20 for us standard -UNIT_SPEED_FORMAT = 'mm/min' -UNIT_FORMAT = 'mm' +UNIT_SPEED_FORMAT = "mm/min" +UNIT_FORMAT = "mm" MACHINE_NAME = "FangLing" -CORNER_MIN = {'x': 0, 'y': 0, 'z': 0} -CORNER_MAX = {'x': 500, 'y': 300, 'z': 300} +CORNER_MIN = {"x": 0, "y": 0, "z": 0} +CORNER_MAX = {"x": 500, "y": 300, "z": 300} PRECISION = 3 # Preamble text will appear at the beginning of the GCODE output file. -#PREAMBLE = '''G17 G54 G40 G49 G80 G90''' -#Changed to match preamble produced by Fusion 360 -PREAMBLE = '''G90 -''' +# PREAMBLE = '''G17 G54 G40 G49 G80 G90''' +# Changed to match preamble produced by Fusion 360 +PREAMBLE = """G90 +""" # Postamble text will appear following the last operation. -POSTAMBLE = '''M8 +POSTAMBLE = """M8 G90 G40 M2 -''' +""" # Pre operation text will be inserted before every operation -PRE_OPERATION = '''''' +PRE_OPERATION = """""" # Post operation text will be inserted after every operation -POST_OPERATION = '''''' +POST_OPERATION = """""" # Tool Change commands will be inserted before a tool change -TOOL_CHANGE = '''''' - - +TOOL_CHANGE = """""" def processArguments(argstring): @@ -148,19 +160,19 @@ def processArguments(argstring): if args.postamble is not None: POSTAMBLE = args.postamble if args.inches: - UNITS = 'G20' - UNIT_SPEED_FORMAT = 'in/min' - UNIT_FORMAT = 'in' + UNITS = "G20" + UNIT_SPEED_FORMAT = "in/min" + UNIT_FORMAT = "in" PRECISION = 4 if args.modal: MODAL = True if args.no_tlo: USE_TLO = False if args.axis_modal: - print ('here') + print("here") OUTPUT_DOUBLES = False - except Exception: # pylint: disable=broad-except + except Exception: # pylint: disable=broad-except return False return True @@ -178,7 +190,9 @@ def export(objectslist, filename, argstring): for obj in objectslist: if not hasattr(obj, "Path"): - print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") + print( + "the object " + obj.Name + " is not a path. Please select only path and Compounds." + ) return None print("postprocessing...") @@ -202,10 +216,10 @@ def export(objectslist, filename, argstring): for obj in objectslist: # Skip inactive operations - if hasattr(obj, 'Active'): + if hasattr(obj, "Active"): if not obj.Active: continue - if hasattr(obj, 'Base') and hasattr(obj.Base, 'Active'): + if hasattr(obj, "Base") and hasattr(obj.Base, "Active"): if not obj.Base.Active: continue @@ -215,12 +229,12 @@ def export(objectslist, filename, argstring): if hasattr(job, "MachineUnits"): if job.MachineUnits == "Metric": UNITS = "G21" - UNIT_FORMAT = 'mm' - UNIT_SPEED_FORMAT = 'mm/min' + UNIT_FORMAT = "mm" + UNIT_SPEED_FORMAT = "mm/min" elif job.MachineUnits == "Imperial": UNITS = "G20" - UNIT_FORMAT = 'in' - UNIT_SPEED_FORMAT = 'in/min' + UNIT_FORMAT = "in" + UNIT_SPEED_FORMAT = "in/min" else: print("Machine units " + job.MachineUnits + " could not be handled.") return None @@ -275,16 +289,33 @@ def parse(pathobj): global UNIT_SPEED_FORMAT out = "" - #print(pathobj.Path.toGCode()) + # print(pathobj.Path.toGCode()) lastcommand = None - precision_string = '.' + str(PRECISION) + 'f' # 'g' instead of 'f' removes trailing zeroes + precision_string = "." + str(PRECISION) + "f" # 'g' instead of 'f' removes trailing zeroes currLocation = {} # keep track for no doubles # the order of parameters # mach3_4 doesn't want K properties on XY plane Arcs need work. - #params = ['X', 'Y', 'Z', 'A', 'B', 'C', 'I', 'J', 'F', 'S', 'T', 'Q', 'R', 'L', 'H', 'D', 'P'] + # params = ['X', 'Y', 'Z', 'A', 'B', 'C', 'I', 'J', 'F', 'S', 'T', 'Q', 'R', 'L', 'H', 'D', 'P'] # FangLing plasma cutters doesn't use Z values - params = ['X', 'Y', 'A', 'B', 'C', 'I', 'J', 'F', 'S', 'T', 'Q', 'R', 'L', 'H', 'D', 'P'] # It have not been checked which parameters FangLing accept + params = [ + "X", + "Y", + "A", + "B", + "C", + "I", + "J", + "F", + "S", + "T", + "Q", + "R", + "L", + "H", + "D", + "P", + ] # It have not been checked which parameters FangLing accept firstmove = Path.Command("G0", {"X": -1, "Y": -1, "Z": -1, "F": 0.0}) currLocation.update(firstmove.Parameters) # set First location Parameters @@ -307,20 +338,34 @@ def parse(pathobj): opHorizRapid = 0 opVertRapid = 0 - if 'Adaptive' in pathobj.Name: + if "Adaptive" in pathobj.Name: adaptiveOp = True - if hasattr(pathobj, 'ToolController'): - if hasattr(pathobj.ToolController, 'HorizRapid') and pathobj.ToolController.HorizRapid > 0: - opHorizRapid = Units.Quantity(pathobj.ToolController.HorizRapid, FreeCAD.Units.Velocity) + if hasattr(pathobj, "ToolController"): + if ( + hasattr(pathobj.ToolController, "HorizRapid") + and pathobj.ToolController.HorizRapid > 0 + ): + opHorizRapid = Units.Quantity( + pathobj.ToolController.HorizRapid, FreeCAD.Units.Velocity + ) else: - FreeCAD.Console.PrintWarning('Tool Controller Horizontal Rapid Values are unset'+ '\n') + FreeCAD.Console.PrintWarning( + "Tool Controller Horizontal Rapid Values are unset" + "\n" + ) - if hasattr(pathobj.ToolController, 'VertRapid') and pathobj.ToolController.VertRapid > 0: - opVertRapid = Units.Quantity(pathobj.ToolController.VertRapid, FreeCAD.Units.Velocity) + if ( + hasattr(pathobj.ToolController, "VertRapid") + and pathobj.ToolController.VertRapid > 0 + ): + opVertRapid = Units.Quantity( + pathobj.ToolController.VertRapid, FreeCAD.Units.Velocity + ) else: - FreeCAD.Console.PrintWarning('Tool Controller Vertical Rapid Values are unset'+ '\n') + FreeCAD.Console.PrintWarning( + "Tool Controller Vertical Rapid Values are unset" + "\n" + ) - #print(pathobj.Path.Commands) + # print(pathobj.Path.Commands) for c in pathobj.Path.Commands: outstring = [] @@ -344,20 +389,20 @@ def parse(pathobj): if adaptiveOp and c.Name in ["G0", "G00"]: if opHorizRapid and opVertRapid: - command = 'G1' + command = "G1" else: - outstring.append('(Tool Controller Rapid Values are unset)' + '\n') + outstring.append("(Tool Controller Rapid Values are unset)" + "\n") # Filter out vertical moves since FangLing plasma cutters does not support them - if command in ["G0", "G00"] and len(c.Parameters) == 1 and 'Z' in c.Parameters: - #print(c, c.Name, len(c.Parameters), list(c.Parameters)) - print('vertical move detected and removed') + if command in ["G0", "G00"] and len(c.Parameters) == 1 and "Z" in c.Parameters: + # print(c, c.Name, len(c.Parameters), list(c.Parameters)) + print("vertical move detected and removed") if command in ["G54"]: - #print(c, c.Name, len(c.Parameters), list(c.Parameters)) - print('Set coordinate system removed') + # print(c, c.Name, len(c.Parameters), list(c.Parameters)) + print("Set coordinate system removed") else: - if command in ["G0", "G00"] and not 'X' in c.Parameters and not 'Y' in c.Parameters: - print('No horizontal move detected so removed') + if command in ["G0", "G00"] and not "X" in c.Parameters and not "Y" in c.Parameters: + print("No horizontal move detected so removed") else: outstring.append(command) @@ -366,22 +411,27 @@ def parse(pathobj): if command == lastcommand: outstring.pop(0) - if c.Name[0] == '(' and not OUTPUT_COMMENTS: # command is a comment + if c.Name[0] == "(" and not OUTPUT_COMMENTS: # command is a comment continue # Now add the remaining parameters in order for param in params: if param in c.Parameters: - if param == 'F': + if param == "F": continue - elif param in ['T', 'H', 'D', 'S']: + elif param in ["T", "H", "D", "S"]: outstring.append(param + str(int(c.Parameters[param]))) - elif not OUTPUT_DOUBLES and param in currLocation and currLocation[param] == c.Parameters[param]: + elif ( + not OUTPUT_DOUBLES + and param in currLocation + and currLocation[param] == c.Parameters[param] + ): continue else: pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outstring.append( - param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string)) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) + ) # store the latest command lastcommand = command @@ -389,20 +439,20 @@ def parse(pathobj): # Check for Tool Change: # Tool changes not supported on FangLing plasma cutters - if command == 'M6': - outstring.pop(0) # remove the M6 - outstring.pop(0) # remove the tool number + if command == "M6": + outstring.pop(0) # remove the M6 + outstring.pop(0) # remove the tool number # stop the spindle - #out += linenumber() + " M5\n" - #for line in TOOL_CHANGE.splitlines(True): - #out += linenumber() + line + # out += linenumber() + " M5\n" + # for line in TOOL_CHANGE.splitlines(True): + # out += linenumber() + line # add height offset # No TLO available in g-code - #if USE_TLO: + # if USE_TLO: # tool_height = '\nG43 H' + str(int(c.Parameters['T'])) # outstring.append(tool_height) - print('M6 tool change removed') + print("M6 tool change removed") if command == "message": if not OUTPUT_COMMENTS: @@ -422,11 +472,12 @@ def parse(pathobj): return out + # print(__name__ + " gcode postprocessor loaded.") def writeFile(filename, final): - if not filename == '-': + if not filename == "-": gfile = pyopen(filename, "w") gfile.write(final) gfile.close() diff --git a/src/Mod/CAM/Path/Post/scripts/fanuc_post.py b/src/Mod/CAM/Path/Post/scripts/fanuc_post.py index d87115c4cc..2edc7abafe 100644 --- a/src/Mod/CAM/Path/Post/scripts/fanuc_post.py +++ b/src/Mod/CAM/Path/Post/scripts/fanuc_post.py @@ -50,20 +50,14 @@ now = datetime.datetime.now() parser = argparse.ArgumentParser(prog="fanuc", add_help=False) parser.add_argument("--no-header", action="store_true", help="suppress header output") -parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" -) -parser.add_argument( - "--line-numbers", action="store_true", help="prefix with line numbers" -) +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") parser.add_argument( "--no-show-editor", action="store_true", help="don't pop up editor before writing output", ) -parser.add_argument( - "--precision", default="3", help="number of digits of precision, default=3" -) +parser.add_argument("--precision", default="3", help="number of digits of precision, default=3") parser.add_argument( "--preamble", help='set commands to be issued before the first command, default="G17\nG90"', @@ -139,8 +133,6 @@ POST_OPERATION = """""" TOOL_CHANGE = """""" - - def processArguments(argstring): global OUTPUT_HEADER global OUTPUT_COMMENTS @@ -202,9 +194,7 @@ def export(objectslist, filename, argstring): for obj in objectslist: if not hasattr(obj, "Path"): print( - "the object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "the object " + obj.Name + " is not a path. Please select only path and Compounds." ) return None @@ -247,19 +237,13 @@ def export(objectslist, filename, argstring): # do the pre_op if OUTPUT_COMMENTS: gcode += linenumber() + "(BEGIN OPERATION: %s)\n" % obj.Label.upper() - gcode += linenumber() + "(MACHINE UNITS: %s)\n" % ( - UNIT_SPEED_FORMAT.upper() - ) + gcode += linenumber() + "(MACHINE UNITS: %s)\n" % (UNIT_SPEED_FORMAT.upper()) for line in PRE_OPERATION.splitlines(True): gcode += linenumber() + line # get coolant mode coolantMode = "None" - if ( - hasattr(obj, "CoolantMode") - or hasattr(obj, "Base") - and hasattr(obj.Base, "CoolantMode") - ): + if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): if hasattr(obj, "CoolantMode"): coolantMode = obj.CoolantMode else: @@ -455,9 +439,7 @@ def parse(pathobj): ): continue else: - pos = Units.Quantity( - c.Parameters[param], FreeCAD.Units.Length - ) + pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) paramstring += ( " " + param @@ -482,9 +464,7 @@ def parse(pathobj): ): continue else: - pos = Units.Quantity( - c.Parameters[param], FreeCAD.Units.Length - ) + pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) paramstring += ( " " + param @@ -498,9 +478,7 @@ def parse(pathobj): # Q is the peck depth of the threading operation for param in ["F", "P", "Q"]: if param in c.Parameters: - value = Units.Quantity( - c.Parameters[param], FreeCAD.Units.Length - ) + value = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) paramstring += ( " " + param @@ -539,9 +517,7 @@ def parse(pathobj): "G0", "G00", ]: # fanuc doesn't use rapid speeds - speed = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + speed = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) if speed.getValueAs(UNIT_SPEED_FORMAT) > 0.0: outstring.append( param @@ -568,14 +544,9 @@ def parse(pathobj): ): continue else: - pos = Units.Quantity( - c.Parameters[param], FreeCAD.Units.Length - ) + pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outstring.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) if adaptiveOp and c.Name in ["G0", "G00"]: diff --git a/src/Mod/CAM/Path/Post/scripts/gcode_pre.py b/src/Mod/CAM/Path/Post/scripts/gcode_pre.py index 515bfb0bbe..714298b7d5 100644 --- a/src/Mod/CAM/Path/Post/scripts/gcode_pre.py +++ b/src/Mod/CAM/Path/Post/scripts/gcode_pre.py @@ -81,9 +81,6 @@ class PathNoJobException(Exception): super().__init__("No job object") - - - def open(filename): """called when freecad opens a file.""" Path.Log.track(filename) @@ -104,7 +101,8 @@ def matchToolController(op, toolnumber): def _isImportEnvironmentReady(): """_isImportEnvironmentReady(docname)... Helper function to verify an active document exists, and that a Job object is available - as a receiver for the Custom operation(s) that will be created as a result of the import process.""" + as a receiver for the Custom operation(s) that will be created as a result of the import process. + """ # Verify active document exists if FreeCAD.ActiveDocument is None: diff --git a/src/Mod/CAM/Path/Post/scripts/generic_post.py b/src/Mod/CAM/Path/Post/scripts/generic_post.py index fa624b486c..1601c549ef 100644 --- a/src/Mod/CAM/Path/Post/scripts/generic_post.py +++ b/src/Mod/CAM/Path/Post/scripts/generic_post.py @@ -71,7 +71,7 @@ class Generic(PostProcessor): Implementing it would be a good idea """ - return tooltip + return tooltip @property def tooltipArgs(self): diff --git a/src/Mod/CAM/Path/Post/scripts/grbl_post.py b/src/Mod/CAM/Path/Post/scripts/grbl_post.py index a694acf7d6..19437c297e 100644 --- a/src/Mod/CAM/Path/Post/scripts/grbl_post.py +++ b/src/Mod/CAM/Path/Post/scripts/grbl_post.py @@ -52,9 +52,7 @@ grbl_post.export(object, "/path/to/file.ncc") OUTPUT_COMMENTS = True # default output of comments in output gCode file OUTPUT_HEADER = True # default output header in output gCode file OUTPUT_LINE_NUMBERS = False # default doesn't output line numbers in output gCode file -OUTPUT_BCNC = ( - False # default doesn't add bCNC operation block headers in output gCode file -) +OUTPUT_BCNC = False # default doesn't add bCNC operation block headers in output gCode file SHOW_EDITOR = True # default show the resulting file dialog output in GUI PRECISION = 3 # Default precision for metric (see http://linuxcnc.org/docs/2.7/html/gcode/overview.html#_g_code_best_practices) TRANSLATE_DRILL_CYCLES = False # If true, G81, G82 & G83 are translated in G0/G1 moves @@ -72,8 +70,12 @@ RETURN_TO = None # no movements after end of program MODAL = False # if true commands are suppressed if the same as previous line. LINENR = 100 # line number starting value LINEINCR = 10 # line number increment -OUTPUT_TOOL_CHANGE = False # default don't output M6 tool changes (comment it) as grbl currently does not handle it -DRILL_RETRACT_MODE = "G98" # Default value of drill retractations (CURRENT_Z) other possible value is G99 +OUTPUT_TOOL_CHANGE = ( + False # default don't output M6 tool changes (comment it) as grbl currently does not handle it +) +DRILL_RETRACT_MODE = ( + "G98" # Default value of drill retractations (CURRENT_Z) other possible value is G99 +) MOTION_MODE = "G90" # G90 for absolute moves, G91 for relative UNITS = "G21" # G21 for metric, G20 for us standard UNIT_FORMAT = "mm" @@ -89,14 +91,10 @@ TOOL_CHANGE = """""" # Tool Change commands will be inserted before a tool chan # Parser arguments list & definition parser = argparse.ArgumentParser(prog="grbl", add_help=False) parser.add_argument("--comments", action="store_true", help="output comment (default)") -parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" -) +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") parser.add_argument("--header", action="store_true", help="output headers (default)") parser.add_argument("--no-header", action="store_true", help="suppress header output") -parser.add_argument( - "--line-numbers", action="store_true", help="prefix with line numbers" -) +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") parser.add_argument( "--no-line-numbers", action="store_true", @@ -112,9 +110,7 @@ parser.add_argument( action="store_true", help="don't pop up editor before writing output", ) -parser.add_argument( - "--precision", default="3", help="number of digits of precision, default=3" -) +parser.add_argument("--precision", default="3", help="number of digits of precision, default=3") parser.add_argument( "--translate_drill", action="store_true", @@ -136,9 +132,7 @@ parser.add_argument( parser.add_argument( "--inches", action="store_true", help="Convert output for US imperial mode (G20)" ) -parser.add_argument( - "--tool-change", action="store_true", help="Insert M6 for all tool changes" -) +parser.add_argument("--tool-change", action="store_true", help="Insert M6 for all tool changes") parser.add_argument( "--wait-for-spindle", type=int, @@ -316,9 +310,7 @@ def export(objectslist, filename, argstring): # print("*"*70 + "\n") if not hasattr(obj, "Path"): print( - "The object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "The object " + obj.Name + " is not a path. Please select only path and Compounds." ) return @@ -338,11 +330,7 @@ def export(objectslist, filename, argstring): # get coolant mode coolantMode = "None" - if ( - hasattr(obj, "CoolantMode") - or hasattr(obj, "Base") - and hasattr(obj.Base, "CoolantMode") - ): + if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): if hasattr(obj, "CoolantMode"): coolantMode = obj.CoolantMode else: @@ -469,9 +457,7 @@ def parse(pathobj): return out else: # parsing simple path - if not hasattr( - pathobj, "Path" - ): # groups might contain non-path things like stock. + if not hasattr(pathobj, "Path"): # groups might contain non-path things like stock. return out if OUTPUT_COMMENTS: @@ -493,9 +479,7 @@ def parse(pathobj): if param in c.Parameters: if param == "F": if command not in RAPID_MOVES: - speed = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + speed = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) if speed.getValueAs(UNIT_SPEED_FORMAT) > 0.0: outstring.append( param @@ -509,16 +493,11 @@ def parse(pathobj): elif param in ["D", "P", "L"]: outstring.append(param + str(c.Parameters[param])) elif param in ["A", "B", "C"]: - outstring.append( - param + format(c.Parameters[param], precision_string) - ) + outstring.append(param + format(c.Parameters[param], precision_string)) else: # [X, Y, Z, U, V, W, I, J, K, R, Q] (Conversion eventuelle mm/inches) pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outstring.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) # store the latest command @@ -548,11 +527,7 @@ def parse(pathobj): if SPINDLE_WAIT > 0: if command in ("M3", "M03", "M4", "M04"): out += linenumber() + format_outstring(outstring) + "\n" - out += ( - linenumber() - + format_outstring(["G4", "P%s" % SPINDLE_WAIT]) - + "\n" - ) + out += linenumber() + format_outstring(["G4", "P%s" % SPINDLE_WAIT]) + "\n" outstring = [] # Check for Tool Change: @@ -599,9 +574,8 @@ def drill_translate(outstring, cmd, params): global UNIT_FORMAT global UNIT_SPEED_FORMAT - strFormat = "." + str(PRECISION) + "f" - strG0_Initial_Z=("G0 Z" + format(float(CURRENT_Z.getValueAs(UNIT_FORMAT)), strFormat) + "\n") + strG0_Initial_Z = "G0 Z" + format(float(CURRENT_Z.getValueAs(UNIT_FORMAT)), strFormat) + "\n" trBuff = "" @@ -628,8 +602,8 @@ def drill_translate(outstring, cmd, params): drill_Z += CURRENT_Z RETRACT_Z += CURRENT_Z -# if DRILL_RETRACT_MODE == "G98" and CURRENT_Z >= RETRACT_Z: -# RETRACT_Z = CURRENT_Z + # if DRILL_RETRACT_MODE == "G98" and CURRENT_Z >= RETRACT_Z: + # RETRACT_Z = CURRENT_Z # get the other parameters drill_feedrate = Units.Quantity(params["F"], FreeCAD.Units.Velocity) @@ -650,9 +624,7 @@ def drill_translate(outstring, cmd, params): "G0 Z" + format(float(RETRACT_Z.getValueAs(UNIT_FORMAT)), strFormat) + "\n" ) strF_Feedrate = ( - " F" - + format(float(drill_feedrate.getValueAs(UNIT_SPEED_FORMAT)), ".2f") - + "\n" + " F" + format(float(drill_feedrate.getValueAs(UNIT_SPEED_FORMAT)), ".2f") + "\n" ) print(strF_Feedrate) @@ -710,9 +682,7 @@ def drill_translate(outstring, cmd, params): trBuff += ( linenumber() + "G1 Z" - + format( - float(next_Stop_Z.getValueAs(UNIT_FORMAT)), strFormat - ) + + format(float(next_Stop_Z.getValueAs(UNIT_FORMAT)), strFormat) + strF_Feedrate ) trBuff += linenumber() + strG0_RETRACT_Z @@ -725,10 +695,10 @@ def drill_translate(outstring, cmd, params): + strF_Feedrate ) - if DRILL_RETRACT_MODE == "G98" : - trBuff += (linenumber() + strG0_Initial_Z) + if DRILL_RETRACT_MODE == "G98": + trBuff += linenumber() + strG0_Initial_Z else: - trBuff += (linenumber() + strG0_RETRACT_Z) + trBuff += linenumber() + strG0_RETRACT_Z break except Exception as e: diff --git a/src/Mod/CAM/Path/Post/scripts/heidenhain_post.py b/src/Mod/CAM/Path/Post/scripts/heidenhain_post.py index 8cce063d03..e00754e57a 100644 --- a/src/Mod/CAM/Path/Post/scripts/heidenhain_post.py +++ b/src/Mod/CAM/Path/Post/scripts/heidenhain_post.py @@ -233,23 +233,17 @@ parser.add_argument( action="store_true", help="try to replace repetitive movements with LBL", ) -parser.add_argument( - "--first-lbl", default="1", help="change the first LBL number, default=1" -) +parser.add_argument("--first-lbl", default="1", help="change the first LBL number, default=1") parser.add_argument( "--no-show-editor", action="store_true", help="don't pop up editor before writing output", ) -parser.add_argument( - "--no-warns", action="store_true", help="don't pop up post-processor warnings" -) +parser.add_argument("--no-warns", action="store_true", help="don't pop up post-processor warnings") TOOLTIP_ARGS = parser.format_help() - - def processArguments(argstring): global MACHINE_SKIP_PARAMS global MACHINE_USE_FMAX @@ -332,9 +326,7 @@ def export(objectslist, filename, argstring): for obj in objectslist: if not hasattr(obj, "Path"): print( - "the object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "the object " + obj.Name + " is not a path. Please select only path and Compounds." ) return @@ -463,9 +455,7 @@ def export(objectslist, filename, argstring): # Rapid movement if command == "G0": Spindle_Status = "" - if ( - Spindle_Active == False - ): # At first rapid movement we turn on spindle + if Spindle_Active == False: # At first rapid movement we turn on spindle Spindle_Status += str(MACHINE_SPINDLE_DIRECTION) # Activate spindle Spindle_Active = True else: # At last rapid movement we turn off spindle @@ -482,9 +472,7 @@ def export(objectslist, filename, argstring): # Linear movement if command == "G1": - parsedElem = HEIDEN_Line( - c.Parameters, Compensation, Feed, False, "", Cmd_Count - ) + parsedElem = HEIDEN_Line(c.Parameters, Compensation, Feed, False, "", Cmd_Count) if parsedElem is not None: POSTGCODE.append(parsedElem) @@ -604,9 +592,7 @@ def HEIDEN_ToolCall(tool_Params): # create a linear movement -def HEIDEN_Line( - line_Params, line_comp, line_feed, line_rapid, line_M_funct, Cmd_Number -): +def HEIDEN_Line(line_Params, line_comp, line_feed, line_rapid, line_M_funct, Cmd_Number): global FEED_MAX_SPEED global COMPENSATION_DIFF_STATUS global G_FUNCTION_STORE @@ -632,9 +618,7 @@ def HEIDEN_Line( H_Line_New[i] = 0 if i in line_Params: if line_Params[i] != 0 or line_M_funct != "": - H_Line += " I" + HEIDEN_Format( - i, line_Params[i] - ) # print incremental + H_Line += " I" + HEIDEN_Format(i, line_Params[i]) # print incremental # update to absolute position H_Line_New[i] = MACHINE_LAST_POSITION[i] + H_Line_New[i] else: # absolute @@ -648,21 +632,13 @@ def HEIDEN_Line( return None if COMPENSATION_DIFF_STATUS[0]: # Diff from compensated ad not compensated path - if COMPENSATION_DIFF_STATUS[ - 1 - ]: # skip if already compensated, not active by now + if COMPENSATION_DIFF_STATUS[1]: # skip if already compensated, not active by now Cmd_Number -= 1 # align # initialize like true, set false if not same point compensated and not compensated i = True for j in H_Line_Params[0]: - if ( - j in STORED_COMPENSATED_OBJ[Cmd_Number].Parameters - and j in line_Params - ): - if ( - STORED_COMPENSATED_OBJ[Cmd_Number].Parameters[j] - != line_Params[j] - ): + if j in STORED_COMPENSATED_OBJ[Cmd_Number].Parameters and j in line_Params: + if STORED_COMPENSATED_OBJ[Cmd_Number].Parameters[j] != line_Params[j]: i = False if i == False: H_Line_Params[1][0] = "R" + line_comp @@ -683,10 +659,7 @@ def HEIDEN_Line( if MACHINE_USE_FMAX and line_rapid: H_Line += " FMAX" else: - if ( - MACHINE_SKIP_PARAMS == False - or H_Line_Params[1][1] != MACHINE_STORED_PARAMS[1] - ): + if MACHINE_SKIP_PARAMS == False or H_Line_Params[1][1] != MACHINE_STORED_PARAMS[1]: MACHINE_STORED_PARAMS[1] = H_Line_Params[1][1] H_Line += HEIDEN_Format(" F", H_Line_Params[1][1]) @@ -712,9 +685,7 @@ def HEIDEN_Line( # create a arc movement -def HEIDEN_Arc( - arc_Params, arc_direction, arc_comp, arc_feed, arc_rapid, arc_M_funct, Cmd_Number -): +def HEIDEN_Arc(arc_Params, arc_direction, arc_comp, arc_feed, arc_rapid, arc_M_funct, Cmd_Number): global FEED_MAX_SPEED global COMPENSATION_DIFF_STATUS global G_FUNCTION_STORE @@ -772,11 +743,7 @@ def HEIDEN_Arc( def Axis_Select(a, b, c, incr): if a in arc_Params and b in arc_Params: _H_ArcCenter = ( - incr - + HEIDEN_Format(a, H_Arc_CC[a]) - + " " - + incr - + HEIDEN_Format(b, H_Arc_CC[b]) + incr + HEIDEN_Format(a, H_Arc_CC[a]) + " " + incr + HEIDEN_Format(b, H_Arc_CC[b]) ) if c in arc_Params and arc_Params[c] != MACHINE_LAST_POSITION[c]: # if there are 3 axis movements it need to be polar arc @@ -826,14 +793,8 @@ def HEIDEN_Arc( Cmd_Number -= 1 # align i = True for j in H_Arc_Params[0]: - if ( - j in STORED_COMPENSATED_OBJ[Cmd_Number].Parameters - and j in arc_Params - ): - if ( - STORED_COMPENSATED_OBJ[Cmd_Number].Parameters[j] - != arc_Params[j] - ): + if j in STORED_COMPENSATED_OBJ[Cmd_Number].Parameters and j in arc_Params: + if STORED_COMPENSATED_OBJ[Cmd_Number].Parameters[j] != arc_Params[j]: i = False if i == False: H_Arc_Params[1][0] = "R" + arc_comp @@ -854,10 +815,7 @@ def HEIDEN_Arc( if MACHINE_USE_FMAX and arc_rapid: H_ArcPoint += " FMAX" else: - if ( - MACHINE_SKIP_PARAMS == False - or H_Arc_Params[1][1] != MACHINE_STORED_PARAMS[1] - ): + if MACHINE_SKIP_PARAMS == False or H_Arc_Params[1][1] != MACHINE_STORED_PARAMS[1]: MACHINE_STORED_PARAMS[1] = H_Arc_Params[1][1] H_ArcPoint += HEIDEN_Format(" F", H_Arc_Params[1][1]) @@ -936,11 +894,7 @@ def HEIDEN_PolarArc(pol_cc_X, pol_cc_Y, pol_X, pol_Y, pol_Z, pol_Axis, pol_Incr) pol_Angle = pol_Angle + 360 pol_Result = ( - "P" - + HEIDEN_Format(" PA+", pol_Angle) - + " " - + pol_Incr - + HEIDEN_Format(pol_Axis, pol_Z) + "P" + HEIDEN_Format(" PA+", pol_Angle) + " " + pol_Incr + HEIDEN_Format(pol_Axis, pol_Z) ) return pol_Result @@ -1014,9 +968,7 @@ def HEIDEN_Drill( # update Z value to R + actual_Z if first call if G_FUNCTION_STORE[drill_Type] == False: MACHINE_LAST_POSITION["Z"] = drill_Defs["DIST"] + MACHINE_LAST_POSITION["Z"] - drill_Movement = ( - "L" + HEIDEN_Format(" Z", MACHINE_LAST_POSITION["Z"]) + drill_Rapid - ) + drill_Movement = "L" + HEIDEN_Format(" Z", MACHINE_LAST_POSITION["Z"]) + drill_Rapid drill_Output.append(drill_Movement) # update X and Y position @@ -1176,9 +1128,7 @@ def HEIDEN_LBL_Replace(): for j in range(CellStart, CellStop, -1): POSTGCODE.pop(j) # add the LBL calls - POSTGCODE.insert( - CellStop + 1, "CALL LBL " + str(FIRST_LBL - LBL_Shift) - ) + POSTGCODE.insert(CellStop + 1, "CALL LBL " + str(FIRST_LBL - LBL_Shift)) if Gcode_Lenght != len(POSTGCODE): LBL_Shift = 0 Rows = len(STORED_LBL[0]) - 1 diff --git a/src/Mod/CAM/Path/Post/scripts/jtech_post.py b/src/Mod/CAM/Path/Post/scripts/jtech_post.py index e58bc17925..2b152031aa 100644 --- a/src/Mod/CAM/Path/Post/scripts/jtech_post.py +++ b/src/Mod/CAM/Path/Post/scripts/jtech_post.py @@ -46,20 +46,14 @@ now = datetime.datetime.now() parser = argparse.ArgumentParser(prog="jtech", add_help=False) parser.add_argument("--no-header", action="store_true", help="suppress header output") -parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" -) -parser.add_argument( - "--line-numbers", action="store_true", help="prefix with line numbers" -) +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") parser.add_argument( "--no-show-editor", action="store_true", help="don't pop up editor before writing output", ) -parser.add_argument( - "--precision", default="3", help="number of digits of precision, default=3" -) +parser.add_argument("--precision", default="3", help="number of digits of precision, default=3") parser.add_argument( "--preamble", help='set commands to be issued before the first command, default="M05 S0\nG90"', @@ -76,9 +70,7 @@ parser.add_argument( action="store_true", help="Output the Same G-command Name USE NonModal Mode", ) -parser.add_argument( - "--axis-modal", action="store_true", help="Output the Same Axis Value Mode" -) +parser.add_argument("--axis-modal", action="store_true", help="Output the Same Axis Value Mode") parser.add_argument( "--power-on-delay", default="255", @@ -94,9 +86,7 @@ OUTPUT_HEADER = True OUTPUT_LINE_NUMBERS = False SHOW_EDITOR = True MODAL = False # if true commands are suppressed if the same as previous line. -OUTPUT_DOUBLES = ( - True # if false duplicate axis values are suppressed if the same as previous line. -) +OUTPUT_DOUBLES = True # if false duplicate axis values are suppressed if the same as previous line. COMMAND_SPACE = " " LINENR = 100 # line number starting value @@ -137,8 +127,6 @@ TOOL_CHANGE = """""" POWER_ON_DELAY = 0 - - def processArguments(argstring): global OUTPUT_HEADER global OUTPUT_COMMENTS @@ -194,9 +182,7 @@ def export(objectslist, filename, argstring): for obj in objectslist: if not hasattr(obj, "Path"): print( - "the object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "the object " + obj.Name + " is not a path. Please select only path and Compounds." ) return None @@ -336,12 +322,8 @@ def parse(pathobj): if param == "F" and ( currLocation[param] != c.Parameters[param] or OUTPUT_DOUBLES ): - if ( - c.Name not in RAPID_MOVES - ): # linuxcnc doesn't use rapid speeds - speed = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + if c.Name not in RAPID_MOVES: # linuxcnc doesn't use rapid speeds + speed = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) if speed.getValueAs(UNIT_SPEED_FORMAT) > 0.0: outstring.append( param @@ -368,14 +350,9 @@ def parse(pathobj): ): continue else: - pos = Units.Quantity( - c.Parameters[param], FreeCAD.Units.Length - ) + pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outstring.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) # store the latest command diff --git a/src/Mod/CAM/Path/Post/scripts/linuxcnc_post.py b/src/Mod/CAM/Path/Post/scripts/linuxcnc_post.py index 804694acb6..3532c8d9d3 100644 --- a/src/Mod/CAM/Path/Post/scripts/linuxcnc_post.py +++ b/src/Mod/CAM/Path/Post/scripts/linuxcnc_post.py @@ -46,20 +46,14 @@ now = datetime.datetime.now() parser = argparse.ArgumentParser(prog="linuxcnc", add_help=False) parser.add_argument("--no-header", action="store_true", help="suppress header output") -parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" -) -parser.add_argument( - "--line-numbers", action="store_true", help="prefix with line numbers" -) +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") parser.add_argument( "--no-show-editor", action="store_true", help="don't pop up editor before writing output", ) -parser.add_argument( - "--precision", default="3", help="number of digits of precision, default=3" -) +parser.add_argument("--precision", default="3", help="number of digits of precision, default=3") parser.add_argument( "--preamble", help='set commands to be issued before the first command, default="G17\nG90"', @@ -76,9 +70,7 @@ parser.add_argument( action="store_true", help="Output the Same G-command Name USE NonModal Mode", ) -parser.add_argument( - "--axis-modal", action="store_true", help="Output the Same Axis Value Mode" -) +parser.add_argument("--axis-modal", action="store_true", help="Output the Same Axis Value Mode") parser.add_argument( "--no-tlo", action="store_true", @@ -94,9 +86,7 @@ OUTPUT_LINE_NUMBERS = False SHOW_EDITOR = True MODAL = False # if true commands are suppressed if the same as previous line. USE_TLO = True # if true G43 will be output following tool changes -OUTPUT_DOUBLES = ( - True # if false duplicate axis values are suppressed if the same as previous line. -) +OUTPUT_DOUBLES = True # if false duplicate axis values are suppressed if the same as previous line. COMMAND_SPACE = " " LINENR = 100 # line number starting value @@ -130,8 +120,6 @@ POST_OPERATION = """""" TOOL_CHANGE = """""" - - def processArguments(argstring): global OUTPUT_HEADER global OUTPUT_COMMENTS @@ -192,9 +180,7 @@ def export(objectslist, filename, argstring): for obj in objectslist: if not hasattr(obj, "Path"): print( - "the object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "the object " + obj.Name + " is not a path. Please select only path and Compounds." ) return None @@ -233,11 +219,7 @@ def export(objectslist, filename, argstring): # get coolant mode coolantMode = "None" - if ( - hasattr(obj, "CoolantMode") - or hasattr(obj, "Base") - and hasattr(obj.Base, "CoolantMode") - ): + if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): if hasattr(obj, "CoolantMode"): coolantMode = obj.CoolantMode else: @@ -386,9 +368,7 @@ def parse(pathobj): "G0", "G00", ]: # linuxcnc doesn't use rapid speeds - speed = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + speed = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) if speed.getValueAs(UNIT_SPEED_FORMAT) > 0.0: outstring.append( param @@ -417,21 +397,13 @@ def parse(pathobj): else: if param in ("A", "B", "C"): outstring.append( - param - + format( - float(c.Parameters[param]), - precision_string - ) + param + format(float(c.Parameters[param]), precision_string) ) else: - pos = Units.Quantity( - c.Parameters[param], FreeCAD.Units.Length - ) + pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outstring.append( param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) # store the latest command diff --git a/src/Mod/CAM/Path/Post/scripts/mach3_mach4_post.py b/src/Mod/CAM/Path/Post/scripts/mach3_mach4_post.py index 5790586344..4933f6b244 100644 --- a/src/Mod/CAM/Path/Post/scripts/mach3_mach4_post.py +++ b/src/Mod/CAM/Path/Post/scripts/mach3_mach4_post.py @@ -46,20 +46,14 @@ now = datetime.datetime.now() parser = argparse.ArgumentParser(prog="mach3_4", add_help=False) parser.add_argument("--no-header", action="store_true", help="suppress header output") -parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" -) -parser.add_argument( - "--line-numbers", action="store_true", help="prefix with line numbers" -) +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") parser.add_argument( "--no-show-editor", action="store_true", help="don't pop up editor before writing output", ) -parser.add_argument( - "--precision", default="3", help="number of digits of precision, default=3" -) +parser.add_argument("--precision", default="3", help="number of digits of precision, default=3") parser.add_argument( "--preamble", help='set commands to be issued before the first command, default="G17\nG90"', @@ -76,9 +70,7 @@ parser.add_argument( action="store_true", help="Output the Same G-command Name USE NonModal Mode", ) -parser.add_argument( - "--axis-modal", action="store_true", help="Output the Same Axis Value Mode" -) +parser.add_argument("--axis-modal", action="store_true", help="Output the Same Axis Value Mode") parser.add_argument( "--no-tlo", action="store_true", @@ -94,9 +86,7 @@ OUTPUT_LINE_NUMBERS = False SHOW_EDITOR = True MODAL = False # if true commands are suppressed if the same as previous line. USE_TLO = True # if true G43 will be output following tool changes -OUTPUT_DOUBLES = ( - True # if false duplicate axis values are suppressed if the same as previous line. -) +OUTPUT_DOUBLES = True # if false duplicate axis values are suppressed if the same as previous line. COMMAND_SPACE = " " LINENR = 100 # line number starting value @@ -130,8 +120,6 @@ POST_OPERATION = """""" TOOL_CHANGE = """""" - - def processArguments(argstring): global OUTPUT_HEADER global OUTPUT_COMMENTS @@ -192,9 +180,7 @@ def export(objectslist, filename, argstring): for obj in objectslist: if not hasattr(obj, "Path"): print( - "the object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "the object " + obj.Name + " is not a path. Please select only path and Compounds." ) return None @@ -236,11 +222,7 @@ def export(objectslist, filename, argstring): # get coolant mode coolantMode = "None" - if ( - hasattr(obj, "CoolantMode") - or hasattr(obj, "Base") - and hasattr(obj.Base, "CoolantMode") - ): + if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): if hasattr(obj, "CoolantMode"): coolantMode = obj.CoolantMode else: @@ -418,9 +400,7 @@ def parse(pathobj): "G0", "G00", ]: # mach3_4 doesn't use rapid speeds - speed = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + speed = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) if speed.getValueAs(UNIT_SPEED_FORMAT) > 0.0: outstring.append( param @@ -447,14 +427,9 @@ def parse(pathobj): ): continue else: - pos = Units.Quantity( - c.Parameters[param], FreeCAD.Units.Length - ) + pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outstring.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) if adaptiveOp and c.Name in ["G0", "G00"]: diff --git a/src/Mod/CAM/Path/Post/scripts/marlin_post.py b/src/Mod/CAM/Path/Post/scripts/marlin_post.py index abebe51ae5..5abe205e33 100644 --- a/src/Mod/CAM/Path/Post/scripts/marlin_post.py +++ b/src/Mod/CAM/Path/Post/scripts/marlin_post.py @@ -106,12 +106,8 @@ parser = argparse.ArgumentParser(prog="marlin", add_help=False) parser.add_argument("--header", action="store_true", help="output headers (default)") parser.add_argument("--no-header", action="store_true", help="suppress header output") parser.add_argument("--comments", action="store_true", help="output comment (default)") -parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" -) -parser.add_argument( - "--finish-comments", action="store_true", help="output finish-comment" -) +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") +parser.add_argument("--finish-comments", action="store_true", help="output finish-comment") parser.add_argument( "--no-finish-comments", action="store_true", @@ -123,17 +119,13 @@ parser.add_argument( action="store_true", help="suppress path-comment output (default)", ) -parser.add_argument( - "--marlin-config", action="store_true", help="output #defines for Marlin" -) +parser.add_argument("--marlin-config", action="store_true", help="output #defines for Marlin") parser.add_argument( "--no-marlin-config", action="store_true", help="suppress output #defines for Marlin (default)", ) -parser.add_argument( - "--line-numbers", action="store_true", help="prefix with line numbers" -) +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") parser.add_argument( "--no-line-numbers", action="store_true", @@ -149,9 +141,7 @@ parser.add_argument( action="store_true", help="do not pop up editor before writing output", ) -parser.add_argument( - "--precision", default="3", help="number of digits of precision, default=3" -) +parser.add_argument("--precision", default="3", help="number of digits of precision, default=3") parser.add_argument( "--translate_drill", action="store_true", @@ -168,9 +158,7 @@ parser.add_argument( parser.add_argument( "--postamble", help='set commands to be issued after the last command, default="M5"' ) -parser.add_argument( - "--tool-change", action="store_true", help="Insert M6 for all tool changes" -) +parser.add_argument("--tool-change", action="store_true", help="Insert M6 for all tool changes") parser.add_argument( "--wait-for-spindle", type=int, @@ -364,9 +352,7 @@ def export(objectslist, filename, argstring): # print('\n' + '*'*70 + '\n') if not hasattr(obj, "Path"): print( - "The object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "The object " + obj.Name + " is not a path. Please select only path and Compounds." ) return @@ -386,11 +372,7 @@ def export(objectslist, filename, argstring): # Get coolant mode: coolantMode = "None" # None is the word returned from the operation - if ( - hasattr(obj, "CoolantMode") - or hasattr(obj, "Base") - and hasattr(obj.Base, "CoolantMode") - ): + if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): if hasattr(obj, "CoolantMode"): coolantMode = obj.CoolantMode else: @@ -560,9 +542,7 @@ def parse(pathobj): if param in c.Parameters: if param == "F": if command not in RAPID_MOVES: - feedRate = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + feedRate = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) if feedRate.getValueAs(UNIT_FEED_FORMAT) > 0.0: outlist.append( param @@ -574,17 +554,12 @@ def parse(pathobj): elif param in ["T", "H", "D", "S", "P", "L"]: outlist.append(param + str(c.Parameters[param])) elif param in ["A", "B", "C"]: - outlist.append( - param + format(c.Parameters[param], precision_string) - ) + outlist.append(param + format(c.Parameters[param], precision_string)) # [X, Y, Z, U, V, W, I, J, K, R, Q] else: pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outlist.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) # Store the latest command: @@ -651,9 +626,7 @@ def parse(pathobj): else: # This line contains a comment, and possibly more right_index = outlist[list_index].find(")") comment_area = outlist[list_index][left_index : right_index + 1] - line_minus_comment = ( - outlist[list_index].replace(comment_area, "").strip() - ) + line_minus_comment = outlist[list_index].replace(comment_area, "").strip() if line_minus_comment: # Line contained more than just a comment tmplist.append(line_minus_comment) diff --git a/src/Mod/CAM/Path/Post/scripts/opensbp_post.py b/src/Mod/CAM/Path/Post/scripts/opensbp_post.py index afe4b60f1a..0dadd890e0 100644 --- a/src/Mod/CAM/Path/Post/scripts/opensbp_post.py +++ b/src/Mod/CAM/Path/Post/scripts/opensbp_post.py @@ -81,7 +81,6 @@ POST_OPERATION = """""" TOOL_CHANGE = """""" - CurrentState = {} diff --git a/src/Mod/CAM/Path/Post/scripts/opensbp_pre.py b/src/Mod/CAM/Path/Post/scripts/opensbp_pre.py index 0772b0031d..e0d27390e2 100644 --- a/src/Mod/CAM/Path/Post/scripts/opensbp_pre.py +++ b/src/Mod/CAM/Path/Post/scripts/opensbp_pre.py @@ -64,8 +64,6 @@ AXIS = ( SPEEDS = "XY", "Z", "A", "B" - - def open(filename): "called when freecad opens a file." docname = os.path.splitext(os.path.basename(filename))[0] diff --git a/src/Mod/CAM/Path/Post/scripts/philips_post.py b/src/Mod/CAM/Path/Post/scripts/philips_post.py index 5561bc0c94..9a67cb7957 100644 --- a/src/Mod/CAM/Path/Post/scripts/philips_post.py +++ b/src/Mod/CAM/Path/Post/scripts/philips_post.py @@ -128,9 +128,7 @@ SWAP_G2_G3 = True # some machines have the sign of the X-axis swapped, so they # this might be special with some maho machines or even with mine and # might be changed in the machine constants as well -SWAP_Y_Z = ( - True # machines with an angle milling head do not switch axes, so we do it here -) +SWAP_Y_Z = True # machines with an angle milling head do not switch axes, so we do it here # possible values: # True if Y and Z values have to be swapped # False do not swap @@ -213,16 +211,10 @@ parser.add_argument("--header", action="store_true", help="create header output" parser.add_argument("--no-header", action="store_true", help="suppress header output") parser.add_argument("--comments", action="store_true", help="create comment output") -parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" -) +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") -parser.add_argument( - "--line-numbers", action="store_true", help="prefix with line numbers" -) -parser.add_argument( - "--no-line-numbers", action="store_true", help="omit line number prefixes" -) +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") +parser.add_argument("--no-line-numbers", action="store_true", help="omit line number prefixes") parser.add_argument( "--show-editor", action="store_true", help="pop up editor before writing output" @@ -298,8 +290,6 @@ GCODE_FOOTER = "M30" linenr = 0 # variable has to be global because it is used by linenumberify and export - - def angleUnder180(command, lastX, lastY, x, y, i, j): # radius R can be used iff angle is < 180. # This is the case @@ -391,9 +381,7 @@ def export(objectslist, filename, argstring): for obj in objectslist: if not hasattr(obj, "Path"): print( - "the object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "the object " + obj.Name + " is not a path. Please select only path and Compounds." ) return myMachine = None @@ -451,8 +439,7 @@ def export(objectslist, filename, argstring): pass else: outstring.append( - param - + PostUtils.fmt(feed, FEED_DECIMALS, UNITS) + param + PostUtils.fmt(feed, FEED_DECIMALS, UNITS) ) elif param == "H": outstring.append(param + str(int(c.Parameters["H"]))) @@ -462,9 +449,7 @@ def export(objectslist, filename, argstring): # converted from entered value outstring.append( param - + PostUtils.fmt( - c.Parameters["S"], SPINDLE_DECIMALS, "G21" - ) + + PostUtils.fmt(c.Parameters["S"], SPINDLE_DECIMALS, "G21") ) elif param == "T": outstring.append(param + str(int(c.Parameters["T"]))) @@ -486,21 +471,15 @@ def export(objectslist, filename, argstring): i, j, ): - outstring.append( - "R" + PostUtils.fmt(r, AXIS_DECIMALS, UNITS) - ) + outstring.append("R" + PostUtils.fmt(r, AXIS_DECIMALS, UNITS)) else: if RADIUS_COMMENT: outstring.append( - "(R" - + PostUtils.fmt(r, AXIS_DECIMALS, UNITS) - + ")" + "(R" + PostUtils.fmt(r, AXIS_DECIMALS, UNITS) + ")" ) if ABSOLUTE_CIRCLE_CENTER: i += lastX - outstring.append( - param + PostUtils.fmt(i, AXIS_DECIMALS, UNITS) - ) + outstring.append(param + PostUtils.fmt(i, AXIS_DECIMALS, UNITS)) elif param == "J" and (command == "G2" or command == "G3"): # this is the special case for circular paths, # where incremental center has to be changed to @@ -530,8 +509,7 @@ def export(objectslist, filename, argstring): ) else: outstring.append( - param - + PostUtils.fmt(j, AXIS_DECIMALS, UNITS) + param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS) ) elif param == "K" and (command == "G2" or command == "G3"): # this is the special case for circular paths, @@ -540,9 +518,7 @@ def export(objectslist, filename, argstring): outstring.append( "(" + param - + PostUtils.fmt( - c.Parameters[param], AXIS_DECIMALS, UNITS - ) + + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS) + ")" ) z = c.Parameters["Z"] @@ -565,36 +541,23 @@ def export(objectslist, filename, argstring): k += lastZ if SWAP_Y_Z: # we have to swap j and k as well - outstring.append( - "J" + PostUtils.fmt(j, AXIS_DECIMALS, UNITS) - ) + outstring.append("J" + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: - outstring.append( - param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS) - ) + outstring.append(param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == "Y" and SWAP_Y_Z: outstring.append( - "Z" - + PostUtils.fmt( - c.Parameters[param], AXIS_DECIMALS, UNITS - ) + "Z" + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS) ) elif param == "Z" and SWAP_Y_Z: outstring.append( - "Y" - + PostUtils.fmt( - c.Parameters[param], AXIS_DECIMALS, UNITS - ) + "Y" + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS) ) else: # To Do: suppress unknown commands, if this is done here, all X parameters are suppressed # this is an unknown command, don't create GCode for it # print("parameter " + param + " for command " + command + " ignored") outstring.append( - param - + PostUtils.fmt( - c.Parameters[param], AXIS_DECIMALS, UNITS - ) + param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS) ) if param in MODALPARAMS: diff --git a/src/Mod/CAM/Path/Post/scripts/refactored_test_post.py b/src/Mod/CAM/Path/Post/scripts/refactored_test_post.py index 9f248017f9..de684319ab 100644 --- a/src/Mod/CAM/Path/Post/scripts/refactored_test_post.py +++ b/src/Mod/CAM/Path/Post/scripts/refactored_test_post.py @@ -156,9 +156,7 @@ def init_arguments( """Initialize the shared argument definitions.""" parser: Parser - parser = UtilsArguments.init_shared_arguments( - values, argument_defaults, arguments_visible - ) + parser = UtilsArguments.init_shared_arguments(values, argument_defaults, arguments_visible) # # Add any argument definitions that are not shared with all other # postprocessors here. diff --git a/src/Mod/CAM/Path/Post/scripts/rml_post.py b/src/Mod/CAM/Path/Post/scripts/rml_post.py index e39b735256..2aa25c1627 100644 --- a/src/Mod/CAM/Path/Post/scripts/rml_post.py +++ b/src/Mod/CAM/Path/Post/scripts/rml_post.py @@ -40,8 +40,6 @@ import Path.Post.Utils as PostUtils from builtins import open as pyopen - - # Entrypoint used by FreeCAD def export(objectslist, filename, argstring): "Export objects as Roland Modela code." diff --git a/src/Mod/CAM/Path/Post/scripts/rrf_post.py b/src/Mod/CAM/Path/Post/scripts/rrf_post.py index 5dd9c9f158..a18d14b341 100644 --- a/src/Mod/CAM/Path/Post/scripts/rrf_post.py +++ b/src/Mod/CAM/Path/Post/scripts/rrf_post.py @@ -104,12 +104,8 @@ parser = argparse.ArgumentParser(prog="rrf", add_help=False) parser.add_argument("--header", action="store_true", help="output headers (default)") parser.add_argument("--no-header", action="store_true", help="suppress header output") parser.add_argument("--comments", action="store_true", help="output comment (default)") -parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" -) -parser.add_argument( - "--finish-comments", action="store_true", help="output finish-comment" -) +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") +parser.add_argument("--finish-comments", action="store_true", help="output finish-comment") parser.add_argument( "--no-finish-comments", action="store_true", @@ -127,9 +123,7 @@ parser.add_argument( action="store_true", help="suppress output #defines for RRF (default)", ) -parser.add_argument( - "--line-numbers", action="store_true", help="prefix with line numbers" -) +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") parser.add_argument( "--no-line-numbers", action="store_true", @@ -145,9 +139,7 @@ parser.add_argument( action="store_true", help="do not pop up editor before writing output", ) -parser.add_argument( - "--precision", default="3", help="number of digits of precision, default=3" -) +parser.add_argument("--precision", default="3", help="number of digits of precision, default=3") parser.add_argument( "--translate_drill", action="store_true", @@ -164,9 +156,7 @@ parser.add_argument( parser.add_argument( "--postamble", help='set commands to be issued after the last command, default="M5"' ) -parser.add_argument( - "--tool-change", action="store_true", help="Insert M6 for all tool changes" -) +parser.add_argument("--tool-change", action="store_true", help="Insert M6 for all tool changes") parser.add_argument( "--wait-for-spindle", type=int, @@ -360,9 +350,7 @@ def export(objectslist, filename, argstring): # print('\n' + '*'*70 + '\n') if not hasattr(obj, "Path"): print( - "The object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "The object " + obj.Name + " is not a path. Please select only path and Compounds." ) return @@ -382,11 +370,7 @@ def export(objectslist, filename, argstring): # Get coolant mode: coolantMode = "None" # None is the word returned from the operation - if ( - hasattr(obj, "CoolantMode") - or hasattr(obj, "Base") - and hasattr(obj.Base, "CoolantMode") - ): + if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): if hasattr(obj, "CoolantMode"): coolantMode = obj.CoolantMode else: @@ -551,9 +535,7 @@ def parse(pathobj): if param in c.Parameters: if param == "F": if command not in RAPID_MOVES: - feedRate = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + feedRate = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) if feedRate.getValueAs(UNIT_FEED_FORMAT) > 0.0: outlist.append( param @@ -568,17 +550,12 @@ def parse(pathobj): elif param in ["H", "D", "S", "P", "L"]: outlist.append(param + str(c.Parameters[param])) elif param in ["A", "B", "C"]: - outlist.append( - param + format(c.Parameters[param], precision_string) - ) + outlist.append(param + format(c.Parameters[param], precision_string)) # [X, Y, Z, U, V, W, I, J, K, R, Q] else: pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outlist.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) # Store the latest command: @@ -652,9 +629,7 @@ def parse(pathobj): else: # This line contains a comment, and possibly more right_index = outlist[list_index].find(")") comment_area = outlist[list_index][left_index : right_index + 1] - line_minus_comment = ( - outlist[list_index].replace(comment_area, "").strip() - ) + line_minus_comment = outlist[list_index].replace(comment_area, "").strip() if line_minus_comment: # Line contained more than just a comment tmplist.append(line_minus_comment) diff --git a/src/Mod/CAM/Path/Post/scripts/slic3r_pre.py b/src/Mod/CAM/Path/Post/scripts/slic3r_pre.py index 538f90646b..c312474164 100644 --- a/src/Mod/CAM/Path/Post/scripts/slic3r_pre.py +++ b/src/Mod/CAM/Path/Post/scripts/slic3r_pre.py @@ -31,8 +31,6 @@ import FreeCAD from builtins import open as pyopen - - def open(filename): "called when freecad opens a file." docname = os.path.splitext(os.path.basename(filename))[0] diff --git a/src/Mod/CAM/Path/Post/scripts/smoothie_post.py b/src/Mod/CAM/Path/Post/scripts/smoothie_post.py index 127e0aca8a..9d863b357f 100644 --- a/src/Mod/CAM/Path/Post/scripts/smoothie_post.py +++ b/src/Mod/CAM/Path/Post/scripts/smoothie_post.py @@ -48,12 +48,8 @@ parser = argparse.ArgumentParser(prog="linuxcnc", add_help=False) parser.add_argument("--header", action="store_true", help="output headers (default)") parser.add_argument("--no-header", action="store_true", help="suppress header output") parser.add_argument("--comments", action="store_true", help="output comment (default)") -parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" -) -parser.add_argument( - "--line-numbers", action="store_true", help="prefix with line numbers" -) +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") parser.add_argument( "--no-line-numbers", action="store_true", @@ -69,9 +65,7 @@ parser.add_argument( action="store_true", help="don't pop up editor before writing output", ) -parser.add_argument( - "--precision", default="4", help="number of digits of precision, default=4" -) +parser.add_argument("--precision", default="4", help="number of digits of precision, default=4") parser.add_argument( "--preamble", help='set commands to be issued before the first command, default="G17\nG90"', @@ -142,8 +136,6 @@ TOOL_CHANGE = """""" PRECISION = 5 - - def processArguments(argstring): global OUTPUT_HEADER global OUTPUT_COMMENTS @@ -416,9 +408,7 @@ def parse(pathobj): "G0", "G00", ]: # linuxcnc doesn't use rapid speeds - speed = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + speed = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) outstring.append( param + format( @@ -434,10 +424,7 @@ def parse(pathobj): else: pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) outstring.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) if command in ["G1", "G01", "G2", "G02", "G3", "G03"]: outstring.append("S" + str(SPINDLE_SPEED)) diff --git a/src/Mod/CAM/Path/Post/scripts/uccnc_post.py b/src/Mod/CAM/Path/Post/scripts/uccnc_post.py index b7506cf966..a1382bb9a5 100644 --- a/src/Mod/CAM/Path/Post/scripts/uccnc_post.py +++ b/src/Mod/CAM/Path/Post/scripts/uccnc_post.py @@ -246,20 +246,14 @@ UNIT_SPEED_FORMAT = UNIT_SPEED_FORMAT_METRIC parser = argparse.ArgumentParser(prog=__name__, add_help=False) parser.add_argument("--name", help="GCode program name") parser.add_argument("--no-header", action="store_true", help="suppress header output") -parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" -) -parser.add_argument( - "--line-numbers", action="store_true", help="suppress prefix with line numbers" -) +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") +parser.add_argument("--line-numbers", action="store_true", help="suppress prefix with line numbers") parser.add_argument( "--no-show-editor", action="store_true", help="don't pop up editor before writing output", ) -parser.add_argument( - "--precision", default="3", help="number of digits of precision, default=3" -) +parser.add_argument("--precision", default="3", help="number of digits of precision, default=3") parser.add_argument( "--preamble", help='set commands to be issued before the first command, default="G17\nG90\nG54"', @@ -413,9 +407,7 @@ def export(objectslist, filename, argstring): for obj in objectslist: if not hasattr(obj, "Path"): print( - "the object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "the object " + obj.Name + " is not a path. Please select only path and Compounds." ) return None @@ -617,9 +609,7 @@ def parse(pathobj): currLocation[param] != c.Parameters[param] or REPEAT_ARGUMENTS ): if c.Name not in ["G0", "G00"]: # No F in G0 - speed = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + speed = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) if speed.getValueAs(UNIT_SPEED_FORMAT) > 0.0: commandlist.append( param @@ -646,14 +636,9 @@ def parse(pathobj): ): continue else: - pos = Units.Quantity( - c.Parameters[param], FreeCAD.Units.Length - ) + pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) commandlist.append( - param - + format( - float(pos.getValueAs(UNIT_FORMAT)), precision_string - ) + param + format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) ) # store the latest command diff --git a/src/Mod/CAM/Path/Post/scripts/wedm_post.py b/src/Mod/CAM/Path/Post/scripts/wedm_post.py index ca64fc5e34..fef75e01ff 100644 --- a/src/Mod/CAM/Path/Post/scripts/wedm_post.py +++ b/src/Mod/CAM/Path/Post/scripts/wedm_post.py @@ -49,39 +49,23 @@ now = datetime.datetime.now() parser = argparse.ArgumentParser(prog="wedm", add_help=False) parser.add_argument("--no-header", action="store_true", help="suppress header output") +parser.add_argument("--no-comments", action="store_true", help="suppress comment output") parser.add_argument( - "--no-comments", action="store_true", help="suppress comment output" + "--comments-character", default="", help="Use provided character before comments" ) parser.add_argument( - "--comments-character", - default="", - help="Use provided character before comments") -parser.add_argument( - "--command-space", - default=" ", - help="Use provided character as space in commands") -parser.add_argument( - "--endline-character", - default="", - help="Use provided character at end of line") -parser.add_argument( - "--line-numbers", action="store_true", help="prefix with line numbers" + "--command-space", default=" ", help="Use provided character as space in commands" ) +parser.add_argument("--endline-character", default="", help="Use provided character at end of line") +parser.add_argument("--line-numbers", action="store_true", help="prefix with line numbers") parser.add_argument( "--no-show-editor", action="store_true", help="don't pop up editor before writing output", ) -parser.add_argument( - "--scale", - default="1", - help="Scale factor for coordinates") -parser.add_argument( - "--precision", default="3", help="number of digits of precision, default=3" -) -parser.add_argument( - "--fixed-length", default="0", help="use fixed length coordinates, default=0" -) +parser.add_argument("--scale", default="1", help="Scale factor for coordinates") +parser.add_argument("--precision", default="3", help="number of digits of precision, default=3") +parser.add_argument("--fixed-length", default="0", help="use fixed length coordinates, default=0") parser.add_argument( "--preamble", help='set commands to be issued before the first command, default="G17\nG90"', @@ -98,9 +82,7 @@ parser.add_argument( action="store_true", help="Output the Same G-command Name USE NonModal Mode", ) -parser.add_argument( - "--axis-modal", action="store_true", help="Output the Same Axis Value Mode" -) +parser.add_argument("--axis-modal", action="store_true", help="Output the Same Axis Value Mode") parser.add_argument( "--no-tlo", action="store_true", @@ -116,22 +98,18 @@ parser.add_argument( action="store_true", help="Don't output units G20/G21", ) -parser.add_argument( - "--relative", - action="store_true", - help="Generate Relative GCODE") +parser.add_argument("--relative", action="store_true", help="Generate Relative GCODE") parser.add_argument( "--two-digit-codes", action="store_true", - help="Add trailing 0 to codes lower than 10 (G1 -> G01)") -parser.add_argument( - "--force-sign", - action="store_true", - help="Always add sign to coordinates") + help="Add trailing 0 to codes lower than 10 (G1 -> G01)", +) +parser.add_argument("--force-sign", action="store_true", help="Always add sign to coordinates") parser.add_argument( "--ignore-operations", default="", - help="Ignore provided operations, use Labels and separate with ','") + help="Ignore provided operations, use Labels and separate with ','", +) TOOLTIP_ARGS = parser.format_help() @@ -145,9 +123,7 @@ OUTPUT_LINE_NUMBERS = False SHOW_EDITOR = True MODAL = False # if true commands are suppressed if the same as previous line. USE_TLO = True # if true G43 will be output following tool changes -OUTPUT_DOUBLES = ( - True # if false duplicate axis values are suppressed if the same as previous line. -) +OUTPUT_DOUBLES = True # if false duplicate axis values are suppressed if the same as previous line. LINENR = 100 # line number starting value USE_RAPIDS = False OMIT_UNITS = False @@ -186,8 +162,6 @@ POST_OPERATION = """""" TOOL_CHANGE = """""" - - def processArguments(argstring): global OUTPUT_HEADER global OUTPUT_COMMENTS @@ -207,7 +181,7 @@ def processArguments(argstring): global MODAL global USE_TLO global OUTPUT_DOUBLES - global LOCATION # keep track for incremental + global LOCATION # keep track for incremental global USE_RAPIDS global OMIT_UNITS global RELATIVE_GCODE @@ -251,12 +225,12 @@ def processArguments(argstring): if args.omit_units: OMIT_UNITS = True if args.relative: - print ("relative") + print("relative") RELATIVE_GCODE = True - #PREAMBLE = PREAMBLE.replace("G90", "") - #PREAMBLE = PREAMBLE.replace("G91", "") + # PREAMBLE = PREAMBLE.replace("G90", "") + # PREAMBLE = PREAMBLE.replace("G91", "") PREAMBLE += "\nG91" - LOCATION = {'X':0, 'Y':0, 'Z':0} + LOCATION = {"X": 0, "Y": 0, "Z": 0} if args.two_digit_codes: TWO_DIGIT_CODES = True if args.force_sign: @@ -281,9 +255,7 @@ def export(objectslist, filename, argstring): for obj in objectslist: if not hasattr(obj, "Path"): print( - "the object " - + obj.Name - + " is not a path. Please select only path and Compounds." + "the object " + obj.Name + " is not a path. Please select only path and Compounds." ) return None @@ -325,12 +297,12 @@ def export(objectslist, filename, argstring): print(job.MachineUnits) if job.MachineUnits == "Metric": UNITS = "G21" - UNIT_FORMAT = 'mm' - UNIT_SPEED_FORMAT = 'mm/min' + UNIT_FORMAT = "mm" + UNIT_SPEED_FORMAT = "mm/min" else: UNITS = "G20" - UNIT_FORMAT = 'in' - UNIT_SPEED_FORMAT = 'in/min' + UNIT_FORMAT = "in" + UNIT_SPEED_FORMAT = "in/min" # ignore selected operations if obj.Label in IGNORE_OPERATIONS: @@ -338,17 +310,17 @@ def export(objectslist, filename, argstring): # do the pre_op if OUTPUT_COMMENTS: gcode += linenumber() + COMMENT_CHAR + "(begin operation: %s)\n" % obj.Label - gcode += linenumber() + COMMENT_CHAR + "(machine: %s, %s)\n" % (MACHINE_NAME, UNIT_SPEED_FORMAT) + gcode += ( + linenumber() + + COMMENT_CHAR + + "(machine: %s, %s)\n" % (MACHINE_NAME, UNIT_SPEED_FORMAT) + ) for line in PRE_OPERATION.splitlines(True): gcode += linenumber() + line # get coolant mode coolantMode = "None" - if ( - hasattr(obj, "CoolantMode") - or hasattr(obj, "Base") - and hasattr(obj.Base, "CoolantMode") - ): + if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): if hasattr(obj, "CoolantMode"): coolantMode = obj.CoolantMode else: @@ -469,9 +441,9 @@ def parse(pathobj): # out += linenumber() + COMMENT_CHAR + "(" + pathobj.Label + ")\n" for c in PathUtils.getPathWithPlacement(pathobj).Commands: - # For Debug Only - # if OUTPUT_COMMENTS: - # out += linenumber() + COMMENT_CHAR + "(" + str(c) + ")\n" + # For Debug Only + # if OUTPUT_COMMENTS: + # out += linenumber() + COMMENT_CHAR + "(" + str(c) + ")\n" outstring = [] command = c.Name @@ -484,9 +456,9 @@ def parse(pathobj): if command == lastcommand: outstring.pop(0) - if command[0] == "(": # command is a comment - if OUTPUT_COMMENTS: # Edit comment with COMMENT_CHAR - outstring.insert(0,COMMENT_CHAR) + if command[0] == "(": # command is a comment + if OUTPUT_COMMENTS: # Edit comment with COMMENT_CHAR + outstring.insert(0, COMMENT_CHAR) else: continue @@ -501,9 +473,7 @@ def parse(pathobj): "G0", "G00", ]: # linuxcnc doesn't use rapid speeds - speed = Units.Quantity( - c.Parameters["F"], FreeCAD.Units.Velocity - ) + speed = Units.Quantity(c.Parameters["F"], FreeCAD.Units.Velocity) if speed.getValueAs(UNIT_SPEED_FORMAT) > 0.0: outstring.append( param @@ -530,31 +500,41 @@ def parse(pathobj): (not OUTPUT_DOUBLES) and (param in currLocation) and (currLocation[param] == c.Parameters[param]) - ): + ): continue else: if RELATIVE_GCODE and (param != "I" and param != "J"): - pos = Units.Quantity(c.Parameters[param] - currLocation[param], FreeCAD.Units.Length) - print(f'currlocation: {currLocation[param]} param: {c.Parameters[param]} pos: {pos}') + pos = Units.Quantity( + c.Parameters[param] - currLocation[param], FreeCAD.Units.Length + ) + print( + f"currlocation: {currLocation[param]} param: {c.Parameters[param]} pos: {pos}" + ) if pos == 0: # Remove no movement - continue; + continue else: pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length) - pos = pos*SCALE + pos = pos * SCALE sign = "" if pos >= 0 and FORCE_SIGN: sign = "+" - stringout = sign+format(float(pos.getValueAs(UNIT_FORMAT)), precision_string) + stringout = sign + format( + float(pos.getValueAs(UNIT_FORMAT)), precision_string + ) # Remove unneeded 0s on incremental moves this is needed since some numbers are zero only after applying precision - if RELATIVE_GCODE and command in move_comands and (float(stringout) == 0): - continue; + if ( + RELATIVE_GCODE + and command in move_comands + and (float(stringout) == 0) + ): + continue # Force trailing zeros if FIXED_LENGTH > 0: - extra = 1 if stringout[0] in ["+","-"] else 0 + extra = 1 if stringout[0] in ["+", "-"] else 0 stringout = stringout.zfill(FIXED_LENGTH + extra) outstring.append(param + stringout) @@ -582,10 +562,10 @@ def parse(pathobj): if len(outstring) >= 1: if len(outstring) == 1 and (outstring[0] == "G0" or outstring[0] == "G1"): # Don't write empty moves (Generated when Z moves are ignored for EDM) - print('Ignoring: '+ command + ':' + outstring[0]) + print("Ignoring: " + command + ":" + outstring[0]) continue if TWO_DIGIT_CODES and len(command) == 2 and outstring[0] == command: - outstring[0] = command[0]+"0"+command[1] + outstring[0] = command[0] + "0" + command[1] if OUTPUT_LINE_NUMBERS: outstring.insert(0, (linenumber())) @@ -599,12 +579,12 @@ def parse(pathobj): out += w # Note: Do *not* strip `out`, since that forces the allocation # of a contiguous string & thus quadratic complexity. - out += ENDLINE+"\n" + out += ENDLINE + "\n" # store the latest command after written lastcommand = command - return out + # print(__name__ + " gcode postprocessor loaded.") diff --git a/src/Mod/CAM/Path/Preferences.py b/src/Mod/CAM/Path/Preferences.py index ae26412631..88dee7a4dc 100644 --- a/src/Mod/CAM/Path/Preferences.py +++ b/src/Mod/CAM/Path/Preferences.py @@ -98,9 +98,7 @@ def allAvailablePostProcessors(): def allEnabledPostProcessors(include=None): blacklist = postProcessorBlacklist() enabled = [ - processor - for processor in allAvailablePostProcessors() - if processor not in blacklist + processor for processor in allAvailablePostProcessors() if processor not in blacklist ] if include: postlist = list(set(include + enabled)) @@ -279,9 +277,7 @@ def suppressVelocity(): return preferences().GetBool(WarningSuppressVelocity, False) -def setPreferencesAdvanced( - ocl, warnSpeeds, warnRapids, warnModes, warnOCL, warnVelocity -): +def setPreferencesAdvanced(ocl, warnSpeeds, warnRapids, warnModes, warnOCL, warnVelocity): preferences().SetBool(EnableAdvancedOCLFeatures, ocl) preferences().SetBool(WarningSuppressAllSpeeds, warnSpeeds) preferences().SetBool(WarningSuppressRapidSpeeds, warnRapids) @@ -295,9 +291,7 @@ def lastFileToolLibrary(): if filename.endswith(".fctl") and os.path.isfile(filename): return filename - libpath = preferences().GetString( - LastPathToolLibrary, pathDefaultToolsPath("Library") - ) + libpath = preferences().GetString(LastPathToolLibrary, pathDefaultToolsPath("Library")) libFiles = [f for f in glob.glob(libpath + "/*.fctl")] libFiles.sort() if len(libFiles) >= 1: diff --git a/src/Mod/CAM/Path/Tool/Bit.py b/src/Mod/CAM/Path/Tool/Bit.py index 62b3f4c4ce..b2b2905128 100644 --- a/src/Mod/CAM/Path/Tool/Bit.py +++ b/src/Mod/CAM/Path/Tool/Bit.py @@ -147,9 +147,7 @@ class ToolBit(object): "App::PropertyLink", "BitBody", "Base", - QT_TRANSLATE_NOOP( - "App::Property", "The parametrized body representing the tool bit" - ), + QT_TRANSLATE_NOOP("App::Property", "The parametrized body representing the tool bit"), ) obj.addProperty( "App::PropertyFile", @@ -167,9 +165,7 @@ class ToolBit(object): "App::PropertyStringList", "BitPropertyNames", "Base", - QT_TRANSLATE_NOOP( - "App::Property", "List of all properties inherited from the bit" - ), + QT_TRANSLATE_NOOP("App::Property", "List of all properties inherited from the bit"), ) if path: @@ -205,9 +201,7 @@ class ToolBit(object): "App::PropertyStringList", "BitPropertyNames", "Base", - QT_TRANSLATE_NOOP( - "App::Property", "List of all properties inherited from the bit" - ), + QT_TRANSLATE_NOOP("App::Property", "List of all properties inherited from the bit"), ) propNames = [] for prop in obj.PropertiesList: @@ -348,9 +342,7 @@ class ToolBit(object): (doc, docOpened) = self._loadBitBody(obj, path) except FileNotFoundError: Path.Log.error( - "Could not find shape file {} for tool bit {}".format( - obj.BitShape, obj.Label - ) + "Could not find shape file {} for tool bit {}".format(obj.BitShape, obj.Label) ) return @@ -366,23 +358,17 @@ class ToolBit(object): if bitBody.ViewObject: bitBody.ViewObject.Visibility = False - Path.Log.debug( - "bitBody.{} ({}): {}".format(bitBody.Label, bitBody.Name, type(bitBody)) - ) + Path.Log.debug("bitBody.{} ({}): {}".format(bitBody.Label, bitBody.Name, type(bitBody))) propNames = [] - for attributes in [ - o for o in bitBody.Group if PathPropertyBag.IsPropertyBag(o) - ]: + for attributes in [o for o in bitBody.Group if PathPropertyBag.IsPropertyBag(o)]: Path.Log.debug("Process properties from {}".format(attributes.Label)) for prop in attributes.Proxy.getCustomProperties(): self._setupProperty(obj, prop, attributes) propNames.append(prop) if not propNames: Path.Log.error( - "Did not find a PropertyBag in {} - not a ToolBit shape?".format( - docName - ) + "Did not find a PropertyBag in {} - not a ToolBit shape?".format(docName) ) # has to happen last because it could trigger op.execute evaluations @@ -445,9 +431,7 @@ class ToolBit(object): obj.File = path return True except (OSError, IOError) as e: - Path.Log.error( - "Could not save tool {} to {} ({})".format(obj.Label, path, e) - ) + Path.Log.error("Could not save tool {} to {} ({})".format(obj.Label, path, e)) raise def templateAttrs(self, obj): diff --git a/src/Mod/CAM/Path/Tool/Controller.py b/src/Mod/CAM/Path/Tool/Controller.py index 2b8cc0a3ac..8b5e4b3fb5 100644 --- a/src/Mod/CAM/Path/Tool/Controller.py +++ b/src/Mod/CAM/Path/Tool/Controller.py @@ -72,9 +72,7 @@ class ToolController: "App::PropertyFloat", "SpindleSpeed", "Tool", - QT_TRANSLATE_NOOP( - "App::Property", "The speed of the cutting spindle in RPM" - ), + QT_TRANSLATE_NOOP("App::Property", "The speed of the cutting spindle in RPM"), ) obj.addProperty( "App::PropertyEnumeration", @@ -177,15 +175,11 @@ class ToolController: if template.get(ToolControllerTemplate.HorizRapid): obj.HorizRapid = template.get(ToolControllerTemplate.HorizRapid) if template.get(ToolControllerTemplate.SpindleSpeed): - obj.SpindleSpeed = float( - template.get(ToolControllerTemplate.SpindleSpeed) - ) + obj.SpindleSpeed = float(template.get(ToolControllerTemplate.SpindleSpeed)) if template.get(ToolControllerTemplate.SpindleDir): obj.SpindleDir = template.get(ToolControllerTemplate.SpindleDir) if template.get(ToolControllerTemplate.ToolNumber): - obj.ToolNumber = int( - template.get(ToolControllerTemplate.ToolNumber) - ) + obj.ToolNumber = int(template.get(ToolControllerTemplate.ToolNumber)) if template.get(ToolControllerTemplate.Tool): self.ensureToolBit(obj) toolVersion = template.get(ToolControllerTemplate.Tool).get( @@ -205,11 +199,7 @@ class ToolController: Path.Log.error( f"{obj.Name} - unknown Tool version {toolVersion} - ignoring" ) - if ( - obj.Tool - and obj.Tool.ViewObject - and obj.Tool.ViewObject.Visibility - ): + if obj.Tool and obj.Tool.ViewObject and obj.Tool.ViewObject.Visibility: obj.Tool.ViewObject.Visibility = False if template.get(ToolControllerTemplate.Expressions): for exprDef in template.get(ToolControllerTemplate.Expressions): @@ -225,9 +215,7 @@ class ToolController: ) ) else: - Path.Log.error( - "PathToolController template has no version - corrupted template file?" - ) + Path.Log.error("PathToolController template has no version - corrupted template file?") def templateAttrs(self, obj): """templateAttrs(obj) ... answer a dictionary with all properties that should be stored for a template.""" diff --git a/src/Mod/CAM/Path/Tool/Gui/Bit.py b/src/Mod/CAM/Path/Tool/Gui/Bit.py index fc15c0ec88..423e6f9c66 100644 --- a/src/Mod/CAM/Path/Tool/Gui/Bit.py +++ b/src/Mod/CAM/Path/Tool/Gui/Bit.py @@ -112,9 +112,7 @@ class ViewProvider(object): if os.path.exists(vobj.Object.BitShape): self.setEdit(vobj) else: - msg = translate( - "CAM_Toolbit", "Toolbit cannot be edited: Shapefile not found" - ) + msg = translate("CAM_Toolbit", "Toolbit cannot be edited: Shapefile not found") diag = QtGui.QMessageBox(QtGui.QMessageBox.Warning, "Error", msg) diag.setWindowModality(QtCore.Qt.ApplicationModal) diag.exec_() @@ -166,7 +164,8 @@ class TaskPanel: class ToolBitGuiFactory(PathToolBit.ToolBitFactory): def Create(self, name="ToolBit", shapeFile=None, path=None): """Create(name = 'ToolBit') ... creates a new tool bit. - It is assumed the tool will be edited immediately so the internal bit body is still attached.""" + It is assumed the tool will be edited immediately so the internal bit body is still attached. + """ Path.Log.track(name, shapeFile, path) FreeCAD.ActiveDocument.openTransaction("Create ToolBit") diff --git a/src/Mod/CAM/Path/Tool/Gui/BitCmd.py b/src/Mod/CAM/Path/Tool/Gui/BitCmd.py index 2d80a13062..d8094e5a24 100644 --- a/src/Mod/CAM/Path/Tool/Gui/BitCmd.py +++ b/src/Mod/CAM/Path/Tool/Gui/BitCmd.py @@ -47,9 +47,7 @@ class CommandToolBitCreate: return { "Pixmap": "CAM_ToolBit", "MenuText": QT_TRANSLATE_NOOP("CAM_ToolBitCreate", "Create Tool"), - "ToolTip": QT_TRANSLATE_NOOP( - "CAM_ToolBitCreate", "Creates a new ToolBit object" - ), + "ToolTip": QT_TRANSLATE_NOOP("CAM_ToolBitCreate", "Creates a new ToolBit object"), } def IsActive(self): diff --git a/src/Mod/CAM/Path/Tool/Gui/BitEdit.py b/src/Mod/CAM/Path/Tool/Gui/BitEdit.py index 52a1d37dd9..9b18fe7f4f 100644 --- a/src/Mod/CAM/Path/Tool/Gui/BitEdit.py +++ b/src/Mod/CAM/Path/Tool/Gui/BitEdit.py @@ -176,9 +176,7 @@ class ToolBitEditor(object): label.setEditable(False) value = QtGui.QStandardItem() - value.setData( - PathUtil.getPropertyValueString(tool, prop), QtCore.Qt.DisplayRole - ) + value.setData(PathUtil.getPropertyValueString(tool, prop), QtCore.Qt.DisplayRole) value.setData(tool, _Delegate.ObjectRole) value.setData(prop, _Delegate.PropertyRole) @@ -262,9 +260,7 @@ class ToolBitEditor(object): path = self.tool.BitShape if not path: path = Path.Preferences.lastPathToolShape() - foo = QtGui.QFileDialog.getOpenFileName( - self.form, "Path - Tool Shape", path, "*.fcstd" - ) + foo = QtGui.QFileDialog.getOpenFileName(self.form, "Path - Tool Shape", path, "*.fcstd") if foo and foo[0]: Path.Preferences.setLastPathToolShape(os.path.dirname(foo[0])) self.form.shapePath.setText(foo[0]) diff --git a/src/Mod/CAM/Path/Tool/Gui/BitLibrary.py b/src/Mod/CAM/Path/Tool/Gui/BitLibrary.py index 982b1f1c7a..ff635f6b79 100644 --- a/src/Mod/CAM/Path/Tool/Gui/BitLibrary.py +++ b/src/Mod/CAM/Path/Tool/Gui/BitLibrary.py @@ -93,9 +93,7 @@ def checkWorkingDir(): if workingdir[-8:] == os.path.sep + "Library": workingdir = workingdir[:-8] # trim off trailing /Library if user chose it - Path.Preferences.setLastPathToolLibrary( - "{}{}Library".format(workingdir, os.path.sep) - ) + Path.Preferences.setLastPathToolLibrary("{}{}Library".format(workingdir, os.path.sep)) Path.Preferences.setLastPathToolBit("{}{}Bit".format(workingdir, os.path.sep)) Path.Log.debug("setting workingdir to: {}".format(workingdir)) @@ -142,9 +140,9 @@ def checkWorkingDir(): ret = qm.question( None, "", - translate( - "CAM_ToolBit", "Copy example files to new {} directory?" - ).format(dir), + translate("CAM_ToolBit", "Copy example files to new {} directory?").format( + dir + ), qm.Yes | qm.No, ) if ret == qm.Yes: @@ -158,10 +156,7 @@ def checkWorkingDir(): # if no library is set, choose the first one in the Library directory if Path.Preferences.lastFileToolLibrary() is None: libFiles = [ - f - for f in glob.glob( - Path.Preferences.lastPathToolLibrary() + os.path.sep + "*.fctl" - ) + f for f in glob.glob(Path.Preferences.lastPathToolLibrary() + os.path.sep + "*.fctl") ] Path.Preferences.setLastFileToolLibrary(libFiles[0]) @@ -209,9 +204,7 @@ class _TableView(PySide.QtGui.QTableView): PySide.QtCore.Qt.EditRole, ) if col == 0: - model.setData( - model.index(dstRow, col), srcItem.data(_PathRole), _PathRole - ) + model.setData(model.index(dstRow, col), srcItem.data(_PathRole), _PathRole) # Even a clone of a tool gets its own uuid so it can be identified when # rearranging the order or inserting/deleting rows model.setData(model.index(dstRow, col), UUID.uuid4(), _UuidRole) @@ -441,9 +434,7 @@ class ToolBitSelector(object): self.form.tools.setModel(self.toolModel) self.form.tools.selectionModel().selectionChanged.connect(self.enableButtons) - self.form.tools.doubleClicked.connect( - partial(self.selectedOrAllToolControllers) - ) + self.form.tools.doubleClicked.connect(partial(self.selectedOrAllToolControllers)) # Set the library model to the combobox self.form.cboLibraries.setModel(self.libraryModel) @@ -471,21 +462,14 @@ class ToolBitSelector(object): libPath = item.data(_PathRole) self.form.cboLibraries.setToolTip(f"{libPath}") else: - self.form.cboLibraries.setToolTip( - translate("CAM_Toolbit", "Select a library") - ) + self.form.cboLibraries.setToolTip(translate("CAM_Toolbit", "Select a library")) else: - self.form.cboLibraries.setToolTip( - translate("CAM_Toolbit", "No library selected") - ) + self.form.cboLibraries.setToolTip(translate("CAM_Toolbit", "No library selected")) def enableButtons(self): selected = len(self.form.tools.selectedIndexes()) >= 1 if selected: - jobs = ( - len([1 for j in FreeCAD.ActiveDocument.Objects if j.Name[:3] == "Job"]) - >= 1 - ) + jobs = len([1 for j in FreeCAD.ActiveDocument.Objects if j.Name[:3] == "Job"]) >= 1 self.form.addToolController.setEnabled(selected and jobs) def libraryEditorOpen(self): @@ -538,9 +522,7 @@ class ToolBitSelector(object): tools = self.selectedOrAllTools() for tool in tools: - tc = PathToolControllerGui.Create( - "TC: {}".format(tool[1].Label), tool[1], tool[0] - ) + tc = PathToolControllerGui.Create("TC: {}".format(tool[1].Label), tool[1], tool[0]) job.Proxy.addToolController(tc) FreeCAD.ActiveDocument.recompute() @@ -577,9 +559,7 @@ class ToolBitLibrary(object): self.listModel = PySide.QtGui.QStandardItemModel() self.form = FreeCADGui.PySideUic.loadUi(":/panels/ToolBitLibraryEdit.ui") self.toolTableView = _TableView(self.form.toolTableGroup) - self.form.toolTableGroup.layout().replaceWidget( - self.form.toolTable, self.toolTableView - ) + self.form.toolTableGroup.layout().replaceWidget(self.form.toolTable, self.toolTableView) self.form.toolTable.hide() self.setupUI() self.title = self.form.windowTitle() @@ -631,9 +611,7 @@ class ToolBitLibrary(object): def toolDelete(self): Path.Log.track() - selectedRows = set( - [index.row() for index in self.toolTableView.selectedIndexes()] - ) + selectedRows = set([index.row() for index in self.toolTableView.selectedIndexes()]) for row in sorted(list(selectedRows), key=lambda r: -r): self.toolModel.removeRows(row, 1) @@ -725,9 +703,7 @@ class ToolBitLibrary(object): self.temptool, self.form.toolTableGroup, loadBitBody=False ) - QBtn = ( - PySide.QtGui.QDialogButtonBox.Ok | PySide.QtGui.QDialogButtonBox.Cancel - ) + QBtn = PySide.QtGui.QDialogButtonBox.Ok | PySide.QtGui.QDialogButtonBox.Cancel buttonBox = PySide.QtGui.QDialogButtonBox(QBtn) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) @@ -754,11 +730,7 @@ class ToolBitLibrary(object): if not (filename and filename[0]): self.loadData() - path = ( - filename[0] - if filename[0].endswith(".fctl") - else "{}.fctl".format(filename[0]) - ) + path = filename[0] if filename[0].endswith(".fctl") else "{}.fctl".format(filename[0]) library = {} tools = [] library["version"] = 1 @@ -774,9 +746,7 @@ class ToolBitLibrary(object): library["version"] = 1 library["tools"] = tools for row in range(self.toolModel.rowCount()): - toolNr = self.toolModel.data( - self.toolModel.index(row, 0), PySide.QtCore.Qt.EditRole - ) + toolNr = self.toolModel.data(self.toolModel.index(row, 0), PySide.QtCore.Qt.EditRole) toolPath = self.toolModel.data(self.toolModel.index(row, 0), _PathRole) if Path.Preferences.toolsStoreAbsolutePaths(): bitPath = toolPath @@ -882,30 +852,20 @@ class ToolBitLibrary(object): self.form, translate("CAM_ToolBit", "Save toolbit library"), Path.Preferences.lastPathToolLibrary(), - "{};;{};;{}".format( - TooltableTypeJSON, TooltableTypeLinuxCNC, TooltableTypeCamotics - ), + "{};;{};;{}".format(TooltableTypeJSON, TooltableTypeLinuxCNC, TooltableTypeCamotics), ) if filename and filename[0]: if filename[1] == TooltableTypeLinuxCNC: - path = ( - filename[0] - if filename[0].endswith(".tbl") - else "{}.tbl".format(filename[0]) - ) + path = filename[0] if filename[0].endswith(".tbl") else "{}.tbl".format(filename[0]) self.libararySaveLinuxCNC(path) elif filename[1] == TooltableTypeCamotics: path = ( - filename[0] - if filename[0].endswith(".json") - else "{}.json".format(filename[0]) + filename[0] if filename[0].endswith(".json") else "{}.json".format(filename[0]) ) self.libararySaveCamotics(path) else: path = ( - filename[0] - if filename[0].endswith(".fctl") - else "{}.fctl".format(filename[0]) + filename[0] if filename[0].endswith(".fctl") else "{}.fctl".format(filename[0]) ) self.path = path self.librarySave() @@ -944,9 +904,7 @@ class ToolBitLibrary(object): ) frontangle = bit.FrontAngle if hasattr(bit, "FrontAngle") else "0" backangle = bit.BackAngle if hasattr(bit, "BackAngle") else "0" - orientation = ( - bit.Orientation if hasattr(bit, "Orientation") else "0" - ) + orientation = bit.Orientation if hasattr(bit, "Orientation") else "0" remark = bit.Label fp.write( @@ -994,14 +952,10 @@ class ToolBitLibrary(object): } toollist = {} - unitstring = ( - "imperial" if FreeCAD.Units.getSchema() in [2, 3, 5, 7] else "metric" - ) + unitstring = "imperial" if FreeCAD.Units.getSchema() in [2, 3, 5, 7] else "metric" for row in range(self.toolModel.rowCount()): - toolNr = self.toolModel.data( - self.toolModel.index(row, 0), PySide.QtCore.Qt.EditRole - ) + toolNr = self.toolModel.data(self.toolModel.index(row, 0), PySide.QtCore.Qt.EditRole) toolPath = self.toolModel.data(self.toolModel.index(row, 0), _PathRole) Path.Log.debug(toolPath) @@ -1027,9 +981,7 @@ class ToolBitLibrary(object): ) toolitem["description"] = bit.Label toolitem["length"] = ( - float(bit.Length.getUserPreferred()[0].split()[0]) - if hasattr(bit, "Length") - else 10 + float(bit.Length.getUserPreferred()[0].split()[0]) if hasattr(bit, "Length") else 10 ) if hasattr(bit, "Camotics"): diff --git a/src/Mod/CAM/Path/Tool/Gui/BitLibraryCmd.py b/src/Mod/CAM/Path/Tool/Gui/BitLibraryCmd.py index 53e2a447b7..ceb23ef406 100644 --- a/src/Mod/CAM/Path/Tool/Gui/BitLibraryCmd.py +++ b/src/Mod/CAM/Path/Tool/Gui/BitLibraryCmd.py @@ -72,9 +72,7 @@ class CommandToolBitLibraryOpen: def GetResources(self): return { "Pixmap": "CAM_ToolTable", - "MenuText": QT_TRANSLATE_NOOP( - "CAM_ToolBitLibraryOpen", "ToolBit Library editor" - ), + "MenuText": QT_TRANSLATE_NOOP("CAM_ToolBitLibraryOpen", "ToolBit Library editor"), "ToolTip": QT_TRANSLATE_NOOP( "CAM_ToolBitLibraryOpen", "Open an editor to manage ToolBit libraries" ), diff --git a/src/Mod/CAM/Path/Tool/Gui/Controller.py b/src/Mod/CAM/Path/Tool/Gui/Controller.py index 3e72b6ee1b..29a107943a 100644 --- a/src/Mod/CAM/Path/Tool/Gui/Controller.py +++ b/src/Mod/CAM/Path/Tool/Gui/Controller.py @@ -139,9 +139,7 @@ class CommandPathToolController(object): def GetResources(self): return { "Pixmap": "CAM_LengthOffset", - "MenuText": QT_TRANSLATE_NOOP( - "CAM_ToolController", "Add Tool Controller to the Job" - ), + "MenuText": QT_TRANSLATE_NOOP("CAM_ToolController", "Add Tool Controller to the Job"), "ToolTip": QT_TRANSLATE_NOOP("CAM_ToolController", "Add Tool Controller"), } @@ -184,21 +182,13 @@ class ToolControllerEditor(object): self.obj = obj comboToPropertyMap = [("spindleDirection", "SpindleDir")] - enumTups = PathToolController.ToolController.propertyEnumerations( - dataType="raw" - ) + enumTups = PathToolController.ToolController.propertyEnumerations(dataType="raw") PathGuiUtil.populateCombobox(self.form, enumTups, comboToPropertyMap) self.vertFeed = PathGuiUtil.QuantitySpinBox(self.form.vertFeed, obj, "VertFeed") - self.horizFeed = PathGuiUtil.QuantitySpinBox( - self.form.horizFeed, obj, "HorizFeed" - ) - self.vertRapid = PathGuiUtil.QuantitySpinBox( - self.form.vertRapid, obj, "VertRapid" - ) - self.horizRapid = PathGuiUtil.QuantitySpinBox( - self.form.horizRapid, obj, "HorizRapid" - ) + self.horizFeed = PathGuiUtil.QuantitySpinBox(self.form.horizFeed, obj, "HorizFeed") + self.vertRapid = PathGuiUtil.QuantitySpinBox(self.form.vertRapid, obj, "VertRapid") + self.horizRapid = PathGuiUtil.QuantitySpinBox(self.form.horizRapid, obj, "HorizRapid") self.editor = None self.form.toolBox.widget(1).hide() diff --git a/src/Mod/CAM/PathCommands.py b/src/Mod/CAM/PathCommands.py index 34db4c977a..9658b7f8e3 100644 --- a/src/Mod/CAM/PathCommands.py +++ b/src/Mod/CAM/PathCommands.py @@ -92,9 +92,7 @@ class _CommandSelectLoop: obj = sel.Object edge1 = sel.SubObjects[0] if "Face" in sel.SubElementNames[0]: - loop = horizontalFaceLoop( - sel.Object, sel.SubObjects[0], sel.SubElementNames - ) + loop = horizontalFaceLoop(sel.Object, sel.SubObjects[0], sel.SubElementNames) if loop: FreeCADGui.Selection.clearSelection() FreeCADGui.Selection.addSelection(sel.Object, loop) @@ -111,9 +109,7 @@ class _CommandSelectLoop: for i in loopwire.Edges: for e in elist: if e.hashCode() == i.hashCode(): - FreeCADGui.Selection.addSelection( - obj, "Edge" + str(elist.index(e) + 1) - ) + FreeCADGui.Selection.addSelection(obj, "Edge" + str(elist.index(e) + 1)) elif FreeCAD.GuiUp: QtGui.QMessageBox.information( None, @@ -189,12 +185,8 @@ class _CopyOperation: def GetResources(self): return { "Pixmap": "CAM_OpCopy", - "MenuText": QT_TRANSLATE_NOOP( - "CAM_OperationCopy", "Copy the operation in the job" - ), - "ToolTip": QT_TRANSLATE_NOOP( - "CAM_OperationCopy", "Copy the operation in the job" - ), + "MenuText": QT_TRANSLATE_NOOP("CAM_OperationCopy", "Copy the operation in the job"), + "ToolTip": QT_TRANSLATE_NOOP("CAM_OperationCopy", "Copy the operation in the job"), "CmdType": "ForEdit", } diff --git a/src/Mod/CAM/PathGlobal.h b/src/Mod/CAM/PathGlobal.h index 22bd897467..c00676fb35 100644 --- a/src/Mod/CAM/PathGlobal.h +++ b/src/Mod/CAM/PathGlobal.h @@ -29,18 +29,18 @@ // Path #ifndef PathExport #ifdef Path_EXPORTS -# define PathExport FREECAD_DECL_EXPORT +#define PathExport FREECAD_DECL_EXPORT #else -# define PathExport FREECAD_DECL_IMPORT +#define PathExport FREECAD_DECL_IMPORT #endif #endif // PathGui #ifndef PathGuiExport #ifdef PathGui_EXPORTS -# define PathGuiExport FREECAD_DECL_EXPORT +#define PathGuiExport FREECAD_DECL_EXPORT #else -# define PathGuiExport FREECAD_DECL_IMPORT +#define PathGuiExport FREECAD_DECL_IMPORT #endif #endif @@ -62,4 +62,4 @@ #endif #endif -#endif //PATH_GLOBAL_H +#endif // PATH_GLOBAL_H diff --git a/src/Mod/CAM/PathPythonGui/simple_edit_panel.py b/src/Mod/CAM/PathPythonGui/simple_edit_panel.py index 738e040c9a..a581b85451 100644 --- a/src/Mod/CAM/PathPythonGui/simple_edit_panel.py +++ b/src/Mod/CAM/PathPythonGui/simple_edit_panel.py @@ -1,4 +1,3 @@ - import FreeCAD import FreeCADGui from PySide import QtGui @@ -59,8 +58,7 @@ class SimpleEditPanel: enum = self.obj.getEnumerationsOfProperty(prop_name) # Populate the combo box with the enumeration elements, use the form context for translation elements = [ - translate(self.form.objectName(), custom_lbls.get(itm, itm)) - for itm in enum + translate(self.form.objectName(), custom_lbls.get(itm, itm)) for itm in enum ] widget.clear() widget.addItems(elements) @@ -88,7 +86,9 @@ class SimpleEditPanel: ) def getStandardButtons(self): - return QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Cancel + return ( + QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Cancel + ) def clicked(self, button): # callback for standard buttons diff --git a/src/Mod/CAM/PathScripts/PathUtils.py b/src/Mod/CAM/PathScripts/PathUtils.py index 9d02eacce5..0b48c04b1e 100644 --- a/src/Mod/CAM/PathScripts/PathUtils.py +++ b/src/Mod/CAM/PathScripts/PathUtils.py @@ -106,9 +106,7 @@ def loopdetect(obj, edge1, edge2): candidates.append((wire.hashCode(), wire)) if e.hashCode() == edge2.hashCode(): candidates.append((wire.hashCode(), wire)) - loop = set( - [x for x in candidates if candidates.count(x) > 1] - ) # return the duplicate item + loop = set([x for x in candidates if candidates.count(x) > 1]) # return the duplicate item if len(loop) != 1: return None loopwire = next(x for x in loop)[1] @@ -122,8 +120,7 @@ def horizontalEdgeLoop(obj, edge): loops = [ w for w in wires - if all(Path.Geom.isHorizontal(e) for e in w.Edges) - and Path.Geom.isHorizontal(Part.Face(w)) + if all(Path.Geom.isHorizontal(e) for e in w.Edges) and Path.Geom.isHorizontal(Part.Face(w)) ] if len(loops) == 1: return loops[0] @@ -194,16 +191,13 @@ def filterArcs(arcEdge): else: arcstpt = arcEdge.valueAt(arcEdge.FirstParameter) arcmid = arcEdge.valueAt( - (arcEdge.LastParameter - arcEdge.FirstParameter) * 0.5 - + arcEdge.FirstParameter + (arcEdge.LastParameter - arcEdge.FirstParameter) * 0.5 + arcEdge.FirstParameter ) arcquad1 = arcEdge.valueAt( - (arcEdge.LastParameter - arcEdge.FirstParameter) * 0.25 - + arcEdge.FirstParameter + (arcEdge.LastParameter - arcEdge.FirstParameter) * 0.25 + arcEdge.FirstParameter ) # future midpt for arc1 arcquad2 = arcEdge.valueAt( - (arcEdge.LastParameter - arcEdge.FirstParameter) * 0.75 - + arcEdge.FirstParameter + (arcEdge.LastParameter - arcEdge.FirstParameter) * 0.75 + arcEdge.FirstParameter ) # future midpt for arc2 arcendpt = arcEdge.valueAt(arcEdge.LastParameter) # reconstruct with 2 arcs @@ -336,16 +330,11 @@ def getOffsetArea( def reverseEdge(e): if DraftGeomUtils.geomType(e) == "Circle": arcstpt = e.valueAt(e.FirstParameter) - arcmid = e.valueAt( - (e.LastParameter - e.FirstParameter) * 0.5 + e.FirstParameter - ) + arcmid = e.valueAt((e.LastParameter - e.FirstParameter) * 0.5 + e.FirstParameter) arcendpt = e.valueAt(e.LastParameter) arcofCirc = Part.ArcOfCircle(arcendpt, arcmid, arcstpt) newedge = arcofCirc.toShape() - elif ( - DraftGeomUtils.geomType(e) == "LineSegment" - or DraftGeomUtils.geomType(e) == "Line" - ): + elif DraftGeomUtils.geomType(e) == "LineSegment" or DraftGeomUtils.geomType(e) == "Line": stpt = e.valueAt(e.FirstParameter) endpt = e.valueAt(e.LastParameter) newedge = Part.makeLine(endpt, stpt) @@ -536,9 +525,7 @@ def guessDepths(objshape, subs=None): elif fbb.ZMax == fbb.ZMin and fbb.ZMax > bb.ZMin: # face/shelf final = fbb.ZMin - return depth_params( - clearance, safe, start, 1.0, 0.0, final, user_depths=None, equalstep=False - ) + return depth_params(clearance, safe, start, 1.0, 0.0, final, user_depths=None, equalstep=False) def drillTipLength(tool): @@ -552,8 +539,7 @@ def drillTipLength(tool): if angle <= 0 or angle >= 180: Path.Log.error( - translate("Path", "Invalid Cutting Edge Angle %.2f, must be >0° and <=180°") - % angle + translate("Path", "Invalid Cutting Edge Angle %.2f, must be >0° and <=180°") % angle ) return 0.0 @@ -562,9 +548,7 @@ def drillTipLength(tool): if length < 0: Path.Log.error( - translate( - "Path", "Cutting Edge Angle (%.2f) results in negative tool tip length" - ) + translate("Path", "Cutting Edge Angle (%.2f) results in negative tool tip length") % angle ) return 0.0 @@ -707,13 +691,9 @@ class depth_params(object): return depths if equalstep: - depths += self.__equal_steps( - self.__start_depth, depths[-1], self.__step_down - )[1:] + depths += self.__equal_steps(self.__start_depth, depths[-1], self.__step_down)[1:] else: - depths += self.__fixed_steps( - self.__start_depth, depths[-1], self.__step_down - )[1:] + depths += self.__fixed_steps(self.__start_depth, depths[-1], self.__step_down)[1:] depths.reverse() @@ -842,6 +822,7 @@ def RtoIJ(startpoint, command): return newcommand + def getPathWithPlacement(pathobj): """ Applies the rotation, and then position of the obj's Placement @@ -853,6 +834,7 @@ def getPathWithPlacement(pathobj): return applyPlacementToPath(pathobj.Placement, pathobj.Path) + def applyPlacementToPath(placement, path): """ Applies the rotation, and then position of the placement to path @@ -871,17 +853,13 @@ def applyPlacementToPath(placement, path): currY = 0 currZ = 0 for cmd in path.Commands: - if ( - (cmd.Name in CmdMoveRapid) - or (cmd.Name in CmdMove) - or (cmd.Name in CmdDrill) - ): + if (cmd.Name in CmdMoveRapid) or (cmd.Name in CmdMove) or (cmd.Name in CmdDrill): params = cmd.Parameters currX = x = params.get("X", currX) currY = y = params.get("Y", currY) currZ = z = params.get("Z", currZ) - x, y, z = placement.Rotation.multVec(FreeCAD.Vector(x, y ,z)) + x, y, z = placement.Rotation.multVec(FreeCAD.Vector(x, y, z)) if x != currX: params.update({"X": x}) diff --git a/src/Mod/CAM/PathScripts/PathUtilsGui.py b/src/Mod/CAM/PathScripts/PathUtilsGui.py index 5f9bade9b8..d2e9b3ed77 100644 --- a/src/Mod/CAM/PathScripts/PathUtilsGui.py +++ b/src/Mod/CAM/PathScripts/PathUtilsGui.py @@ -58,9 +58,7 @@ class PathUtilsUserInput(object): r = form.exec_() if not r: return None - return [ - i for i in controllers if i.Label == form.uiToolController.currentText() - ][0] + return [i for i in controllers if i.Label == form.uiToolController.currentText()][0] def chooseJob(self, jobs): job = None diff --git a/src/Mod/CAM/PathSimulator/App/AppPathSimulator.cpp b/src/Mod/CAM/PathSimulator/App/AppPathSimulator.cpp index 0f7d49343e..3b8d1dcf5b 100644 --- a/src/Mod/CAM/PathSimulator/App/AppPathSimulator.cpp +++ b/src/Mod/CAM/PathSimulator/App/AppPathSimulator.cpp @@ -29,16 +29,19 @@ #include "PathSimPy.h" -namespace PathSimulator { -class Module : public Py::ExtensionModule +namespace PathSimulator +{ +class Module: public Py::ExtensionModule { public: - Module() : Py::ExtensionModule("PathSimulator") + Module() + : Py::ExtensionModule("PathSimulator") { - initialize("This module is the PathSimulator module."); // register with Python + initialize("This module is the PathSimulator module."); // register with Python } - ~Module() override {} + ~Module() override + {} private: }; @@ -49,34 +52,34 @@ PyObject* initModule() } -} // namespace PathSimulator +} // namespace PathSimulator /* Python entry */ PyMOD_INIT_FUNC(PathSimulator) { - // load dependent module - try { - Base::Interpreter().runString("import Part"); - Base::Interpreter().runString("import Path"); - Base::Interpreter().runString("import Mesh"); - } - catch (const Base::Exception& e) { - PyErr_SetString(PyExc_ImportError, e.what()); - PyMOD_Return(nullptr); - } + // load dependent module + try { + Base::Interpreter().runString("import Part"); + Base::Interpreter().runString("import Path"); + Base::Interpreter().runString("import Mesh"); + } + catch (const Base::Exception& e) { + PyErr_SetString(PyExc_ImportError, e.what()); + PyMOD_Return(nullptr); + } - // + // PyObject* mod = PathSimulator::initModule(); Base::Console().Log("Loading PathSimulator module.... done\n"); - // Add Types to module - Base::Interpreter().addType(&PathSimulator::PathSimPy::Type, mod, "PathSim"); + // Add Types to module + Base::Interpreter().addType(&PathSimulator::PathSimPy::Type, mod, "PathSim"); - // NOTE: To finish the initialization of our own type objects we must - // call PyType_Ready, otherwise we run into a segmentation fault, later on. - // This function is responsible for adding inherited slots from a type's base class. - PathSimulator::PathSim::init(); + // NOTE: To finish the initialization of our own type objects we must + // call PyType_Ready, otherwise we run into a segmentation fault, later on. + // This function is responsible for adding inherited slots from a type's base class. + PathSimulator::PathSim::init(); - PyMOD_Return(mod); + PyMOD_Return(mod); } diff --git a/src/Mod/CAM/PathSimulator/App/PathSim.cpp b/src/Mod/CAM/PathSimulator/App/PathSim.cpp index 10ef7fc88a..efc53a98f4 100644 --- a/src/Mod/CAM/PathSimulator/App/PathSim.cpp +++ b/src/Mod/CAM/PathSimulator/App/PathSim.cpp @@ -28,60 +28,54 @@ using namespace Base; using namespace PathSimulator; -TYPESYSTEM_SOURCE(PathSimulator::PathSim , Base::BaseClass); +TYPESYSTEM_SOURCE(PathSimulator::PathSim, Base::BaseClass); PathSim::PathSim() -{ -} +{} PathSim::~PathSim() -{ -} +{} -void PathSim::BeginSimulation(Part::TopoShape * stock, float resolution) +void PathSim::BeginSimulation(Part::TopoShape* stock, float resolution) { - Base::BoundBox3d bbox = stock->getBoundBox(); - m_stock = std::make_unique(bbox.MinX, bbox.MinY, bbox.MinZ, bbox.LengthX(), bbox.LengthY(), bbox.LengthZ(), resolution); + Base::BoundBox3d bbox = stock->getBoundBox(); + m_stock = std::make_unique(bbox.MinX, + bbox.MinY, + bbox.MinZ, + bbox.LengthX(), + bbox.LengthY(), + bbox.LengthZ(), + resolution); } void PathSim::SetToolShape(const TopoDS_Shape& toolShape, float resolution) { - m_tool = std::make_unique(toolShape, resolution); + m_tool = std::make_unique(toolShape, resolution); } -Base::Placement * PathSim::ApplyCommand(Base::Placement * pos, Command * cmd) +Base::Placement* PathSim::ApplyCommand(Base::Placement* pos, Command* cmd) { - Point3D fromPos(*pos); - Point3D toPos(*pos); - toPos.UpdateCmd(*cmd); - if (m_tool) - { - if (cmd->Name == "G0" || cmd->Name == "G1") - { - m_stock->ApplyLinearTool(fromPos, toPos, *m_tool); - } - else if (cmd->Name == "G2") - { - Vector3d vcent = cmd->getCenter(); - Point3D cent(vcent); - m_stock->ApplyCircularTool(fromPos, toPos, cent, *m_tool, false); - } - else if (cmd->Name == "G3") - { - Vector3d vcent = cmd->getCenter(); - Point3D cent(vcent); - m_stock->ApplyCircularTool(fromPos, toPos, cent, *m_tool, true); - } - } + Point3D fromPos(*pos); + Point3D toPos(*pos); + toPos.UpdateCmd(*cmd); + if (m_tool) { + if (cmd->Name == "G0" || cmd->Name == "G1") { + m_stock->ApplyLinearTool(fromPos, toPos, *m_tool); + } + else if (cmd->Name == "G2") { + Vector3d vcent = cmd->getCenter(); + Point3D cent(vcent); + m_stock->ApplyCircularTool(fromPos, toPos, cent, *m_tool, false); + } + else if (cmd->Name == "G3") { + Vector3d vcent = cmd->getCenter(); + Point3D cent(vcent); + m_stock->ApplyCircularTool(fromPos, toPos, cent, *m_tool, true); + } + } - Base::Placement *plc = new Base::Placement(); - Vector3d vec(toPos.x, toPos.y, toPos.z); - plc->setPosition(vec); - return plc; + Base::Placement* plc = new Base::Placement(); + Vector3d vec(toPos.x, toPos.y, toPos.z); + plc->setPosition(vec); + return plc; } - - - - - - diff --git a/src/Mod/CAM/PathSimulator/App/PathSim.h b/src/Mod/CAM/PathSimulator/App/PathSim.h index 13ebdb6350..1ae91f541e 100644 --- a/src/Mod/CAM/PathSimulator/App/PathSim.h +++ b/src/Mod/CAM/PathSimulator/App/PathSim.h @@ -38,26 +38,26 @@ using namespace Path; namespace PathSimulator { - /** The representation of a CNC Toolpath Simulator */ +/** The representation of a CNC Toolpath Simulator */ - class PathSimulatorExport PathSim : public Base::BaseClass - { - TYPESYSTEM_HEADER(); +class PathSimulatorExport PathSim: public Base::BaseClass +{ + TYPESYSTEM_HEADER(); - public: - PathSim(); - ~PathSim(); +public: + PathSim(); + ~PathSim(); - void BeginSimulation(Part::TopoShape * stock, float resolution); - void SetToolShape(const TopoDS_Shape& toolShape, float resolution); - Base::Placement * ApplyCommand(Base::Placement * pos, Command * cmd); + void BeginSimulation(Part::TopoShape* stock, float resolution); + void SetToolShape(const TopoDS_Shape& toolShape, float resolution); + Base::Placement* ApplyCommand(Base::Placement* pos, Command* cmd); - public: - std::unique_ptr m_stock; - std::unique_ptr m_tool; - }; +public: + std::unique_ptr m_stock; + std::unique_ptr m_tool; +}; -} //namespace Path +} // namespace PathSimulator -#endif // PATHSIMULATOR_PathSim_H +#endif // PATHSIMULATOR_PathSim_H diff --git a/src/Mod/CAM/PathSimulator/App/PathSimPyImp.cpp b/src/Mod/CAM/PathSimulator/App/PathSimPyImp.cpp index cbbd7a39c1..3df111fb77 100644 --- a/src/Mod/CAM/PathSimulator/App/PathSimPyImp.cpp +++ b/src/Mod/CAM/PathSimulator/App/PathSimPyImp.cpp @@ -1,24 +1,24 @@ /************************************************************************** -* Copyright (c) 2017 Shai Seger * -* * -* This file is part of the FreeCAD CAx development system. * -* * -* This library is free software; you can redistribute it and/or * -* modify it under the terms of the GNU Library General Public * -* License as published by the Free Software Foundation; either * -* version 2 of the License, or (at your option) any later version. * -* * -* This library is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Library General Public License for more details. * -* * -* You should have received a copy of the GNU Library General Public * -* License along with this library; see the file COPYING.LIB. If not, * -* write to the Free Software Foundation, Inc., 59 Temple Place, * -* Suite 330, Boston, MA 02111-1307, USA * -* * -***************************************************************************/ + * Copyright (c) 2017 Shai Seger * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ #include "PreCompiled.h" @@ -43,7 +43,7 @@ std::string PathSimPy::representation() const return std::string(""); } -PyObject *PathSimPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +PyObject* PathSimPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper { // create a new instance of PathSimPy and the Twin object return new PathSimPy(new PathSim); @@ -56,82 +56,97 @@ int PathSimPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) } -PyObject* PathSimPy::BeginSimulation(PyObject * args, PyObject * kwds) +PyObject* PathSimPy::BeginSimulation(PyObject* args, PyObject* kwds) { - static const std::array kwlist { "stock", "resolution", nullptr }; - PyObject *pObjStock; - float resolution; - if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "O!f", kwlist, &(Part::TopoShapePy::Type), &pObjStock, &resolution)) - return nullptr; - PathSim *sim = getPathSimPtr(); - Part::TopoShape *stock = static_cast(pObjStock)->getTopoShapePtr(); - sim->BeginSimulation(stock, resolution); - Py_IncRef(Py_None); - return Py_None; -} - -PyObject* PathSimPy::SetToolShape(PyObject * args) -{ - PyObject *pObjToolShape; - float resolution; - if (!PyArg_ParseTuple(args, "O!f", &(Part::TopoShapePy::Type), &pObjToolShape, &resolution)) - return nullptr; - PathSim *sim = getPathSimPtr(); - const TopoDS_Shape& toolShape = static_cast(pObjToolShape)->getTopoShapePtr()->getShape(); - sim->SetToolShape(toolShape, resolution); - Py_IncRef(Py_None); - return Py_None; -} - -PyObject* PathSimPy::GetResultMesh(PyObject * args) -{ - if (!PyArg_ParseTuple(args, "")) - return nullptr; - cStock *stock = getPathSimPtr()->m_stock.get(); - if (!stock) - { - PyErr_SetString(PyExc_RuntimeError, "Simulation has stock object"); - return nullptr; - } - - Mesh::MeshObject *meshOuter = new Mesh::MeshObject(); - Mesh::MeshPy *meshOuterpy = new Mesh::MeshPy(meshOuter); - Mesh::MeshObject *meshInner = new Mesh::MeshObject(); - Mesh::MeshPy *meshInnerpy = new Mesh::MeshPy(meshInner); - stock->Tessellate(*meshOuter, *meshInner); - PyObject *tuple = PyTuple_New(2); - PyTuple_SetItem(tuple, 0, meshOuterpy); - PyTuple_SetItem(tuple, 1, meshInnerpy); - return tuple; -} - - -PyObject* PathSimPy::ApplyCommand(PyObject * args, PyObject * kwds) -{ - static const std::array kwlist { "position", "command", nullptr }; - PyObject *pObjPlace; - PyObject *pObjCmd; - if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "O!O!", kwlist, &(Base::PlacementPy::Type), &pObjPlace, - &(Path::CommandPy::Type), &pObjCmd)) { + static const std::array kwlist {"stock", "resolution", nullptr}; + PyObject* pObjStock; + float resolution; + if (!Base::Wrapped_ParseTupleAndKeywords(args, + kwds, + "O!f", + kwlist, + &(Part::TopoShapePy::Type), + &pObjStock, + &resolution)) { return nullptr; } - PathSim *sim = getPathSimPtr(); - Base::Placement *pos = static_cast(pObjPlace)->getPlacementPtr(); - Path::Command *cmd = static_cast(pObjCmd)->getCommandPtr(); - Base::Placement *newpos = sim->ApplyCommand(pos, cmd); - //Base::Console().Log("Done...\n"); - //Base::Console().Refresh(); - Base::PlacementPy *newposPy = new Base::PlacementPy(newpos); - return newposPy; + PathSim* sim = getPathSimPtr(); + Part::TopoShape* stock = static_cast(pObjStock)->getTopoShapePtr(); + sim->BeginSimulation(stock, resolution); + Py_IncRef(Py_None); + return Py_None; +} + +PyObject* PathSimPy::SetToolShape(PyObject* args) +{ + PyObject* pObjToolShape; + float resolution; + if (!PyArg_ParseTuple(args, "O!f", &(Part::TopoShapePy::Type), &pObjToolShape, &resolution)) { + return nullptr; + } + PathSim* sim = getPathSimPtr(); + const TopoDS_Shape& toolShape = + static_cast(pObjToolShape)->getTopoShapePtr()->getShape(); + sim->SetToolShape(toolShape, resolution); + Py_IncRef(Py_None); + return Py_None; +} + +PyObject* PathSimPy::GetResultMesh(PyObject* args) +{ + if (!PyArg_ParseTuple(args, "")) { + return nullptr; + } + cStock* stock = getPathSimPtr()->m_stock.get(); + if (!stock) { + PyErr_SetString(PyExc_RuntimeError, "Simulation has stock object"); + return nullptr; + } + + Mesh::MeshObject* meshOuter = new Mesh::MeshObject(); + Mesh::MeshPy* meshOuterpy = new Mesh::MeshPy(meshOuter); + Mesh::MeshObject* meshInner = new Mesh::MeshObject(); + Mesh::MeshPy* meshInnerpy = new Mesh::MeshPy(meshInner); + stock->Tessellate(*meshOuter, *meshInner); + PyObject* tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, meshOuterpy); + PyTuple_SetItem(tuple, 1, meshInnerpy); + return tuple; +} + + +PyObject* PathSimPy::ApplyCommand(PyObject* args, PyObject* kwds) +{ + static const std::array kwlist {"position", "command", nullptr}; + PyObject* pObjPlace; + PyObject* pObjCmd; + if (!Base::Wrapped_ParseTupleAndKeywords(args, + kwds, + "O!O!", + kwlist, + &(Base::PlacementPy::Type), + &pObjPlace, + &(Path::CommandPy::Type), + &pObjCmd)) { + return nullptr; + } + PathSim* sim = getPathSimPtr(); + Base::Placement* pos = static_cast(pObjPlace)->getPlacementPtr(); + Path::Command* cmd = static_cast(pObjCmd)->getCommandPtr(); + Base::Placement* newpos = sim->ApplyCommand(pos, cmd); + // Base::Console().Log("Done...\n"); + // Base::Console().Refresh(); + Base::PlacementPy* newposPy = new Base::PlacementPy(newpos); + return newposPy; } Py::Object PathSimPy::getTool() const { - //return Py::Object(); + // return Py::Object(); throw Py::AttributeError("Not yet implemented"); } -PyObject *PathSimPy::getCustomAttributes(const char* /*attr*/) const +PyObject* PathSimPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } @@ -140,5 +155,3 @@ int PathSimPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { return 0; } - - diff --git a/src/Mod/CAM/PathSimulator/App/PreCompiled.h b/src/Mod/CAM/PathSimulator/App/PreCompiled.h index 14ea3ae0a3..a89f828e6e 100644 --- a/src/Mod/CAM/PathSimulator/App/PreCompiled.h +++ b/src/Mod/CAM/PathSimulator/App/PreCompiled.h @@ -50,7 +50,6 @@ // Xerces #include -#endif //_PreComp_ +#endif //_PreComp_ #endif - diff --git a/src/Mod/CAM/PathSimulator/App/VolSim.cpp b/src/Mod/CAM/PathSimulator/App/VolSim.cpp index 6f5a457428..b915b64ee4 100644 --- a/src/Mod/CAM/PathSimulator/App/VolSim.cpp +++ b/src/Mod/CAM/PathSimulator/App/VolSim.cpp @@ -1,24 +1,24 @@ /************************************************************************** -* Copyright (c) 2017 Shai Seger * -* * -* This file is part of the FreeCAD CAx development system. * -* * -* This library is free software; you can redistribute it and/or * -* modify it under the terms of the GNU Library General Public * -* License as published by the Free Software Foundation; either * -* version 2 of the License, or (at your option) any later version. * -* * -* This library is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Library General Public License for more details. * -* * -* You should have received a copy of the GNU Library General Public * -* License along with this library; see the file COPYING.LIB. If not, * -* write to the Free Software Foundation, Inc., 59 Temple Place, * -* Suite 330, Boston, MA 02111-1307, USA * -* * -***************************************************************************/ + * Copyright (c) 2017 Shai Seger * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ @@ -37,633 +37,630 @@ // stock //************************************************************************************************************ cStock::cStock(float px, float py, float pz, float lx, float ly, float lz, float res) - : m_px(px), m_py(py), m_pz(pz), m_lx(lx), m_ly(ly), m_lz(lz), m_res(res) + : m_px(px) + , m_py(py) + , m_pz(pz) + , m_lx(lx) + , m_ly(ly) + , m_lz(lz) + , m_res(res) { - m_x = (int)(m_lx / res) + 1; - m_y = (int)(m_ly / res) + 1; - m_stock.Init(m_x, m_y); - m_attr.Init(m_x, m_y); - m_plane = pz + lz; - for (int y = 0; y < m_y; y++) - for (int x = 0; x < m_x; x++) - { - m_stock[x][y] = m_plane; - m_attr[x][y] = 0; - } + m_x = (int)(m_lx / res) + 1; + m_y = (int)(m_ly / res) + 1; + m_stock.Init(m_x, m_y); + m_attr.Init(m_x, m_y); + m_plane = pz + lz; + for (int y = 0; y < m_y; y++) { + for (int x = 0; x < m_x; x++) { + m_stock[x][y] = m_plane; + m_attr[x][y] = 0; + } + } } cStock::~cStock() +{} + + +float cStock::FindRectTop(int& xp, int& yp, int& x_size, int& y_size, bool scanHoriz) { -} + float z = m_stock[xp][yp]; + bool xr_ok = true; + bool xl_ok = scanHoriz; + bool yu_ok = true; + bool yd_ok = !scanHoriz; + x_size = 1; + y_size = 1; + while (xr_ok || xl_ok || yu_ok || yd_ok) { + // sweep right x direction + if (xr_ok) { + int tx = xp + x_size; + if (tx >= m_x) { + xr_ok = false; + } + else { + for (int y = yp; y < yp + y_size; y++) { + if ((m_attr[tx][y] & SIM_TESSEL_TOP) != 0 || fabs(z - m_stock[tx][y]) > m_res) { + xr_ok = false; + break; + } + } + if (xr_ok) { + x_size++; + } + } + } + // sweep left x direction + if (xl_ok) { + int tx = xp - 1; + if (tx < 0) { + xl_ok = false; + } + else { + for (int y = yp; y < yp + y_size; y++) { + if ((m_attr[tx][y] & SIM_TESSEL_TOP) != 0 || fabs(z - m_stock[tx][y]) > m_res) { + xl_ok = false; + break; + } + } + if (xl_ok) { + x_size++; + xp--; + } + } + } -float cStock::FindRectTop(int & xp, int & yp, int & x_size, int & y_size, bool scanHoriz) -{ - float z = m_stock[xp][yp]; - bool xr_ok = true; - bool xl_ok = scanHoriz; - bool yu_ok = true; - bool yd_ok = !scanHoriz; - x_size = 1; - y_size = 1; - while (xr_ok || xl_ok || yu_ok || yd_ok) { - // sweep right x direction - if (xr_ok) - { - int tx = xp + x_size; - if (tx >= m_x) - xr_ok = false; - else - { - for (int y = yp; y < yp + y_size; y++) - { - if ((m_attr[tx][y] & SIM_TESSEL_TOP) != 0 || fabs(z - m_stock[tx][y]) > m_res) - { - xr_ok = false; - break; - } - } - if (xr_ok) - x_size++; - } - } + // sweep up y direction + if (yu_ok) { + int ty = yp + y_size; + if (ty >= m_y) { + yu_ok = false; + } + else { + for (int x = xp; x < xp + x_size; x++) { + if ((m_attr[x][ty] & SIM_TESSEL_TOP) != 0 || fabs(z - m_stock[x][ty]) > m_res) { + yu_ok = false; + break; + } + } + if (yu_ok) { + y_size++; + } + } + } - // sweep left x direction - if (xl_ok) - { - int tx = xp - 1; - if (tx < 0) - xl_ok = false; - else - { - for (int y = yp; y < yp + y_size; y++) - { - if ((m_attr[tx][y] & SIM_TESSEL_TOP) != 0 || fabs(z - m_stock[tx][y]) > m_res) - { - xl_ok = false; - break; - } - } - if (xl_ok) - { - x_size++; - xp--; - } - } - } - - // sweep up y direction - if (yu_ok) - { - int ty = yp + y_size; - if (ty >= m_y) - yu_ok = false; - else - { - for (int x = xp; x < xp + x_size; x++) - { - if ((m_attr[x][ty] & SIM_TESSEL_TOP) != 0 || fabs(z - m_stock[x][ty]) > m_res) - { - yu_ok = false; - break; - } - } - if (yu_ok) - y_size++; - } - } - - // sweep down y direction - if (yd_ok) - { - int ty = yp - 1; - if (ty < 0) - yd_ok = false; - else - { - for (int x = xp; x < xp + x_size; x++) - { - if ((m_attr[x][ty] & SIM_TESSEL_TOP) != 0 || fabs(z - m_stock[x][ty]) > m_res) - { - yd_ok = false; - break; - } - } - if (yd_ok) - { - y_size++; - yp--; - } - } - } - } - return z; + // sweep down y direction + if (yd_ok) { + int ty = yp - 1; + if (ty < 0) { + yd_ok = false; + } + else { + for (int x = xp; x < xp + x_size; x++) { + if ((m_attr[x][ty] & SIM_TESSEL_TOP) != 0 || fabs(z - m_stock[x][ty]) > m_res) { + yd_ok = false; + break; + } + } + if (yd_ok) { + y_size++; + yp--; + } + } + } + } + return z; } int cStock::TesselTop(int xp, int yp) { - int x_size, y_size; - float z = FindRectTop(xp, yp, x_size, y_size, true); - bool farRect = false; - while (y_size / x_size > 5) - { - farRect = true; - yp += x_size * 5; - z = FindRectTop(xp, yp, x_size, y_size, true); - } + int x_size, y_size; + float z = FindRectTop(xp, yp, x_size, y_size, true); + bool farRect = false; + while (y_size / x_size > 5) { + farRect = true; + yp += x_size * 5; + z = FindRectTop(xp, yp, x_size, y_size, true); + } - while (x_size / y_size > 5) - { - farRect = true; - xp += y_size * 5; - z = FindRectTop(xp, yp, x_size, y_size, false); - } + while (x_size / y_size > 5) { + farRect = true; + xp += y_size * 5; + z = FindRectTop(xp, yp, x_size, y_size, false); + } - // mark all points inside - for (int y = yp; y < yp + y_size; y++) - for (int x = xp; x < xp + x_size; x++) - m_attr[x][y] |= SIM_TESSEL_TOP; + // mark all points inside + for (int y = yp; y < yp + y_size; y++) { + for (int x = xp; x < xp + x_size; x++) { + m_attr[x][y] |= SIM_TESSEL_TOP; + } + } - if (z > m_pz + m_res) - { - // generate 4 3d points - Point3D pbl(xp, yp, z); - Point3D pbr(xp + x_size, yp, z); - Point3D ptl(xp, yp + y_size, z); - Point3D ptr(xp + x_size, yp + y_size, z); - if (fabs(m_pz + m_lz - z) < SIM_EPSILON) - AddQuad(pbl, pbr, ptr, ptl, facetsOuter); - else - AddQuad(pbl, pbr, ptr, ptl, facetsInner); - } + if (z > m_pz + m_res) { + // generate 4 3d points + Point3D pbl(xp, yp, z); + Point3D pbr(xp + x_size, yp, z); + Point3D ptl(xp, yp + y_size, z); + Point3D ptr(xp + x_size, yp + y_size, z); + if (fabs(m_pz + m_lz - z) < SIM_EPSILON) { + AddQuad(pbl, pbr, ptr, ptl, facetsOuter); + } + else { + AddQuad(pbl, pbr, ptr, ptl, facetsInner); + } + } - if (farRect) - return -1; - return std::max(0, x_size - 1); - //return 0; + if (farRect) { + return -1; + } + return std::max(0, x_size - 1); + // return 0; } -void cStock::FindRectBot(int & xp, int & yp, int & x_size, int & y_size, bool scanHoriz) +void cStock::FindRectBot(int& xp, int& yp, int& x_size, int& y_size, bool scanHoriz) { - bool xr_ok = true; - bool xl_ok = scanHoriz; - bool yu_ok = true; - bool yd_ok = !scanHoriz; - x_size = 1; - y_size = 1; - while (xr_ok || xl_ok || yu_ok || yd_ok) { - // sweep right x direction - if (xr_ok) - { - int tx = xp + x_size; - if (tx >= m_x) - xr_ok = false; - else - { - for (int y = yp; y < yp + y_size; y++) - { - if ((m_attr[tx][y] & SIM_TESSEL_BOT) != 0 || (m_stock[tx][y] - m_pz) < m_res) - { - xr_ok = false; - break; - } - } - if (xr_ok) - x_size++; - } - } + bool xr_ok = true; + bool xl_ok = scanHoriz; + bool yu_ok = true; + bool yd_ok = !scanHoriz; + x_size = 1; + y_size = 1; + while (xr_ok || xl_ok || yu_ok || yd_ok) { + // sweep right x direction + if (xr_ok) { + int tx = xp + x_size; + if (tx >= m_x) { + xr_ok = false; + } + else { + for (int y = yp; y < yp + y_size; y++) { + if ((m_attr[tx][y] & SIM_TESSEL_BOT) != 0 || (m_stock[tx][y] - m_pz) < m_res) { + xr_ok = false; + break; + } + } + if (xr_ok) { + x_size++; + } + } + } - // sweep left x direction - if (xl_ok) - { - int tx = xp - 1; - if (tx < 0) - xl_ok = false; - else - { - for (int y = yp; y < yp + y_size; y++) - { - if ((m_attr[tx][y] & SIM_TESSEL_BOT) != 0 || (m_stock[tx][y] - m_pz) < m_res) - { - xl_ok = false; - break; - } - } - if (xl_ok) - { - x_size++; - xp--; - } - } - } + // sweep left x direction + if (xl_ok) { + int tx = xp - 1; + if (tx < 0) { + xl_ok = false; + } + else { + for (int y = yp; y < yp + y_size; y++) { + if ((m_attr[tx][y] & SIM_TESSEL_BOT) != 0 || (m_stock[tx][y] - m_pz) < m_res) { + xl_ok = false; + break; + } + } + if (xl_ok) { + x_size++; + xp--; + } + } + } - // sweep up y direction - if (yu_ok) - { - int ty = yp + y_size; - if (ty >= m_y) - yu_ok = false; - else - { - for (int x = xp; x < xp + x_size; x++) - { - if ((m_attr[x][ty] & SIM_TESSEL_BOT) != 0 || (m_stock[x][ty] - m_pz) < m_res) - { - yu_ok = false; - break; - } - } - if (yu_ok) - y_size++; - } - } + // sweep up y direction + if (yu_ok) { + int ty = yp + y_size; + if (ty >= m_y) { + yu_ok = false; + } + else { + for (int x = xp; x < xp + x_size; x++) { + if ((m_attr[x][ty] & SIM_TESSEL_BOT) != 0 || (m_stock[x][ty] - m_pz) < m_res) { + yu_ok = false; + break; + } + } + if (yu_ok) { + y_size++; + } + } + } - // sweep down y direction - if (yd_ok) - { - int ty = yp - 1; - if (ty < 0) - yd_ok = false; - else - { - for (int x = xp; x < xp + x_size; x++) - { - if ((m_attr[x][ty] & SIM_TESSEL_BOT) != 0 || (m_stock[x][ty] - m_pz) < m_res) - { - yd_ok = false; - break; - } - } - if (yd_ok) - { - y_size++; - yp--; - } - } - } - } + // sweep down y direction + if (yd_ok) { + int ty = yp - 1; + if (ty < 0) { + yd_ok = false; + } + else { + for (int x = xp; x < xp + x_size; x++) { + if ((m_attr[x][ty] & SIM_TESSEL_BOT) != 0 || (m_stock[x][ty] - m_pz) < m_res) { + yd_ok = false; + break; + } + } + if (yd_ok) { + y_size++; + yp--; + } + } + } + } } int cStock::TesselBot(int xp, int yp) { - int x_size, y_size; - FindRectBot(xp, yp, x_size, y_size, true); - bool farRect = false; - while (y_size / x_size > 5) - { - farRect = true; - yp += x_size * 5; - FindRectTop(xp, yp, x_size, y_size, true); - } + int x_size, y_size; + FindRectBot(xp, yp, x_size, y_size, true); + bool farRect = false; + while (y_size / x_size > 5) { + farRect = true; + yp += x_size * 5; + FindRectTop(xp, yp, x_size, y_size, true); + } - while (x_size / y_size > 5) - { - farRect = true; - xp += y_size * 5; - FindRectTop(xp, yp, x_size, y_size, false); - } + while (x_size / y_size > 5) { + farRect = true; + xp += y_size * 5; + FindRectTop(xp, yp, x_size, y_size, false); + } - // mark all points inside - for (int y = yp; y < yp + y_size; y++) - for (int x = xp; x < xp + x_size; x++) - m_attr[x][y] |= SIM_TESSEL_BOT; + // mark all points inside + for (int y = yp; y < yp + y_size; y++) { + for (int x = xp; x < xp + x_size; x++) { + m_attr[x][y] |= SIM_TESSEL_BOT; + } + } - // generate 4 3d points - Point3D pbl(xp, yp, m_pz); - Point3D pbr(xp + x_size, yp, m_pz); - Point3D ptl(xp, yp + y_size, m_pz); - Point3D ptr(xp + x_size, yp + y_size, m_pz); - AddQuad(pbl, ptl, ptr, pbr, facetsOuter); + // generate 4 3d points + Point3D pbl(xp, yp, m_pz); + Point3D pbr(xp + x_size, yp, m_pz); + Point3D ptl(xp, yp + y_size, m_pz); + Point3D ptr(xp + x_size, yp + y_size, m_pz); + AddQuad(pbl, ptl, ptr, pbr, facetsOuter); - if (farRect) - return -1; - return std::max(0, x_size - 1); - //return 0; + if (farRect) { + return -1; + } + return std::max(0, x_size - 1); + // return 0; } int cStock::TesselSidesX(int yp) { - float lastz1 = m_pz; - if (yp < m_y) - lastz1 = std::max(m_stock[0][yp], m_pz); - float lastz2 = m_pz; - if (yp > 0) - lastz2 = std::max(m_stock[0][yp - 1], m_pz); + float lastz1 = m_pz; + if (yp < m_y) { + lastz1 = std::max(m_stock[0][yp], m_pz); + } + float lastz2 = m_pz; + if (yp > 0) { + lastz2 = std::max(m_stock[0][yp - 1], m_pz); + } - std::vector *facets = &facetsInner; - if (yp == 0 || yp == m_y) - facets = &facetsOuter; + std::vector* facets = &facetsInner; + if (yp == 0 || yp == m_y) { + facets = &facetsOuter; + } - //bool lastzclip = (lastz - m_pz) < m_res; - int lastpoint = 0; - for (int x = 1; x <= m_x; x++) - { - float newz1 = m_pz; - if (yp < m_y && x < m_x) - newz1 = std::max(m_stock[x][yp], m_pz); - float newz2 = m_pz; - if (yp > 0 && x < m_x) - newz2 = std::max(m_stock[x][yp - 1], m_pz); + // bool lastzclip = (lastz - m_pz) < m_res; + int lastpoint = 0; + for (int x = 1; x <= m_x; x++) { + float newz1 = m_pz; + if (yp < m_y && x < m_x) { + newz1 = std::max(m_stock[x][yp], m_pz); + } + float newz2 = m_pz; + if (yp > 0 && x < m_x) { + newz2 = std::max(m_stock[x][yp - 1], m_pz); + } - if (fabs(lastz1 - lastz2) > m_res) - { - if (fabs(newz1 - lastz1) < m_res && fabs(newz2 - lastz2) < m_res) - continue; - Point3D pbl(lastpoint, yp, lastz1); - Point3D pbr(x, yp, lastz1); - Point3D ptl(lastpoint, yp, lastz2); - Point3D ptr(x, yp, lastz2); - AddQuad(pbl, ptl, ptr, pbr, *facets); - } - lastz1 = newz1; - lastz2 = newz2; - lastpoint = x; - } - return 0; + if (fabs(lastz1 - lastz2) > m_res) { + if (fabs(newz1 - lastz1) < m_res && fabs(newz2 - lastz2) < m_res) { + continue; + } + Point3D pbl(lastpoint, yp, lastz1); + Point3D pbr(x, yp, lastz1); + Point3D ptl(lastpoint, yp, lastz2); + Point3D ptr(x, yp, lastz2); + AddQuad(pbl, ptl, ptr, pbr, *facets); + } + lastz1 = newz1; + lastz2 = newz2; + lastpoint = x; + } + return 0; } int cStock::TesselSidesY(int xp) { - float lastz1 = m_pz; - if (xp < m_x) - lastz1 = std::max(m_stock[xp][0], m_pz); - float lastz2 = m_pz; - if (xp > 0) - lastz2 = std::max(m_stock[xp - 1][0], m_pz); + float lastz1 = m_pz; + if (xp < m_x) { + lastz1 = std::max(m_stock[xp][0], m_pz); + } + float lastz2 = m_pz; + if (xp > 0) { + lastz2 = std::max(m_stock[xp - 1][0], m_pz); + } - std::vector *facets = &facetsInner; - if (xp == 0 || xp == m_x) - facets = &facetsOuter; + std::vector* facets = &facetsInner; + if (xp == 0 || xp == m_x) { + facets = &facetsOuter; + } - //bool lastzclip = (lastz - m_pz) < m_res; - int lastpoint = 0; - for (int y = 1; y <= m_y; y++) - { - float newz1 = m_pz; - if (xp < m_x && y < m_y) - newz1 = std::max(m_stock[xp][y], m_pz); - float newz2 = m_pz; - if (xp > 0 && y < m_y) - newz2 = std::max(m_stock[xp - 1][y], m_pz); + // bool lastzclip = (lastz - m_pz) < m_res; + int lastpoint = 0; + for (int y = 1; y <= m_y; y++) { + float newz1 = m_pz; + if (xp < m_x && y < m_y) { + newz1 = std::max(m_stock[xp][y], m_pz); + } + float newz2 = m_pz; + if (xp > 0 && y < m_y) { + newz2 = std::max(m_stock[xp - 1][y], m_pz); + } - if (fabs(lastz1 - lastz2) > m_res) - { - if (fabs(newz1 - lastz1) < m_res && fabs(newz2 - lastz2) < m_res) - continue; - Point3D pbr(xp, lastpoint, lastz1); - Point3D pbl(xp, y, lastz1); - Point3D ptr(xp, lastpoint, lastz2); - Point3D ptl(xp, y, lastz2); - AddQuad(pbl, ptl, ptr, pbr, *facets); - } - lastz1 = newz1; - lastz2 = newz2; - lastpoint = y; - } - return 0; + if (fabs(lastz1 - lastz2) > m_res) { + if (fabs(newz1 - lastz1) < m_res && fabs(newz2 - lastz2) < m_res) { + continue; + } + Point3D pbr(xp, lastpoint, lastz1); + Point3D pbl(xp, y, lastz1); + Point3D ptr(xp, lastpoint, lastz2); + Point3D ptl(xp, y, lastz2); + AddQuad(pbl, ptl, ptr, pbr, *facets); + } + lastz1 = newz1; + lastz2 = newz2; + lastpoint = y; + } + return 0; } -void cStock::SetFacetPoints(MeshCore::MeshGeomFacet & facet, Point3D & p1, Point3D & p2, Point3D & p3) +void cStock::SetFacetPoints(MeshCore::MeshGeomFacet& facet, Point3D& p1, Point3D& p2, Point3D& p3) { - facet._aclPoints[0][0] = p1.x * m_res + m_px; - facet._aclPoints[0][1] = p1.y * m_res + m_py; - facet._aclPoints[0][2] = p1.z; - facet._aclPoints[1][0] = p2.x * m_res + m_px; - facet._aclPoints[1][1] = p2.y * m_res + m_py; - facet._aclPoints[1][2] = p2.z; - facet._aclPoints[2][0] = p3.x * m_res + m_px; - facet._aclPoints[2][1] = p3.y * m_res + m_py; - facet._aclPoints[2][2] = p3.z; - facet.CalcNormal(); + facet._aclPoints[0][0] = p1.x * m_res + m_px; + facet._aclPoints[0][1] = p1.y * m_res + m_py; + facet._aclPoints[0][2] = p1.z; + facet._aclPoints[1][0] = p2.x * m_res + m_px; + facet._aclPoints[1][1] = p2.y * m_res + m_py; + facet._aclPoints[1][2] = p2.z; + facet._aclPoints[2][0] = p3.x * m_res + m_px; + facet._aclPoints[2][1] = p3.y * m_res + m_py; + facet._aclPoints[2][2] = p3.z; + facet.CalcNormal(); } -void cStock::AddQuad(Point3D & p1, Point3D & p2, Point3D & p3, Point3D & p4, std::vector & facets) +void cStock::AddQuad(Point3D& p1, + Point3D& p2, + Point3D& p3, + Point3D& p4, + std::vector& facets) { - MeshCore::MeshGeomFacet facet; - SetFacetPoints(facet, p1, p2, p3); - facets.push_back(facet); - SetFacetPoints(facet, p1, p3, p4); - facets.push_back(facet); + MeshCore::MeshGeomFacet facet; + SetFacetPoints(facet, p1, p2, p3); + facets.push_back(facet); + SetFacetPoints(facet, p1, p3, p4); + facets.push_back(facet); } -void cStock::Tessellate(Mesh::MeshObject & meshOuter, Mesh::MeshObject & meshInner) +void cStock::Tessellate(Mesh::MeshObject& meshOuter, Mesh::MeshObject& meshInner) { - // reset attribs - for (int y = 0; y < m_y; y++) - for (int x = 0; x < m_x; x++) - m_attr[x][y] = 0; + // reset attribs + for (int y = 0; y < m_y; y++) { + for (int x = 0; x < m_x; x++) { + m_attr[x][y] = 0; + } + } - facetsOuter.clear(); - facetsInner.clear(); + facetsOuter.clear(); + facetsInner.clear(); - for (int y = 0; y < m_y; y++) - { - for (int x = 0; x < m_x; x++) - { - int attr = m_attr[x][y]; - if ((attr & SIM_TESSEL_TOP) == 0) - x += TesselTop(x, y); - } - } - for (int y = 0; y < m_y; y++) - { - for (int x = 0; x < m_x; x++) - { - if ((m_stock[x][y] - m_pz) < m_res) - m_attr[x][y] |= SIM_TESSEL_BOT; - if ((m_attr[x][y] & SIM_TESSEL_BOT) == 0) - x += TesselBot(x, y); - } - } - for (int y = 0; y <= m_y; y++) - TesselSidesX(y); - for (int x = 0; x <= m_x; x++) - TesselSidesY(x); - meshOuter.addFacets(facetsOuter); - meshInner.addFacets(facetsInner); - facetsOuter.clear(); - facetsInner.clear(); + for (int y = 0; y < m_y; y++) { + for (int x = 0; x < m_x; x++) { + int attr = m_attr[x][y]; + if ((attr & SIM_TESSEL_TOP) == 0) { + x += TesselTop(x, y); + } + } + } + for (int y = 0; y < m_y; y++) { + for (int x = 0; x < m_x; x++) { + if ((m_stock[x][y] - m_pz) < m_res) { + m_attr[x][y] |= SIM_TESSEL_BOT; + } + if ((m_attr[x][y] & SIM_TESSEL_BOT) == 0) { + x += TesselBot(x, y); + } + } + } + for (int y = 0; y <= m_y; y++) { + TesselSidesX(y); + } + for (int x = 0; x <= m_x; x++) { + TesselSidesY(x); + } + meshOuter.addFacets(facetsOuter); + meshInner.addFacets(facetsInner); + facetsOuter.clear(); + facetsInner.clear(); } void cStock::CreatePocket(float cxf, float cyf, float radf, float height) { - int cx = (int)((cxf - m_px) / m_res); - int cy = (int)((cyf - m_py) / m_res); - int rad = (int)(radf / m_res); - int drad = rad * rad; - int ys = std::max(0, cy - rad); - int ye = std::min(m_x, cy + rad); - int xs = std::max(0, cx - rad); - int xe = std::min(m_x, cx + rad); - for (int y = ys; y < ye; y++) - { - for (int x = xs; x < xe; x++) - { - if (((x - cx)*(x - cx) + (y - cy) * (y - cy)) < drad) - if (m_stock[x][y] > height) m_stock[x][y] = height; - } - } + int cx = (int)((cxf - m_px) / m_res); + int cy = (int)((cyf - m_py) / m_res); + int rad = (int)(radf / m_res); + int drad = rad * rad; + int ys = std::max(0, cy - rad); + int ye = std::min(m_x, cy + rad); + int xs = std::max(0, cx - rad); + int xe = std::min(m_x, cx + rad); + for (int y = ys; y < ye; y++) { + for (int x = xs; x < xe; x++) { + if (((x - cx) * (x - cx) + (y - cy) * (y - cy)) < drad) { + if (m_stock[x][y] > height) { + m_stock[x][y] = height; + } + } + } + } } -void cStock::ApplyLinearTool(Point3D & p1, Point3D & p2, cSimTool & tool) +void cStock::ApplyLinearTool(Point3D& p1, Point3D& p2, cSimTool& tool) { - // translate coordinates - Point3D pi1 = ToInner(p1); - Point3D pi2 = ToInner(p2); - float rad = tool.radius; - rad /= m_res; - float cupAngle = 180; + // translate coordinates + Point3D pi1 = ToInner(p1); + Point3D pi2 = ToInner(p2); + float rad = tool.radius; + rad /= m_res; + float cupAngle = 180; - // strait motion - float perpDirX = 1; - float perpDirY = 0; - cLineSegment path(pi1, pi2); - if (path.lenXY > SIM_EPSILON) // only if moving along xy - { - perpDirX = -path.pDirXY.y; - perpDirY = path.pDirXY.x; - Point3D start(perpDirX * rad + pi1.x, perpDirY * rad + pi1.y, pi1.z); - Point3D mainWay = path.pDir * SIM_WALK_RES; - Point3D sideWay(-perpDirX * SIM_WALK_RES, -perpDirY * SIM_WALK_RES, 0); - int lenSteps = (int)(path.len / SIM_WALK_RES) + 1; - int radSteps = (int)(rad * 2 / SIM_WALK_RES) + 1; - float zstep = (pi2.z - pi1.z) / radSteps; - float tstep = 2.0 / radSteps; - float t = -1; - for (int j = 0; j < radSteps; j++) - { - float z = pi1.z + tool.GetToolProfileAt(t); - Point3D p = start; - for (int i = 0; i < lenSteps; i++) - { - int x = (int)p.x; - int y = (int)p.y; - if (x >= 0 && y >= 0 && x < m_x && y < m_y) - { - if (m_stock[x][y] > z) - m_stock[x][y] = z; - } - p.Add(mainWay); - z += zstep; - } - t += tstep; - start.Add(sideWay); - } - } - else - cupAngle = 360; + // strait motion + float perpDirX = 1; + float perpDirY = 0; + cLineSegment path(pi1, pi2); + if (path.lenXY > SIM_EPSILON) // only if moving along xy + { + perpDirX = -path.pDirXY.y; + perpDirY = path.pDirXY.x; + Point3D start(perpDirX * rad + pi1.x, perpDirY * rad + pi1.y, pi1.z); + Point3D mainWay = path.pDir * SIM_WALK_RES; + Point3D sideWay(-perpDirX * SIM_WALK_RES, -perpDirY * SIM_WALK_RES, 0); + int lenSteps = (int)(path.len / SIM_WALK_RES) + 1; + int radSteps = (int)(rad * 2 / SIM_WALK_RES) + 1; + float zstep = (pi2.z - pi1.z) / radSteps; + float tstep = 2.0 / radSteps; + float t = -1; + for (int j = 0; j < radSteps; j++) { + float z = pi1.z + tool.GetToolProfileAt(t); + Point3D p = start; + for (int i = 0; i < lenSteps; i++) { + int x = (int)p.x; + int y = (int)p.y; + if (x >= 0 && y >= 0 && x < m_x && y < m_y) { + if (m_stock[x][y] > z) { + m_stock[x][y] = z; + } + } + p.Add(mainWay); + z += zstep; + } + t += tstep; + start.Add(sideWay); + } + } + else { + cupAngle = 360; + } - // end cup - for (float r = 0.5f; r <= rad; r += (float)SIM_WALK_RES) - { - Point3D cupCirc(perpDirX * r, perpDirY * r, pi2.z); - float rotang = 180 * SIM_WALK_RES / (3.1415926535 * r); - cupCirc.SetRotationAngle(-rotang); - float z = pi2.z + tool.GetToolProfileAt(r / rad); - for (float a = 0; a < cupAngle; a += rotang) - { - int x = (int)(pi2.x + cupCirc.x); - int y = (int)(pi2.y + cupCirc.y); - if (x >= 0 && y >= 0 && x < m_x && y < m_y) - { - if (m_stock[x][y] > z) - m_stock[x][y] = z; - } - cupCirc.Rotate(); - } - } + // end cup + for (float r = 0.5f; r <= rad; r += (float)SIM_WALK_RES) { + Point3D cupCirc(perpDirX * r, perpDirY * r, pi2.z); + float rotang = 180 * SIM_WALK_RES / (3.1415926535 * r); + cupCirc.SetRotationAngle(-rotang); + float z = pi2.z + tool.GetToolProfileAt(r / rad); + for (float a = 0; a < cupAngle; a += rotang) { + int x = (int)(pi2.x + cupCirc.x); + int y = (int)(pi2.y + cupCirc.y); + if (x >= 0 && y >= 0 && x < m_x && y < m_y) { + if (m_stock[x][y] > z) { + m_stock[x][y] = z; + } + } + cupCirc.Rotate(); + } + } } -void cStock::ApplyCircularTool(Point3D & p1, Point3D & p2, Point3D & cent, cSimTool & tool, bool isCCW) +void cStock::ApplyCircularTool(Point3D& p1, Point3D& p2, Point3D& cent, cSimTool& tool, bool isCCW) { - // translate coordinates - Point3D pi1 = ToInner(p1); - Point3D pi2 = ToInner(p2); - Point3D centi(cent.x / m_res, cent.y / m_res, cent.z); - float rad = tool.radius; - rad /= m_res; - float cpx = centi.x; - float cpy = centi.y; + // translate coordinates + Point3D pi1 = ToInner(p1); + Point3D pi2 = ToInner(p2); + Point3D centi(cent.x / m_res, cent.y / m_res, cent.z); + float rad = tool.radius; + rad /= m_res; + float cpx = centi.x; + float cpy = centi.y; - Point3D xynorm = unit(Point3D(-cpx, -cpy, 0)); - float crad = sqrt(cpx * cpx + cpy * cpy); - //bool shortRad = (crad - rad) < 0.0001; - //if (shortRad) - // rad = crad; - float crad1 = std::max((float)0.5, crad - rad); - float crad2 = crad + rad; + Point3D xynorm = unit(Point3D(-cpx, -cpy, 0)); + float crad = sqrt(cpx * cpx + cpy * cpy); + // bool shortRad = (crad - rad) < 0.0001; + // if (shortRad) + // rad = crad; + float crad1 = std::max((float)0.5, crad - rad); + float crad2 = crad + rad; - float sang = atan2(-cpy, -cpx); // start angle + float sang = atan2(-cpy, -cpx); // start angle - cpx += pi1.x; - cpy += pi1.y; - double eang = atan2(pi2.y - cpy, pi2.x - cpx); // end angle + cpx += pi1.x; + cpy += pi1.y; + double eang = atan2(pi2.y - cpy, pi2.x - cpx); // end angle - double ang = eang - sang; - if (!isCCW && ang > 0) - ang -= 2 * 3.1415926; - if (isCCW && ang < 0) - ang += 2 * 3.1415926; - ang = fabs(ang); + double ang = eang - sang; + if (!isCCW && ang > 0) { + ang -= 2 * 3.1415926; + } + if (isCCW && ang < 0) { + ang += 2 * 3.1415926; + } + ang = fabs(ang); - // apply path - Point3D cupCirc; - float tstep = (float)SIM_WALK_RES / rad; - float t = -1; - for (float r = crad1; r <= crad2; r += (float)SIM_WALK_RES) - { - cupCirc.x = xynorm.x * r; - cupCirc.y = xynorm.y * r; - float rotang = (float)SIM_WALK_RES / r; - int ndivs = (int)(ang / rotang) + 1; - if (!isCCW) - rotang = -rotang; - cupCirc.SetRotationAngleRad(rotang); - float z = pi1.z + tool.GetToolProfileAt(t); - float zstep = (pi2.z - pi1.z) / ndivs; - for (int i = 0; i< ndivs; i++) - { - int x = (int)(cpx + cupCirc.x); - int y = (int)(cpy + cupCirc.y); - if (x >= 0 && y >= 0 && x < m_x && y < m_y) - { - if (m_stock[x][y] > z) - m_stock[x][y] = z; - } - z += zstep; - cupCirc.Rotate(); - } - t += tstep; - } + // apply path + Point3D cupCirc; + float tstep = (float)SIM_WALK_RES / rad; + float t = -1; + for (float r = crad1; r <= crad2; r += (float)SIM_WALK_RES) { + cupCirc.x = xynorm.x * r; + cupCirc.y = xynorm.y * r; + float rotang = (float)SIM_WALK_RES / r; + int ndivs = (int)(ang / rotang) + 1; + if (!isCCW) { + rotang = -rotang; + } + cupCirc.SetRotationAngleRad(rotang); + float z = pi1.z + tool.GetToolProfileAt(t); + float zstep = (pi2.z - pi1.z) / ndivs; + for (int i = 0; i < ndivs; i++) { + int x = (int)(cpx + cupCirc.x); + int y = (int)(cpy + cupCirc.y); + if (x >= 0 && y >= 0 && x < m_x && y < m_y) { + if (m_stock[x][y] > z) { + m_stock[x][y] = z; + } + } + z += zstep; + cupCirc.Rotate(); + } + t += tstep; + } - // apply end cup - xynorm.SetRotationAngleRad(ang); - xynorm.Rotate(); - for (float r = 0.5f; r <= rad; r += (float)SIM_WALK_RES) - { - Point3D cupCirc(xynorm.x * r, xynorm.y * r, 0); - float rotang = (float)SIM_WALK_RES / r; - int ndivs = (int)(3.1415926535 / rotang) + 1; - if (!isCCW) - rotang = -rotang; - cupCirc.SetRotationAngleRad(rotang); - float z = pi2.z + tool.GetToolProfileAt(r / rad); - for (int i = 0; i < ndivs; i++) - { - int x = (int)(pi2.x + cupCirc.x); - int y = (int)(pi2.y + cupCirc.y); - if (x >= 0 && y >= 0 && x < m_x && y < m_y) - { - if (m_stock[x][y] > z) - m_stock[x][y] = z; - } - cupCirc.Rotate(); - } - } + // apply end cup + xynorm.SetRotationAngleRad(ang); + xynorm.Rotate(); + for (float r = 0.5f; r <= rad; r += (float)SIM_WALK_RES) { + Point3D cupCirc(xynorm.x * r, xynorm.y * r, 0); + float rotang = (float)SIM_WALK_RES / r; + int ndivs = (int)(3.1415926535 / rotang) + 1; + if (!isCCW) { + rotang = -rotang; + } + cupCirc.SetRotationAngleRad(rotang); + float z = pi2.z + tool.GetToolProfileAt(r / rad); + for (int i = 0; i < ndivs; i++) { + int x = (int)(pi2.x + cupCirc.x); + int y = (int)(pi2.y + cupCirc.y); + if (x >= 0 && y >= 0 && x < m_x && y < m_y) { + if (m_stock[x][y] > z) { + m_stock[x][y] = z; + } + } + cupCirc.Rotate(); + } + } } @@ -671,22 +668,23 @@ void cStock::ApplyCircularTool(Point3D & p1, Point3D & p2, Point3D & cent, cSimT // Line Segment //************************************************************************************************************ -void cLineSegment::SetPoints(Point3D & p1, Point3D & p2) +void cLineSegment::SetPoints(Point3D& p1, Point3D& p2) { - pStart = p1; - pDir = unit(p2 - p1); - Point3D dirXY(pDir.x, pDir.y, 0); - lenXY = length(dirXY); - len = length(p2 - p1); - if (len > SIM_EPSILON) - pDirXY = unit(dirXY); + pStart = p1; + pDir = unit(p2 - p1); + Point3D dirXY(pDir.x, pDir.y, 0); + lenXY = length(dirXY); + len = length(p2 - p1); + if (len > SIM_EPSILON) { + pDirXY = unit(dirXY); + } } -void cLineSegment::PointAt(float dist, Point3D & retp) +void cLineSegment::PointAt(float dist, Point3D& retp) { - retp.x = pStart.x + pDir.x * dist; - retp.y = pStart.y + pDir.y * dist; - retp.z = pStart.z + pDir.z * dist; + retp.x = pStart.x + pDir.x * dist; + retp.y = pStart.y + pDir.y * dist; + retp.z = pStart.z + pDir.z * dist; } //************************************************************************************************************ @@ -695,98 +693,102 @@ void cLineSegment::PointAt(float dist, Point3D & retp) void Point3D::SetRotationAngleRad(float angle) { - sina = sin(angle); - cosa = cos(angle); + sina = sin(angle); + cosa = cos(angle); } void Point3D::SetRotationAngle(float angle) { - SetRotationAngleRad(angle * 2 * 3.1415926535 / 360); + SetRotationAngleRad(angle * 2 * 3.1415926535 / 360); } -void Point3D::UpdateCmd(Path::Command & cmd) +void Point3D::UpdateCmd(Path::Command& cmd) { - if (cmd.has("X")) - x = cmd.getPlacement().getPosition()[0]; - if (cmd.has("Y")) - y = cmd.getPlacement().getPosition()[1]; - if (cmd.has("Z")) - z = cmd.getPlacement().getPosition()[2]; + if (cmd.has("X")) { + x = cmd.getPlacement().getPosition()[0]; + } + if (cmd.has("Y")) { + y = cmd.getPlacement().getPosition()[1]; + } + if (cmd.has("Z")) { + z = cmd.getPlacement().getPosition()[2]; + } } //************************************************************************************************************ // Simulation tool //************************************************************************************************************ -cSimTool::cSimTool(const TopoDS_Shape& toolShape, float res){ +cSimTool::cSimTool(const TopoDS_Shape& toolShape, float res) +{ - BRepCheck_Analyzer aChecker(toolShape); + BRepCheck_Analyzer aChecker(toolShape); bool shapeIsValid = aChecker.IsValid() ? true : false; - if(!shapeIsValid){ - throw Base::RuntimeError("Path Simulation: Error in tool geometry"); - } + if (!shapeIsValid) { + throw Base::RuntimeError("Path Simulation: Error in tool geometry"); + } - Bnd_Box boundBox; + Bnd_Box boundBox; BRepBndLib::Add(toolShape, boundBox); - boundBox.SetGap(0.0); - Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; - boundBox.Get(xMin, yMin, zMin, xMax, yMax, zMax); - radius = (xMax - xMin) / 2; - length = zMax - zMin; + boundBox.SetGap(0.0); + Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; + boundBox.Get(xMin, yMin, zMin, xMax, yMax, zMax); + radius = (xMax - xMin) / 2; + length = zMax - zMin; - Base::Vector3d pnt; - pnt.x = 0; - pnt.y = 0; - pnt.z = 0; + Base::Vector3d pnt; + pnt.x = 0; + pnt.y = 0; + pnt.z = 0; - int radValue = (int)(radius / res) + 1; + int radValue = (int)(radius / res) + 1; - // Measure the performance of the profile extraction - //auto start = std::chrono::high_resolution_clock::now(); + // Measure the performance of the profile extraction + // auto start = std::chrono::high_resolution_clock::now(); - for (int x = 0; x < radValue; x++) - { - // find the face of the tool by checking z points across the - // radius to see if the point is inside the shape - pnt.x = x * res; - bool inside = isInside(toolShape, pnt, res); + for (int x = 0; x < radValue; x++) { + // find the face of the tool by checking z points across the + // radius to see if the point is inside the shape + pnt.x = x * res; + bool inside = isInside(toolShape, pnt, res); - // move down until the point is outside the shape - while(inside && std::abs(pnt.z) < length ){ - pnt.z -= res; - inside = isInside(toolShape, pnt, res); - } + // move down until the point is outside the shape + while (inside && std::abs(pnt.z) < length) { + pnt.z -= res; + inside = isInside(toolShape, pnt, res); + } - // move up until the point is first inside the shape and record the position - while (!inside && pnt.z < length) - { - pnt.z += res; - inside = isInside(toolShape, pnt, res); + // move up until the point is first inside the shape and record the position + while (!inside && pnt.z < length) { + pnt.z += res; + inside = isInside(toolShape, pnt, res); - if (inside){ - toolShapePoint shapePoint; - shapePoint.radiusPos = pnt.x; - shapePoint.heightPos = pnt.z; - m_toolShape.push_back(shapePoint); - break; - } - } - } - - // Report the performance of the profile extraction - //auto stop = std::chrono::high_resolution_clock::now(); - //auto duration = std::chrono::duration_cast(stop - start); - //Base::Console().Log("cSimTool::cSimTool - Tool Profile Extraction Took: %i ms\n", duration.count() / 1000); + if (inside) { + toolShapePoint shapePoint; + shapePoint.radiusPos = pnt.x; + shapePoint.heightPos = pnt.z; + m_toolShape.push_back(shapePoint); + break; + } + } + } + // Report the performance of the profile extraction + // auto stop = std::chrono::high_resolution_clock::now(); + // auto duration = std::chrono::duration_cast(stop - start); + // Base::Console().Log("cSimTool::cSimTool - Tool Profile Extraction Took: %i ms\n", + // duration.count() / 1000); } -float cSimTool::GetToolProfileAt(float pos) // pos is -1..1 location along the radius of the tool (0 is center) +float cSimTool::GetToolProfileAt( + float pos) // pos is -1..1 location along the radius of the tool (0 is center) { toolShapePoint test; test.radiusPos = std::abs(pos) * radius; - auto it = std::lower_bound(m_toolShape.begin(), m_toolShape.end(), test, toolShapePoint::less_than()); + auto it = + std::lower_bound(m_toolShape.begin(), m_toolShape.end(), test, toolShapePoint::less_than()); return it != m_toolShape.end() ? it->heightPos : 0.0f; } @@ -800,20 +802,20 @@ bool cSimTool::isInside(const TopoDS_Shape& toolShape, Base::Vector3d pnt, float gp_Pnt vertex = gp_Pnt(pnt.x, pnt.y, pnt.z); solidClassifier.Perform(vertex, res); bool inside = (solidClassifier.State() == stateIn); - if (checkFace && solidClassifier.IsOnAFace()){ + if (checkFace && solidClassifier.IsOnAFace()) { inside = true; - } - return inside; - }catch (...) { + } + return inside; + } + catch (...) { return false; - } + } } -cVolSim::cVolSim() : stock(nullptr) -{ -} +cVolSim::cVolSim() + : stock(nullptr) +{} cVolSim::~cVolSim() -{ -} +{} diff --git a/src/Mod/CAM/PathSimulator/App/VolSim.h b/src/Mod/CAM/PathSimulator/App/VolSim.h index 8b4bf5253d..7a42f49c41 100644 --- a/src/Mod/CAM/PathSimulator/App/VolSim.h +++ b/src/Mod/CAM/PathSimulator/App/VolSim.h @@ -1,26 +1,26 @@ /************************************************************************** -* Copyright (c) 2017 Shai Seger * -* * -* This file is part of the FreeCAD CAx development system. * -* * -* This library is free software; you can redistribute it and/or * -* modify it under the terms of the GNU Library General Public * -* License as published by the Free Software Foundation; either * -* version 2 of the License, or (at your option) any later version. * -* * -* This library is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Library General Public License for more details. * -* * -* You should have received a copy of the GNU Library General Public * -* License along with this library; see the file COPYING.LIB. If not, * -* write to the Free Software Foundation, Inc., 59 Temple Place, * -* Suite 330, Boston, MA 02111-1307, USA * -* * -*************************************************************************** -* Volumetric Path simulation engine * -***************************************************************************/ + * Copyright (c) 2017 Shai Seger * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + *************************************************************************** + * Volumetric Path simulation engine * + ***************************************************************************/ #ifndef PATHSIMULATOR_VolSim_H #define PATHSIMULATOR_VolSim_H @@ -32,155 +32,239 @@ #define SIM_EPSILON 0.00001 -#define SIM_TESSEL_TOP 1 -#define SIM_TESSEL_BOT 2 -#define SIM_WALK_RES 0.6 // step size in pixel units (to make sure all pixels in the path are visited) +#define SIM_TESSEL_TOP 1 +#define SIM_TESSEL_BOT 2 +#define SIM_WALK_RES \ + 0.6 // step size in pixel units (to make sure all pixels in the path are visited) -struct toolShapePoint { - float radiusPos; - float heightPos; +struct toolShapePoint +{ + float radiusPos; + float heightPos; - struct less_than{ - bool operator()(const toolShapePoint &a, const toolShapePoint &b){ - return a.radiusPos < b.radiusPos; - } - }; + struct less_than + { + bool operator()(const toolShapePoint& a, const toolShapePoint& b) + { + return a.radiusPos < b.radiusPos; + } + }; }; struct Point3D { - Point3D() : x(0), y(0), z(0), sina(0), cosa(0) {} - Point3D(float x, float y, float z) : x(x), y(y), z(z), sina(0), cosa(0) {} - explicit Point3D(Base::Vector3d & vec) : x(vec[0]), y(vec[1]), z(vec[2]), sina(0), cosa(0) {} - explicit Point3D(Base::Placement & pl) : x(pl.getPosition()[0]), y(pl.getPosition()[1]), z(pl.getPosition()[2]), sina(0), cosa(0) {} - inline void set(float px, float py, float pz) { x = px; y = py; z = pz; } - inline void Add(Point3D & p) { x += p.x; y += p.y; z += p.z; } - inline void Rotate() { float tx = x; x = x * cosa - y * sina; y = tx * sina + y * cosa; } - void UpdateCmd(Path::Command & cmd); - void SetRotationAngle(float angle); - void SetRotationAngleRad(float angle); - float x, y, z; - float sina, cosa; + Point3D() + : x(0) + , y(0) + , z(0) + , sina(0) + , cosa(0) + {} + Point3D(float x, float y, float z) + : x(x) + , y(y) + , z(z) + , sina(0) + , cosa(0) + {} + explicit Point3D(Base::Vector3d& vec) + : x(vec[0]) + , y(vec[1]) + , z(vec[2]) + , sina(0) + , cosa(0) + {} + explicit Point3D(Base::Placement& pl) + : x(pl.getPosition()[0]) + , y(pl.getPosition()[1]) + , z(pl.getPosition()[2]) + , sina(0) + , cosa(0) + {} + inline void set(float px, float py, float pz) + { + x = px; + y = py; + z = pz; + } + inline void Add(Point3D& p) + { + x += p.x; + y += p.y; + z += p.z; + } + inline void Rotate() + { + float tx = x; + x = x * cosa - y * sina; + y = tx * sina + y * cosa; + } + void UpdateCmd(Path::Command& cmd); + void SetRotationAngle(float angle); + void SetRotationAngleRad(float angle); + float x, y, z; + float sina, cosa; }; // some vector manipulations -inline static Point3D operator + (const Point3D & a, const Point3D & b) { return Point3D(a.x + b.x, a.y + b.y, a.z + b.z); } -inline static Point3D operator - (const Point3D & a, const Point3D & b) { return Point3D(a.x - b.x, a.y - b.y, a.z - b.z); } -inline static Point3D operator * (const Point3D & a, double b) { return Point3D(a.x * b, a.y * b, a.z * b); } -inline static Point3D operator / (const Point3D & a, double b) { return a * (1.0f / b); } -inline static double dot(const Point3D & a, const Point3D & b) { return a.x * b.x + a.y * b.y + a.z * b.z; } -inline static double length(const Point3D & a) { return sqrtf(dot(a, a)); } -inline static Point3D unit(const Point3D & a) { return a / length(a); } +inline static Point3D operator+(const Point3D& a, const Point3D& b) +{ + return Point3D(a.x + b.x, a.y + b.y, a.z + b.z); +} +inline static Point3D operator-(const Point3D& a, const Point3D& b) +{ + return Point3D(a.x - b.x, a.y - b.y, a.z - b.z); +} +inline static Point3D operator*(const Point3D& a, double b) +{ + return Point3D(a.x * b, a.y * b, a.z * b); +} +inline static Point3D operator/(const Point3D& a, double b) +{ + return a * (1.0f / b); +} +inline static double dot(const Point3D& a, const Point3D& b) +{ + return a.x * b.x + a.y * b.y + a.z * b.z; +} +inline static double length(const Point3D& a) +{ + return sqrtf(dot(a, a)); +} +inline static Point3D unit(const Point3D& a) +{ + return a / length(a); +} struct Triangle3D { - Triangle3D() {} - Triangle3D(Point3D & p1, Point3D & p2, Point3D & p3) - { - points[0] = p1; - points[1] = p2; - points[2] = p3; - } - Point3D points[3]; + Triangle3D() + {} + Triangle3D(Point3D& p1, Point3D& p2, Point3D& p3) + { + points[0] = p1; + points[1] = p2; + points[2] = p3; + } + Point3D points[3]; }; struct cLineSegment { - cLineSegment() : len(0), lenXY(0) {} - cLineSegment(Point3D & p1, Point3D & p2) { SetPoints(p1, p2); } - void SetPoints(Point3D & p1, Point3D & p2); - void PointAt(float dist, Point3D & retp); - Point3D pStart; - Point3D pDir; - Point3D pDirXY; - float len; - float lenXY; + cLineSegment() + : len(0) + , lenXY(0) + {} + cLineSegment(Point3D& p1, Point3D& p2) + { + SetPoints(p1, p2); + } + void SetPoints(Point3D& p1, Point3D& p2); + void PointAt(float dist, Point3D& retp); + Point3D pStart; + Point3D pDir; + Point3D pDirXY; + float len; + float lenXY; }; class cSimTool { public: cSimTool(const TopoDS_Shape& toolShape, float res); - ~cSimTool() {} + ~cSimTool() + {} - float GetToolProfileAt(float pos); - bool isInside(const TopoDS_Shape& toolShape, Base::Vector3d pnt, float res); + float GetToolProfileAt(float pos); + bool isInside(const TopoDS_Shape& toolShape, Base::Vector3d pnt, float res); -/* m_toolShape has to be populated with linearly increased - radiusPos to get the tool profile at given position */ - std::vector m_toolShape; + /* m_toolShape has to be populated with linearly increased + radiusPos to get the tool profile at given position */ + std::vector m_toolShape; float radius; - float length; + float length; }; -template +template class Array2D { public: - Array2D() : data(nullptr), height(0) {} + Array2D() + : data(nullptr) + , height(0) + {} - ~Array2D() - { - if (data) - delete[] data; - } + ~Array2D() + { + if (data) { + delete[] data; + } + } - void Init(int x, int y) - { - data = new T[x * y]; - height = y; - } + void Init(int x, int y) + { + data = new T[x * y]; + height = y; + } - T *operator [] (int i) { return data + i * height; } + T* operator[](int i) + { + return data + i * height; + } private: - T *data; - int height; + T* data; + int height; }; class cStock { public: - cStock(float px, float py, float pz, float lx, float ly, float lz, float res); - ~cStock(); - void Tessellate(Mesh::MeshObject & meshOuter, Mesh::MeshObject & meshInner); + cStock(float px, float py, float pz, float lx, float ly, float lz, float res); + ~cStock(); + void Tessellate(Mesh::MeshObject& meshOuter, Mesh::MeshObject& meshInner); void CreatePocket(float x, float y, float rad, float height); - void ApplyLinearTool(Point3D & p1, Point3D & p2, cSimTool &tool); - void ApplyCircularTool(Point3D & p1, Point3D & p2, Point3D & cent, cSimTool &tool, bool isCCW); - inline Point3D ToInner(Point3D & p) { - return Point3D((p.x - m_px) / m_res, (p.y - m_py) / m_res, p.z); - } + void ApplyLinearTool(Point3D& p1, Point3D& p2, cSimTool& tool); + void ApplyCircularTool(Point3D& p1, Point3D& p2, Point3D& cent, cSimTool& tool, bool isCCW); + inline Point3D ToInner(Point3D& p) + { + return Point3D((p.x - m_px) / m_res, (p.y - m_py) / m_res, p.z); + } private: - float FindRectTop(int & xp, int & yp, int & x_size, int & y_size, bool scanHoriz); - void FindRectBot(int & xp, int & yp, int & x_size, int & y_size, bool scanHoriz); - void SetFacetPoints(MeshCore::MeshGeomFacet & facet, Point3D & p1, Point3D & p2, Point3D & p3); - void AddQuad(Point3D & p1, Point3D & p2, Point3D & p3, Point3D & p4, std::vector & facets); - int TesselTop(int x, int y); - int TesselBot(int x, int y); - int TesselSidesX(int yp); - int TesselSidesY(int xp); - Array2D m_stock; - Array2D m_attr; - float m_px, m_py, m_pz; // stock zero position - float m_lx, m_ly, m_lz; // stock dimensions - float m_res; // resoulution - float m_plane; // stock plane height - int m_x, m_y; // stock array size - std::vector facetsOuter; - std::vector facetsInner; + float FindRectTop(int& xp, int& yp, int& x_size, int& y_size, bool scanHoriz); + void FindRectBot(int& xp, int& yp, int& x_size, int& y_size, bool scanHoriz); + void SetFacetPoints(MeshCore::MeshGeomFacet& facet, Point3D& p1, Point3D& p2, Point3D& p3); + void AddQuad(Point3D& p1, + Point3D& p2, + Point3D& p3, + Point3D& p4, + std::vector& facets); + int TesselTop(int x, int y); + int TesselBot(int x, int y); + int TesselSidesX(int yp); + int TesselSidesY(int xp); + Array2D m_stock; + Array2D m_attr; + float m_px, m_py, m_pz; // stock zero position + float m_lx, m_ly, m_lz; // stock dimensions + float m_res; // resoulution + float m_plane; // stock plane height + int m_x, m_y; // stock array size + std::vector facetsOuter; + std::vector facetsInner; }; class cVolSim { public: - cVolSim(); - ~cVolSim(); - void CreateStock(); + cVolSim(); + ~cVolSim(); + void CreateStock(); private: - cStock *stock; + cStock* stock; }; #endif // PATHSIMULATOR_VolSim_H diff --git a/src/Mod/CAM/PathSimulator/AppGL/CAMSim.cpp b/src/Mod/CAM/PathSimulator/AppGL/CAMSim.cpp index e5665c735d..b6d04af20b 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/CAMSim.cpp +++ b/src/Mod/CAM/PathSimulator/AppGL/CAMSim.cpp @@ -31,7 +31,6 @@ #include - using namespace Base; using namespace CAMSimulator; @@ -47,7 +46,7 @@ void CAMSimulator::CAMSim::resetSimulation() DlgCAMSimulator::GetInstance()->resetSimulation(); } -void CAMSim::addTool(const std::vector &toolProfilePoints, +void CAMSim::addTool(const std::vector& toolProfilePoints, int toolNumber, float diameter, float resolution) diff --git a/src/Mod/CAM/PathSimulator/AppGL/CAMSim.h b/src/Mod/CAM/PathSimulator/AppGL/CAMSim.h index 2fb85b655d..c467d7fc37 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/CAMSim.h +++ b/src/Mod/CAM/PathSimulator/AppGL/CAMSim.h @@ -59,7 +59,7 @@ public: void BeginSimulation(const Part::TopoShape& stock, float resolution); void resetSimulation(); - void addTool(const std::vector &toolProfilePoints, + void addTool(const std::vector& toolProfilePoints, int toolNumber, float diameter, float resolution); diff --git a/src/Mod/CAM/PathSimulator/AppGL/CAMSimPyImp.cpp b/src/Mod/CAM/PathSimulator/AppGL/CAMSimPyImp.cpp index 5932b7aaed..7ee0eea34b 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/CAMSimPyImp.cpp +++ b/src/Mod/CAM/PathSimulator/AppGL/CAMSimPyImp.cpp @@ -68,8 +68,13 @@ PyObject* CAMSimPy::BeginSimulation(PyObject* args, PyObject* kwds) static const std::array kwlist {"stock", "resolution", nullptr}; PyObject* pObjStock; float resolution; - if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds,"O!f", - kwlist, &(Part::TopoShapePy::Type), &pObjStock, &resolution)) { + if (!Base::Wrapped_ParseTupleAndKeywords(args, + kwds, + "O!f", + kwlist, + &(Part::TopoShapePy::Type), + &pObjStock, + &resolution)) { return nullptr; } CAMSim* sim = getCAMSimPtr(); @@ -81,14 +86,23 @@ PyObject* CAMSimPy::BeginSimulation(PyObject* args, PyObject* kwds) PyObject* CAMSimPy::AddTool(PyObject* args, PyObject* kwds) { - static const std::array kwlist { - "shape", "toolnumber", "diameter", "resolution", nullptr}; + static const std::array kwlist {"shape", + "toolnumber", + "diameter", + "resolution", + nullptr}; PyObject* pObjToolShape; int toolNumber; float resolution; float diameter; - if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "Oiff", kwlist, &pObjToolShape, - &toolNumber, &diameter, &resolution)) { + if (!Base::Wrapped_ParseTupleAndKeywords(args, + kwds, + "Oiff", + kwlist, + &pObjToolShape, + &toolNumber, + &diameter, + &resolution)) { return nullptr; } // The tool shape is defined by a list of 2d points that represents the tool revolving profile @@ -111,8 +125,13 @@ PyObject* CAMSimPy::SetBaseShape(PyObject* args, PyObject* kwds) static const std::array kwlist {"shape", "resolution", nullptr}; PyObject* pObjBaseShape; float resolution; - if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds,"O!f", - kwlist, &(Part::TopoShapePy::Type), &pObjBaseShape, &resolution)) { + if (!Base::Wrapped_ParseTupleAndKeywords(args, + kwds, + "O!f", + kwlist, + &(Part::TopoShapePy::Type), + &pObjBaseShape, + &resolution)) { return nullptr; } if (!PyArg_ParseTuple(args, "O!f", &(Part::TopoShapePy::Type), &pObjBaseShape, &resolution)) { diff --git a/src/Mod/CAM/PathSimulator/AppGL/DlgCAMSimulator.cpp b/src/Mod/CAM/PathSimulator/AppGL/DlgCAMSimulator.cpp index 4b1a61ac1a..6bf28fa2d0 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/DlgCAMSimulator.cpp +++ b/src/Mod/CAM/PathSimulator/AppGL/DlgCAMSimulator.cpp @@ -39,24 +39,29 @@ namespace CAMSimulator static const float MouseScrollDelta = 120.0f; DlgCAMSimulator::DlgCAMSimulator(QWindow* parent) - : QWindow(parent) { + : QWindow(parent) +{ setSurfaceType(QWindow::OpenGLSurface); mMillSimulator = new MillSimulation(); } -void DlgCAMSimulator::render(QPainter* painter) { +void DlgCAMSimulator::render(QPainter* painter) +{ Q_UNUSED(painter); } -void DlgCAMSimulator::render() { +void DlgCAMSimulator::render() +{ mMillSimulator->ProcessSim((unsigned int)(QDateTime::currentMSecsSinceEpoch())); } -void DlgCAMSimulator::renderLater() { +void DlgCAMSimulator::renderLater() +{ requestUpdate(); } -bool DlgCAMSimulator::event(QEvent* event) { +bool DlgCAMSimulator::event(QEvent* event) +{ switch (event->type()) { case QEvent::UpdateRequest: renderNow(); @@ -67,7 +72,8 @@ bool DlgCAMSimulator::event(QEvent* event) { return QWindow::event(event); } -void DlgCAMSimulator::exposeEvent(QExposeEvent* event) { +void DlgCAMSimulator::exposeEvent(QExposeEvent* event) +{ Q_UNUSED(event); if (isExposed()) { @@ -75,36 +81,42 @@ void DlgCAMSimulator::exposeEvent(QExposeEvent* event) { } } -void DlgCAMSimulator::mouseMoveEvent(QMouseEvent* ev) { +void DlgCAMSimulator::mouseMoveEvent(QMouseEvent* ev) +{ int modifiers = (ev->modifiers() & Qt::ShiftModifier) != 0 ? MS_KBD_SHIFT : 0; modifiers |= (ev->modifiers() & Qt::ControlModifier) != 0 ? MS_KBD_CONTROL : 0; modifiers |= (ev->modifiers() & Qt::AltModifier) != 0 ? MS_KBD_ALT : 0; mMillSimulator->MouseMove(ev->x(), ev->y(), modifiers); } -void DlgCAMSimulator::mousePressEvent(QMouseEvent* ev) { +void DlgCAMSimulator::mousePressEvent(QMouseEvent* ev) +{ mMillSimulator->MousePress(ev->button(), true, ev->x(), ev->y()); } -void DlgCAMSimulator::mouseReleaseEvent(QMouseEvent* ev) { +void DlgCAMSimulator::mouseReleaseEvent(QMouseEvent* ev) +{ mMillSimulator->MousePress(ev->button(), false, ev->x(), ev->y()); } -void DlgCAMSimulator::wheelEvent(QWheelEvent* ev) { +void DlgCAMSimulator::wheelEvent(QWheelEvent* ev) +{ mMillSimulator->MouseScroll((float)ev->angleDelta().y() / MouseScrollDelta); } -void DlgCAMSimulator::resetSimulation() { -} +void DlgCAMSimulator::resetSimulation() +{} -void DlgCAMSimulator::addGcodeCommand(const char* cmd) { +void DlgCAMSimulator::addGcodeCommand(const char* cmd) +{ mMillSimulator->AddGcodeLine(cmd); } void DlgCAMSimulator::addTool(const std::vector& toolProfilePoints, int toolNumber, float diameter, - float resolution) { + float resolution) +{ Q_UNUSED(resolution) std::string toolCmd = "T" + std::to_string(toolNumber); mMillSimulator->AddGcodeLine(toolCmd.c_str()); @@ -113,7 +125,8 @@ void DlgCAMSimulator::addTool(const std::vector& toolProfilePoints, } } -void DlgCAMSimulator::hideEvent(QHideEvent* ev) { +void DlgCAMSimulator::hideEvent(QHideEvent* ev) +{ mMillSimulator->Clear(); doGlCleanup(); mAnimating = false; @@ -122,7 +135,8 @@ void DlgCAMSimulator::hideEvent(QHideEvent* ev) { mInstance = nullptr; } -void DlgCAMSimulator::resizeEvent(QResizeEvent* event) { +void DlgCAMSimulator::resizeEvent(QResizeEvent* event) +{ if (!mContext) { return; } @@ -139,7 +153,8 @@ void DlgCAMSimulator::resizeEvent(QResizeEvent* event) { void DlgCAMSimulator::GetMeshData(const Part::TopoShape& tshape, float resolution, std::vector& verts, - std::vector& indices) { + std::vector& indices) +{ std::vector normalCount; int nVerts = 0; for (auto& shape : tshape.getSubTopoShapes(TopAbs_FACE)) { @@ -183,7 +198,8 @@ void DlgCAMSimulator::GetMeshData(const Part::TopoShape& tshape, } } -void DlgCAMSimulator::startSimulation(const Part::TopoShape& stock, float quality) { +void DlgCAMSimulator::startSimulation(const Part::TopoShape& stock, float quality) +{ mQuality = quality; mNeedsInitialize = true; show(); @@ -192,7 +208,8 @@ void DlgCAMSimulator::startSimulation(const Part::TopoShape& stock, float qualit setAnimating(true); } -void DlgCAMSimulator::initialize() { +void DlgCAMSimulator::initialize() +{ mMillSimulator->InitSimulation(mQuality); const qreal retinaScale = devicePixelRatio(); @@ -200,7 +217,8 @@ void DlgCAMSimulator::initialize() { glEnable(GL_MULTISAMPLE); } -void DlgCAMSimulator::checkInitialization() { +void DlgCAMSimulator::checkInitialization() +{ if (!mContext) { mLastContext = QOpenGLContext::currentContext(); mContext = new QOpenGLContext(this); @@ -223,7 +241,8 @@ void DlgCAMSimulator::checkInitialization() { } } -void DlgCAMSimulator::doGlCleanup() { +void DlgCAMSimulator::doGlCleanup() +{ if (mLastContext != nullptr) { mLastContext->makeCurrent(this); } @@ -233,7 +252,8 @@ void DlgCAMSimulator::doGlCleanup() { } } -void DlgCAMSimulator::renderNow() { +void DlgCAMSimulator::renderNow() +{ static unsigned int lastTime = 0; static int frameCount = 0; static int fps = 0; @@ -260,7 +280,8 @@ void DlgCAMSimulator::renderNow() { (void)fps; } -void DlgCAMSimulator::setAnimating(bool animating) { +void DlgCAMSimulator::setAnimating(bool animating) +{ mAnimating = animating; if (animating) { @@ -268,7 +289,8 @@ void DlgCAMSimulator::setAnimating(bool animating) { } } -DlgCAMSimulator* DlgCAMSimulator::GetInstance() { +DlgCAMSimulator* DlgCAMSimulator::GetInstance() +{ if (mInstance == nullptr) { QSurfaceFormat format; format.setVersion(4, 1); // Request OpenGL 4.1 - for MacOS @@ -287,14 +309,16 @@ DlgCAMSimulator* DlgCAMSimulator::GetInstance() { return mInstance; } -void DlgCAMSimulator::SetStockShape(const Part::TopoShape& shape, float resolution) { +void DlgCAMSimulator::SetStockShape(const Part::TopoShape& shape, float resolution) +{ std::vector verts; std::vector indices; GetMeshData(shape, resolution, verts, indices); mMillSimulator->SetArbitraryStock(verts, indices); } -void DlgCAMSimulator::SetBaseShape(const Part::TopoShape& tshape, float resolution) { +void DlgCAMSimulator::SetBaseShape(const Part::TopoShape& tshape, float resolution) +{ std::vector verts; std::vector indices; GetMeshData(tshape, resolution, verts, indices); @@ -312,10 +336,12 @@ SimStock::SimStock(float px, float py, float pz, float lx, float ly, float lz, f , mPz(pz + 0.005 * lz) , mLx(lx) , mLy(ly) - , mLz(1.01 * lz) { + , mLz(1.01 * lz) +{ (void)res; } -SimStock::~SimStock() {} +SimStock::~SimStock() +{} } // namespace CAMSimulator diff --git a/src/Mod/CAM/PathSimulator/AppGL/DlgCAMSimulator.h b/src/Mod/CAM/PathSimulator/AppGL/DlgCAMSimulator.h index 6e62f6194d..7acf3da759 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/DlgCAMSimulator.h +++ b/src/Mod/CAM/PathSimulator/AppGL/DlgCAMSimulator.h @@ -37,7 +37,7 @@ namespace MillSim // use short declaration as using 'include' causes a header loop class MillSimulation; struct Vertex; -} +} // namespace MillSim namespace CAMSimulator { @@ -69,7 +69,7 @@ public: void SetStockShape(const Part::TopoShape& tshape, float resolution); void SetBaseShape(const Part::TopoShape& tshape, float resolution); - public: // slots: +public: // slots: void renderLater(); void renderNow(); void startSimulation(const Part::TopoShape& stock, float quality); diff --git a/src/Mod/CAM/PathSimulator/AppGL/EndMill.h b/src/Mod/CAM/PathSimulator/AppGL/EndMill.h index 66db2a2eb9..98438ec332 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/EndMill.h +++ b/src/Mod/CAM/PathSimulator/AppGL/EndMill.h @@ -35,7 +35,7 @@ namespace MillSim class EndMill { public: - std::vectorprofilePoints; + std::vector profilePoints; float radius; int nPoints = 0; int toolId = -1; diff --git a/src/Mod/CAM/PathSimulator/AppGL/GlUtils.h b/src/Mod/CAM/PathSimulator/AppGL/GlUtils.h index 6a168abffb..d46eca829f 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/GlUtils.h +++ b/src/Mod/CAM/PathSimulator/AppGL/GlUtils.h @@ -32,12 +32,12 @@ constexpr auto EPSILON = 0.00001f; #define EQ_FLOAT(x, y) (fabs((x) - (y)) < EPSILON) -#define MS_MOUSE_LEFT 0x01 +#define MS_MOUSE_LEFT 0x01 #define MS_MOUSE_RIGHT 0x02 -#define MS_MOUSE_MID 0x04 -#define MS_KBD_SHIFT 0x08 +#define MS_MOUSE_MID 0x04 +#define MS_KBD_SHIFT 0x08 #define MS_KBD_CONTROL 0x10 -#define MS_KBD_ALT 0x20 +#define MS_KBD_ALT 0x20 #define GL(x) \ { \ diff --git a/src/Mod/CAM/PathSimulator/AppGL/GuiDisplay.cpp b/src/Mod/CAM/PathSimulator/AppGL/GuiDisplay.cpp index b3005f41ff..a5c0f20b3a 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/GuiDisplay.cpp +++ b/src/Mod/CAM/PathSimulator/AppGL/GuiDisplay.cpp @@ -28,20 +28,20 @@ using namespace MillSim; GuiItem guiItems[] = { - {eGuiItemSlider, 0, 0, 240, -36, 0}, - {eGuiItemThumb, 0, 0, 328, -50, 1}, - {eGuiItemPause, 0, 0, 40, -50, 'P', true}, - {eGuiItemPlay, 0, 0, 40, -50, 'S', false}, - {eGuiItemSingleStep, 0, 0, 80, -50, 'T'}, - {eGuiItemFaster, 0, 0, 120, -50, 'F'}, - {eGuiItemRotate, 0, 0, -140, -50, ' ', false, GUIITEM_CHECKABLE}, - {eGuiItemCharXImg, 0, 0, 160, -50, 0, false, 0}, // 620 - {eGuiItemChar0Img, 0, 0, 200, -50, 0, false, 0}, - {eGuiItemChar1Img, 0, 0, 185, -50, 0, false, 0}, - {eGuiItemChar4Img, 0, 0, 180, -50, 0, true, 0}, - {eGuiItemPath, 0, 0, -100, -50, 'L', false, GUIITEM_CHECKABLE}, + {eGuiItemSlider, 0, 0, 240, -36, 0}, + {eGuiItemThumb, 0, 0, 328, -50, 1}, + {eGuiItemPause, 0, 0, 40, -50, 'P', true}, + {eGuiItemPlay, 0, 0, 40, -50, 'S', false}, + {eGuiItemSingleStep, 0, 0, 80, -50, 'T'}, + {eGuiItemFaster, 0, 0, 120, -50, 'F'}, + {eGuiItemRotate, 0, 0, -140, -50, ' ', false, GUIITEM_CHECKABLE}, + {eGuiItemCharXImg, 0, 0, 160, -50, 0, false, 0}, // 620 + {eGuiItemChar0Img, 0, 0, 200, -50, 0, false, 0}, + {eGuiItemChar1Img, 0, 0, 185, -50, 0, false, 0}, + {eGuiItemChar4Img, 0, 0, 180, -50, 0, true, 0}, + {eGuiItemPath, 0, 0, -100, -50, 'L', false, GUIITEM_CHECKABLE}, {eGuiItemAmbientOclusion, 0, 0, -60, -50, 'A', false, GUIITEM_CHECKABLE}, - {eGuiItemView, 0, 0, -180, -50, 'V', false}, + {eGuiItemView, 0, 0, -180, -50, 'V', false}, }; #define NUM_GUI_ITEMS (sizeof(guiItems) / sizeof(GuiItem)) @@ -197,9 +197,8 @@ void GuiDisplay::MouseCursorPos(int x, int y) if (g->actionKey == 0) { continue; } - bool mouseCursorContained = - x > g->posx() && x < (g->posx() + g->texItem.w) && - y > g->posy() && y < (g->posy() + g->texItem.h); + bool mouseCursorContained = x > g->posx() && x < (g->posx() + g->texItem.w) && y > g->posy() + && y < (g->posy() + g->texItem.h); g->mouseOver = !g->hidden && mouseCursorContained; diff --git a/src/Mod/CAM/PathSimulator/AppGL/GuiDisplay.h b/src/Mod/CAM/PathSimulator/AppGL/GuiDisplay.h index d98c2f1c64..b6ad0fb5bd 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/GuiDisplay.h +++ b/src/Mod/CAM/PathSimulator/AppGL/GuiDisplay.h @@ -55,17 +55,19 @@ struct GuiItem { eGuiItems name; unsigned int vbo, vao; - int sx, sy; // screen location - int actionKey; // action key when item pressed + int sx, sy; // screen location + int actionKey; // action key when item pressed bool hidden {}; // is item hidden unsigned int flags {}; bool mouseOver {}; TextureItem texItem {}; - int posx() { + int posx() + { return sx >= 0 ? sx : gWindowSizeW + sx; } - int posy() { + int posy() + { return sy >= 0 ? sy : gWindowSizeH + sy; } void setPosx(int x) @@ -78,8 +80,8 @@ struct GuiItem } }; -#define GUIITEM_CHECKABLE 0x01 -#define GUIITEM_CHECKED 0x02 +#define GUIITEM_CHECKABLE 0x01 +#define GUIITEM_CHECKED 0x02 struct Vertex2D diff --git a/src/Mod/CAM/PathSimulator/AppGL/MillMotion.h b/src/Mod/CAM/PathSimulator/AppGL/MillMotion.h index 6e0bc427a1..9b9f1d2afd 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/MillMotion.h +++ b/src/Mod/CAM/PathSimulator/AppGL/MillMotion.h @@ -62,4 +62,4 @@ static inline void MotionPosToVec(vec3 vec, const MillMotion* motion) vec[2] = motion->z; } } // namespace MillSim -#endif \ No newline at end of file +#endif diff --git a/src/Mod/CAM/PathSimulator/AppGL/MillPathLine.cpp b/src/Mod/CAM/PathSimulator/AppGL/MillPathLine.cpp index c35976de9a..508a10529e 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/MillPathLine.cpp +++ b/src/Mod/CAM/PathSimulator/AppGL/MillPathLine.cpp @@ -28,16 +28,22 @@ void MillPathLine::GenerateModel() // vertex attribs glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(MillPathPosition), - (void*)offsetof(MillPathPosition, X)); + glVertexAttribPointer(0, + 3, + GL_FLOAT, + GL_FALSE, + sizeof(MillPathPosition), + (void*)offsetof(MillPathPosition, X)); glEnableVertexAttribArray(1); - glVertexAttribIPointer(1, 1, GL_INT, sizeof(MillPathPosition), - (void*)offsetof(MillPathPosition, SegmentId)); + glVertexAttribIPointer(1, + 1, + GL_INT, + sizeof(MillPathPosition), + (void*)offsetof(MillPathPosition, SegmentId)); // unbind and free glBindVertexArray(0); MillPathPointsBuffer.clear(); - } void MillPathLine::Clear() @@ -55,6 +61,4 @@ void MillPathLine::Render() glDrawArrays(GL_LINE_STRIP, 0, mNumVerts); } -} // namespace Millsim - - +} // namespace MillSim diff --git a/src/Mod/CAM/PathSimulator/AppGL/MillPathLine.h b/src/Mod/CAM/PathSimulator/AppGL/MillPathLine.h index c62d486a36..a015aefeaf 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/MillPathLine.h +++ b/src/Mod/CAM/PathSimulator/AppGL/MillPathLine.h @@ -28,7 +28,6 @@ protected: int mNumVerts; }; -} // namespace Millsim +} // namespace MillSim #endif // !__millpathline_h__ - diff --git a/src/Mod/CAM/PathSimulator/AppGL/MillPathSegment.cpp b/src/Mod/CAM/PathSimulator/AppGL/MillPathSegment.cpp index 1f76aa6767..72ba80cf8d 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/MillPathSegment.cpp +++ b/src/Mod/CAM/PathSimulator/AppGL/MillPathSegment.cpp @@ -103,9 +103,9 @@ MillPathSegment::MillPathSegment(EndMill* _endmill, MillMotion* from, MillMotion } else { endmill->GenerateArcSegmentDL(mRadius, - mStepAngRad * SWEEP_ARC_PAD, - mDiff[PZ] / numSimSteps, - &mShape); + mStepAngRad * SWEEP_ARC_PAD, + mDiff[PZ] / numSimSteps, + &mShape); numSimSteps++; } diff --git a/src/Mod/CAM/PathSimulator/AppGL/MillSimulation.cpp b/src/Mod/CAM/PathSimulator/AppGL/MillSimulation.cpp index 7824a3a59e..77344bc7b6 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/MillSimulation.cpp +++ b/src/Mod/CAM/PathSimulator/AppGL/MillSimulation.cpp @@ -493,7 +493,6 @@ void MillSimulation::HandleGuiAction(eGuiItems actionItem, bool checked) default: break; - } guiDisplay.UpdatePlayState(mSimPlaying); } @@ -623,7 +622,7 @@ void MillSimulation::UpdateWindowScale(int width, int height) bool MillSimulation::LoadGCodeFile(const char* fileName) { if (mCodeParser.Parse(fileName)) { - std::cout << "GCode file loaded successfully" << std::endl; + std::cout << "GCode file loaded successfully" << std::endl; return true; } return false; diff --git a/src/Mod/CAM/PathSimulator/AppGL/MillSimulation.h b/src/Mod/CAM/PathSimulator/AppGL/MillSimulation.h index 9a3911591d..e7ade679ae 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/MillSimulation.h +++ b/src/Mod/CAM/PathSimulator/AppGL/MillSimulation.h @@ -37,9 +37,9 @@ #include #include -#define VIEWITEM_SIMULATION 1 -#define VIEWITEM_BASE_SHAPE 2 -#define VIEWITEM_MAX 4 +#define VIEWITEM_SIMULATION 1 +#define VIEWITEM_BASE_SHAPE 2 +#define VIEWITEM_MAX 4 namespace MillSim { @@ -82,7 +82,6 @@ public: void UpdateWindowScale(int width, int height); - protected: void InitDisplay(float quality); void GlsimStart(); @@ -139,7 +138,6 @@ protected: bool mIsInStock = false; bool mSimPlaying = false; bool mSingleStep = false; - }; } // namespace MillSim #endif diff --git a/src/Mod/CAM/PathSimulator/AppGL/PreCompiled.h b/src/Mod/CAM/PathSimulator/AppGL/PreCompiled.h index 14ea3ae0a3..a89f828e6e 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/PreCompiled.h +++ b/src/Mod/CAM/PathSimulator/AppGL/PreCompiled.h @@ -50,7 +50,6 @@ // Xerces #include -#endif //_PreComp_ +#endif //_PreComp_ #endif - diff --git a/src/Mod/CAM/PathSimulator/AppGL/Shader.cpp b/src/Mod/CAM/PathSimulator/AppGL/Shader.cpp index c03d6449f0..e27673b839 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/Shader.cpp +++ b/src/Mod/CAM/PathSimulator/AppGL/Shader.cpp @@ -137,7 +137,7 @@ void Shader::UpdateSsaoTexSlot(int ssaoSlot) } } -void Shader::UpdateKernelVals(int nVals, float *vals) +void Shader::UpdateKernelVals(int nVals, float* vals) { glUniform3fv(mSamplesPos, nVals, vals); } @@ -372,7 +372,7 @@ const char* FragShaderFlat = R"( )"; - const char* VertShader2DFbo = R"( +const char* VertShader2DFbo = R"( #version 330 core layout(location = 0) in vec2 aPosition; @@ -387,7 +387,7 @@ const char* FragShaderFlat = R"( } )"; - const char* FragShader2dFbo = R"( +const char* FragShader2dFbo = R"( #version 330 out vec4 FragColor; @@ -419,7 +419,7 @@ const char* VertShaderGeom = R"( void main() { vec4 viewPos = view * model * vec4(aPos, 1.0); - FragPos = viewPos.xyz; + FragPos = viewPos.xyz; mat3 normalMatrix = transpose(inverse(mat3(view * model))); Normal = normalMatrix * (invertedNormals ? -aNormal : aNormal); @@ -440,7 +440,7 @@ const char* FragShaderGeom = R"( uniform vec3 objectColor; void main() - { + { // store the fragment position vector in the first gbuffer texture texPosition = FragPos; // also store the per-fragment normals into the gbuffer @@ -468,7 +468,7 @@ const char* FragShaderSSAO = R"( float bias = 0.025; // tile noise texture over screen based on screen dimensions divided by noise size - const vec2 noiseScale = vec2(800.0/4.0, 600.0/4.0); + const vec2 noiseScale = vec2(800.0/4.0, 600.0/4.0); uniform mat4 projection; @@ -488,7 +488,7 @@ const char* FragShaderSSAO = R"( { // get sample position vec3 samplePos = TBN * ssaoSamples[i]; // from tangent to view-space - samplePos = fragPos + samplePos * radius; + samplePos = fragPos + samplePos * radius; // project sample position (to sample texture) (to get position on screen/texture) vec4 offset = vec4(samplePos, 1.0); @@ -527,7 +527,7 @@ const char* FragShaderSSAOLighting = R"( uniform float lightLinear; void main() - { + { // retrieve data from gbuffer vec4 DiffuseA = texture(texAlbedo, texCoord); vec3 Diffuse = DiffuseA.rgb; @@ -542,7 +542,7 @@ const char* FragShaderSSAOLighting = R"( vec3 lightDir = normalize(lightPos - FragPos); vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Diffuse * lightColor; // specular - vec3 halfwayDir = normalize(lightDir + viewDir); + vec3 halfwayDir = normalize(lightDir + viewDir); float spec = pow(max(dot(Normal, halfwayDir), 0.0), 16.0); vec3 specular = lightColor * spec; // attenuation @@ -570,7 +570,7 @@ const char* FragShaderStdLighting = R"( uniform vec3 lightAmbient; void main() - { + { // retrieve data from gbuffer vec4 DiffuseA = texture(texAlbedo, texCoord); vec3 Diffuse = DiffuseA.rgb; @@ -578,13 +578,13 @@ const char* FragShaderStdLighting = R"( vec3 Normal = texture(texNormal, texCoord).rgb; // then calculate lighting as usual - vec3 lighting = lightAmbient * Diffuse; + vec3 lighting = lightAmbient * Diffuse; vec3 viewDir = normalize(-FragPos); // viewpos is (0.0.0) // diffuse vec3 lightDir = normalize(lightPos - FragPos); vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Diffuse * lightColor; // specular - vec3 halfwayDir = normalize(lightDir + viewDir); + vec3 halfwayDir = normalize(lightDir + viewDir); float spec = pow(max(dot(Normal, halfwayDir), 0.0), 16.0); vec3 specular = lightColor * spec; // attenuation @@ -604,13 +604,13 @@ const char* FragShaderSSAOBlur = R"( uniform sampler2D texSsao; - void main() + void main() { vec2 texelSize = 1.0 / vec2(textureSize(texSsao, 0)); float result = 0.0; - for (int x = -2; x <= 1; ++x) + for (int x = -2; x <= 1; ++x) { - for (int y = -2; y <= 1; ++y) + for (int y = -2; y <= 1; ++y) { vec2 offset = vec2(float(x), float(y)) * texelSize; result += texture(texSsao, texCoord + offset).r; diff --git a/src/Mod/CAM/PathSimulator/AppGL/Shader.h b/src/Mod/CAM/PathSimulator/AppGL/Shader.h index c808ee9dc1..47c867fb72 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/Shader.h +++ b/src/Mod/CAM/PathSimulator/AppGL/Shader.h @@ -50,7 +50,7 @@ public: void UpdateNormalTexSlot(int normalSlot); void UpdateNoiseTexSlot(int noiseSlot); void UpdateSsaoTexSlot(int ssaoSlot); - void UpdateKernelVals(int nVals, float *vals); + void UpdateKernelVals(int nVals, float* vals); void UpdateCurSegment(int curSeg); unsigned int CompileShader(const char* vertShader, const char* fragShader); void Activate(); diff --git a/src/Mod/CAM/PathSimulator/AppGL/SimDisplay.cpp b/src/Mod/CAM/PathSimulator/AppGL/SimDisplay.cpp index 08d94f24dd..bee1c69b09 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/SimDisplay.cpp +++ b/src/Mod/CAM/PathSimulator/AppGL/SimDisplay.cpp @@ -80,7 +80,6 @@ void SimDisplay::InitShaders() // Mill Path Line Shader shaderLinePath.CompileShader(VertShader3DLine, FragShader3DLine); - } void SimDisplay::CreateFboQuad() @@ -111,7 +110,15 @@ void SimDisplay::CreateDisplayFbos() // a color texture for the frame buffer glGenTextures(1, &mFboColTexture); glBindTexture(GL_TEXTURE_2D, mFboColTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, gWindowSizeW, gWindowSizeH, 0, GL_RGBA, GL_UBYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA8, + gWindowSizeW, + gWindowSizeH, + 0, + GL_RGBA, + GL_UBYTE, + NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mFboColTexture, 0); @@ -119,7 +126,15 @@ void SimDisplay::CreateDisplayFbos() // a position texture for the frame buffer glGenTextures(1, &mFboPosTexture); glBindTexture(GL_TEXTURE_2D, mFboPosTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, gWindowSizeW, gWindowSizeH, 0, GL_RGBA, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA16F, + gWindowSizeW, + gWindowSizeH, + 0, + GL_RGBA, + GL_FLOAT, + NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mFboPosTexture, 0); @@ -127,7 +142,15 @@ void SimDisplay::CreateDisplayFbos() // a normal texture for the frame buffer glGenTextures(1, &mFboNormTexture); glBindTexture(GL_TEXTURE_2D, mFboNormTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, gWindowSizeW, gWindowSizeH, 0, GL_RGBA, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA16F, + gWindowSizeW, + gWindowSizeH, + 0, + GL_RGBA, + GL_FLOAT, + NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, mFboNormTexture, 0); @@ -206,7 +229,7 @@ void SimDisplay::CreateSsaoFbos() vec3_set(sample, randomFloats(generator) * 2.0f - 1.0f, randomFloats(generator) * 2.0f - 1.0f, - randomFloats(generator));// * 2.0f - 1.0f); + randomFloats(generator)); // * 2.0f - 1.0f); vec3_norm(sample, sample); vec3_scale(sample, sample, randomFloats(generator)); float scale = float(i) / 64.0f; diff --git a/src/Mod/CAM/PathSimulator/AppGL/SimShapes.cpp b/src/Mod/CAM/PathSimulator/AppGL/SimShapes.cpp index f151aa10f1..246ae24c3e 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/SimShapes.cpp +++ b/src/Mod/CAM/PathSimulator/AppGL/SimShapes.cpp @@ -102,7 +102,7 @@ void Shape::RotateProfile(float* profPoints, float nx = ny * sx; ny *= sy; - vbuffer[vidx++] = {x1, y1, prevz, nx, ny, nz }; + vbuffer[vidx++] = {x1, y1, prevz, nx, ny, nz}; vbuffer[vidx++] = {x2, y2, z2, nx, ny, nz}; if (j != nSlices) { diff --git a/src/Mod/CAM/PathSimulator/AppGL/SimShapes.h b/src/Mod/CAM/PathSimulator/AppGL/SimShapes.h index e065250972..9b1970391b 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/SimShapes.h +++ b/src/Mod/CAM/PathSimulator/AppGL/SimShapes.h @@ -122,7 +122,6 @@ protected: int* vc2idx, int* ic1idx, int* ic2idx); - }; } // namespace MillSim diff --git a/src/Mod/CAM/PathSimulator/AppGL/SolidObject.cpp b/src/Mod/CAM/PathSimulator/AppGL/SolidObject.cpp index 263d15e167..02522440e0 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/SolidObject.cpp +++ b/src/Mod/CAM/PathSimulator/AppGL/SolidObject.cpp @@ -60,8 +60,7 @@ void SolidObject::GenerateSolid(std::vector& verts, std::vector & verts, std::vector& indices); + void GenerateSolid(std::vector& verts, std::vector& indices); vec3 center = {}; vec3 size = {}; vec3 position = {}; diff --git a/src/Mod/CAM/PathSimulator/AppGL/StockObject.cpp b/src/Mod/CAM/PathSimulator/AppGL/StockObject.cpp index 1586448f69..e1259320e6 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/StockObject.cpp +++ b/src/Mod/CAM/PathSimulator/AppGL/StockObject.cpp @@ -27,8 +27,7 @@ using namespace MillSim; StockObject::StockObject() -{ -} +{} void StockObject::GenerateBoxStock(float x, float y, float z, float l, float w, float h) { diff --git a/src/Mod/CAM/PathSimulator/AppGL/StockObject.h b/src/Mod/CAM/PathSimulator/AppGL/StockObject.h index d6926c8237..0902bd4b4e 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/StockObject.h +++ b/src/Mod/CAM/PathSimulator/AppGL/StockObject.h @@ -28,7 +28,7 @@ namespace MillSim { -class StockObject : public SolidObject +class StockObject: public SolidObject { public: StockObject(); diff --git a/src/Mod/CAM/PathSimulator/AppGL/TextureLoader.cpp b/src/Mod/CAM/PathSimulator/AppGL/TextureLoader.cpp index 095db63843..f4f15aef18 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/TextureLoader.cpp +++ b/src/Mod/CAM/PathSimulator/AppGL/TextureLoader.cpp @@ -46,7 +46,9 @@ TextureItem texItems[] = { int sssize = -1; -TextureLoader::TextureLoader(std::string imgFolder, std::vector fileNames, int textureSize) +TextureLoader::TextureLoader(std::string imgFolder, + std::vector fileNames, + int textureSize) : mImageFolder(imgFolder) { int buffsize = textureSize * textureSize * sizeof(unsigned int); @@ -63,15 +65,15 @@ TextureLoader::TextureLoader(std::string imgFolder, std::vector fil // parse compressed image into a texture buffer bool TextureLoader::AddImage(TextureItem* texItem, - QImage& pixmap, - unsigned int* buffPos, - int stride) + QImage& pixmap, + unsigned int* buffPos, + int stride) { int width = pixmap.width(); int height = pixmap.height(); buffPos += stride * texItem->ty + texItem->tx; for (int i = 0; i < height; i++) { - unsigned int* line = reinterpret_cast(pixmap.scanLine(i)); + unsigned int* line = reinterpret_cast(pixmap.scanLine(i)); for (int j = 0; j < width; j++) { buffPos[j] = line[j]; } diff --git a/src/Mod/CAM/PathSimulator/AppGL/TextureLoader.h b/src/Mod/CAM/PathSimulator/AppGL/TextureLoader.h index 0f74d7106d..ba9841a015 100644 --- a/src/Mod/CAM/PathSimulator/AppGL/TextureLoader.h +++ b/src/Mod/CAM/PathSimulator/AppGL/TextureLoader.h @@ -31,8 +31,8 @@ namespace MillSim struct TextureItem { - int tx{}, ty{}; // texture location - int w{}, h{}; // item size + int tx {}, ty {}; // texture location + int w {}, h {}; // item size }; class TextureLoader diff --git a/src/Mod/CAM/PathSimulator/PathSimulator.dox b/src/Mod/CAM/PathSimulator/PathSimulator.dox index 065c59ef12..6a628f3be8 100644 --- a/src/Mod/CAM/PathSimulator/PathSimulator.dox +++ b/src/Mod/CAM/PathSimulator/PathSimulator.dox @@ -1,3 +1,2 @@ /** \defgroup TEMPLATE PathSimulator * \ingroup WORKBENCHES */ - diff --git a/src/Mod/CAM/TestCAMApp.py b/src/Mod/CAM/TestCAMApp.py index cd72d79484..fc917045d4 100644 --- a/src/Mod/CAM/TestCAMApp.py +++ b/src/Mod/CAM/TestCAMApp.py @@ -44,9 +44,10 @@ from Tests.TestPathHelixGenerator import TestPathHelixGenerator from Tests.TestPathLog import TestPathLog from Tests.TestPathOpUtil import TestPathOpUtil -#from Tests.TestPathPost import TestPathPost +# from Tests.TestPathPost import TestPathPost from Tests.TestPathPost import TestPathPostUtils from Tests.TestPathPost import TestBuildPostList + # from Tests.TestPathPost import TestOutputNameSubstitution from Tests.TestPathPost import TestPostProcessorFactory from Tests.TestPathPost import TestResolvingPostProcessorName @@ -100,7 +101,7 @@ False if TestPathHelpers.__name__ else True # False if TestPathHelix.__name__ else True False if TestPathLog.__name__ else True False if TestPathOpUtil.__name__ else True -#False if TestPathPost.__name__ else True +# False if TestPathPost.__name__ else True False if TestPostProcessorFactory.__name__ else True False if TestResolvingPostProcessorName.__name__ else True False if TestPathPostUtils.__name__ else True diff --git a/src/Mod/CAM/Tests/FilePathTestUtils.py b/src/Mod/CAM/Tests/FilePathTestUtils.py index 518b667469..503410ee87 100644 --- a/src/Mod/CAM/Tests/FilePathTestUtils.py +++ b/src/Mod/CAM/Tests/FilePathTestUtils.py @@ -1,5 +1,3 @@ - - import os from unittest import TestCase diff --git a/src/Mod/CAM/Tests/PathTestUtils.py b/src/Mod/CAM/Tests/PathTestUtils.py index 91749180dd..ffdbf01cd1 100644 --- a/src/Mod/CAM/Tests/PathTestUtils.py +++ b/src/Mod/CAM/Tests/PathTestUtils.py @@ -51,9 +51,7 @@ class PathTestBase(unittest.TestCase): def assertLine(self, edge, pt1, pt2): """Verify that edge is a line from pt1 to pt2.""" # Depending on the setting of LineOld .... - self.assertTrue( - type(edge.Curve) is Part.Line or type(edge.Curve) is Part.LineSegment - ) + self.assertTrue(type(edge.Curve) is Part.Line or type(edge.Curve) is Part.LineSegment) self.assertCoincide(pt1, edge.valueAt(edge.FirstParameter)) self.assertCoincide(pt2, edge.valueAt(edge.LastParameter)) @@ -90,9 +88,7 @@ class PathTestBase(unittest.TestCase): """Verify that the edge goes through the given 3 points, representing start, mid and end point respectively.""" self.assertCoincide(edge.valueAt(edge.FirstParameter), p1) self.assertCoincide(edge.valueAt(edge.LastParameter), p3) - self.assertCoincide( - edge.valueAt((edge.FirstParameter + edge.LastParameter) / 2), p2 - ) + self.assertCoincide(edge.valueAt((edge.FirstParameter + edge.LastParameter) / 2), p2) def assertCylinderAt(self, solid, pt, r, h): """Verify that solid is a cylinder at the specified location.""" @@ -103,9 +99,7 @@ class PathTestBase(unittest.TestCase): base = solid.Edges[2] self.assertCircle(lid, Vector(pt.x, pt.y, pt.z + h), r) - self.assertLine( - hull, Vector(pt.x + r, pt.y, pt.z), Vector(pt.x + r, pt.y, pt.z + h) - ) + self.assertLine(hull, Vector(pt.x + r, pt.y, pt.z), Vector(pt.x + r, pt.y, pt.z + h)) self.assertCircle(base, Vector(pt.x, pt.y, pt.z), r) def assertConeAt(self, solid, pt, r1, r2, h): @@ -117,9 +111,7 @@ class PathTestBase(unittest.TestCase): base = solid.Edges[2] self.assertCircle(lid, Vector(pt.x, pt.y, pt.z + h), r2) - self.assertLine( - hull, Vector(pt.x + r1, pt.y, pt.z), Vector(pt.x + r2, pt.y, pt.z + h) - ) + self.assertLine(hull, Vector(pt.x + r1, pt.y, pt.z), Vector(pt.x + r2, pt.y, pt.z + h)) self.assertCircle(base, Vector(pt.x, pt.y, pt.z), r1) def assertCommandEqual(self, c1, c2): @@ -158,9 +150,7 @@ class PathTestBase(unittest.TestCase): else: def valueAt(e, fraction): - return e.valueAt( - e.FirstParameter + (e.LastParameter - e.FirstParameter) * fraction - ) + return e.valueAt(e.FirstParameter + (e.LastParameter - e.FirstParameter) * fraction) if Path.Geom.pointsCoincide(e1.Vertexes[0].Point, e2.Vertexes[0].Point): self.assertCoincide(e1.Vertexes[-1].Point, e2.Vertexes[-1].Point) diff --git a/src/Mod/CAM/Tests/TestCAMSanity.py b/src/Mod/CAM/Tests/TestCAMSanity.py index 6dde6a3b10..0289b23f79 100644 --- a/src/Mod/CAM/Tests/TestCAMSanity.py +++ b/src/Mod/CAM/Tests/TestCAMSanity.py @@ -38,6 +38,7 @@ import urllib import tempfile from Tests.PathTestUtils import PathTestBase + class TestCAMSanity(PathTestBase): @classmethod def setUpClass(cls): diff --git a/src/Mod/CAM/Tests/TestLinuxCNCPost.py b/src/Mod/CAM/Tests/TestLinuxCNCPost.py index 465818c805..1917d4f3a5 100644 --- a/src/Mod/CAM/Tests/TestLinuxCNCPost.py +++ b/src/Mod/CAM/Tests/TestLinuxCNCPost.py @@ -147,14 +147,12 @@ M2 Test imperial / inches """ self.compare_sixth_line( - "G0 X10 Y20 Z30", - "G0 X10.000 Y20.000 Z30.000 ", - "--no-header --no-show-editor" + "G0 X10 Y20 Z30", "G0 X10.000 Y20.000 Z30.000 ", "--no-header --no-show-editor" ) self.compare_sixth_line( "G0 X10 Y20 Z30", "G0 X10.00 Y20.00 Z30.00 ", - "--no-header --precision=2 --no-show-editor" + "--no-header --precision=2 --no-show-editor", ) def test020(self): @@ -164,7 +162,7 @@ M2 self.compare_sixth_line( "G0 X10 Y20 Z30", "N160 G0 X10.000 Y20.000 Z30.000 ", - "--no-header --line-numbers --no-show-editor" + "--no-header --line-numbers --no-show-editor", ) def test030(self): @@ -277,162 +275,147 @@ M2 """ Test comment """ - self.compare_sixth_line( - "(comment)", - "(comment) ", - "--no-header --no-show-editor" - ) + self.compare_sixth_line("(comment)", "(comment) ", "--no-header --no-show-editor") def test100(self): - """Test A, B, & C axis output for values between 0 and 90 degrees - """ + """Test A, B, & C axis output for values between 0 and 90 degrees""" self.compare_sixth_line( "G1 X10 Y20 Z30 A40 B50 C60", "G1 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 ", - "--no-header --no-show-editor" + "--no-header --no-show-editor", ) self.compare_sixth_line( "G1 X10 Y20 Z30 A40 B50 C60", "G1 X0.3937 Y0.7874 Z1.1811 A40.0000 B50.0000 C60.0000 ", - "--no-header --inches --no-show-editor" + "--no-header --inches --no-show-editor", ) def test110(self): - """Test A, B, & C axis output for 89 degrees - """ + """Test A, B, & C axis output for 89 degrees""" self.compare_sixth_line( "G1 X10 Y20 Z30 A89 B89 C89", "G1 X10.000 Y20.000 Z30.000 A89.000 B89.000 C89.000 ", - "--no-header --no-show-editor" + "--no-header --no-show-editor", ) self.compare_sixth_line( "G1 X10 Y20 Z30 A89 B89 C89", "G1 X0.3937 Y0.7874 Z1.1811 A89.0000 B89.0000 C89.0000 ", - "--no-header --inches --no-show-editor" + "--no-header --inches --no-show-editor", ) def test120(self): - """Test A, B, & C axis output for 90 degrees - """ + """Test A, B, & C axis output for 90 degrees""" self.compare_sixth_line( "G1 X10 Y20 Z30 A90 B90 C90", "G1 X10.000 Y20.000 Z30.000 A90.000 B90.000 C90.000 ", - "--no-header --no-show-editor" + "--no-header --no-show-editor", ) self.compare_sixth_line( "G1 X10 Y20 Z30 A90 B90 C90", "G1 X0.3937 Y0.7874 Z1.1811 A90.0000 B90.0000 C90.0000 ", - "--no-header --inches --no-show-editor" + "--no-header --inches --no-show-editor", ) def test130(self): - """Test A, B, & C axis output for 91 degrees - """ + """Test A, B, & C axis output for 91 degrees""" self.compare_sixth_line( "G1 X10 Y20 Z30 A91 B91 C91", "G1 X10.000 Y20.000 Z30.000 A91.000 B91.000 C91.000 ", - "--no-header --no-show-editor" + "--no-header --no-show-editor", ) self.compare_sixth_line( "G1 X10 Y20 Z30 A91 B91 C91", "G1 X0.3937 Y0.7874 Z1.1811 A91.0000 B91.0000 C91.0000 ", - "--no-header --inches --no-show-editor" + "--no-header --inches --no-show-editor", ) def test140(self): - """Test A, B, & C axis output for values between 90 and 180 degrees - """ + """Test A, B, & C axis output for values between 90 and 180 degrees""" self.compare_sixth_line( "G1 X10 Y20 Z30 A100 B110 C120", "G1 X10.000 Y20.000 Z30.000 A100.000 B110.000 C120.000 ", - "--no-header --no-show-editor" + "--no-header --no-show-editor", ) self.compare_sixth_line( "G1 X10 Y20 Z30 A100 B110 C120", "G1 X0.3937 Y0.7874 Z1.1811 A100.0000 B110.0000 C120.0000 ", - "--no-header --inches --no-show-editor" + "--no-header --inches --no-show-editor", ) def test150(self): - """Test A, B, & C axis output for values between 180 and 360 degrees - """ + """Test A, B, & C axis output for values between 180 and 360 degrees""" self.compare_sixth_line( "G1 X10 Y20 Z30 A240 B250 C260", "G1 X10.000 Y20.000 Z30.000 A240.000 B250.000 C260.000 ", - "--no-header --no-show-editor" + "--no-header --no-show-editor", ) self.compare_sixth_line( "G1 X10 Y20 Z30 A240 B250 C260", "G1 X0.3937 Y0.7874 Z1.1811 A240.0000 B250.0000 C260.0000 ", - "--no-header --inches --no-show-editor" + "--no-header --inches --no-show-editor", ) def test160(self): - """Test A, B, & C axis output for values greater than 360 degrees - """ + """Test A, B, & C axis output for values greater than 360 degrees""" self.compare_sixth_line( "G1 X10 Y20 Z30 A440 B450 C460", "G1 X10.000 Y20.000 Z30.000 A440.000 B450.000 C460.000 ", - "--no-header --no-show-editor" + "--no-header --no-show-editor", ) self.compare_sixth_line( "G1 X10 Y20 Z30 A440 B450 C460", "G1 X0.3937 Y0.7874 Z1.1811 A440.0000 B450.0000 C460.0000 ", - "--no-header --inches --no-show-editor" + "--no-header --inches --no-show-editor", ) def test170(self): - """Test A, B, & C axis output for values between 0 and -90 degrees - """ + """Test A, B, & C axis output for values between 0 and -90 degrees""" self.compare_sixth_line( "G1 X10 Y20 Z30 A-40 B-50 C-60", "G1 X10.000 Y20.000 Z30.000 A-40.000 B-50.000 C-60.000 ", - "--no-header --no-show-editor" + "--no-header --no-show-editor", ) self.compare_sixth_line( "G1 X10 Y20 Z30 A-40 B-50 C-60", "G1 X0.3937 Y0.7874 Z1.1811 A-40.0000 B-50.0000 C-60.0000 ", - "--no-header --inches --no-show-editor" + "--no-header --inches --no-show-editor", ) def test180(self): - """Test A, B, & C axis output for values between -90 and -180 degrees - """ + """Test A, B, & C axis output for values between -90 and -180 degrees""" self.compare_sixth_line( "G1 X10 Y20 Z30 A-100 B-110 C-120", "G1 X10.000 Y20.000 Z30.000 A-100.000 B-110.000 C-120.000 ", - "--no-header --no-show-editor" + "--no-header --no-show-editor", ) self.compare_sixth_line( "G1 X10 Y20 Z30 A-100 B-110 C-120", "G1 X0.3937 Y0.7874 Z1.1811 A-100.0000 B-110.0000 C-120.0000 ", - "--no-header --inches --no-show-editor" + "--no-header --inches --no-show-editor", ) def test190(self): - """Test A, B, & C axis output for values between -180 and -360 degrees - """ + """Test A, B, & C axis output for values between -180 and -360 degrees""" self.compare_sixth_line( "G1 X10 Y20 Z30 A-240 B-250 C-260", "G1 X10.000 Y20.000 Z30.000 A-240.000 B-250.000 C-260.000 ", - "--no-header --no-show-editor" + "--no-header --no-show-editor", ) self.compare_sixth_line( "G1 X10 Y20 Z30 A-240 B-250 C-260", "G1 X0.3937 Y0.7874 Z1.1811 A-240.0000 B-250.0000 C-260.0000 ", - "--no-header --inches --no-show-editor" + "--no-header --inches --no-show-editor", ) def test200(self): - """Test A, B, & C axis output for values below -360 degrees - """ + """Test A, B, & C axis output for values below -360 degrees""" self.compare_sixth_line( "G1 X10 Y20 Z30 A-440 B-450 C-460", "G1 X10.000 Y20.000 Z30.000 A-440.000 B-450.000 C-460.000 ", - "--no-header --no-show-editor" + "--no-header --no-show-editor", ) self.compare_sixth_line( "G1 X10 Y20 Z30 A-440 B-450 C-460", "G1 X0.3937 Y0.7874 Z1.1811 A-440.0000 B-450.0000 C-460.0000 ", - "--no-header --inches --no-show-editor" + "--no-header --inches --no-show-editor", ) diff --git a/src/Mod/CAM/Tests/TestPathAdaptive.py b/src/Mod/CAM/Tests/TestPathAdaptive.py index bbc6c042f7..68d5b75993 100644 --- a/src/Mod/CAM/Tests/TestPathAdaptive.py +++ b/src/Mod/CAM/Tests/TestPathAdaptive.py @@ -48,14 +48,11 @@ class TestPathAdaptive(PathTestBase): """ cls.needsInit = True - @classmethod def initClass(cls): # Open existing FreeCAD document with test geometry cls.needsInit = False - cls.doc = FreeCAD.open( - FreeCAD.getHomePath() + "Mod/CAM/Tests/test_adaptive.fcstd" - ) + cls.doc = FreeCAD.open(FreeCAD.getHomePath() + "Mod/CAM/Tests/test_adaptive.fcstd") # Create Job object, adding geometry objects from file opened above cls.job = PathJob.Create("Job", [cls.doc.Fusion], None) @@ -137,9 +134,7 @@ class TestPathAdaptive(PathTestBase): # self.assertTrue(expected_moves_test01 == operationMoves, # "expected_moves_test01: {}\noperationMoves: {}".format(expected_moves_test01, operationMoves)) - self.assertTrue( - len(adaptive.Path.Commands) > 100, "Command count not greater than 100." - ) + self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") def test02(self): """test02() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different.""" @@ -166,9 +161,7 @@ class TestPathAdaptive(PathTestBase): _addViewProvider(adaptive) self.doc.recompute() - self.assertTrue( - len(adaptive.Path.Commands) > 100, "Command count not greater than 100." - ) + self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") def test03(self): """test03() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different.""" @@ -195,9 +188,7 @@ class TestPathAdaptive(PathTestBase): _addViewProvider(adaptive) self.doc.recompute() - self.assertTrue( - len(adaptive.Path.Commands) > 100, "Command count not greater than 100." - ) + self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") def test04(self): """test04() Verify path generated non-closed edges with differing Z-heights that are closed with Z=1 projection: "Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19".""" @@ -238,9 +229,7 @@ class TestPathAdaptive(PathTestBase): _addViewProvider(adaptive) self.doc.recompute() - self.assertTrue( - len(adaptive.Path.Commands) > 100, "Command count not greater than 100." - ) + self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") def test05(self): """test05() Verify path generated closed wire with differing Z-heights: "Edge13", "Edge7", "Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19".""" @@ -283,9 +272,7 @@ class TestPathAdaptive(PathTestBase): _addViewProvider(adaptive) self.doc.recompute() - self.assertTrue( - len(adaptive.Path.Commands) > 100, "Command count not greater than 100." - ) + self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") def test06(self): """test06() Verify path generated with outer and inner edge loops at same Z height: "Edge15", "Edge30", "Edge31", "Edge29", "Edge19", "Edge18", "Edge35", "Edge32", "Edge34", "Edge33".""" @@ -329,15 +316,12 @@ class TestPathAdaptive(PathTestBase): self.doc.recompute() # Check command count - self.assertTrue( - len(adaptive.Path.Commands) > 100, "Command count not greater than 100." - ) + self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") # Check if any paths originate inside inner hole of donut. They should not. isInBox = False edges = [ - self.doc.Fusion.Shape.getElement(e) - for e in ["Edge35", "Edge32", "Edge33", "Edge34"] + self.doc.Fusion.Shape.getElement(e) for e in ["Edge35", "Edge32", "Edge33", "Edge34"] ] square = Part.Wire(edges) sqrBB = square.BoundBox @@ -374,15 +358,12 @@ class TestPathAdaptive(PathTestBase): _addViewProvider(adaptive) self.doc.recompute() - self.assertTrue( - len(adaptive.Path.Commands) > 100, "Command count not greater than 100." - ) + self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") # Check if any paths originate inside inner hole of donut. They should not. isInBox = False edges = [ - self.doc.Fusion.Shape.getElement(e) - for e in ["Edge35", "Edge32", "Edge33", "Edge34"] + self.doc.Fusion.Shape.getElement(e) for e in ["Edge35", "Edge32", "Edge33", "Edge34"] ] square = Part.Wire(edges) sqrBB = square.BoundBox @@ -401,8 +382,7 @@ class TestPathAdaptive(PathTestBase): # Check if any paths originate inside inner hole of donut. They should not. isInBox = False edges = [ - self.doc.Fusion.Shape.getElement(e) - for e in ["Edge35", "Edge32", "Edge33", "Edge34"] + self.doc.Fusion.Shape.getElement(e) for e in ["Edge35", "Edge32", "Edge33", "Edge34"] ] square = Part.Wire(edges) sqrBB = square.BoundBox @@ -531,9 +511,7 @@ def _addViewProvider(adaptiveOp): if FreeCAD.GuiUp: PathOpGui = PathAdaptiveGui.PathOpGui cmdRes = PathAdaptiveGui.Command.res - adaptiveOp.ViewObject.Proxy = PathOpGui.ViewProvider( - adaptiveOp.ViewObject, cmdRes - ) + adaptiveOp.ViewObject.Proxy = PathOpGui.ViewProvider(adaptiveOp.ViewObject, cmdRes) # Example string literal of expected path moves from an operation diff --git a/src/Mod/CAM/Tests/TestPathCore.py b/src/Mod/CAM/Tests/TestPathCore.py index a3f963e206..e3d4eeb455 100644 --- a/src/Mod/CAM/Tests/TestPathCore.py +++ b/src/Mod/CAM/Tests/TestPathCore.py @@ -58,9 +58,7 @@ class TestPathCore(PathTestBase): self.assertEqual(str(c4), "Command G1 [ X:4 Y:5 ]") # use placement - self.assertEqual( - str(c3.Placement), "Placement [Pos=(34,1.2,0), Yaw-Pitch-Roll=(0,0,0)]" - ) + self.assertEqual(str(c3.Placement), "Placement [Pos=(34,1.2,0), Yaw-Pitch-Roll=(0,0,0)]") self.assertEqual(c3.toGCode(), "G1 X34.000000 Y1.200000") p1 = FreeCAD.Placement() p1.Base = FreeCAD.Vector(3, 2, 1) @@ -93,9 +91,7 @@ class TestPathCore(PathTestBase): p = Path.Path([c1, c2]) self.assertAlmostEqual(str(p), "Path [ size:2 length:3.2361 ]", places=4) - self.assertEqual( - str(p.Commands), "[Command G1 [ X:1 Y:0 ], Command G1 [ X:0 Y:2 ]]" - ) + self.assertEqual(str(p.Commands), "[Command G1 [ X:1 Y:0 ], Command G1 [ X:0 Y:2 ]]") self.assertAlmostEqual(p.Length, 3.2361, places=4) p.addCommands(c1) self.assertEqual( diff --git a/src/Mod/CAM/Tests/TestPathDepthParams.py b/src/Mod/CAM/Tests/TestPathDepthParams.py index a8ccd95579..b2cf3d916b 100644 --- a/src/Mod/CAM/Tests/TestPathDepthParams.py +++ b/src/Mod/CAM/Tests/TestPathDepthParams.py @@ -228,9 +228,7 @@ class depthTestCases(unittest.TestCase): d = PathUtils.depth_params(**args) r = [i for i in d] - self.assertListEqual( - r, expected, "Expected {}, but result of {}".format(expected, r) - ) + self.assertListEqual(r, expected, "Expected {}, but result of {}".format(expected, r)) def test010(self): """stepping down with single stepdown roughly equal to total depth""" @@ -248,9 +246,7 @@ class depthTestCases(unittest.TestCase): d = PathUtils.depth_params(**args) r = [i for i in d] - self.assertListEqual( - r, expected, "Expected {}, but result of {}".format(expected, r) - ) + self.assertListEqual(r, expected, "Expected {}, but result of {}".format(expected, r)) args = { "clearance_height": 20.0, @@ -264,6 +260,4 @@ class depthTestCases(unittest.TestCase): d = PathUtils.depth_params(**args) r = [i for i in d] - self.assertListEqual( - r, expected, "Expected {}, but result of {}".format(expected, r) - ) + self.assertListEqual(r, expected, "Expected {}, but result of {}".format(expected, r)) diff --git a/src/Mod/CAM/Tests/TestPathDressupDogbone.py b/src/Mod/CAM/Tests/TestPathDressupDogbone.py index a7f8fd61d0..6580767cd5 100644 --- a/src/Mod/CAM/Tests/TestPathDressupDogbone.py +++ b/src/Mod/CAM/Tests/TestPathDressupDogbone.py @@ -152,9 +152,7 @@ class TestDressupDogbone(PathTestBase): doc.recompute() dog = dogbone.Proxy - locs = sorted( - [bone[1] for bone in dog.bones], key=lambda xy: xy[0] * 1000 + xy[1] - ) + locs = sorted([bone[1] for bone in dog.bones], key=lambda xy: xy[0] * 1000 + xy[1]) def formatBoneLoc(pt): return "(%.2f, %.2f)" % (pt[0], pt[1]) diff --git a/src/Mod/CAM/Tests/TestPathDrillable.py b/src/Mod/CAM/Tests/TestPathDrillable.py index 8642183335..9e0df98838 100644 --- a/src/Mod/CAM/Tests/TestPathDrillable.py +++ b/src/Mod/CAM/Tests/TestPathDrillable.py @@ -64,9 +64,7 @@ class TestPathDrillable(PathTestUtils.PathTestBase): # Invalid types candidate = self.obj.getSubObject("Vertex1") - self.assertRaises( - TypeError, lambda: Drillable.isDrillable(self.obj.Shape, candidate) - ) + self.assertRaises(TypeError, lambda: Drillable.isDrillable(self.obj.Shape, candidate)) # Test cylinder faces @@ -77,14 +75,10 @@ class TestPathDrillable(PathTestUtils.PathTestBase): self.assertTrue(Drillable.isDrillable(self.obj.Shape, candidate)) # Drilling with smaller bit - self.assertTrue( - Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=20) - ) + self.assertTrue(Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=20)) # Drilling with bit too large - self.assertFalse( - Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=30) - ) + self.assertFalse(Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=30)) # off-axis hole candidate = self.obj.getSubObject("Face44") @@ -97,9 +91,7 @@ class TestPathDrillable(PathTestUtils.PathTestBase): # Passing explicit vector self.assertTrue( - Drillable.isDrillable( - self.obj.Shape, candidate, vector=App.Vector(0, -1, 0) - ) + Drillable.isDrillable(self.obj.Shape, candidate, vector=App.Vector(0, -1, 0)) ) # Drilling with smaller bit @@ -157,14 +149,10 @@ class TestPathDrillable(PathTestUtils.PathTestBase): ) # Drilling with smaller bit - self.assertTrue( - Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=10) - ) + self.assertTrue(Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=10)) # Drilling with bit too large - self.assertFalse( - Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=30) - ) + self.assertFalse(Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=30)) # off-axis circular face hole candidate = self.obj.getSubObject("Face58") @@ -177,9 +165,7 @@ class TestPathDrillable(PathTestUtils.PathTestBase): # Passing explicit vector self.assertTrue( - Drillable.isDrillable( - self.obj.Shape, candidate, vector=App.Vector(0, -1, 0) - ) + Drillable.isDrillable(self.obj.Shape, candidate, vector=App.Vector(0, -1, 0)) ) # raised face @@ -222,15 +208,11 @@ class TestPathDrillable(PathTestUtils.PathTestBase): ) # Drilling with smaller bit - self.assertTrue( - Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=10) - ) + self.assertTrue(Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=10)) # Drilling with bit too large self.assertFalse( - Drillable.isDrillable( - self.obj.Shape, candidate, tooldiameter=30, vector=None - ) + Drillable.isDrillable(self.obj.Shape, candidate, tooldiameter=30, vector=None) ) # off-axis circular edge diff --git a/src/Mod/CAM/Tests/TestPathGeneratorDogboneII.py b/src/Mod/CAM/Tests/TestPathGeneratorDogboneII.py index f295aad816..de8af7fd5a 100644 --- a/src/Mod/CAM/Tests/TestPathGeneratorDogboneII.py +++ b/src/Mod/CAM/Tests/TestPathGeneratorDogboneII.py @@ -86,10 +86,7 @@ class TestGeneratorDogboneII(PathTestUtils.PathTestBase): self.assertEqual(f"[{', '.join(kinks)}]", s) def assertBones(self, maneuver, threshold, s): - bones = [ - f"({int(b.x())},{int(b.y())})" - for b in findDogboneKinks(maneuver, threshold) - ] + bones = [f"({int(b.x())},{int(b.y())})" for b in findDogboneKinks(maneuver, threshold)] self.assertEqual(f"[{', '.join(bones)}]", s) def assertBone(self, bone, s, digits=0): @@ -124,9 +121,7 @@ class TestGeneratorDogboneII(PathTestUtils.PathTestBase): def test30(self): """Verify dogbone detection""" - self.assertBones( - MNVR("G1X1/G1Y1/G1X0/G1Y0"), PI / 4, "[(1,0), (1,1), (0,1), (0,0)]" - ) + self.assertBones(MNVR("G1X1/G1Y1/G1X0/G1Y0"), PI / 4, "[(1,0), (1,1), (0,1), (0,0)]") self.assertBones(MNVR("G1X1/G1Y1/G1X0/G1Y0"), -PI / 4, "[]") # no bones on flat angle @@ -138,9 +133,7 @@ class TestGeneratorDogboneII(PathTestUtils.PathTestBase): self.assertBones(MNVR("G1X1/G3Y2J1/G1X0/G1Y0"), -PI / 4, "[]") # a bone on perpendicular arc - self.assertBones( - MNVR("G1X1/G3X3I1/G1Y1/G1X0/G1Y0"), PI / 4, "[(3,1), (0,1), (0,0)]" - ) + self.assertBones(MNVR("G1X1/G3X3I1/G1Y1/G1X0/G1Y0"), PI / 4, "[(3,1), (0,1), (0,0)]") self.assertBones(MNVR("G1X1/G3X3I1/G1Y1/G1X0/G1Y0"), -PI / 4, "[(1,0)]") def test40(self): diff --git a/src/Mod/CAM/Tests/TestPathGeom.py b/src/Mod/CAM/Tests/TestPathGeom.py index 303b53d3a6..9722c0ad98 100644 --- a/src/Mod/CAM/Tests/TestPathGeom.py +++ b/src/Mod/CAM/Tests/TestPathGeom.py @@ -44,18 +44,10 @@ class TestPathGeom(PathTestBase): def test01(self): """Verify diffAngle functionality.""" - self.assertRoughly( - Path.Geom.diffAngle(0, +0 * math.pi / 4, "Climb") / math.pi, 0 / 4.0 - ) - self.assertRoughly( - Path.Geom.diffAngle(0, +3 * math.pi / 4, "Climb") / math.pi, 5 / 4.0 - ) - self.assertRoughly( - Path.Geom.diffAngle(0, -3 * math.pi / 4, "Climb") / math.pi, 3 / 4.0 - ) - self.assertRoughly( - Path.Geom.diffAngle(0, +4 * math.pi / 4, "Climb") / math.pi, 4 / 4.0 - ) + self.assertRoughly(Path.Geom.diffAngle(0, +0 * math.pi / 4, "Climb") / math.pi, 0 / 4.0) + self.assertRoughly(Path.Geom.diffAngle(0, +3 * math.pi / 4, "Climb") / math.pi, 5 / 4.0) + self.assertRoughly(Path.Geom.diffAngle(0, -3 * math.pi / 4, "Climb") / math.pi, 3 / 4.0) + self.assertRoughly(Path.Geom.diffAngle(0, +4 * math.pi / 4, "Climb") / math.pi, 4 / 4.0) self.assertRoughly( Path.Geom.diffAngle(0, +0 * math.pi / 4, "Conventional") / math.pi, 0 / 4.0 ) @@ -139,19 +131,13 @@ class TestPathGeom(PathTestBase): # lines self.assertTrue( - Path.Geom.isVertical( - Part.Edge(Part.LineSegment(Vector(-1, -1, -1), Vector(-1, -1, 8))) - ) + Path.Geom.isVertical(Part.Edge(Part.LineSegment(Vector(-1, -1, -1), Vector(-1, -1, 8)))) ) self.assertFalse( - Path.Geom.isVertical( - Part.Edge(Part.LineSegment(Vector(-1, -1, -1), Vector(1, -1, 8))) - ) + Path.Geom.isVertical(Part.Edge(Part.LineSegment(Vector(-1, -1, -1), Vector(1, -1, 8)))) ) self.assertFalse( - Path.Geom.isVertical( - Part.Edge(Part.LineSegment(Vector(-1, -1, -1), Vector(-1, 1, 8))) - ) + Path.Geom.isVertical(Part.Edge(Part.LineSegment(Vector(-1, -1, -1), Vector(-1, 1, 8)))) ) self.assertTrue( @@ -170,57 +156,37 @@ class TestPathGeom(PathTestBase): ) ) self.assertFalse( - Path.Geom.isHorizontal( - Part.Edge(Part.LineSegment(Vector(1, -1, -1), Vector(1, -1, 8))) - ) + Path.Geom.isHorizontal(Part.Edge(Part.LineSegment(Vector(1, -1, -1), Vector(1, -1, 8)))) ) self.assertFalse( - Path.Geom.isHorizontal( - Part.Edge(Part.LineSegment(Vector(-1, 1, -1), Vector(-1, 1, 8))) - ) + Path.Geom.isHorizontal(Part.Edge(Part.LineSegment(Vector(-1, 1, -1), Vector(-1, 1, 8)))) ) # circles self.assertTrue( - Path.Geom.isVertical( - Part.Edge(Part.makeCircle(4, Vector(), Vector(0, 1, 0))) - ) + Path.Geom.isVertical(Part.Edge(Part.makeCircle(4, Vector(), Vector(0, 1, 0)))) ) self.assertTrue( - Path.Geom.isVertical( - Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 0, 0))) - ) + Path.Geom.isVertical(Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 0, 0)))) ) self.assertTrue( - Path.Geom.isVertical( - Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 1, 0))) - ) + Path.Geom.isVertical(Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 1, 0)))) ) self.assertFalse( - Path.Geom.isVertical( - Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 1, 1))) - ) + Path.Geom.isVertical(Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 1, 1)))) ) self.assertTrue( - Path.Geom.isHorizontal( - Part.Edge(Part.makeCircle(4, Vector(), Vector(0, 0, 1))) - ) + Path.Geom.isHorizontal(Part.Edge(Part.makeCircle(4, Vector(), Vector(0, 0, 1)))) ) self.assertFalse( - Path.Geom.isHorizontal( - Part.Edge(Part.makeCircle(4, Vector(), Vector(0, 1, 1))) - ) + Path.Geom.isHorizontal(Part.Edge(Part.makeCircle(4, Vector(), Vector(0, 1, 1)))) ) self.assertFalse( - Path.Geom.isHorizontal( - Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 0, 1))) - ) + Path.Geom.isHorizontal(Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 0, 1)))) ) self.assertFalse( - Path.Geom.isHorizontal( - Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 1, 1))) - ) + Path.Geom.isHorizontal(Part.Edge(Part.makeCircle(4, Vector(), Vector(1, 1, 1)))) ) # bezier curves @@ -311,37 +277,21 @@ class TestPathGeom(PathTestBase): def test07(self): """Verify speed interpolation works for different pitches""" # horizontal - self.assertRoughly( - 100, Path.Geom.speedBetweenPoints(Vector(), Vector(1, 1, 0), 100, 50) - ) - self.assertRoughly( - 100, Path.Geom.speedBetweenPoints(Vector(1, 1, 0), Vector(), 100, 50) - ) + self.assertRoughly(100, Path.Geom.speedBetweenPoints(Vector(), Vector(1, 1, 0), 100, 50)) + self.assertRoughly(100, Path.Geom.speedBetweenPoints(Vector(1, 1, 0), Vector(), 100, 50)) # vertical - self.assertRoughly( - 50, Path.Geom.speedBetweenPoints(Vector(), Vector(0, 0, 1), 100, 50) - ) - self.assertRoughly( - 50, Path.Geom.speedBetweenPoints(Vector(0, 0, 1), Vector(), 100, 50) - ) + self.assertRoughly(50, Path.Geom.speedBetweenPoints(Vector(), Vector(0, 0, 1), 100, 50)) + self.assertRoughly(50, Path.Geom.speedBetweenPoints(Vector(0, 0, 1), Vector(), 100, 50)) # 45° - self.assertRoughly( - 75, Path.Geom.speedBetweenPoints(Vector(), Vector(1, 0, 1), 100, 50) - ) - self.assertRoughly( - 75, Path.Geom.speedBetweenPoints(Vector(), Vector(0, 1, 1), 100, 50) - ) + self.assertRoughly(75, Path.Geom.speedBetweenPoints(Vector(), Vector(1, 0, 1), 100, 50)) + self.assertRoughly(75, Path.Geom.speedBetweenPoints(Vector(), Vector(0, 1, 1), 100, 50)) self.assertRoughly( 75, Path.Geom.speedBetweenPoints(Vector(), Vector(0.707, 0.707, 1), 100, 50), 0.01, ) - self.assertRoughly( - 75, Path.Geom.speedBetweenPoints(Vector(1, 0, 1), Vector(), 100, 50) - ) - self.assertRoughly( - 75, Path.Geom.speedBetweenPoints(Vector(0, 1, 1), Vector(), 100, 50) - ) + self.assertRoughly(75, Path.Geom.speedBetweenPoints(Vector(1, 0, 1), Vector(), 100, 50)) + self.assertRoughly(75, Path.Geom.speedBetweenPoints(Vector(0, 1, 1), Vector(), 100, 50)) self.assertRoughly( 75, Path.Geom.speedBetweenPoints(Vector(0.707, 0.707, 1), Vector(), 100, 50), @@ -393,37 +343,21 @@ class TestPathGeom(PathTestBase): def test08(self): """Verify speed interpolation works for different pitches if vSpeed > hSpeed""" # horizontal - self.assertRoughly( - 50, Path.Geom.speedBetweenPoints(Vector(), Vector(1, 1, 0), 50, 100) - ) - self.assertRoughly( - 50, Path.Geom.speedBetweenPoints(Vector(1, 1, 0), Vector(), 50, 100) - ) + self.assertRoughly(50, Path.Geom.speedBetweenPoints(Vector(), Vector(1, 1, 0), 50, 100)) + self.assertRoughly(50, Path.Geom.speedBetweenPoints(Vector(1, 1, 0), Vector(), 50, 100)) # vertical - self.assertRoughly( - 100, Path.Geom.speedBetweenPoints(Vector(), Vector(0, 0, 1), 50, 100) - ) - self.assertRoughly( - 100, Path.Geom.speedBetweenPoints(Vector(0, 0, 1), Vector(), 50, 100) - ) + self.assertRoughly(100, Path.Geom.speedBetweenPoints(Vector(), Vector(0, 0, 1), 50, 100)) + self.assertRoughly(100, Path.Geom.speedBetweenPoints(Vector(0, 0, 1), Vector(), 50, 100)) # 45° - self.assertRoughly( - 75, Path.Geom.speedBetweenPoints(Vector(), Vector(1, 0, 1), 50, 100) - ) - self.assertRoughly( - 75, Path.Geom.speedBetweenPoints(Vector(), Vector(0, 1, 1), 50, 100) - ) + self.assertRoughly(75, Path.Geom.speedBetweenPoints(Vector(), Vector(1, 0, 1), 50, 100)) + self.assertRoughly(75, Path.Geom.speedBetweenPoints(Vector(), Vector(0, 1, 1), 50, 100)) self.assertRoughly( 75, Path.Geom.speedBetweenPoints(Vector(), Vector(0.707, 0.707, 1), 50, 100), 0.01, ) - self.assertRoughly( - 75, Path.Geom.speedBetweenPoints(Vector(1, 0, 1), Vector(), 50, 100) - ) - self.assertRoughly( - 75, Path.Geom.speedBetweenPoints(Vector(0, 1, 1), Vector(), 50, 100) - ) + self.assertRoughly(75, Path.Geom.speedBetweenPoints(Vector(1, 0, 1), Vector(), 50, 100)) + self.assertRoughly(75, Path.Geom.speedBetweenPoints(Vector(0, 1, 1), Vector(), 50, 100)) self.assertRoughly( 75, Path.Geom.speedBetweenPoints(Vector(0.707, 0.707, 1), Vector(), 50, 100), @@ -492,9 +426,7 @@ class TestPathGeom(PathTestBase): p2 = Vector(-1, 0, 2) self.assertArc( Path.Geom.edgeForCmd( - Path.Command( - "G2", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 0, "J": 1, "K": 0} - ), + Path.Command("G2", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 0, "J": 1, "K": 0}), p1, ), p1, @@ -503,9 +435,7 @@ class TestPathGeom(PathTestBase): ) self.assertArc( Path.Geom.edgeForCmd( - Path.Command( - "G3", {"X": p1.x, "Y": p1.y, "z": p1.z, "I": -1, "J": 0, "K": 0} - ), + Path.Command("G3", {"X": p1.x, "Y": p1.y, "z": p1.z, "I": -1, "J": 0, "K": 0}), p2, ), p2, @@ -520,9 +450,7 @@ class TestPathGeom(PathTestBase): p2 = Vector(1, 0, 2) self.assertCurve( Path.Geom.edgeForCmd( - Path.Command( - "G2", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 0, "J": -1, "K": 1} - ), + Path.Command("G2", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 0, "J": -1, "K": 1}), p1, ), p1, @@ -533,9 +461,7 @@ class TestPathGeom(PathTestBase): p2 = Vector(0, -1, 2) self.assertCurve( Path.Geom.edgeForCmd( - Path.Command( - "G3", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 1, "J": 0, "K": 1} - ), + Path.Command("G3", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 1, "J": 0, "K": 1}), p1, ), p1, @@ -548,9 +474,7 @@ class TestPathGeom(PathTestBase): p2 = Vector(-1, 0, 0) self.assertCurve( Path.Geom.edgeForCmd( - Path.Command( - "G2", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 0, "J": 1, "K": -1} - ), + Path.Command("G2", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 0, "J": 1, "K": -1}), p1, ), p1, @@ -561,9 +485,7 @@ class TestPathGeom(PathTestBase): p2 = Vector(0, -1, 0) self.assertCurve( Path.Geom.edgeForCmd( - Path.Command( - "G3", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 1, "J": 0, "K": -1} - ), + Path.Command("G3", {"X": p2.x, "Y": p2.y, "Z": p2.z, "I": 1, "J": 0, "K": -1}), p1, ), p1, @@ -594,28 +516,18 @@ class TestPathGeom(PathTestBase): }, ) - self.assertCommandEqual( - cmds(p1, p2, p3, False), cmd("G2", p3, Vector(0, 10, 0)) - ) - self.assertCommandEqual( - cmds(p1, p4, p3, False), cmd("G3", p3, Vector(0, 10, 0)) - ) + self.assertCommandEqual(cmds(p1, p2, p3, False), cmd("G2", p3, Vector(0, 10, 0))) + self.assertCommandEqual(cmds(p1, p4, p3, False), cmd("G3", p3, Vector(0, 10, 0))) - self.assertCommandEqual( - cmds(p1, p2, p3, True), cmd("G3", p1, Vector(0, -10, 0)) - ) - self.assertCommandEqual( - cmds(p1, p4, p3, True), cmd("G2", p1, Vector(0, -10, 0)) - ) + self.assertCommandEqual(cmds(p1, p2, p3, True), cmd("G3", p1, Vector(0, -10, 0))) + self.assertCommandEqual(cmds(p1, p4, p3, True), cmd("G2", p1, Vector(0, -10, 0))) def test41(self): """Verify circle results in proper G2/G3 commands.""" def cmds(center, radius, up=True): norm = Vector(0, 0, 1) if up else Vector(0, 0, -1) - return Path.Geom.cmdsForEdge(Part.Edge(Part.Circle(center, norm, radius)))[ - 0 - ] + return Path.Geom.cmdsForEdge(Part.Edge(Part.Circle(center, norm, radius)))[0] def cmd(g, end, off): return Path.Command( @@ -680,14 +592,10 @@ class TestPathGeom(PathTestBase): self.assertCurve(e, p1, p2 + Vector(0, 0, 1), p3 + Vector(0, 0, 2)) e = Path.Geom.arcToHelix(Part.Edge(Part.Arc(p1, p2, p3)), 3, 7) - self.assertCurve( - e, p1 + Vector(0, 0, 3), p2 + Vector(0, 0, 5), p3 + Vector(0, 0, 7) - ) + self.assertCurve(e, p1 + Vector(0, 0, 3), p2 + Vector(0, 0, 5), p3 + Vector(0, 0, 7)) e = Path.Geom.arcToHelix(Part.Edge(Part.Arc(p1, p2, p3)), 9, 1) - self.assertCurve( - e, p1 + Vector(0, 0, 9), p2 + Vector(0, 0, 5), p3 + Vector(0, 0, 1) - ) + self.assertCurve(e, p1 + Vector(0, 0, 9), p2 + Vector(0, 0, 5), p3 + Vector(0, 0, 1)) dz = Vector(0, 0, 3) p11 = p1 + dz @@ -704,9 +612,7 @@ class TestPathGeom(PathTestBase): p2 = Vector(10 - 10 * math.sin(math.pi / 4), -10 * math.cos(math.pi / 4), 1) p3 = Vector(0, 0, 1) e = Path.Geom.arcToHelix(Part.Edge(Part.Arc(p1, p2, p3)), 0, 5) - self.assertCurve( - e, Vector(10, -10, 0), Vector(p2.x, p2.y, 2.5), Vector(0, 0, 5) - ) + self.assertCurve(e, Vector(10, -10, 0), Vector(p2.x, p2.y, 2.5), Vector(0, 0, 5)) def test62(self): """Verify splitArcAt returns proper subarcs.""" @@ -724,12 +630,8 @@ class TestPathGeom(PathTestBase): self.assertCurve(e[0], p1, p12, p2) self.assertCurve(e[1], p2, p23, p3) - p34 = Vector( - 10 - 10 * math.sin(1 * math.pi / 8), -10 * math.cos(1 * math.pi / 8), 0 - ) - p45 = Vector( - 10 - 10 * math.sin(5 * math.pi / 8), -10 * math.cos(5 * math.pi / 8), 0 - ) + p34 = Vector(10 - 10 * math.sin(1 * math.pi / 8), -10 * math.cos(1 * math.pi / 8), 0) + p45 = Vector(10 - 10 * math.sin(5 * math.pi / 8), -10 * math.cos(5 * math.pi / 8), 0) e = Path.Geom.splitArcAt(arc, p12) self.assertCurve(e[0], p1, p34, p12) @@ -791,12 +693,8 @@ class TestPathGeom(PathTestBase): self.assertCoincide(s, tail.valueAt(tail.FirstParameter), 0.005) i = arc.valueAt(arc.LastParameter) j = tail.valueAt(tail.LastParameter) - print( - "(%.2f, %.2f, %.2f) vs. (%.2f, %.2f, %.2f)" % (i.x, i.y, i.z, j.x, j.y, j.z) - ) - self.assertCoincide( - arc.valueAt(arc.LastParameter), tail.valueAt(tail.LastParameter), 0.005 - ) + print("(%.2f, %.2f, %.2f) vs. (%.2f, %.2f, %.2f)" % (i.x, i.y, i.z, j.x, j.y, j.z)) + self.assertCoincide(arc.valueAt(arc.LastParameter), tail.valueAt(tail.LastParameter), 0.005) # make sure the radii match self.assertRoughly(arc.Curve.Radius, head.Curve.Radius, 0.001) @@ -866,9 +764,7 @@ class TestPathGeom(PathTestBase): def test75(self): """Flip a B-spline""" spline = Part.BSplineCurve() - spline.interpolate( - [Vector(1, 2, 3), Vector(-3, 0, 7), Vector(-3, 1, 9), Vector(1, 3, 5)] - ) + spline.interpolate([Vector(1, 2, 3), Vector(-3, 0, 7), Vector(-3, 1, 9), Vector(1, 3, 5)]) edge = Part.Edge(spline) self.assertEdgeShapesMatch(edge, Path.Geom.flipEdge(edge)) diff --git a/src/Mod/CAM/Tests/TestPathHelix.py b/src/Mod/CAM/Tests/TestPathHelix.py index 04aaf7b268..239a779dbe 100644 --- a/src/Mod/CAM/Tests/TestPathHelix.py +++ b/src/Mod/CAM/Tests/TestPathHelix.py @@ -36,9 +36,7 @@ class TestPathHelix(PathTestUtils.PathTestBase): def setUp(self): self.clone = None - self.doc = FreeCAD.open( - FreeCAD.getHomePath() + "Mod/CAM/Tests/test_holes00.fcstd" - ) + self.doc = FreeCAD.open(FreeCAD.getHomePath() + "Mod/CAM/Tests/test_holes00.fcstd") self.job = PathJob.Create("Job", [self.doc.Body]) def tearDown(self): @@ -59,9 +57,7 @@ class TestPathHelix(PathTestUtils.PathTestBase): model = base[0] for sub in base[1]: pos = proxy.holePosition(op, model, sub) - self.assertRoughly( - round(pos.Length / 10, 0), proxy.holeDiameter(op, model, sub) - ) + self.assertRoughly(round(pos.Length / 10, 0), proxy.holeDiameter(op, model, sub)) def test02(self): """Verify Helix generates proper holes for rotated model""" @@ -88,9 +84,7 @@ class TestPathHelix(PathTestUtils.PathTestBase): for deg in range(self.RotateBy, 360, self.RotateBy): self.tearDown() - self.doc = FreeCAD.open( - FreeCAD.getHomePath() + "Mod/CAM/Tests/test_holes00.fcstd" - ) + self.doc = FreeCAD.open(FreeCAD.getHomePath() + "Mod/CAM/Tests/test_holes00.fcstd") self.doc.Body.Placement.Rotation = FreeCAD.Rotation(deg, 0, 0) self.job = PathJob.Create("Job", [self.doc.Body]) @@ -113,9 +107,7 @@ class TestPathHelix(PathTestUtils.PathTestBase): """Verify Helix generates proper holes for rotated clone base model""" for deg in range(self.RotateBy, 360, self.RotateBy): self.tearDown() - self.doc = FreeCAD.open( - FreeCAD.getHomePath() + "Mod/CAM/Tests/test_holes00.fcstd" - ) + self.doc = FreeCAD.open(FreeCAD.getHomePath() + "Mod/CAM/Tests/test_holes00.fcstd") self.clone = Draft.clone(self.doc.Body) self.clone.Placement.Rotation = FreeCAD.Rotation(deg, 0, 0) diff --git a/src/Mod/CAM/Tests/TestPathHelixGenerator.py b/src/Mod/CAM/Tests/TestPathHelixGenerator.py index b2b3a380c0..e8eef6c282 100644 --- a/src/Mod/CAM/Tests/TestPathHelixGenerator.py +++ b/src/Mod/CAM/Tests/TestPathHelixGenerator.py @@ -88,9 +88,7 @@ G0 X5.000000 Y5.000000 Z18.000000G0 Z20.000000" gcode = "".join([r.toGCode() for r in result]) print(gcode) - self.assertTrue( - gcode == self.expectedHelixGCode, "Incorrect helix g-code generated" - ) + self.assertTrue(gcode == self.expectedHelixGCode, "Incorrect helix g-code generated") def test01(self): """Test Value and Type checking""" diff --git a/src/Mod/CAM/Tests/TestPathHelpers.py b/src/Mod/CAM/Tests/TestPathHelpers.py index 159931475a..082f4a6748 100644 --- a/src/Mod/CAM/Tests/TestPathHelpers.py +++ b/src/Mod/CAM/Tests/TestPathHelpers.py @@ -134,9 +134,7 @@ class TestPathHelpers(PathTestBase): self.assertTrue(len(results) == 2) e1 = results[0] self.assertTrue(isinstance(e1.Curve, Part.Circle)) - self.assertTrue( - Path.Geom.pointsCoincide(edge.Curve.Location, e1.Curve.Location) - ) + self.assertTrue(Path.Geom.pointsCoincide(edge.Curve.Location, e1.Curve.Location)) self.assertTrue(edge.Curve.Radius == e1.Curve.Radius) # filter a 180 degree arc diff --git a/src/Mod/CAM/Tests/TestPathLanguage.py b/src/Mod/CAM/Tests/TestPathLanguage.py index cece1fd609..90b06085a1 100644 --- a/src/Mod/CAM/Tests/TestPathLanguage.py +++ b/src/Mod/CAM/Tests/TestPathLanguage.py @@ -54,9 +54,7 @@ class TestPathLanguage(PathTestUtils.PathTestBase): self.assertEqual(str(MNVR("G0")), "G0{}") self.assertEqual(str(MNVR("G0X3")), "G0{'X': 3.0}") self.assertEqual(str(MNVR("G0X3Y7")), "G0{'X': 3.0, 'Y': 7.0}") - self.assertEqual( - str(MNVR("G0X3Y7/G0Z0")), "G0{'X': 3.0, 'Y': 7.0}\nG0{'Z': 0.0}" - ) + self.assertEqual(str(MNVR("G0X3Y7/G0Z0")), "G0{'X': 3.0, 'Y': 7.0}\nG0{'Z': 0.0}") self.assertEqual(len(MNVR("G0X3Y7").instr), 1) self.assertEqual(len(MNVR("G0X3Y7/G0Z0").instr), 2) self.assertEqual(type(MNVR("G0X3Y7").instr[0]), PathLanguage.MoveStraight) @@ -66,9 +64,7 @@ class TestPathLanguage(PathTestUtils.PathTestBase): self.assertEqual(str(MNVR("G1")), "G1{}") self.assertEqual(str(MNVR("G1X3")), "G1{'X': 3.0}") self.assertEqual(str(MNVR("G1X3Y7")), "G1{'X': 3.0, 'Y': 7.0}") - self.assertEqual( - str(MNVR("G1X3Y7/G1Z0")), "G1{'X': 3.0, 'Y': 7.0}\nG1{'Z': 0.0}" - ) + self.assertEqual(str(MNVR("G1X3Y7/G1Z0")), "G1{'X': 3.0, 'Y': 7.0}\nG1{'Z': 0.0}") self.assertEqual(len(MNVR("G1X3Y7").instr), 1) self.assertEqual(len(MNVR("G1X3Y7/G1Z0").instr), 2) self.assertEqual(type(MNVR("G1X3Y7").instr[0]), PathLanguage.MoveStraight) diff --git a/src/Mod/CAM/Tests/TestPathOpDeburr.py b/src/Mod/CAM/Tests/TestPathOpDeburr.py index 2f1ec44cfa..0663b9ff52 100644 --- a/src/Mod/CAM/Tests/TestPathOpDeburr.py +++ b/src/Mod/CAM/Tests/TestPathOpDeburr.py @@ -133,15 +133,11 @@ class TestPathOpDeburr(PathTestUtils.PathTestBase): self.assertRoughly(0.1, depth) self.assertRoughly(4, offset) self.assertTrue(info) - (depth, offset, __, info) = PathDeburr.toolDepthAndOffset( - 1, 0.1, tool, not info - ) + (depth, offset, __, info) = PathDeburr.toolDepthAndOffset(1, 0.1, tool, not info) self.assertRoughly(0.1, depth) self.assertRoughly(4, offset) self.assertTrue(info) - (depth, offset, __, info) = PathDeburr.toolDepthAndOffset( - 1, 0.1, tool, not info - ) + (depth, offset, __, info) = PathDeburr.toolDepthAndOffset(1, 0.1, tool, not info) self.assertRoughly(0.1, depth) self.assertRoughly(4, offset) self.assertTrue(info) @@ -159,15 +155,11 @@ class TestPathOpDeburr(PathTestUtils.PathTestBase): self.assertRoughly(1.1, depth) self.assertRoughly(0.1, offset) self.assertTrue(info) - (depth, offset, __, info) = PathDeburr.toolDepthAndOffset( - 1, 0.1, tool, not info - ) + (depth, offset, __, info) = PathDeburr.toolDepthAndOffset(1, 0.1, tool, not info) self.assertRoughly(1.1, depth) self.assertRoughly(0.1, offset) self.assertTrue(info) - (depth, offset, __, info) = PathDeburr.toolDepthAndOffset( - 1, 0.1, tool, not info - ) + (depth, offset, __, info) = PathDeburr.toolDepthAndOffset(1, 0.1, tool, not info) self.assertRoughly(1.1, depth) self.assertRoughly(0.1, offset) self.assertTrue(info) diff --git a/src/Mod/CAM/Tests/TestPathOpUtil.py b/src/Mod/CAM/Tests/TestPathOpUtil.py index 72b8973cff..028e0f7d8b 100644 --- a/src/Mod/CAM/Tests/TestPathOpUtil.py +++ b/src/Mod/CAM/Tests/TestPathOpUtil.py @@ -103,14 +103,10 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): def test01(self): """Verify isWireClockwise for single edge circle wires.""" self.assertTrue( - PathOpUtil.isWireClockwise( - Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, -1)) - ) + PathOpUtil.isWireClockwise(Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, -1))) ) self.assertFalse( - PathOpUtil.isWireClockwise( - Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, +1)) - ) + PathOpUtil.isWireClockwise(Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, +1))) ) def test02(self): @@ -200,8 +196,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): wires = [ w for w in obj.Shape.Wires - if 1 == len(w.Edges) - and Path.Geom.isRoughly(0, w.Edges[0].Vertexes[0].Point.z) + if 1 == len(w.Edges) and Path.Geom.isRoughly(0, w.Edges[0].Vertexes[0].Point.z) ] self.assertEqual(2, len(wires)) w = wires[1] if wires[0].BoundBox.isInside(wires[1].BoundBox) else wires[0] @@ -224,8 +219,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): wires = [ w for w in obj.Shape.Wires - if 1 == len(w.Edges) - and Path.Geom.isRoughly(0, w.Edges[0].Vertexes[0].Point.z) + if 1 == len(w.Edges) and Path.Geom.isRoughly(0, w.Edges[0].Vertexes[0].Point.z) ] self.assertEqual(2, len(wires)) w = wires[0] if wires[0].BoundBox.isInside(wires[1].BoundBox) else wires[1] @@ -329,9 +323,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): end = e.Vertexes[1].Point v = end - begin angle = Path.Geom.getAngle(v) - if Path.Geom.isRoughly(0, angle) or Path.Geom.isRoughly( - math.pi, math.fabs(angle) - ): + if Path.Geom.isRoughly(0, angle) or Path.Geom.isRoughly(math.pi, math.fabs(angle)): if lastAngle: self.assertRoughly(-refAngle, lastAngle) elif Path.Geom.isRoughly(+refAngle, angle): @@ -371,9 +363,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): wire = PathOpUtil.offsetWire(getWire(obj.Tool), getPositiveShape(obj), 3, True) self.assertEqual(8, len(wire.Edges)) self.assertEqual(4, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) - self.assertEqual( - 4, len([e for e in wire.Edges if Part.Circle == type(e.Curve)]) - ) + self.assertEqual(4, len([e for e in wire.Edges if Part.Circle == type(e.Curve)])) for e in wire.Edges: if Part.Line == type(e.Curve): if Path.Geom.isRoughly(e.Vertexes[0].Point.x, e.Vertexes[1].Point.x): @@ -389,9 +379,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): wire = PathOpUtil.offsetWire(getWire(obj.Tool), getPositiveShape(obj), 3, False) self.assertEqual(8, len(wire.Edges)) self.assertEqual(4, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) - self.assertEqual( - 4, len([e for e in wire.Edges if Part.Circle == type(e.Curve)]) - ) + self.assertEqual(4, len([e for e in wire.Edges if Part.Circle == type(e.Curve)])) for e in wire.Edges: if Part.Line == type(e.Curve): if Path.Geom.isRoughly(e.Vertexes[0].Point.x, e.Vertexes[1].Point.x): @@ -410,9 +398,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): wire = PathOpUtil.offsetWire(getWire(obj.Tool), getPositiveShape(obj), 3, True) self.assertEqual(6, len(wire.Edges)) self.assertEqual(3, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) - self.assertEqual( - 3, len([e for e in wire.Edges if Part.Circle == type(e.Curve)]) - ) + self.assertEqual(3, len([e for e in wire.Edges if Part.Circle == type(e.Curve)])) length = 60 * math.sin(math.radians(60)) for e in wire.Edges: if Part.Line == type(e.Curve): @@ -425,9 +411,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): wire = PathOpUtil.offsetWire(getWire(obj.Tool), getPositiveShape(obj), 3, False) self.assertEqual(6, len(wire.Edges)) self.assertEqual(3, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) - self.assertEqual( - 3, len([e for e in wire.Edges if Part.Circle == type(e.Curve)]) - ) + self.assertEqual(3, len([e for e in wire.Edges if Part.Circle == type(e.Curve)])) for e in wire.Edges: if Part.Line == type(e.Curve): self.assertRoughly(length, e.Length) @@ -442,9 +426,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): wire = PathOpUtil.offsetWire(getWire(obj.Tool), getPositiveShape(obj), 3, True) self.assertEqual(6, len(wire.Edges)) self.assertEqual(3, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) - self.assertEqual( - 3, len([e for e in wire.Edges if Part.Circle == type(e.Curve)]) - ) + self.assertEqual(3, len([e for e in wire.Edges if Part.Circle == type(e.Curve)])) length = 40 radius = 20 + 3 for e in wire.Edges: @@ -458,9 +440,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): wire = PathOpUtil.offsetWire(getWire(obj.Tool), getPositiveShape(obj), 3, False) self.assertEqual(6, len(wire.Edges)) self.assertEqual(3, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) - self.assertEqual( - 3, len([e for e in wire.Edges if Part.Circle == type(e.Curve)]) - ) + self.assertEqual(3, len([e for e in wire.Edges if Part.Circle == type(e.Curve)])) for e in wire.Edges: if Part.Line == type(e.Curve): self.assertRoughly(length, e.Length) @@ -539,9 +519,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): wire = PathOpUtil.offsetWire(getWire(obj.Tool), getNegativeShape(obj), 3, True) self.assertEqual(6, len(wire.Edges)) self.assertEqual(3, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) - self.assertEqual( - 3, len([e for e in wire.Edges if Part.Circle == type(e.Curve)]) - ) + self.assertEqual(3, len([e for e in wire.Edges if Part.Circle == type(e.Curve)])) length = 40 radius = 20 - 3 for e in wire.Edges: @@ -555,9 +533,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): wire = PathOpUtil.offsetWire(getWire(obj.Tool), getNegativeShape(obj), 3, False) self.assertEqual(6, len(wire.Edges)) self.assertEqual(3, len([e for e in wire.Edges if Part.Line == type(e.Curve)])) - self.assertEqual( - 3, len([e for e in wire.Edges if Part.Circle == type(e.Curve)]) - ) + self.assertEqual(3, len([e for e in wire.Edges if Part.Circle == type(e.Curve)])) for e in wire.Edges: if Part.Line == type(e.Curve): self.assertRoughly(length, e.Length) @@ -576,9 +552,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): # let's offset the horizontal edge for starters hEdges = [ - e - for e in w.Edges - if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) + e for e in w.Edges if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) ] x = length / 2 @@ -615,9 +589,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): # let's offset the horizontal edge for starters hEdges = [ - e - for e in w.Edges - if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) + e for e in w.Edges if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) ] x = length / 2 @@ -740,9 +712,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): # let's offset the horizontal edge for starters hEdges = [ - e - for e in w.Edges - if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) + e for e in w.Edges if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) ] x = length / 2 @@ -779,9 +749,7 @@ class TestPathOpUtil(PathTestUtils.PathTestBase): # let's offset the horizontal edge for starters hEdges = [ - e - for e in w.Edges - if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) + e for e in w.Edges if Path.Geom.isRoughly(e.Vertexes[0].Point.y, e.Vertexes[1].Point.y) ] x = length / 2 diff --git a/src/Mod/CAM/Tests/TestPathPost.py b/src/Mod/CAM/Tests/TestPathPost.py index 8f4a8fdb59..ebb7c26e35 100644 --- a/src/Mod/CAM/Tests/TestPathPost.py +++ b/src/Mod/CAM/Tests/TestPathPost.py @@ -134,9 +134,7 @@ class TestFileNameGenerator(unittest.TestCase): FreeCAD.setActiveDocument(self.doc.Label) teststring = "" self.job.PostProcessorOutputFile = teststring - Path.Preferences.setOutputFileDefaults( - teststring, "Append Unique ID on conflict" - ) + Path.Preferences.setOutputFileDefaults(teststring, "Append Unique ID on conflict") generator = PostUtils.FilenameGenerator(job=self.job) filename_generator = generator.generate_filenames() @@ -149,15 +147,15 @@ class TestFileNameGenerator(unittest.TestCase): # filename = PathPost.resolveFileName(self.job, subpart, 0) # self.assertEqual(filename, os.path.normpath(f"{self.testfilename}.nc")) - assertFilePathsEqual( self, filename, os.path.join(self.testfilepath, f"{self.testfilename}.nc")) + assertFilePathsEqual( + self, filename, os.path.join(self.testfilepath, f"{self.testfilename}.nc") + ) def test010(self): # Substitute current file path teststring = "%D/testfile.nc" self.job.PostProcessorOutputFile = teststring - Path.Preferences.setOutputFileDefaults( - teststring, "Append Unique ID on conflict" - ) + Path.Preferences.setOutputFileDefaults(teststring, "Append Unique ID on conflict") generator = PostUtils.FilenameGenerator(job=self.job) filename_generator = generator.generate_filenames() @@ -170,9 +168,7 @@ class TestFileNameGenerator(unittest.TestCase): # Test basic string substitution without splitting teststring = "~/Desktop/%j.nc" self.job.PostProcessorOutputFile = teststring - Path.Preferences.setOutputFileDefaults( - teststring, "Append Unique ID on conflict" - ) + Path.Preferences.setOutputFileDefaults(teststring, "Append Unique ID on conflict") # outlist = PathPost.buildPostList(self.job) # self.assertTrue(len(outlist) == 1) @@ -188,9 +184,7 @@ class TestFileNameGenerator(unittest.TestCase): def test020(self): teststring = "%d.nc" self.job.PostProcessorOutputFile = teststring - Path.Preferences.setOutputFileDefaults( - teststring, "Append Unique ID on conflict" - ) + Path.Preferences.setOutputFileDefaults(teststring, "Append Unique ID on conflict") generator = PostUtils.FilenameGenerator(job=self.job) filename_generator = generator.generate_filenames() @@ -203,9 +197,7 @@ class TestFileNameGenerator(unittest.TestCase): def test030(self): teststring = "%M/outfile.nc" self.job.PostProcessorOutputFile = teststring - Path.Preferences.setOutputFileDefaults( - teststring, "Append Unique ID on conflict" - ) + Path.Preferences.setOutputFileDefaults(teststring, "Append Unique ID on conflict") generator = PostUtils.FilenameGenerator(job=self.job) filename_generator = generator.generate_filenames() @@ -217,9 +209,7 @@ class TestFileNameGenerator(unittest.TestCase): # unused substitution strings should be ignored teststring = "%d%T%t%W%O/testdoc.nc" self.job.PostProcessorOutputFile = teststring - Path.Preferences.setOutputFileDefaults( - teststring, "Append Unique ID on conflict" - ) + Path.Preferences.setOutputFileDefaults(teststring, "Append Unique ID on conflict") generator = PostUtils.FilenameGenerator(job=self.job) filename_generator = generator.generate_filenames() @@ -255,9 +245,7 @@ class TestFileNameGenerator(unittest.TestCase): # explicitly using the sequence number should include it where indicated. teststring = "%S-%d.nc" self.job.PostProcessorOutputFile = teststring - Path.Preferences.setOutputFileDefaults( - teststring, "Append Unique ID on conflict" - ) + Path.Preferences.setOutputFileDefaults(teststring, "Append Unique ID on conflict") generator = PostUtils.FilenameGenerator(job=self.job) filename_generator = generator.generate_filenames() @@ -271,9 +259,7 @@ class TestFileNameGenerator(unittest.TestCase): """Test subpart naming""" teststring = "%M/outfile.nc" self.job.PostProcessorOutputFile = teststring - Path.Preferences.setOutputFileDefaults( - teststring, "Append Unique ID on conflict" - ) + Path.Preferences.setOutputFileDefaults(teststring, "Append Unique ID on conflict") generator = PostUtils.FilenameGenerator(job=self.job) generator.set_subpartname("Tool") @@ -589,15 +575,11 @@ class TestPathPostUtils(unittest.TestCase): testpath = Path.Path(commands) self.assertTrue(len(testpath.Commands) == 9) - self.assertTrue( - len([c for c in testpath.Commands if c.Name in ["G2", "G3"]]) == 4 - ) + self.assertTrue(len([c for c in testpath.Commands if c.Name in ["G2", "G3"]]) == 4) results = PostUtils.splitArcs(testpath) # self.assertTrue(len(results.Commands) == 117) - self.assertTrue( - len([c for c in results.Commands if c.Name in ["G2", "G3"]]) == 0 - ) + self.assertTrue(len([c for c in results.Commands if c.Name in ["G2", "G3"]]) == 0) class TestBuildPostList(unittest.TestCase): diff --git a/src/Mod/CAM/Tests/TestPathPreferences.py b/src/Mod/CAM/Tests/TestPathPreferences.py index dab369098f..8102fe7aa6 100644 --- a/src/Mod/CAM/Tests/TestPathPreferences.py +++ b/src/Mod/CAM/Tests/TestPathPreferences.py @@ -39,9 +39,7 @@ class TestPathPreferences(PathTestUtils.PathTestBase): def test02(self): """Path/Post/scripts is part of the posts search path.""" paths = Path.Preferences.searchPathsPost() - self.assertEqual( - len([p for p in paths if p.endswith("/Path/Post/scripts/")]), 1 - ) + self.assertEqual(len([p for p in paths if p.endswith("/Path/Post/scripts/")]), 1) def test03(self): """Available post processors include linuxcnc, grbl and opensbp.""" @@ -53,19 +51,11 @@ class TestPathPreferences(PathTestUtils.PathTestBase): def test10(self): """Default paths for tools are resolved correctly""" + self.assertTrue(Path.Preferences.pathDefaultToolsPath().endswith("/CAM/Tools/")) + self.assertTrue(Path.Preferences.pathDefaultToolsPath("Bit").endswith("/CAM/Tools/Bit")) self.assertTrue( - Path.Preferences.pathDefaultToolsPath().endswith("/CAM/Tools/") + Path.Preferences.pathDefaultToolsPath("Library").endswith("/CAM/Tools/Library") ) self.assertTrue( - Path.Preferences.pathDefaultToolsPath("Bit").endswith("/CAM/Tools/Bit") - ) - self.assertTrue( - Path.Preferences.pathDefaultToolsPath("Library").endswith( - "/CAM/Tools/Library" - ) - ) - self.assertTrue( - Path.Preferences.pathDefaultToolsPath("Template").endswith( - "/CAM/Tools/Template" - ) + Path.Preferences.pathDefaultToolsPath("Template").endswith("/CAM/Tools/Template") ) diff --git a/src/Mod/CAM/Tests/TestPathProfile.py b/src/Mod/CAM/Tests/TestPathProfile.py index c7549b91ec..f41cb7cbf8 100644 --- a/src/Mod/CAM/Tests/TestPathProfile.py +++ b/src/Mod/CAM/Tests/TestPathProfile.py @@ -54,9 +54,7 @@ class TestPathProfile(PathTestBase): def initClass(cls): # Open existing FreeCAD document with test geometry cls.needsInit = False - cls.doc = FreeCAD.open( - FreeCAD.getHomePath() + "Mod/CAM/Tests/test_profile.fcstd" - ) + cls.doc = FreeCAD.open(FreeCAD.getHomePath() + "Mod/CAM/Tests/test_profile.fcstd") # Create Job object, adding geometry objects from file opened above cls.job = PathJob.Create("Job", [cls.doc.Body], None) @@ -114,7 +112,9 @@ class TestPathProfile(PathTestBase): profile = PathProfile.Create("Profile1") profile.Base = [(self.doc.Body, ["Face18"])] # (base, subs_list) profile.Label = "test01+" - profile.Comment = "test01() Verify path generated on Face18, outside, with tool compensation." + profile.Comment = ( + "test01() Verify path generated on Face18, outside, with tool compensation." + ) # Set additional operation properties # setDepthsAndHeights(adaptive) @@ -127,22 +127,24 @@ class TestPathProfile(PathTestBase): moves = getGcodeMoves(profile.Path.Commands, includeRapids=False) operationMoves = "; ".join(moves) - #FreeCAD.Console.PrintMessage("test01_moves: " + operationMoves + "\n") + # FreeCAD.Console.PrintMessage("test01_moves: " + operationMoves + "\n") - - expected_moves = \ - "G1 X16.47 Y16.47 Z10.0; G3 I-2.48 J-2.48 K0.0 X13.93 Y17.5 Z10.0; " \ - "G1 X-13.93 Y17.5 Z10.0; G3 I-0.06 J-3.51 K0.0 X-17.5 Y13.93 Z10.0; " \ - "G1 X-17.5 Y-13.93 Z10.0; G3 I3.51 J-0.06 K0.0 X-13.93 Y-17.5 Z10.0; " \ - "G1 X13.93 Y-17.5 Z10.0; G3 I0.06 J3.51 K0.0 X17.5 Y-13.93 Z10.0; " \ - "G1 X17.5 Y13.93 Z10.0; G3 I-3.51 J0.06 K0.0 X16.47 Y16.47 Z10.0; " \ - "G1 X23.55 Y23.54 Z10.0; G2 I-9.55 J-9.54 K0.0 X27.5 Y14.1 Z10.0; " \ - "G1 X27.5 Y-14.0 Z10.0; G2 I-13.5 J0.0 K0.0 X14.1 Y-27.5 Z10.0; " \ - "G1 X-14.0 Y-27.5 Z10.0; G2 I0.0 J13.5 K0.0 X-27.5 Y-14.1 Z10.0; " \ - "G1 X-27.5 Y14.0 Z10.0; G2 I13.5 J-0.0 K0.0 X-14.1 Y27.5 Z10.0; " \ - "G1 X14.0 Y27.5 Z10.0; G2 I-0.0 J-13.5 K0.0 X23.55 Y23.54 Z10.0" - self.assertTrue(expected_moves == operationMoves, - "expected_moves: {}\noperationMoves: {}".format(expected_moves, operationMoves)) + expected_moves = ( + "G1 X16.47 Y16.47 Z10.0; G3 I-2.48 J-2.48 K0.0 X13.93 Y17.5 Z10.0; " + "G1 X-13.93 Y17.5 Z10.0; G3 I-0.06 J-3.51 K0.0 X-17.5 Y13.93 Z10.0; " + "G1 X-17.5 Y-13.93 Z10.0; G3 I3.51 J-0.06 K0.0 X-13.93 Y-17.5 Z10.0; " + "G1 X13.93 Y-17.5 Z10.0; G3 I0.06 J3.51 K0.0 X17.5 Y-13.93 Z10.0; " + "G1 X17.5 Y13.93 Z10.0; G3 I-3.51 J0.06 K0.0 X16.47 Y16.47 Z10.0; " + "G1 X23.55 Y23.54 Z10.0; G2 I-9.55 J-9.54 K0.0 X27.5 Y14.1 Z10.0; " + "G1 X27.5 Y-14.0 Z10.0; G2 I-13.5 J0.0 K0.0 X14.1 Y-27.5 Z10.0; " + "G1 X-14.0 Y-27.5 Z10.0; G2 I0.0 J13.5 K0.0 X-27.5 Y-14.1 Z10.0; " + "G1 X-27.5 Y14.0 Z10.0; G2 I13.5 J-0.0 K0.0 X-14.1 Y27.5 Z10.0; " + "G1 X14.0 Y27.5 Z10.0; G2 I-0.0 J-13.5 K0.0 X23.55 Y23.54 Z10.0" + ) + self.assertTrue( + expected_moves == operationMoves, + "expected_moves: {}\noperationMoves: {}".format(expected_moves, operationMoves), + ) def test02(self): """test02() Verify path generated on Face18, outside, without compensation.""" @@ -164,21 +166,25 @@ class TestPathProfile(PathTestBase): moves = getGcodeMoves(profile.Path.Commands, includeRapids=False) operationMoves = "; ".join(moves) - #FreeCAD.Console.PrintMessage("test02_moves: " + operationMoves + "\n") + # FreeCAD.Console.PrintMessage("test02_moves: " + operationMoves + "\n") - expected_moves = "G1 X18.24 Y18.24 Z10.0; G3 I-4.24 J-4.24 K0.0 X14.0 Y20.0 Z10.0; " \ - "G1 X-14.0 Y20.0 Z10.0; G3 I0.0 J-6.0 K0.0 X-20.0 Y14.0 Z10.0; " \ - "G1 X-20.0 Y-14.0 Z10.0; G3 I6.0 J0.0 K0.0 X-14.0 Y-20.0 Z10.0; " \ - "G1 X14.0 Y-20.0 Z10.0; G3 I-0.0 J6.0 K0.0 X20.0 Y-14.0 Z10.0; " \ - "G1 X20.0 Y14.0 Z10.0; G3 I-6.0 J-0.0 K0.0 X18.24 Y18.24 Z10.0; " \ - "G1 X21.78 Y21.78 Z10.0; G2 I-7.78 J-7.78 K0.0 X25.0 Y14.0 Z10.0; " \ - "G1 X25.0 Y-14.0 Z10.0; G2 I-11.0 J0.0 K0.0 X14.0 Y-25.0 Z10.0; " \ - "G1 X-14.0 Y-25.0 Z10.0; G2 I0.0 J11.0 K0.0 X-25.0 Y-14.0 Z10.0; " \ - "G1 X-25.0 Y14.0 Z10.0; G2 I11.0 J-0.0 K0.0 X-14.0 Y25.0 Z10.0; " \ - "G1 X14.0 Y25.0 Z10.0; G2 I-0.0 J-11.0 K0.0 X21.78 Y21.78 Z10.0" + expected_moves = ( + "G1 X18.24 Y18.24 Z10.0; G3 I-4.24 J-4.24 K0.0 X14.0 Y20.0 Z10.0; " + "G1 X-14.0 Y20.0 Z10.0; G3 I0.0 J-6.0 K0.0 X-20.0 Y14.0 Z10.0; " + "G1 X-20.0 Y-14.0 Z10.0; G3 I6.0 J0.0 K0.0 X-14.0 Y-20.0 Z10.0; " + "G1 X14.0 Y-20.0 Z10.0; G3 I-0.0 J6.0 K0.0 X20.0 Y-14.0 Z10.0; " + "G1 X20.0 Y14.0 Z10.0; G3 I-6.0 J-0.0 K0.0 X18.24 Y18.24 Z10.0; " + "G1 X21.78 Y21.78 Z10.0; G2 I-7.78 J-7.78 K0.0 X25.0 Y14.0 Z10.0; " + "G1 X25.0 Y-14.0 Z10.0; G2 I-11.0 J0.0 K0.0 X14.0 Y-25.0 Z10.0; " + "G1 X-14.0 Y-25.0 Z10.0; G2 I0.0 J11.0 K0.0 X-25.0 Y-14.0 Z10.0; " + "G1 X-25.0 Y14.0 Z10.0; G2 I11.0 J-0.0 K0.0 X-14.0 Y25.0 Z10.0; " + "G1 X14.0 Y25.0 Z10.0; G2 I-0.0 J-11.0 K0.0 X21.78 Y21.78 Z10.0" + ) - self.assertTrue(expected_moves == operationMoves, - "expected_moves: {}\noperationMoves: {}".format(expected_moves, operationMoves)) + self.assertTrue( + expected_moves == operationMoves, + "expected_moves: {}\noperationMoves: {}".format(expected_moves, operationMoves), + ) def test03(self): """test03() Verify path generated on Face18, outside, @@ -188,8 +194,9 @@ class TestPathProfile(PathTestBase): profile = PathProfile.Create("Profile3") profile.Base = [(self.doc.Body, ["Face18"])] # (base, subs_list) profile.Label = "test03+" - profile.Comment = "test03() Verify path generated on Face4, " \ - "with compensation and extra offset -radius" + profile.Comment = ( + "test03() Verify path generated on Face4, " "with compensation and extra offset -radius" + ) # Set additional operation properties # setDepthsAndHeights(adaptive) @@ -203,27 +210,29 @@ class TestPathProfile(PathTestBase): moves = getGcodeMoves(profile.Path.Commands, includeRapids=False) operationMoves = "; ".join(moves) - #FreeCAD.Console.PrintMessage("test03_moves: " + operationMoves + "\n") + # FreeCAD.Console.PrintMessage("test03_moves: " + operationMoves + "\n") - expected_moves = "G1 X18.24 Y18.24 Z10.0; G3 I-4.24 J-4.24 K0.0 X14.0 Y20.0 Z10.0; " \ - "G1 X-14.0 Y20.0 Z10.0; G3 I0.0 J-6.0 K0.0 X-20.0 Y14.0 Z10.0; " \ - "G1 X-20.0 Y-14.0 Z10.0; G3 I6.0 J0.0 K0.0 X-14.0 Y-20.0 Z10.0; " \ - "G1 X14.0 Y-20.0 Z10.0; G3 I-0.0 J6.0 K0.0 X20.0 Y-14.0 Z10.0; " \ - "G1 X20.0 Y14.0 Z10.0; G3 I-6.0 J-0.0 K0.0 X18.24 Y18.24 Z10.0; " \ - "G1 X21.78 Y21.78 Z10.0; G2 I-7.78 J-7.78 K0.0 X25.0 Y14.0 Z10.0; " \ - "G1 X25.0 Y-14.0 Z10.0; G2 I-11.0 J0.0 K0.0 X14.0 Y-25.0 Z10.0; " \ - "G1 X-14.0 Y-25.0 Z10.0; G2 I0.0 J11.0 K0.0 X-25.0 Y-14.0 Z10.0; " \ - "G1 X-25.0 Y14.0 Z10.0; G2 I11.0 J-0.0 K0.0 X-14.0 Y25.0 Z10.0; " \ - "G1 X14.0 Y25.0 Z10.0; G2 I-0.0 J-11.0 K0.0 X21.78 Y21.78 Z10.0" + expected_moves = ( + "G1 X18.24 Y18.24 Z10.0; G3 I-4.24 J-4.24 K0.0 X14.0 Y20.0 Z10.0; " + "G1 X-14.0 Y20.0 Z10.0; G3 I0.0 J-6.0 K0.0 X-20.0 Y14.0 Z10.0; " + "G1 X-20.0 Y-14.0 Z10.0; G3 I6.0 J0.0 K0.0 X-14.0 Y-20.0 Z10.0; " + "G1 X14.0 Y-20.0 Z10.0; G3 I-0.0 J6.0 K0.0 X20.0 Y-14.0 Z10.0; " + "G1 X20.0 Y14.0 Z10.0; G3 I-6.0 J-0.0 K0.0 X18.24 Y18.24 Z10.0; " + "G1 X21.78 Y21.78 Z10.0; G2 I-7.78 J-7.78 K0.0 X25.0 Y14.0 Z10.0; " + "G1 X25.0 Y-14.0 Z10.0; G2 I-11.0 J0.0 K0.0 X14.0 Y-25.0 Z10.0; " + "G1 X-14.0 Y-25.0 Z10.0; G2 I0.0 J11.0 K0.0 X-25.0 Y-14.0 Z10.0; " + "G1 X-25.0 Y14.0 Z10.0; G2 I11.0 J-0.0 K0.0 X-14.0 Y25.0 Z10.0; " + "G1 X14.0 Y25.0 Z10.0; G2 I-0.0 J-11.0 K0.0 X21.78 Y21.78 Z10.0" + ) - self.assertTrue(expected_moves == operationMoves, - "expected_moves: {}\noperationMoves: {}".format(expected_moves, operationMoves)) + self.assertTrue( + expected_moves == operationMoves, + "expected_moves: {}\noperationMoves: {}".format(expected_moves, operationMoves), + ) def _addViewProvider(profileOp): if FreeCAD.GuiUp: PathOpGui = PathProfileGui.PathOpGui cmdRes = PathProfileGui.Command.res - profileOp.ViewObject.Proxy = PathOpGui.ViewProvider( - profileOp.ViewObject, cmdRes - ) + profileOp.ViewObject.Proxy = PathOpGui.ViewProvider(profileOp.ViewObject, cmdRes) diff --git a/src/Mod/CAM/Tests/TestPathPropertyBag.py b/src/Mod/CAM/Tests/TestPathPropertyBag.py index 43005920be..34311e45f9 100644 --- a/src/Mod/CAM/Tests/TestPathPropertyBag.py +++ b/src/Mod/CAM/Tests/TestPathPropertyBag.py @@ -43,9 +43,7 @@ class TestPathPropertyBag(PathTestUtils.PathTestBase): """adding properties to a PropertyBag is tracked properly""" bag = PathPropertyBag.Create() proxy = bag.Proxy - proxy.addCustomProperty( - "App::PropertyString", "Title", "Address", "Some description" - ) + proxy.addCustomProperty("App::PropertyString", "Title", "Address", "Some description") self.assertTrue(hasattr(bag, "Title")) bag.Title = "Madame" self.assertEqual(bag.Title, "Madame") @@ -56,9 +54,7 @@ class TestPathPropertyBag(PathTestUtils.PathTestBase): """refreshCustomPropertyGroups deletes empty groups""" bag = PathPropertyBag.Create() proxy = bag.Proxy - proxy.addCustomProperty( - "App::PropertyString", "Title", "Address", "Some description" - ) + proxy.addCustomProperty("App::PropertyString", "Title", "Address", "Some description") bag.Title = "Madame" bag.removeProperty("Title") proxy.refreshCustomPropertyGroups() @@ -69,9 +65,7 @@ class TestPathPropertyBag(PathTestUtils.PathTestBase): """refreshCustomPropertyGroups does not delete non-empty groups""" bag = PathPropertyBag.Create() proxy = bag.Proxy - proxy.addCustomProperty( - "App::PropertyString", "Title", "Address", "Some description" - ) + proxy.addCustomProperty("App::PropertyString", "Title", "Address", "Some description") proxy.addCustomProperty("App::PropertyString", "Gender", "Attributes") bag.Title = "Madame" bag.Gender = "Female" diff --git a/src/Mod/CAM/Tests/TestPathSetupSheet.py b/src/Mod/CAM/Tests/TestPathSetupSheet.py index 84b313df22..c81b80dda2 100644 --- a/src/Mod/CAM/Tests/TestPathSetupSheet.py +++ b/src/Mod/CAM/Tests/TestPathSetupSheet.py @@ -69,16 +69,12 @@ class TestPathSetupSheet(PathTestBase): self.assertEqualLocale(attrs[PathSetupSheet.Template.HorizRapid], "0.00 mm/s") self.assertEqualLocale(attrs[PathSetupSheet.Template.VertRapid], "0.00 mm/s") - self.assertEqualLocale( - attrs[PathSetupSheet.Template.SafeHeightOffset], "3.00 mm" - ) + self.assertEqualLocale(attrs[PathSetupSheet.Template.SafeHeightOffset], "3.00 mm") self.assertEqual( attrs[PathSetupSheet.Template.SafeHeightExpression], "OpStockZMax+SetupSheet.SafeHeightOffset", ) - self.assertEqualLocale( - attrs[PathSetupSheet.Template.ClearanceHeightOffset], "5.00 mm" - ) + self.assertEqualLocale(attrs[PathSetupSheet.Template.ClearanceHeightOffset], "5.00 mm") self.assertEqual( attrs[PathSetupSheet.Template.ClearanceHeightExpression], "OpStockZMax+SetupSheet.ClearanceHeightOffset", @@ -110,9 +106,7 @@ class TestPathSetupSheet(PathTestBase): self.assertEqual(o1.HorizRapid.UserString, o2.HorizRapid.UserString) self.assertEqual(o1.SafeHeightOffset.UserString, o2.SafeHeightOffset.UserString) self.assertEqual(o1.SafeHeightExpression, o2.SafeHeightExpression) - self.assertEqual( - o1.ClearanceHeightOffset.UserString, o2.ClearanceHeightOffset.UserString - ) + self.assertEqual(o1.ClearanceHeightOffset.UserString, o2.ClearanceHeightOffset.UserString) self.assertEqual(o1.ClearanceHeightExpression, o2.ClearanceHeightExpression) self.assertEqual(o1.StartDepthExpression, o2.StartDepthExpression) self.assertEqual(o1.FinalDepthExpression, o2.FinalDepthExpression) @@ -187,12 +181,8 @@ class TestPathSetupSheet(PathTestBase): self.assertEqual(ss.expressionReference(), "SetupSheet") - self.assertEqual( - str(ss.encodeTemplateAttributes({"00": 13.00})), "{'00': 13.0}" - ) - self.assertEqual( - str(ss.decodeTemplateAttributes({"00": 13.00})), "{'00': 13.0}" - ) + self.assertEqual(str(ss.encodeTemplateAttributes({"00": 13.00})), "{'00': 13.0}") + self.assertEqual(str(ss.decodeTemplateAttributes({"00": 13.00})), "{'00': 13.0}") def test11(self): """Verify template attributes encoding/decoding of strings.""" @@ -228,9 +218,7 @@ class TestPathSetupSheet(PathTestBase): refstring("{'00': u'SetupSheet.y'}"), ) self.assertEqual( - str( - ss.decodeTemplateAttributes({"00": "${SetupSheet}.y - ${SetupSheet}.z"}) - ), + str(ss.decodeTemplateAttributes({"00": "${SetupSheet}.y - ${SetupSheet}.z"})), refstring("{'00': u'SetupSheet.y - SetupSheet.z'}"), ) @@ -243,11 +231,7 @@ class TestPathSetupSheet(PathTestBase): refstring("{'00': {'01': u'hugo'}}"), ) self.assertEqual( - str( - ss.encodeTemplateAttributes( - {"00": {"01": "SetupSheet.y - SetupSheet.z"}} - ) - ), + str(ss.encodeTemplateAttributes({"00": {"01": "SetupSheet.y - SetupSheet.z"}})), refstring("{'00': {'01': u'${SetupSheet}.y - ${SetupSheet}.z'}}"), ) @@ -256,11 +240,7 @@ class TestPathSetupSheet(PathTestBase): refstring("{'00': {'01': u'hugo'}}"), ) self.assertEqual( - str( - ss.decodeTemplateAttributes( - {"00": {"01": "${SetupSheet}.y - ${SetupSheet}.z"}} - ) - ), + str(ss.decodeTemplateAttributes({"00": {"01": "${SetupSheet}.y - ${SetupSheet}.z"}})), refstring("{'00': {'01': u'SetupSheet.y - SetupSheet.z'}}"), ) @@ -286,16 +266,10 @@ class TestPathSetupSheet(PathTestBase): self.assertEqual(str(encoded["01"][1]), refstring("{'20': u'${SetupSheet}'}")) self.assertEqual(len(encoded["02"]), 1) self.assertEqual(len(encoded["02"][0]["a"]), 2) - self.assertEqual( - str(encoded["02"][0]["a"][0]), refstring("{'b': u'${SetupSheet}'}") - ) - self.assertEqual( - str(encoded["02"][0]["a"][1]), refstring("{'c': u'${SetupSheet}'}") - ) + self.assertEqual(str(encoded["02"][0]["a"][0]), refstring("{'b': u'${SetupSheet}'}")) + self.assertEqual(str(encoded["02"][0]["a"][1]), refstring("{'c': u'${SetupSheet}'}")) self.assertEqual(len(encoded["02"][0]["b"]), 1) - self.assertEqual( - str(encoded["02"][0]["b"][0]), refstring("{'b': u'${SetupSheet}'}") - ) + self.assertEqual(str(encoded["02"][0]["b"][0]), refstring("{'b': u'${SetupSheet}'}")) decoded = ss.decodeTemplateAttributes(encoded) self.assertEqual(len(decoded), len(attrs)) diff --git a/src/Mod/CAM/Tests/TestPathStock.py b/src/Mod/CAM/Tests/TestPathStock.py index c80bd19808..877f63099c 100644 --- a/src/Mod/CAM/Tests/TestPathStock.py +++ b/src/Mod/CAM/Tests/TestPathStock.py @@ -68,9 +68,7 @@ class TestPathStock(PathTestBase): self.assertEqual(13, stock.Width) self.assertEqual(77, stock.Height) - placement = FreeCAD.Placement( - FreeCAD.Vector(-3, 88, 4), FreeCAD.Vector(0, 0, 1), 180 - ) + placement = FreeCAD.Placement(FreeCAD.Vector(-3, 88, 4), FreeCAD.Vector(0, 0, 1), 180) stock = PathStock.CreateBox(self.job, extent, placement) self.assertEqual(17, stock.Length) self.assertEqual(13, stock.Width) @@ -90,9 +88,7 @@ class TestPathStock(PathTestBase): self.assertEqual(37, stock.Radius) self.assertEqual(24, stock.Height) - placement = FreeCAD.Placement( - FreeCAD.Vector(3, 8, -4), FreeCAD.Vector(0, 0, 1), -90 - ) + placement = FreeCAD.Placement(FreeCAD.Vector(3, 8, -4), FreeCAD.Vector(0, 0, 1), -90) stock = PathStock.CreateCylinder(self.job, 1, 88, placement) self.assertEqual(1, stock.Radius) self.assertEqual(88, stock.Height) @@ -102,18 +98,14 @@ class TestPathStock(PathTestBase): """Verify FromTemplate box creation.""" extent = FreeCAD.Vector(17, 13, 77) - placement = FreeCAD.Placement( - FreeCAD.Vector(3, 8, -4), FreeCAD.Vector(0, 0, 1), -90 - ) + placement = FreeCAD.Placement(FreeCAD.Vector(3, 8, -4), FreeCAD.Vector(0, 0, 1), -90) orig = PathStock.CreateBox(self.job, extent, placement) # collect full template template = PathStock.TemplateAttributes(orig) stock = PathStock.CreateFromTemplate(self.job, template) - self.assertEqual( - PathStock.StockType.CreateBox, PathStock.StockType.FromStock(stock) - ) + self.assertEqual(PathStock.StockType.CreateBox, PathStock.StockType.FromStock(stock)) self.assertEqual(orig.Length, stock.Length) self.assertEqual(orig.Width, stock.Width) self.assertEqual(orig.Height, stock.Height) @@ -123,9 +115,7 @@ class TestPathStock(PathTestBase): template = PathStock.TemplateAttributes(orig, False, True) stock = PathStock.CreateFromTemplate(self.job, template) - self.assertEqual( - PathStock.StockType.CreateBox, PathStock.StockType.FromStock(stock) - ) + self.assertEqual(PathStock.StockType.CreateBox, PathStock.StockType.FromStock(stock)) self.assertEqual(100, stock.Length) self.assertEqual(200, stock.Width) self.assertEqual(300, stock.Height) @@ -135,9 +125,7 @@ class TestPathStock(PathTestBase): template = PathStock.TemplateAttributes(orig, True, False) stock = PathStock.CreateFromTemplate(self.job, template) - self.assertEqual( - PathStock.StockType.CreateBox, PathStock.StockType.FromStock(stock) - ) + self.assertEqual(PathStock.StockType.CreateBox, PathStock.StockType.FromStock(stock)) self.assertEqual(orig.Length, stock.Length) self.assertEqual(orig.Width, stock.Width) self.assertEqual(orig.Height, stock.Height) @@ -147,18 +135,14 @@ class TestPathStock(PathTestBase): """Verify FromTemplate cylinder creation.""" radius = 7 height = 12 - placement = FreeCAD.Placement( - FreeCAD.Vector(99, 88, 77), FreeCAD.Vector(1, 1, 1), 123 - ) + placement = FreeCAD.Placement(FreeCAD.Vector(99, 88, 77), FreeCAD.Vector(1, 1, 1), 123) orig = PathStock.CreateCylinder(self.job, radius, height, placement) # full template template = PathStock.TemplateAttributes(orig) stock = PathStock.CreateFromTemplate(self.job, template) - self.assertEqual( - PathStock.StockType.CreateCylinder, PathStock.StockType.FromStock(stock) - ) + self.assertEqual(PathStock.StockType.CreateCylinder, PathStock.StockType.FromStock(stock)) self.assertEqual(orig.Radius, stock.Radius) self.assertEqual(orig.Height, stock.Height) self.assertPlacement(orig.Placement, stock.Placement) @@ -167,9 +151,7 @@ class TestPathStock(PathTestBase): template = PathStock.TemplateAttributes(orig, False, True) stock = PathStock.CreateFromTemplate(self.job, template) - self.assertEqual( - PathStock.StockType.CreateCylinder, PathStock.StockType.FromStock(stock) - ) + self.assertEqual(PathStock.StockType.CreateCylinder, PathStock.StockType.FromStock(stock)) self.assertRoughly(R, stock.Radius.Value) self.assertEqual(300, stock.Height) self.assertPlacement(orig.Placement, stock.Placement) @@ -178,9 +160,7 @@ class TestPathStock(PathTestBase): template = PathStock.TemplateAttributes(orig, True, False) stock = PathStock.CreateFromTemplate(None, template) - self.assertEqual( - PathStock.StockType.CreateCylinder, PathStock.StockType.FromStock(stock) - ) + self.assertEqual(PathStock.StockType.CreateCylinder, PathStock.StockType.FromStock(stock)) self.assertEqual(orig.Radius, stock.Radius) self.assertEqual(orig.Height, stock.Height) self.assertPlacement(FreeCAD.Placement(), stock.Placement) @@ -189,9 +169,7 @@ class TestPathStock(PathTestBase): template = PathStock.TemplateAttributes(orig, True, False) stock = PathStock.CreateFromTemplate(self.job, template) - self.assertEqual( - PathStock.StockType.CreateCylinder, PathStock.StockType.FromStock(stock) - ) + self.assertEqual(PathStock.StockType.CreateCylinder, PathStock.StockType.FromStock(stock)) self.assertEqual(orig.Radius, stock.Radius) self.assertEqual(orig.Height, stock.Height) self.assertPlacement( @@ -213,9 +191,7 @@ class TestPathStock(PathTestBase): # full template template = PathStock.TemplateAttributes(orig) stock = PathStock.CreateFromTemplate(self.job, template) - self.assertEqual( - PathStock.StockType.FromBase, PathStock.StockType.FromStock(stock) - ) + self.assertEqual(PathStock.StockType.FromBase, PathStock.StockType.FromStock(stock)) self.assertEqual(orig.ExtXneg, stock.ExtXneg) self.assertEqual(orig.ExtXpos, stock.ExtXpos) self.assertEqual(orig.ExtYneg, stock.ExtYneg) diff --git a/src/Mod/CAM/Tests/TestPathThreadMilling.py b/src/Mod/CAM/Tests/TestPathThreadMilling.py index 765340e2f6..84ad39caa8 100644 --- a/src/Mod/CAM/Tests/TestPathThreadMilling.py +++ b/src/Mod/CAM/Tests/TestPathThreadMilling.py @@ -78,18 +78,12 @@ class TestPathThreadMilling(PathTestBase): def test01(self): """Verify internal radii with tool crest.""" - self.assertRadii( - PathThreadMilling.threadRadii(True, 20, 18, 2, 0.1), (8, 9.113397) - ) + self.assertRadii(PathThreadMilling.threadRadii(True, 20, 18, 2, 0.1), (8, 9.113397)) def test10(self): """Verify internal thread passes.""" - self.assertList( - PathThreadMilling.threadPasses(1, radii, True, 10, 9, 0, 0), [10] - ) - self.assertList( - PathThreadMilling.threadPasses(2, radii, True, 10, 9, 0, 0), [9.707107, 10] - ) + self.assertList(PathThreadMilling.threadPasses(1, radii, True, 10, 9, 0, 0), [10]) + self.assertList(PathThreadMilling.threadPasses(2, radii, True, 10, 9, 0, 0), [9.707107, 10]) self.assertList( PathThreadMilling.threadPasses(5, radii, True, 10, 9, 0, 0), [9.447214, 9.632456, 9.774597, 9.894427, 10], @@ -102,18 +96,12 @@ class TestPathThreadMilling(PathTestBase): def test21(self): """Verify external radii with tool crest.""" - self.assertRadii( - PathThreadMilling.threadRadii(False, 20, 18, 2, 0.1), (11, 9.513397) - ) + self.assertRadii(PathThreadMilling.threadRadii(False, 20, 18, 2, 0.1), (11, 9.513397)) def test30(self): """Verify external thread passes.""" - self.assertList( - PathThreadMilling.threadPasses(1, radii, False, 10, 9, 0, 0), [9] - ) - self.assertList( - PathThreadMilling.threadPasses(2, radii, False, 10, 9, 0, 0), [9.292893, 9] - ) + self.assertList(PathThreadMilling.threadPasses(1, radii, False, 10, 9, 0, 0), [9]) + self.assertList(PathThreadMilling.threadPasses(2, radii, False, 10, 9, 0, 0), [9.292893, 9]) self.assertList( PathThreadMilling.threadPasses(5, radii, False, 10, 9, 0, 0), [9.552786, 9.367544, 9.225403, 9.105573, 9], diff --git a/src/Mod/CAM/Tests/TestPathVoronoi.py b/src/Mod/CAM/Tests/TestPathVoronoi.py index b94ce2c1f2..9960961671 100644 --- a/src/Mod/CAM/Tests/TestPathVoronoi.py +++ b/src/Mod/CAM/Tests/TestPathVoronoi.py @@ -109,9 +109,7 @@ class TestPathVoronoi(PathTestUtils.PathTestBase): e = e0.toShape() self.assertTrue(type(e.Curve) == Part.LineSegment or type(e.Curve) == Part.Line) self.assertFalse( - Path.Geom.pointsCoincide( - e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter) - ) + Path.Geom.pointsCoincide(e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter)) ) self.assertRoughly(e.valueAt(e.FirstParameter).z, 0) self.assertRoughly(e.valueAt(e.LastParameter).z, 0) @@ -126,9 +124,7 @@ class TestPathVoronoi(PathTestUtils.PathTestBase): e = e0.toShape(13.7) self.assertTrue(type(e.Curve) == Part.LineSegment or type(e.Curve) == Part.Line) self.assertFalse( - Path.Geom.pointsCoincide( - e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter) - ) + Path.Geom.pointsCoincide(e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter)) ) self.assertRoughly(e.valueAt(e.FirstParameter).z, 13.7) self.assertRoughly(e.valueAt(e.LastParameter).z, 13.7) @@ -143,9 +139,7 @@ class TestPathVoronoi(PathTestUtils.PathTestBase): e = e0.toShape(2.37, 5.14) self.assertTrue(type(e.Curve) == Part.LineSegment or type(e.Curve) == Part.Line) self.assertFalse( - Path.Geom.pointsCoincide( - e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter) - ) + Path.Geom.pointsCoincide(e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter)) ) self.assertRoughly(e.valueAt(e.FirstParameter).z, 2.37) self.assertRoughly(e.valueAt(e.LastParameter).z, 5.14) @@ -158,13 +152,9 @@ class TestPathVoronoi(PathTestUtils.PathTestBase): e0 = edges[0] e = e0.toShape() - self.assertTrue( - type(e.Curve) == Part.Parabola or type(e.Curve) == Part.BSplineCurve - ) + self.assertTrue(type(e.Curve) == Part.Parabola or type(e.Curve) == Part.BSplineCurve) self.assertFalse( - Path.Geom.pointsCoincide( - e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter) - ) + Path.Geom.pointsCoincide(e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter)) ) self.assertRoughly(e.valueAt(e.FirstParameter).z, 0) self.assertRoughly(e.valueAt(e.LastParameter).z, 0) @@ -177,13 +167,9 @@ class TestPathVoronoi(PathTestUtils.PathTestBase): e0 = edges[0] e = e0.toShape(13.7) - self.assertTrue( - type(e.Curve) == Part.Parabola or type(e.Curve) == Part.BSplineCurve - ) + self.assertTrue(type(e.Curve) == Part.Parabola or type(e.Curve) == Part.BSplineCurve) self.assertFalse( - Path.Geom.pointsCoincide( - e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter) - ) + Path.Geom.pointsCoincide(e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter)) ) self.assertRoughly(e.valueAt(e.FirstParameter).z, 13.7) self.assertRoughly(e.valueAt(e.LastParameter).z, 13.7) @@ -196,13 +182,9 @@ class TestPathVoronoi(PathTestUtils.PathTestBase): e0 = edges[0] e = e0.toShape(2.37, 5.14) - self.assertTrue( - type(e.Curve) == Part.Parabola or type(e.Curve) == Part.BSplineCurve - ) + self.assertTrue(type(e.Curve) == Part.Parabola or type(e.Curve) == Part.BSplineCurve) self.assertFalse( - Path.Geom.pointsCoincide( - e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter) - ) + Path.Geom.pointsCoincide(e.valueAt(e.FirstParameter), e.valueAt(e.LastParameter)) ) self.assertRoughly(e.valueAt(e.FirstParameter).z, 2.37) self.assertRoughly(e.valueAt(e.LastParameter).z, 5.14) diff --git a/src/Mod/CAM/Tests/TestRefactoredTestPost.py b/src/Mod/CAM/Tests/TestRefactoredTestPost.py index ec481394a7..b51d6b2e9a 100644 --- a/src/Mod/CAM/Tests/TestRefactoredTestPost.py +++ b/src/Mod/CAM/Tests/TestRefactoredTestPost.py @@ -145,9 +145,7 @@ class TestRefactoredTestPost(PathTestUtils.PathTestBase): def test00110(self): """Test axis-precision.""" - self.compare_third_line( - "G0 X10 Y20 Z30", "G0 X10.00 Y20.00 Z30.00", "--axis-precision=2" - ) + self.compare_third_line("G0 X10 Y20 Z30", "G0 X10.00 Y20.00 Z30.00", "--axis-precision=2") ############################################################################# @@ -394,9 +392,7 @@ G21 """ self.docobj.Path = Path.Path([]) postables = [self.docobj] - gcode: str = postprocessor.export( - postables, "-", "--output_all_arguments" - ) + gcode: str = postprocessor.export(postables, "-", "--output_all_arguments") # The argparse help routine turns out to be sensitive to the # number of columns in the terminal window that the tests # are run from. This affects the indenting in the output. diff --git a/src/Mod/CAM/Tests/TestRefactoredTestPostGCodes.py b/src/Mod/CAM/Tests/TestRefactoredTestPostGCodes.py index d014c01fd5..02029ad9d5 100644 --- a/src/Mod/CAM/Tests/TestRefactoredTestPostGCodes.py +++ b/src/Mod/CAM/Tests/TestRefactoredTestPostGCodes.py @@ -125,18 +125,12 @@ class TestRefactoredTestPostGCodes(PathTestUtils.PathTestBase): """Test G0 command Generation.""" self.compare_third_line( "G0 X10 Y20 Z30 A40 B50 C60 U70 V80 W90", - ( - "G0 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " - "U70.000 V80.000 W90.000" - ), + ("G0 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " "U70.000 V80.000 W90.000"), "", ) self.compare_third_line( "G00 X10 Y20 Z30 A40 B50 C60 U70 V80 W90", - ( - "G00 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " - "U70.000 V80.000 W90.000" - ), + ("G00 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " "U70.000 V80.000 W90.000"), "", ) @@ -279,9 +273,7 @@ class TestRefactoredTestPostGCodes(PathTestUtils.PathTestBase): "G10 L2 X1.235 Y2.346 Z3.457 P3", "", ) - self.compare_third_line( - "G10 L2 P0 X0 Y0 Z0", "G10 L2 X0.000 Y0.000 Z0.000 P0", "" - ) + self.compare_third_line("G10 L2 P0 X0 Y0 Z0", "G10 L2 X0.000 Y0.000 Z0.000 P0", "") self.compare_third_line( "G10 L10 P1 X1.23456 Y2.34567 Z3.456789", "G10 L10 X1.235 Y2.346 Z3.457 P1", @@ -363,10 +355,7 @@ class TestRefactoredTestPostGCodes(PathTestUtils.PathTestBase): self.compare_third_line("G28", "G28", "") self.compare_third_line( "G28 X10 Y20 Z30 A40 B50 C60 U70 V80 W90", - ( - "G28 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " - "U70.000 V80.000 W90.000" - ), + ("G28 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " "U70.000 V80.000 W90.000"), "", ) @@ -383,10 +372,7 @@ class TestRefactoredTestPostGCodes(PathTestUtils.PathTestBase): self.compare_third_line("G30", "G30", "") self.compare_third_line( "G30 X10 Y20 Z30 A40 B50 C60 U70 V80 W90", - ( - "G30 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " - "U70.000 V80.000 W90.000" - ), + ("G30 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " "U70.000 V80.000 W90.000"), "", ) @@ -511,10 +497,7 @@ class TestRefactoredTestPostGCodes(PathTestUtils.PathTestBase): "G43.1 X1.234567 Y2.345678 Z3.456789 A4.567891 B5.678912 C6.789123 " "U7.891234 V8.912345 W9.123456" ), - ( - "G43.1 X0.0486 Y0.0923 Z0.1361 A0.1798 B0.2236 C0.2673 " - "U0.3107 V0.3509 W0.3592" - ), + ("G43.1 X0.0486 Y0.0923 Z0.1361 A0.1798 B0.2236 C0.2673 " "U0.3107 V0.3509 W0.3592"), "--inches", ) @@ -542,9 +525,7 @@ class TestRefactoredTestPostGCodes(PathTestUtils.PathTestBase): "C6.789123 U7.891234 V8.912345 W9.123456" ) ), - Path.Command( - "G52 X0 Y0.0 Z0.00 A0.000 B0.0000 C0.00000 U0.000000 V0 W0" - ), + Path.Command("G52 X0 Y0.0 Z0.00 A0.000 B0.0000 C0.00000 U0.000000 V0 W0"), ], """G90 G21 @@ -561,9 +542,7 @@ G52 X0.000 Y0.000 Z0.000 A0.000 B0.000 C0.000 U0.000 V0.000 W0.000 "C6.789123 U7.891234 V8.912345 W9.123456" ) ), - Path.Command( - "G52 X0 Y0.0 Z0.00 A0.000 B0.0000 C0.00000 U0.000000 V0 W0" - ), + Path.Command("G52 X0 Y0.0 Z0.00 A0.000 B0.0000 C0.00000 U0.000000 V0 W0"), ], """G90 G20 @@ -726,9 +705,7 @@ G52 X0.0000 Y0.0000 Z0.0000 A0.0000 B0.0000 C0.0000 U0.0000 V0.0000 W0.0000 self.compare_third_line("G64", "G64", "") self.compare_third_line("G64 P3.456789", "G64 P3.457", "") self.compare_third_line("G64 P3.456789 Q4.567891", "G64 P3.457 Q4.568", "") - self.compare_third_line( - "G64 P3.456789 Q4.567891", "G64 P0.1361 Q0.1798", "--inches" - ) + self.compare_third_line("G64 P3.456789 Q4.567891", "G64 P0.1361 Q0.1798", "--inches") ############################################################################# @@ -1380,10 +1357,7 @@ G90 """Test G92 command Generation.""" self.compare_third_line( "G92 X10 Y20 Z30 A40 B50 C60 U70 V80 W90", - ( - "G92 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " - "U70.000 V80.000 W90.000" - ), + ("G92 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " "U70.000 V80.000 W90.000"), "", ) diff --git a/src/Mod/CAM/Tools/Bit/5mm_Drill.fctb b/src/Mod/CAM/Tools/Bit/5mm_Drill.fctb index 40243399a2..afc4db9c30 100644 --- a/src/Mod/CAM/Tools/Bit/5mm_Drill.fctb +++ b/src/Mod/CAM/Tools/Bit/5mm_Drill.fctb @@ -8,4 +8,4 @@ "TipAngle": "119.0000 \u00b0" }, "attribute": {} -} \ No newline at end of file +} diff --git a/src/Mod/CAM/Tools/Bit/6mm_Ball_End.fctb b/src/Mod/CAM/Tools/Bit/6mm_Ball_End.fctb index 9e9afbabc8..36f1abcfef 100644 --- a/src/Mod/CAM/Tools/Bit/6mm_Ball_End.fctb +++ b/src/Mod/CAM/Tools/Bit/6mm_Ball_End.fctb @@ -9,4 +9,4 @@ "ShankDiameter": "3.0000 mm" }, "attribute": {} -} \ No newline at end of file +} diff --git a/src/Mod/CAM/Tools/Bit/6mm_Bullnose.fctb b/src/Mod/CAM/Tools/Bit/6mm_Bullnose.fctb index 05d80b1d2a..ccff179d77 100644 --- a/src/Mod/CAM/Tools/Bit/6mm_Bullnose.fctb +++ b/src/Mod/CAM/Tools/Bit/6mm_Bullnose.fctb @@ -10,4 +10,4 @@ "ShankDiameter": "3.0000 mm" }, "attribute": {} -} \ No newline at end of file +} diff --git a/src/Mod/CAM/Tools/README.md b/src/Mod/CAM/Tools/README.md index 910640baad..8445d225a6 100644 --- a/src/Mod/CAM/Tools/README.md +++ b/src/Mod/CAM/Tools/README.md @@ -115,4 +115,3 @@ representation. Not that 'Shape' is the only property group which has special meaning for tool bits. All other property groups are copied verbatim to the tool bit object when one is created. - diff --git a/src/Mod/CAM/Tools/toolbit-attributes.py b/src/Mod/CAM/Tools/toolbit-attributes.py index 3545fe55a4..a6e8fb30c8 100755 --- a/src/Mod/CAM/Tools/toolbit-attributes.py +++ b/src/Mod/CAM/Tools/toolbit-attributes.py @@ -83,9 +83,7 @@ parser.add_argument( parser.add_argument( "--save-changes", action="store_true", help="Unless specified the file is not saved" ) -parser.add_argument( - "--freecad", help="Directory FreeCAD binaries (libFreeCAD.so) if not installed" -) +parser.add_argument("--freecad", help="Directory FreeCAD binaries (libFreeCAD.so) if not installed") args = parser.parse_args() if args.freecad: @@ -158,11 +156,7 @@ for i, fname in enumerate(args.path): if not args.print_all and grp == "Shape": continue if args.print or args.print_all: - print( - " {:10} {:20} {:20} {:10} {}".format( - grp, p, ttp, str(val), enm - ) - ) + print(" {:10} {:20} {:20} {:10} {}".format(grp, p, ttp, str(val), enm)) o.Proxy.refreshCustomPropertyGroups() if args.save_changes: doc.recompute() diff --git a/src/Mod/CAM/libarea/Adaptive.cpp b/src/Mod/CAM/libarea/Adaptive.cpp index b83ff67e95..7512418038 100644 --- a/src/Mod/CAM/libarea/Adaptive.cpp +++ b/src/Mod/CAM/libarea/Adaptive.cpp @@ -1,24 +1,24 @@ /************************************************************************** -* Copyright (c) 2018 Kresimir Tusek * -* * -* This file is part of the FreeCAD CAx development system. * -* * -* This library is free software; you can redistribute it and/or * -* modify it under the terms of the GNU Library General Public * -* License as published by the Free Software Foundation; either * -* version 2 of the License, or (at your option) any later version. * -* * -* This library is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Library General Public License for more details. * -* * -* You should have received a copy of the GNU Library General Public * -* License along with this library; see the file COPYING.LIB. If not, * -* write to the Free Software Foundation, Inc., 59 Temple Place, * -* Suite 330, Boston, MA 02111-1307, USA * -* * -***************************************************************************/ + * Copyright (c) 2018 Kresimir Tusek * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ #include "Adaptive.hpp" #include @@ -29,7 +29,7 @@ namespace ClipperLib { -void TranslatePath(const Path &input, Path &output, IntPoint delta); +void TranslatePath(const Path& input, Path& output, IntPoint delta); } namespace AdaptivePath @@ -43,129 +43,135 @@ using namespace std; // Utils - inline //***************************************** -inline double DistanceSqrd(const IntPoint &pt1, const IntPoint &pt2) +inline double DistanceSqrd(const IntPoint& pt1, const IntPoint& pt2) { - double Dx = double(pt1.X - pt2.X); - double dy = double(pt1.Y - pt2.Y); - return (Dx * Dx + dy * dy); + double Dx = double(pt1.X - pt2.X); + double dy = double(pt1.Y - pt2.Y); + return (Dx * Dx + dy * dy); } -inline bool SetSegmentLength(const IntPoint &pt1, IntPoint &pt2, double new_length) +inline bool SetSegmentLength(const IntPoint& pt1, IntPoint& pt2, double new_length) { - double Dx = double(pt2.X - pt1.X); - double dy = double(pt2.Y - pt1.Y); - double l = sqrt(Dx * Dx + dy * dy); - if (l > 0.0) - { - pt2.X = long(pt1.X + new_length * Dx / l); - pt2.Y = long(pt1.Y + new_length * dy / l); - return true; - } - return false; + double Dx = double(pt2.X - pt1.X); + double dy = double(pt2.Y - pt1.Y); + double l = sqrt(Dx * Dx + dy * dy); + if (l > 0.0) { + pt2.X = long(pt1.X + new_length * Dx / l); + pt2.Y = long(pt1.Y + new_length * dy / l); + return true; + } + return false; } -inline bool HasAnyPath(const Paths &paths) +inline bool HasAnyPath(const Paths& paths) { - for (Paths::size_type i = 0; i < paths.size(); i++) - { - if (!paths[i].empty()) - return true; - } - return false; + for (Paths::size_type i = 0; i < paths.size(); i++) { + if (!paths[i].empty()) { + return true; + } + } + return false; } -inline double averageDV(const vector &vec) +inline double averageDV(const vector& vec) { - double s = 0; - std::size_t size = vec.size(); - if (size == 0) - return 0; - for (std::size_t i = 0; i < size; i++) - s += vec[i]; - return s / double(size); + double s = 0; + std::size_t size = vec.size(); + if (size == 0) { + return 0; + } + for (std::size_t i = 0; i < size; i++) { + s += vec[i]; + } + return s / double(size); } -inline DoublePoint rotate(const DoublePoint &in, double rad) +inline DoublePoint rotate(const DoublePoint& in, double rad) { - double c = cos(rad); - double s = sin(rad); - return DoublePoint(c * in.X - s * in.Y, s * in.X + c * in.Y); + double c = cos(rad); + double s = sin(rad); + return DoublePoint(c * in.X - s * in.Y, s * in.X + c * in.Y); } // calculates path length for open path -inline double PathLength(const Path &path) +inline double PathLength(const Path& path) { - double len = 0; - if (path.size() < 2) - return len; - for (size_t i = 1; i < path.size(); i++) - { - len += sqrt(DistanceSqrd(path[i - 1], path[i])); - } - return len; + double len = 0; + if (path.size() < 2) { + return len; + } + for (size_t i = 1; i < path.size(); i++) { + len += sqrt(DistanceSqrd(path[i - 1], path[i])); + } + return len; } -inline double PointSideOfLine(const IntPoint &p1, const IntPoint &p2, const IntPoint &pt) +inline double PointSideOfLine(const IntPoint& p1, const IntPoint& p2, const IntPoint& pt) { - return double((pt.X - p1.X) * (p2.Y - p1.Y) - (pt.Y - p2.Y) * (p2.X - p1.X)); + return double((pt.X - p1.X) * (p2.Y - p1.Y) - (pt.Y - p2.Y) * (p2.X - p1.X)); } -inline double Angle3Points(const DoublePoint &p1, const DoublePoint &p2, const DoublePoint &p3) +inline double Angle3Points(const DoublePoint& p1, const DoublePoint& p2, const DoublePoint& p3) { - double t1 = atan2(p2.Y - p1.Y, p2.X - p1.X); - double t2 = atan2(p3.Y - p2.Y, p3.X - p2.X); - double a = fabs(t2 - t1); - return min(a, 2 * M_PI - a); + double t1 = atan2(p2.Y - p1.Y, p2.X - p1.X); + double t2 = atan2(p3.Y - p2.Y, p3.X - p2.X); + double a = fabs(t2 - t1); + return min(a, 2 * M_PI - a); } -inline DoublePoint DirectionV(const IntPoint &pt1, const IntPoint &pt2) +inline DoublePoint DirectionV(const IntPoint& pt1, const IntPoint& pt2) { - double DX = double(pt2.X - pt1.X); - double DY = double(pt2.Y - pt1.Y); - double l = sqrt(DX * DX + DY * DY); - if (l < NTOL) - return DoublePoint(0, 0); - return DoublePoint(DX / l, DY / l); + double DX = double(pt2.X - pt1.X); + double DY = double(pt2.Y - pt1.Y); + double l = sqrt(DX * DX + DY * DY); + if (l < NTOL) { + return DoublePoint(0, 0); + } + return DoublePoint(DX / l, DY / l); } -inline void NormalizeV(DoublePoint &pt) +inline void NormalizeV(DoublePoint& pt) { - double len = sqrt(pt.X * pt.X + pt.Y * pt.Y); - if (len > NTOL) - { - pt.X /= len; - pt.Y /= len; - } + double len = sqrt(pt.X * pt.X + pt.Y * pt.Y); + if (len > NTOL) { + pt.X /= len; + pt.Y /= len; + } } -inline DoublePoint GetPathDirectionV(const Path &pth, size_t pointIndex) +inline DoublePoint GetPathDirectionV(const Path& pth, size_t pointIndex) { - if (pth.size() < 2) - return DoublePoint(0, 0); - const IntPoint &p1 = pth.at(pointIndex > 0 ? pointIndex - 1 : pth.size() - 1); - const IntPoint &p2 = pth.at(pointIndex); - return DirectionV(p1, p2); + if (pth.size() < 2) { + return DoublePoint(0, 0); + } + const IntPoint& p1 = pth.at(pointIndex > 0 ? pointIndex - 1 : pth.size() - 1); + const IntPoint& p2 = pth.at(pointIndex); + return DirectionV(p1, p2); } // Returns true if points 'a' and 'b' are coincident or nearly so. -bool isClose(const IntPoint &a, const IntPoint &b) { - return abs(a.X - b.X) <= 1 && abs(a.Y - b.Y) <= 1; +bool isClose(const IntPoint& a, const IntPoint& b) +{ + return abs(a.X - b.X) <= 1 && abs(a.Y - b.Y) <= 1; } // Remove coincident and almost-coincident points from Paths. -void filterCloseValues(Paths &ppg) { - for (auto& pth : ppg) { - while (true) { - auto i = std::adjacent_find(pth.begin(), pth.end(), isClose); - if (i == pth.end()) - break; - pth.erase(i); - } - // adjacent_find doesn't compare first with last element, so - // do that manually. - while (pth.size() > 1 && isClose(pth.front(), pth.back())) - pth.pop_back(); - } +void filterCloseValues(Paths& ppg) +{ + for (auto& pth : ppg) { + while (true) { + auto i = std::adjacent_find(pth.begin(), pth.end(), isClose); + if (i == pth.end()) { + break; + } + pth.erase(i); + } + // adjacent_find doesn't compare first with last element, so + // do that manually. + while (pth.size() > 1 && isClose(pth.front(), pth.back())) { + pth.pop_back(); + } + } } //***************************************** @@ -174,749 +180,771 @@ void filterCloseValues(Paths &ppg) { class BoundBox { - public: - BoundBox() - { - minX = 0; - maxX = 0; - minY = 0; - maxY = 0; - } +public: + BoundBox() + { + minX = 0; + maxX = 0; + minY = 0; + maxY = 0; + } - // generic: first point - BoundBox(const IntPoint &p1) - { - minX = p1.X; - maxX = p1.X; - minY = p1.Y; - maxY = p1.Y; - } + // generic: first point + BoundBox(const IntPoint& p1) + { + minX = p1.X; + maxX = p1.X; + minY = p1.Y; + maxY = p1.Y; + } - void SetFirstPoint(const IntPoint &p1) - { - minX = p1.X; - maxX = p1.X; - minY = p1.Y; - maxY = p1.Y; - } + void SetFirstPoint(const IntPoint& p1) + { + minX = p1.X; + maxX = p1.X; + minY = p1.Y; + maxY = p1.Y; + } - // generic: subsequent points - void AddPoint(const IntPoint &pt) - { - minX = min(pt.X, minX); - maxX = max(pt.X, maxX); - minY = min(pt.Y, minY); - maxY = max(pt.Y, maxY); - } + // generic: subsequent points + void AddPoint(const IntPoint& pt) + { + minX = min(pt.X, minX); + maxX = max(pt.X, maxX); + minY = min(pt.Y, minY); + maxY = max(pt.Y, maxY); + } - // line segment: two points - BoundBox(const IntPoint &p1, const IntPoint &p2) - { - if (p1.X < p2.X) - { - minX = p1.X; - maxX = p2.X; - } - else - { - minX = p2.X; - maxX = p1.X; - } - if (p1.Y < p2.Y) - { - minY = p1.Y; - maxY = p2.Y; - } - else - { - minY = p2.Y; - maxY = p1.Y; - } - } + // line segment: two points + BoundBox(const IntPoint& p1, const IntPoint& p2) + { + if (p1.X < p2.X) { + minX = p1.X; + maxX = p2.X; + } + else { + minX = p2.X; + maxX = p1.X; + } + if (p1.Y < p2.Y) { + minY = p1.Y; + maxY = p2.Y; + } + else { + minY = p2.Y; + maxY = p1.Y; + } + } - // for circle: center and radius - BoundBox(const IntPoint ¢er, long radius) - { - minX = center.X - radius; - maxX = center.X + radius; - minY = center.Y - radius; - maxY = center.Y + radius; - } + // for circle: center and radius + BoundBox(const IntPoint& center, long radius) + { + minX = center.X - radius; + maxX = center.X + radius; + minY = center.Y - radius; + maxY = center.Y + radius; + } - // bounds check - intersection - inline bool CollidesWith(const BoundBox &bb2) - { - return minX <= bb2.maxX && maxX >= bb2.minX && minY <= bb2.maxY && maxY >= bb2.minY; - } + // bounds check - intersection + inline bool CollidesWith(const BoundBox& bb2) + { + return minX <= bb2.maxX && maxX >= bb2.minX && minY <= bb2.maxY && maxY >= bb2.minY; + } - // bounds check - contains - inline bool Contains(const BoundBox &bb2) - { - return minX <= bb2.minX && maxX >= bb2.maxX && minY <= bb2.minY && maxY >= bb2.maxY; - } + // bounds check - contains + inline bool Contains(const BoundBox& bb2) + { + return minX <= bb2.minX && maxX >= bb2.maxX && minY <= bb2.minY && maxY >= bb2.maxY; + } - ClipperLib::cInt minX; - ClipperLib::cInt maxX; - ClipperLib::cInt minY; - ClipperLib::cInt maxY; + ClipperLib::cInt minX; + ClipperLib::cInt maxX; + ClipperLib::cInt minY; + ClipperLib::cInt maxY; }; -std::ostream &operator<<(std::ostream &s, const BoundBox &p) +std::ostream& operator<<(std::ostream& s, const BoundBox& p) { - s << "(" << p.minX << "," << p.minY << ") - (" << p.maxX << "," << p.maxY << ")"; - return s; + s << "(" << p.minX << "," << p.minY << ") - (" << p.maxX << "," << p.maxY << ")"; + return s; } -int getPathNestingLevel(const Path &path, const Paths &paths) +int getPathNestingLevel(const Path& path, const Paths& paths) { - int nesting = 0; - for (const auto &other : paths) - { - if (!path.empty() && PointInPolygon(path.front(), other) != 0) - nesting++; - } - return nesting; + int nesting = 0; + for (const auto& other : paths) { + if (!path.empty() && PointInPolygon(path.front(), other) != 0) { + nesting++; + } + } + return nesting; } -void appendDirectChildPaths(Paths &outPaths, const Path &path, const Paths &paths) +void appendDirectChildPaths(Paths& outPaths, const Path& path, const Paths& paths) { - int nesting = getPathNestingLevel(path, paths); - for (const auto &other : paths) - { - if (!path.empty() && !other.empty() && PointInPolygon(other.front(), path) != 0) - { - if (getPathNestingLevel(other, paths) == nesting + 1) - outPaths.push_back(other); - } - } + int nesting = getPathNestingLevel(path, paths); + for (const auto& other : paths) { + if (!path.empty() && !other.empty() && PointInPolygon(other.front(), path) != 0) { + if (getPathNestingLevel(other, paths) == nesting + 1) { + outPaths.push_back(other); + } + } + } } -void AverageDirection(const vector &unityVectors, DoublePoint &output) +void AverageDirection(const vector& unityVectors, DoublePoint& output) { - std::size_t size = unityVectors.size(); - output.X = 0; - output.Y = 0; - // sum vectors - for (std::size_t i = 0; i < size; i++) - { - DoublePoint v = unityVectors[i]; - output.X += v.X; - output.Y += v.Y; - } - // normalize - double magnitude = sqrt(output.X * output.X + output.Y * output.Y); - output.X /= magnitude; - output.Y /= magnitude; + std::size_t size = unityVectors.size(); + output.X = 0; + output.Y = 0; + // sum vectors + for (std::size_t i = 0; i < size; i++) { + DoublePoint v = unityVectors[i]; + output.X += v.X; + output.Y += v.Y; + } + // normalize + double magnitude = sqrt(output.X * output.X + output.Y * output.Y); + output.X /= magnitude; + output.Y /= magnitude; } -double DistancePointToLineSegSquared(const IntPoint &p1, const IntPoint &p2, const IntPoint &pt, - IntPoint &closestPoint, double &ptParameter, bool clamp = true) +double DistancePointToLineSegSquared(const IntPoint& p1, + const IntPoint& p2, + const IntPoint& pt, + IntPoint& closestPoint, + double& ptParameter, + bool clamp = true) { - double D21X = double(p2.X - p1.X); - double D21Y = double(p2.Y - p1.Y); - double DP1X = double(pt.X - p1.X); - double DP1Y = double(pt.Y - p1.Y); - double lsegLenSqr = D21X * D21X + D21Y * D21Y; - if (lsegLenSqr == 0) - { // segment is zero length, return point to point distance - closestPoint = p1; - ptParameter = 0; - return DP1X * DP1X + DP1Y * DP1Y; - } - double parameter = DP1X * D21X + DP1Y * D21Y; - if (clamp) - { - // clamp the parameter - if (parameter < 0) - parameter = 0; - else if (parameter > lsegLenSqr) - parameter = lsegLenSqr; - } - // point on line at parameter - ptParameter = parameter / lsegLenSqr; - closestPoint.X = long(p1.X + ptParameter * D21X); - closestPoint.Y = long(p1.Y + ptParameter * D21Y); - // calculate distance from point on line to pt - double DX = double(pt.X - closestPoint.X); - double DY = double(pt.Y - closestPoint.Y); - return DX * DX + DY * DY; // return distance squared + double D21X = double(p2.X - p1.X); + double D21Y = double(p2.Y - p1.Y); + double DP1X = double(pt.X - p1.X); + double DP1Y = double(pt.Y - p1.Y); + double lsegLenSqr = D21X * D21X + D21Y * D21Y; + if (lsegLenSqr == 0) { // segment is zero length, return point to point distance + closestPoint = p1; + ptParameter = 0; + return DP1X * DP1X + DP1Y * DP1Y; + } + double parameter = DP1X * D21X + DP1Y * D21Y; + if (clamp) { + // clamp the parameter + if (parameter < 0) { + parameter = 0; + } + else if (parameter > lsegLenSqr) { + parameter = lsegLenSqr; + } + } + // point on line at parameter + ptParameter = parameter / lsegLenSqr; + closestPoint.X = long(p1.X + ptParameter * D21X); + closestPoint.Y = long(p1.Y + ptParameter * D21Y); + // calculate distance from point on line to pt + double DX = double(pt.X - closestPoint.X); + double DY = double(pt.Y - closestPoint.Y); + return DX * DX + DY * DY; // return distance squared } -void ScaleUpPaths(Paths &paths,long scaleFactor) { - for(auto &pth:paths) { - for(auto &pt:pth) { - pt.X*=scaleFactor; - pt.Y*=scaleFactor; - } - } -} - -void ScaleDownPaths(Paths &paths,long scaleFactor) { - for(auto &pth:paths) { - for(auto &pt:pth) { - pt.X/=scaleFactor; - pt.Y/=scaleFactor; - } - } -} - - - - -double DistancePointToPathsSqrd(const Paths &paths, const IntPoint &pt, IntPoint &closestPointOnPath, - size_t &clpPathIndex, - size_t &clpSegmentIndex, - double &clpParameter) +void ScaleUpPaths(Paths& paths, long scaleFactor) { - double minDistSq = __DBL_MAX__; - IntPoint clp; - // iterate though paths - for (Path::size_type i = 0; i < paths.size(); i++) - { - const Path *path = &paths[i]; - Path::size_type size = path->size(); - // iterate through segments - for (Path::size_type j = 0; j < size; j++) - { - double ptPar; - double distSq = DistancePointToLineSegSquared(path->at(j > 0 ? j - 1 : size - 1), path->at(j), pt, clp, ptPar); - if (distSq < minDistSq) - { - clpPathIndex = i; - clpSegmentIndex = j; - clpParameter = ptPar; - closestPointOnPath = clp; - minDistSq = distSq; - } - } - } - return minDistSq; + for (auto& pth : paths) { + for (auto& pt : pth) { + pt.X *= scaleFactor; + pt.Y *= scaleFactor; + } + } +} + +void ScaleDownPaths(Paths& paths, long scaleFactor) +{ + for (auto& pth : paths) { + for (auto& pt : pth) { + pt.X /= scaleFactor; + pt.Y /= scaleFactor; + } + } +} + + +double DistancePointToPathsSqrd(const Paths& paths, + const IntPoint& pt, + IntPoint& closestPointOnPath, + size_t& clpPathIndex, + size_t& clpSegmentIndex, + double& clpParameter) +{ + double minDistSq = __DBL_MAX__; + IntPoint clp; + // iterate though paths + for (Path::size_type i = 0; i < paths.size(); i++) { + const Path* path = &paths[i]; + Path::size_type size = path->size(); + // iterate through segments + for (Path::size_type j = 0; j < size; j++) { + double ptPar; + double distSq = DistancePointToLineSegSquared(path->at(j > 0 ? j - 1 : size - 1), + path->at(j), + pt, + clp, + ptPar); + if (distSq < minDistSq) { + clpPathIndex = i; + clpSegmentIndex = j; + clpParameter = ptPar; + closestPointOnPath = clp; + minDistSq = distSq; + } + } + } + return minDistSq; } // joins collinear segments (within the tolerance) -void CleanPath(const Path &inp, Path &outpt, double tolerance) +void CleanPath(const Path& inp, Path& outpt, double tolerance) { - if (inp.size() < 3) - { - outpt = inp; - return; - } - outpt.clear(); - Path tmp; - CleanPolygon(inp, tmp, tolerance); - long size=long(tmp.size()); + if (inp.size() < 3) { + outpt = inp; + return; + } + outpt.clear(); + Path tmp; + CleanPolygon(inp, tmp, tolerance); + long size = long(tmp.size()); - // CleanPolygon will have empty result if all points are collinear, - // need to add first and last point to the output - if(size<=2) { - outpt.push_back(inp.front()); - outpt.push_back(inp.back()); - return; - } + // CleanPolygon will have empty result if all points are collinear, + // need to add first and last point to the output + if (size <= 2) { + outpt.push_back(inp.front()); + outpt.push_back(inp.back()); + return; + } - // restore starting point - double clpPar = 0; - size_t clpSegmentIndex=0; - size_t clpPathIndex=0; - Paths tmpPaths; - tmpPaths.push_back(tmp); - IntPoint clp; - // find point on cleaned poly that is closest to original starting point - DistancePointToPathsSqrd(tmpPaths,inp.front(),clp,clpPathIndex,clpSegmentIndex,clpPar); + // restore starting point + double clpPar = 0; + size_t clpSegmentIndex = 0; + size_t clpPathIndex = 0; + Paths tmpPaths; + tmpPaths.push_back(tmp); + IntPoint clp; + // find point on cleaned poly that is closest to original starting point + DistancePointToPathsSqrd(tmpPaths, inp.front(), clp, clpPathIndex, clpSegmentIndex, clpPar); - // if closes point is not one of the polygon points, add it as separate first point - if(DistanceSqrd(clp,tmp.at(clpSegmentIndex)) > 0 && - DistanceSqrd(clp,tmp.at(clpSegmentIndex>0 ? clpSegmentIndex-1 : size-1)) > 0) outpt.push_back(clp); + // if closes point is not one of the polygon points, add it as separate first point + if (DistanceSqrd(clp, tmp.at(clpSegmentIndex)) > 0 + && DistanceSqrd(clp, tmp.at(clpSegmentIndex > 0 ? clpSegmentIndex - 1 : size - 1)) > 0) { + outpt.push_back(clp); + } - // add remaining points starting from closest - long index; - for (long i = 0; i < size; i++) - { - index = static_cast(clpSegmentIndex + i); - if (index >= size) index -= size; - outpt.push_back(tmp.at(index)); - } + // add remaining points starting from closest + long index; + for (long i = 0; i < size; i++) { + index = static_cast(clpSegmentIndex + i); + if (index >= size) { + index -= size; + } + outpt.push_back(tmp.at(index)); + } - if(DistanceSqrd(outpt.front(),inp.front()) > SAME_POINT_TOL_SQRD_SCALED) - outpt.insert(outpt.begin(), inp.front()); - - if(DistanceSqrd(outpt.back(),inp.back()) > SAME_POINT_TOL_SQRD_SCALED) - outpt.push_back( inp.back()); + if (DistanceSqrd(outpt.front(), inp.front()) > SAME_POINT_TOL_SQRD_SCALED) { + outpt.insert(outpt.begin(), inp.front()); + } + if (DistanceSqrd(outpt.back(), inp.back()) > SAME_POINT_TOL_SQRD_SCALED) { + outpt.push_back(inp.back()); + } } -bool Circle2CircleIntersect(const IntPoint &c1, const IntPoint &c2, double radius, pair &intersections) +bool Circle2CircleIntersect(const IntPoint& c1, + const IntPoint& c2, + double radius, + pair& intersections) { - double DX = double(c2.X - c1.X); - double DY = double(c2.Y - c1.Y); - double d = sqrt(DX * DX + DY * DY); - if (d < NTOL) - return false; // same center - if (d >= radius) - return false; // do not intersect, or intersect in one point (this case not relevant here) - double a_2 = sqrt(4 * radius * radius - d * d) / 2.0; - intersections.first = DoublePoint(0.5 * (c1.X + c2.X) - DY * a_2 / d, 0.5 * (c1.Y + c2.Y) + DX * a_2 / d); - intersections.second = DoublePoint(0.5 * (c1.X + c2.X) + DY * a_2 / d, 0.5 * (c1.Y + c2.Y) - DX * a_2 / d); - return true; + double DX = double(c2.X - c1.X); + double DY = double(c2.Y - c1.Y); + double d = sqrt(DX * DX + DY * DY); + if (d < NTOL) { + return false; // same center + } + if (d >= radius) { + return false; // do not intersect, or intersect in one point (this case not relevant here) + } + double a_2 = sqrt(4 * radius * radius - d * d) / 2.0; + intersections.first = + DoublePoint(0.5 * (c1.X + c2.X) - DY * a_2 / d, 0.5 * (c1.Y + c2.Y) + DX * a_2 / d); + intersections.second = + DoublePoint(0.5 * (c1.X + c2.X) + DY * a_2 / d, 0.5 * (c1.Y + c2.Y) - DX * a_2 / d); + return true; } -bool Line2CircleIntersect(const IntPoint &c, double radius, const IntPoint &p1, const IntPoint &p2, vector &result, bool clamp = true) +bool Line2CircleIntersect(const IntPoint& c, + double radius, + const IntPoint& p1, + const IntPoint& p2, + vector& result, + bool clamp = true) { - // if more intersections returned, first is closer to p1 + // if more intersections returned, first is closer to p1 - //box check for performance - if (clamp) - { - BoundBox cBB(c, (ClipperLib::cInt)radius + 1); // circle bound box - BoundBox sBB(p1, p2); - if (!sBB.CollidesWith(cBB)) - return false; - } + // box check for performance + if (clamp) { + BoundBox cBB(c, (ClipperLib::cInt)radius + 1); // circle bound box + BoundBox sBB(p1, p2); + if (!sBB.CollidesWith(cBB)) { + return false; + } + } - double dx = double(p2.X - p1.X); - double dy = double(p2.Y - p1.Y); - double lcx = double(p1.X - c.X); - double lcy = double(p1.Y - c.Y); - double a = dx * dx + dy * dy; - double b = 2 * dx * lcx + 2 * dy * lcy; - double C = lcx * lcx + lcy * lcy - radius * radius; - double sq = b * b - 4 * a * C; - if (sq < 0) - return false; // no solution - sq = sqrt(sq); - double t1 = (-b - sq) / (2 * a); - double t2 = (-b + sq) / (2 * a); - result.clear(); - if (clamp) - { - if (t1 >= 0.0 && t1 <= 1.0) - result.emplace_back(p1.X + t1 * dx, p1.Y + t1 * dy); - if (t2 >= 0.0 && t2 <= 1.0) - result.emplace_back(p1.X + t2 * dx, p1.Y + t2 * dy); - } - else - { - result.emplace_back(p1.X + t2 * dx, p1.Y + t2 * dy); - result.emplace_back(p1.X + t2 * dx, p1.Y + t2 * dy); - } - return !result.empty(); + double dx = double(p2.X - p1.X); + double dy = double(p2.Y - p1.Y); + double lcx = double(p1.X - c.X); + double lcy = double(p1.Y - c.Y); + double a = dx * dx + dy * dy; + double b = 2 * dx * lcx + 2 * dy * lcy; + double C = lcx * lcx + lcy * lcy - radius * radius; + double sq = b * b - 4 * a * C; + if (sq < 0) { + return false; // no solution + } + sq = sqrt(sq); + double t1 = (-b - sq) / (2 * a); + double t2 = (-b + sq) / (2 * a); + result.clear(); + if (clamp) { + if (t1 >= 0.0 && t1 <= 1.0) { + result.emplace_back(p1.X + t1 * dx, p1.Y + t1 * dy); + } + if (t2 >= 0.0 && t2 <= 1.0) { + result.emplace_back(p1.X + t2 * dx, p1.Y + t2 * dy); + } + } + else { + result.emplace_back(p1.X + t2 * dx, p1.Y + t2 * dy); + result.emplace_back(p1.X + t2 * dx, p1.Y + t2 * dy); + } + return !result.empty(); } // calculate center point of polygon -IntPoint Compute2DPolygonCentroid(const Path &vertices) +IntPoint Compute2DPolygonCentroid(const Path& vertices) { - DoublePoint centroid(0, 0); - double signedArea = 0.0; - double x0 = 0.0; // Current vertex X - double y0 = 0.0; // Current vertex Y - double x1 = 0.0; // Next vertex X - double y1 = 0.0; // Next vertex Y - double a = 0.0; // Partial signed area + DoublePoint centroid(0, 0); + double signedArea = 0.0; + double x0 = 0.0; // Current vertex X + double y0 = 0.0; // Current vertex Y + double x1 = 0.0; // Next vertex X + double y1 = 0.0; // Next vertex Y + double a = 0.0; // Partial signed area - // For all vertices - size_t i = 0; - Path::size_type size = vertices.size(); - for (i = 0; i < size; ++i) - { - x0 = double(vertices[i].X); - y0 = double(vertices[i].Y); - x1 = double(vertices[(i + 1) % size].X); - y1 = double(vertices[(i + 1) % size].Y); - a = x0 * y1 - x1 * y0; - signedArea += a; - centroid.X += (x0 + x1) * a; - centroid.Y += (y0 + y1) * a; - } + // For all vertices + size_t i = 0; + Path::size_type size = vertices.size(); + for (i = 0; i < size; ++i) { + x0 = double(vertices[i].X); + y0 = double(vertices[i].Y); + x1 = double(vertices[(i + 1) % size].X); + y1 = double(vertices[(i + 1) % size].Y); + a = x0 * y1 - x1 * y0; + signedArea += a; + centroid.X += (x0 + x1) * a; + centroid.Y += (y0 + y1) * a; + } - signedArea *= 0.5; - centroid.X /= (6.0 * signedArea); - centroid.Y /= (6.0 * signedArea); - return IntPoint(long(centroid.X), long(centroid.Y)); + signedArea *= 0.5; + centroid.X /= (6.0 * signedArea); + centroid.Y /= (6.0 * signedArea); + return IntPoint(long(centroid.X), long(centroid.Y)); } // point must be within first path (boundary) and must not be within all other paths (holes) -bool IsPointWithinCutRegion(const Paths &toolBoundPaths, const IntPoint &point) +bool IsPointWithinCutRegion(const Paths& toolBoundPaths, const IntPoint& point) { - for (size_t i = 0; i < toolBoundPaths.size(); i++) - { - int pip = PointInPolygon(point, toolBoundPaths[i]); - if (i == 0 && pip == 0) - return false; // is outside or on boundary - if (i > 0 && pip != 0) - return false; // is inside hole - } - return true; + for (size_t i = 0; i < toolBoundPaths.size(); i++) { + int pip = PointInPolygon(point, toolBoundPaths[i]); + if (i == 0 && pip == 0) { + return false; // is outside or on boundary + } + if (i > 0 && pip != 0) { + return false; // is inside hole + } + } + return true; } /* finds intersection of line segment with line segment */ -bool IntersectionPoint(const IntPoint &s1p1, - const IntPoint &s1p2, - const IntPoint &s2p1, - const IntPoint &s2p2, - IntPoint &intersection) +bool IntersectionPoint(const IntPoint& s1p1, + const IntPoint& s1p2, + const IntPoint& s2p1, + const IntPoint& s2p2, + IntPoint& intersection) { - double S1DX = double(s1p2.X - s1p1.X); - double S1DY = double(s1p2.Y - s1p1.Y); - double S2DX = double(s2p2.X - s2p1.X); - double S2DY = double(s2p2.Y - s2p1.Y); - double d = S1DY * S2DX - S2DY * S1DX; - if (fabs(d) < NTOL) - return false; // lines are parallel + double S1DX = double(s1p2.X - s1p1.X); + double S1DY = double(s1p2.Y - s1p1.Y); + double S2DX = double(s2p2.X - s2p1.X); + double S2DY = double(s2p2.Y - s2p1.Y); + double d = S1DY * S2DX - S2DY * S1DX; + if (fabs(d) < NTOL) { + return false; // lines are parallel + } - double LPDX = double(s1p1.X - s2p1.X); - double LPDY = double(s1p1.Y - s2p1.Y); - double p1d = S2DY * LPDX - S2DX * LPDY; - double p2d = S1DY * LPDX - S1DX * LPDY; - if ((d < 0) && (p1d < d || p1d > 0 || p2d < d || p2d > 0)) - return false; // intersection not within segment1 - if ((d > 0) && (p1d < 0 || p1d > d || p2d < 0 || p2d > d)) - return false; // intersection not within segment2 - double t = p1d / d; - intersection = IntPoint(long(s1p1.X + S1DX * t), long(s1p1.Y + S1DY * t)); - return true; + double LPDX = double(s1p1.X - s2p1.X); + double LPDY = double(s1p1.Y - s2p1.Y); + double p1d = S2DY * LPDX - S2DX * LPDY; + double p2d = S1DY * LPDX - S1DX * LPDY; + if ((d < 0) && (p1d < d || p1d > 0 || p2d < d || p2d > 0)) { + return false; // intersection not within segment1 + } + if ((d > 0) && (p1d < 0 || p1d > d || p2d < 0 || p2d > d)) { + return false; // intersection not within segment2 + } + double t = p1d / d; + intersection = IntPoint(long(s1p1.X + S1DX * t), long(s1p1.Y + S1DY * t)); + return true; } /* finds one/first intersection of line segment with paths */ -bool IntersectionPoint(const Paths &paths, const IntPoint &p1, const IntPoint &p2, IntPoint &intersection) +bool IntersectionPoint(const Paths& paths, + const IntPoint& p1, + const IntPoint& p2, + IntPoint& intersection) { - BoundBox segBB(p1, p2); - for (size_t i = 0; i < paths.size(); i++) - { - const Path *path = &paths[i]; - size_t size = path->size(); - if (size < 2) - continue; - BoundBox pathBB(path->front()); - for (size_t j = 0; j < size; j++) - { + BoundBox segBB(p1, p2); + for (size_t i = 0; i < paths.size(); i++) { + const Path* path = &paths[i]; + size_t size = path->size(); + if (size < 2) { + continue; + } + BoundBox pathBB(path->front()); + for (size_t j = 0; j < size; j++) { - const IntPoint *pp2 = &path->at(j); + const IntPoint* pp2 = &path->at(j); - // box check for performance - pathBB.AddPoint(*pp2); - if (!pathBB.CollidesWith(segBB)) - continue; + // box check for performance + pathBB.AddPoint(*pp2); + if (!pathBB.CollidesWith(segBB)) { + continue; + } - const IntPoint *pp1 = &path->at(j > 0 ? j - 1 : size - 1); - double LDY = double(p2.Y - p1.Y); - double LDX = double(p2.X - p1.X); - double PDX = double(pp2->X - pp1->X); - double PDY = double(pp2->Y - pp1->Y); - double d = LDY * PDX - PDY * LDX; - if (fabs(d) < NTOL) - continue; // lines are parallel + const IntPoint* pp1 = &path->at(j > 0 ? j - 1 : size - 1); + double LDY = double(p2.Y - p1.Y); + double LDX = double(p2.X - p1.X); + double PDX = double(pp2->X - pp1->X); + double PDY = double(pp2->Y - pp1->Y); + double d = LDY * PDX - PDY * LDX; + if (fabs(d) < NTOL) { + continue; // lines are parallel + } - double LPDX = double(p1.X - pp1->X); - double LPDY = double(p1.Y - pp1->Y); - double p1d = PDY * LPDX - PDX * LPDY; - double p2d = LDY * LPDX - LDX * LPDY; - if ((d < 0) && (p1d < d || p1d > 0 || p2d < d || p2d > 0)) - continue; // intersection not within segment - if ((d > 0) && (p1d < 0 || p1d > d || p2d < 0 || p2d > d)) - continue; // intersection not within segment - double t = p1d / d; - intersection = IntPoint(long(p1.X + LDX * t), long(p1.Y + LDY * t)); - return true; - } - } - return false; + double LPDX = double(p1.X - pp1->X); + double LPDY = double(p1.Y - pp1->Y); + double p1d = PDY * LPDX - PDX * LPDY; + double p2d = LDY * LPDX - LDX * LPDY; + if ((d < 0) && (p1d < d || p1d > 0 || p2d < d || p2d > 0)) { + continue; // intersection not within segment + } + if ((d > 0) && (p1d < 0 || p1d > d || p2d < 0 || p2d > d)) { + continue; // intersection not within segment + } + double t = p1d / d; + intersection = IntPoint(long(p1.X + LDX * t), long(p1.Y + LDY * t)); + return true; + } + } + return false; } -void SmoothPaths(Paths &paths, double stepSize, long pointCount, long iterations) +void SmoothPaths(Paths& paths, double stepSize, long pointCount, long iterations) { - Paths output; - output.resize(paths.size()); - const long scale=1000; - const double stepScaled = stepSize*scale; + Paths output; + output.resize(paths.size()); + const long scale = 1000; + const double stepScaled = stepSize * scale; - ScaleUpPaths(paths,scale); - vector> points; - for (size_t i = 0; i < paths.size(); i++) - { - for (const auto &pt : paths[i]) - { - if (points.empty()) - { - points.emplace_back(i, pt); - continue; - } - const auto back=points.back(); - const IntPoint & lastPt = back.second; + ScaleUpPaths(paths, scale); + vector> points; + for (size_t i = 0; i < paths.size(); i++) { + for (const auto& pt : paths[i]) { + if (points.empty()) { + points.emplace_back(i, pt); + continue; + } + const auto back = points.back(); + const IntPoint& lastPt = back.second; - const double l = sqrt(DistanceSqrd(lastPt, pt)); + const double l = sqrt(DistanceSqrd(lastPt, pt)); - if (l < 0.5*stepScaled ) - { - if(points.size()>1) points.pop_back(); - points.emplace_back(i, pt); - continue; - } - size_t lastPathIndex = back.first; - const long steps = max(long(l / stepScaled),1L); - const long left=pointCount*iterations*2; - const long right =steps-pointCount*iterations*2; - for (long idx = 0; idx <= steps; idx++) - { - if(idx>left && idx 1) { + points.pop_back(); + } + points.emplace_back(i, pt); + continue; + } + size_t lastPathIndex = back.first; + const long steps = max(long(l / stepScaled), 1L); + const long left = pointCount * iterations * 2; + const long right = steps - pointCount * iterations * 2; + for (long idx = 0; idx <= steps; idx++) { + if (idx > left && idx < right) { + idx = right; + continue; + } + const double p = double(idx) / steps; + const IntPoint ptx(long(lastPt.X + double(pt.X - lastPt.X) * p), + long(lastPt.Y + double(pt.Y - lastPt.Y) * p)); - if(idx==0 && DistanceSqrd(back.second,ptx)1) points.pop_back(); + if (idx == 0 && DistanceSqrd(back.second, ptx) < scale && points.size() > 1) { + points.pop_back(); + } - if (p < 0.5) - points.emplace_back(lastPathIndex, ptx); - else - points.emplace_back(i, ptx); - } - } - } - if (points.empty()) - return; - const long size=long(points.size()); - for(long iter=0;iter= size-1) - ptsToAverage = size-1-i; - for (long j = i-ptsToAverage; j <= i+ptsToAverage; j++) - { - if (j == i) continue; - long index=j; - if(index<0) index=0; - if(index>=size) index=size-1; - IntPoint &p = points[index].second; - avgPoint.X += p.X ; - avgPoint.Y += p.Y ; - cnt++; - } - cp.X=avgPoint.X/cnt; - cp.Y=avgPoint.Y/cnt; - } - } + long ptsToAverage = pointCount; + if (i <= ptsToAverage) { + ptsToAverage = max(i - 1, 0L); + } + else if (i + ptsToAverage >= size - 1) { + ptsToAverage = size - 1 - i; + } + for (long j = i - ptsToAverage; j <= i + ptsToAverage; j++) { + if (j == i) { + continue; + } + long index = j; + if (index < 0) { + index = 0; + } + if (index >= size) { + index = size - 1; + } + IntPoint& p = points[index].second; + avgPoint.X += p.X; + avgPoint.Y += p.Y; + cnt++; + } + cp.X = avgPoint.X / cnt; + cp.Y = avgPoint.Y / cnt; + } + } - for (const auto &pr:points) - { - output[pr.first].push_back(pr.second); - } - for (size_t i = 0; i < paths.size(); i++) - { - CleanPath(output[i], paths[i], 1.4*scale); - } - ScaleDownPaths(paths,scale); + for (const auto& pr : points) { + output[pr.first].push_back(pr.second); + } + for (size_t i = 0; i < paths.size(); i++) { + CleanPath(output[i], paths[i], 1.4 * scale); + } + ScaleDownPaths(paths, scale); } -bool PopPathWithClosestPoint(Paths &paths /*closest path is removed from collection and shifted to start with closest point */ - , - IntPoint p1, Path &result) +bool PopPathWithClosestPoint(Paths& paths /*closest path is removed from collection and shifted to + start with closest point */ + , + IntPoint p1, + Path& result) { - if (paths.empty()) - return false; + if (paths.empty()) { + return false; + } - double minDistSqrd = __DBL_MAX__; - size_t closestPathIndex = 0; - long closestPointIndex = 0; - for (size_t pathIndex = 0; pathIndex < paths.size(); pathIndex++) - { - Path &path = paths.at(pathIndex); - for (size_t i = 0; i < path.size(); i++) - { - double dist = DistanceSqrd(p1, path.at(i)); - if (dist < minDistSqrd) - { - minDistSqrd = dist; - closestPathIndex = pathIndex; - closestPointIndex = long(i); - } - } - } + double minDistSqrd = __DBL_MAX__; + size_t closestPathIndex = 0; + long closestPointIndex = 0; + for (size_t pathIndex = 0; pathIndex < paths.size(); pathIndex++) { + Path& path = paths.at(pathIndex); + for (size_t i = 0; i < path.size(); i++) { + double dist = DistanceSqrd(p1, path.at(i)); + if (dist < minDistSqrd) { + minDistSqrd = dist; + closestPathIndex = pathIndex; + closestPointIndex = long(i); + } + } + } - result.clear(); - // make new path starting with that point - Path &closestPath = paths.at(closestPathIndex); - for (size_t i = 0; i < closestPath.size(); i++) - { - long index = closestPointIndex + long(i); - if (index >= long(closestPath.size())) - index -= long(closestPath.size()); - result.push_back(closestPath.at(index)); - } - // remove the closest path - paths.erase(paths.begin() + closestPathIndex); - return true; + result.clear(); + // make new path starting with that point + Path& closestPath = paths.at(closestPathIndex); + for (size_t i = 0; i < closestPath.size(); i++) { + long index = closestPointIndex + long(i); + if (index >= long(closestPath.size())) { + index -= long(closestPath.size()); + } + result.push_back(closestPath.at(index)); + } + // remove the closest path + paths.erase(paths.begin() + closestPathIndex); + return true; } -void DeduplicatePaths(const Paths &inputs, Paths &outputs) +void DeduplicatePaths(const Paths& inputs, Paths& outputs) { - outputs.clear(); - for (const auto &new_pth : inputs) - { - bool duplicate = false; - // if all points of new path exist on some of the old paths, path is considered duplicate - for (const auto &old_pth : outputs) - { - bool all_points_exists = true; - for (const auto pt1 : new_pth) - { - bool pointExists = false; - for (const auto pt2 : old_pth) - { - if (DistanceSqrd(pt1, pt2) < SAME_POINT_TOL_SQRD_SCALED) - { - pointExists = true; - break; - } - } - if (!pointExists) - { - all_points_exists = false; - break; - } - } - if (all_points_exists) - { - duplicate = true; - break; - } - } + outputs.clear(); + for (const auto& new_pth : inputs) { + bool duplicate = false; + // if all points of new path exist on some of the old paths, path is considered duplicate + for (const auto& old_pth : outputs) { + bool all_points_exists = true; + for (const auto pt1 : new_pth) { + bool pointExists = false; + for (const auto pt2 : old_pth) { + if (DistanceSqrd(pt1, pt2) < SAME_POINT_TOL_SQRD_SCALED) { + pointExists = true; + break; + } + } + if (!pointExists) { + all_points_exists = false; + break; + } + } + if (all_points_exists) { + duplicate = true; + break; + } + } - if (!duplicate && !new_pth.empty()) - { - outputs.push_back(new_pth); - } - } + if (!duplicate && !new_pth.empty()) { + outputs.push_back(new_pth); + } + } } -void ConnectPaths(Paths input, Paths &output) +void ConnectPaths(Paths input, Paths& output) { - output.clear(); - bool newPath = true; - Path joined; - while (!input.empty()) - { - if (newPath) - { - if (!joined.empty()) - output.push_back(joined); - joined.clear(); - for (auto pt : input.front()) - { - joined.push_back(pt); - } - input.erase(input.begin()); - newPath = false; - } - bool anyMatch = false; - for (size_t i = 0; i < input.size(); i++) - { - Path &n = input.at(i); - if (DistanceSqrd(n.front(), joined.back()) < SAME_POINT_TOL_SQRD_SCALED) - { - for (auto pt : n) - joined.push_back(pt); - input.erase(input.begin() + i); - anyMatch = true; - break; - } - else if (DistanceSqrd(n.back(), joined.back()) < SAME_POINT_TOL_SQRD_SCALED) - { - ReversePath(n); - for (auto pt : n) - joined.push_back(pt); - input.erase(input.begin() + i); - anyMatch = true; - break; - } - else if (DistanceSqrd(n.front(), joined.front()) < SAME_POINT_TOL_SQRD_SCALED) - { - for (auto pt : n) - joined.insert(joined.begin(), pt); - input.erase(input.begin() + i); - anyMatch = true; - break; - } - else if (DistanceSqrd(n.back(), joined.front()) < SAME_POINT_TOL_SQRD_SCALED) - { - ReversePath(n); - for (auto pt : n) - joined.insert(joined.begin(), pt); - input.erase(input.begin() + i); - anyMatch = true; - break; - } - } - if (!anyMatch) - newPath = true; - } - if (!joined.empty()) - output.push_back(joined); + output.clear(); + bool newPath = true; + Path joined; + while (!input.empty()) { + if (newPath) { + if (!joined.empty()) { + output.push_back(joined); + } + joined.clear(); + for (auto pt : input.front()) { + joined.push_back(pt); + } + input.erase(input.begin()); + newPath = false; + } + bool anyMatch = false; + for (size_t i = 0; i < input.size(); i++) { + Path& n = input.at(i); + if (DistanceSqrd(n.front(), joined.back()) < SAME_POINT_TOL_SQRD_SCALED) { + for (auto pt : n) { + joined.push_back(pt); + } + input.erase(input.begin() + i); + anyMatch = true; + break; + } + else if (DistanceSqrd(n.back(), joined.back()) < SAME_POINT_TOL_SQRD_SCALED) { + ReversePath(n); + for (auto pt : n) { + joined.push_back(pt); + } + input.erase(input.begin() + i); + anyMatch = true; + break; + } + else if (DistanceSqrd(n.front(), joined.front()) < SAME_POINT_TOL_SQRD_SCALED) { + for (auto pt : n) { + joined.insert(joined.begin(), pt); + } + input.erase(input.begin() + i); + anyMatch = true; + break; + } + else if (DistanceSqrd(n.back(), joined.front()) < SAME_POINT_TOL_SQRD_SCALED) { + ReversePath(n); + for (auto pt : n) { + joined.insert(joined.begin(), pt); + } + input.erase(input.begin() + i); + anyMatch = true; + break; + } + } + if (!anyMatch) { + newPath = true; + } + } + if (!joined.empty()) { + output.push_back(joined); + } } // helper class for measuring performance class PerfCounter { - public: - PerfCounter(string p_name) - { - name = p_name; - count = 0; - running = false; - start_ticks = 0; - total_ticks = 0; - } - inline void Start() - { +public: + PerfCounter(string p_name) + { + name = p_name; + count = 0; + running = false; + start_ticks = 0; + total_ticks = 0; + } + inline void Start() + { #ifdef DEV_MODE - start_ticks = clock(); - if (running) - { - cerr << "PerfCounter already running:" << name << endl; - } - running = true; + start_ticks = clock(); + if (running) { + cerr << "PerfCounter already running:" << name << endl; + } + running = true; #endif - } - inline void Stop() - { + } + inline void Stop() + { #ifdef DEV_MODE - if (!running) - { - cerr << "PerfCounter not running:" << name << endl; - } - total_ticks += clock() - start_ticks; - start_ticks = clock(); - count++; - running = false; + if (!running) { + cerr << "PerfCounter not running:" << name << endl; + } + total_ticks += clock() - start_ticks; + start_ticks = clock(); + count++; + running = false; #endif - } - void DumpResults() - { - double total_time = double(total_ticks) / CLOCKS_PER_SEC; - cout << "Perf: " << name.c_str() << " total_time: " << total_time << " sec, call_count:" << count << " per_call:" << double(total_time / count) << endl; - start_ticks = clock(); - total_ticks = 0; - count = 0; - } + } + void DumpResults() + { + double total_time = double(total_ticks) / CLOCKS_PER_SEC; + cout << "Perf: " << name.c_str() << " total_time: " << total_time + << " sec, call_count:" << count << " per_call:" << double(total_time / count) << endl; + start_ticks = clock(); + total_ticks = 0; + count = 0; + } - private: - string name; - clock_t start_ticks; - clock_t total_ticks; - size_t count; - bool running = false; +private: + string name; + clock_t start_ticks; + clock_t total_ticks; + size_t count; + bool running = false; }; PerfCounter Perf_ProcessPolyNode("ProcessPolyNode"); @@ -935,136 +963,131 @@ PerfCounter Perf_IsClearPath("IsClearPath"); //*********************************** class ClearedArea { - public: - ClearedArea(ClipperLib::cInt p_toolRadiusScaled) - { - toolRadiusScaled = p_toolRadiusScaled; - }; +public: + ClearedArea(ClipperLib::cInt p_toolRadiusScaled) + { + toolRadiusScaled = p_toolRadiusScaled; + }; - void SetClearedPaths(const Paths &paths) - { - clearedPaths = paths; - bboxPathsInvalid = true; - bboxClippedInvalid = true; - } - void ExpandCleared(const Path toClearToolPath) - { - if (toClearToolPath.empty()) - return; - Perf_ExpandCleared.Start(); - clipof.Clear(); - clipof.AddPath(toClearToolPath, JoinType::jtRound, EndType::etOpenRound); - Paths toolCoverPoly; - clipof.Execute(toolCoverPoly, toolRadiusScaled + 1); - clip.Clear(); - clip.AddPaths(clearedPaths, PolyType::ptSubject, true); - clip.AddPaths(toolCoverPoly, PolyType::ptClip, true); - clip.Execute(ClipType::ctUnion, clearedPaths); - CleanPolygons(clearedPaths); - bboxPathsInvalid = true; - bboxClippedInvalid = true; - Perf_ExpandCleared.Stop(); - } + void SetClearedPaths(const Paths& paths) + { + clearedPaths = paths; + bboxPathsInvalid = true; + bboxClippedInvalid = true; + } + void ExpandCleared(const Path toClearToolPath) + { + if (toClearToolPath.empty()) { + return; + } + Perf_ExpandCleared.Start(); + clipof.Clear(); + clipof.AddPath(toClearToolPath, JoinType::jtRound, EndType::etOpenRound); + Paths toolCoverPoly; + clipof.Execute(toolCoverPoly, toolRadiusScaled + 1); + clip.Clear(); + clip.AddPaths(clearedPaths, PolyType::ptSubject, true); + clip.AddPaths(toolCoverPoly, PolyType::ptClip, true); + clip.Execute(ClipType::ctUnion, clearedPaths); + CleanPolygons(clearedPaths); + bboxPathsInvalid = true; + bboxClippedInvalid = true; + Perf_ExpandCleared.Stop(); + } - // gets the path sections inside the ext. tool bounding box - Paths &GetBoundedClearedPaths(const IntPoint &toolPos) - { - BoundBox toolBB(toolPos, toolRadiusScaled); - if (!bboxPathsInvalid && clearedBBPathsInFocus.Contains(toolBB)) - { - return clearedBoundedPaths; - } - ClipperLib::cInt delta = focusBBFactor1 * toolRadiusScaled; - clearedBBPathsInFocus.SetFirstPoint(IntPoint(toolPos.X - delta, toolPos.Y - delta)); - clearedBBPathsInFocus.AddPoint(IntPoint(toolPos.X + delta, toolPos.Y + delta)); + // gets the path sections inside the ext. tool bounding box + Paths& GetBoundedClearedPaths(const IntPoint& toolPos) + { + BoundBox toolBB(toolPos, toolRadiusScaled); + if (!bboxPathsInvalid && clearedBBPathsInFocus.Contains(toolBB)) { + return clearedBoundedPaths; + } + ClipperLib::cInt delta = focusBBFactor1 * toolRadiusScaled; + clearedBBPathsInFocus.SetFirstPoint(IntPoint(toolPos.X - delta, toolPos.Y - delta)); + clearedBBPathsInFocus.AddPoint(IntPoint(toolPos.X + delta, toolPos.Y + delta)); - BoundBox bb(toolPos, focusBBFactor2 * toolRadiusScaled); - clearedBoundedPaths.clear(); - for (const auto &pth : clearedPaths) - { - if (pth.size() < 2) - continue; - Path bPath; - size_t size = pth.size(); - for (size_t i = 0; i < size + 1; i++) - { - IntPoint last = (i > 0 ? pth[i - 1] : pth.back()); - IntPoint next = i < size ? pth[i] : pth.front(); - BoundBox ptbox(last, next); - if (ptbox.CollidesWith(bb)) - { - if (bPath.empty() || bPath.back() != last) - bPath.push_back(last); - bPath.push_back(next); - } - else - { - if (!bPath.empty()) - { - clearedBoundedPaths.push_back(bPath); - bPath.clear(); - } - } - } - if (!bPath.empty()) - { - clearedBoundedPaths.push_back(bPath); - bPath.clear(); - } - } - bboxPathsInvalid = false; - return clearedBoundedPaths; - } + BoundBox bb(toolPos, focusBBFactor2 * toolRadiusScaled); + clearedBoundedPaths.clear(); + for (const auto& pth : clearedPaths) { + if (pth.size() < 2) { + continue; + } + Path bPath; + size_t size = pth.size(); + for (size_t i = 0; i < size + 1; i++) { + IntPoint last = (i > 0 ? pth[i - 1] : pth.back()); + IntPoint next = i < size ? pth[i] : pth.front(); + BoundBox ptbox(last, next); + if (ptbox.CollidesWith(bb)) { + if (bPath.empty() || bPath.back() != last) { + bPath.push_back(last); + } + bPath.push_back(next); + } + else { + if (!bPath.empty()) { + clearedBoundedPaths.push_back(bPath); + bPath.clear(); + } + } + } + if (!bPath.empty()) { + clearedBoundedPaths.push_back(bPath); + bPath.clear(); + } + } + bboxPathsInvalid = false; + return clearedBoundedPaths; + } - // get cleared area/poly bounded to toolbox - Paths &GetBoundedClearedAreaClipped(const IntPoint &toolPos) - { - BoundBox toolBB(toolPos, toolRadiusScaled); - if (!bboxClippedInvalid && clearedBBClippedInFocus.Contains(toolBB)) - { - return clearedBoundedClipped; - } - ClipperLib::cInt delta = focusBBFactor1 * toolRadiusScaled; - clearedBBClippedInFocus.SetFirstPoint(IntPoint(toolPos.X - delta, toolPos.Y - delta)); - clearedBBClippedInFocus.AddPoint(IntPoint(toolPos.X + delta, toolPos.Y + delta)); + // get cleared area/poly bounded to toolbox + Paths& GetBoundedClearedAreaClipped(const IntPoint& toolPos) + { + BoundBox toolBB(toolPos, toolRadiusScaled); + if (!bboxClippedInvalid && clearedBBClippedInFocus.Contains(toolBB)) { + return clearedBoundedClipped; + } + ClipperLib::cInt delta = focusBBFactor1 * toolRadiusScaled; + clearedBBClippedInFocus.SetFirstPoint(IntPoint(toolPos.X - delta, toolPos.Y - delta)); + clearedBBClippedInFocus.AddPoint(IntPoint(toolPos.X + delta, toolPos.Y + delta)); - // a little larger area is bounded than checked - ClipperLib::cInt delta2 = focusBBFactor2 * toolRadiusScaled; - Path bbPath; - bbPath.push_back(IntPoint(toolPos.X - delta2, toolPos.Y - delta2)); - bbPath.push_back(IntPoint(toolPos.X + delta2, toolPos.Y - delta2)); - bbPath.push_back(IntPoint(toolPos.X + delta2, toolPos.Y + delta2)); - bbPath.push_back(IntPoint(toolPos.X - delta2, toolPos.Y + delta2)); - clip.Clear(); - clip.AddPath(bbPath, PolyType::ptSubject, true); - clip.AddPaths(clearedPaths, PolyType::ptClip, true); - clip.Execute(ClipType::ctIntersection, clearedBoundedClipped); - bboxClippedInvalid = false; - return clearedBoundedClipped; - } + // a little larger area is bounded than checked + ClipperLib::cInt delta2 = focusBBFactor2 * toolRadiusScaled; + Path bbPath; + bbPath.push_back(IntPoint(toolPos.X - delta2, toolPos.Y - delta2)); + bbPath.push_back(IntPoint(toolPos.X + delta2, toolPos.Y - delta2)); + bbPath.push_back(IntPoint(toolPos.X + delta2, toolPos.Y + delta2)); + bbPath.push_back(IntPoint(toolPos.X - delta2, toolPos.Y + delta2)); + clip.Clear(); + clip.AddPath(bbPath, PolyType::ptSubject, true); + clip.AddPaths(clearedPaths, PolyType::ptClip, true); + clip.Execute(ClipType::ctIntersection, clearedBoundedClipped); + bboxClippedInvalid = false; + return clearedBoundedClipped; + } - // get full cleared area - Paths &GetCleared() - { - return clearedPaths; - } + // get full cleared area + Paths& GetCleared() + { + return clearedPaths; + } - private: - Clipper clip; - ClipperOffset clipof; - Paths clearedPaths; - Paths clearedBoundedClipped; - Paths clearedBoundedPaths; +private: + Clipper clip; + ClipperOffset clipof; + Paths clearedPaths; + Paths clearedBoundedClipped; + Paths clearedBoundedPaths; - ClipperLib::cInt toolRadiusScaled; - BoundBox clearedBBClippedInFocus; - BoundBox clearedBBPathsInFocus; + ClipperLib::cInt toolRadiusScaled; + BoundBox clearedBBClippedInFocus; + BoundBox clearedBBPathsInFocus; - bool bboxClippedInvalid = false; - bool bboxPathsInvalid = false; - // size of the focus BB - const ClipperLib::cInt focusBBFactor1 = 8; - const ClipperLib::cInt focusBBFactor2 = 9; + bool bboxClippedInvalid = false; + bool bboxPathsInvalid = false; + // size of the focus BB + const ClipperLib::cInt focusBBFactor1 = 8; + const ClipperLib::cInt focusBBFactor2 = 9; }; //*************************************** @@ -1072,79 +1095,78 @@ class ClearedArea //*************************************** class Interpolation { - public: - const double MIN_ANGLE = -M_PI / 4; - const double MAX_ANGLE = M_PI / 4; +public: + const double MIN_ANGLE = -M_PI / 4; + const double MAX_ANGLE = M_PI / 4; - void clear() - { - angles.clear(); - areas.clear(); - } - // adds point keeping the incremental order of areas for interpolation to work correctly - void addPoint(double area, double angle) - { - std::size_t size = areas.size(); - if (size == 0 || area > areas[size - 1] + NTOL) - { // first point or largest area point - areas.push_back(area); - angles.push_back(angle); - return; - } + void clear() + { + angles.clear(); + areas.clear(); + } + // adds point keeping the incremental order of areas for interpolation to work correctly + void addPoint(double area, double angle) + { + std::size_t size = areas.size(); + if (size == 0 || area > areas[size - 1] + NTOL) { // first point or largest area point + areas.push_back(area); + angles.push_back(angle); + return; + } - for (std::size_t i = 0; i < size; i++) - { - if (area < areas[i] - NTOL && (i == 0 || area > areas[i - 1] + NTOL)) - { - areas.insert(areas.begin() + i, area); - angles.insert(angles.begin() + i, angle); - } - } - } + for (std::size_t i = 0; i < size; i++) { + if (area < areas[i] - NTOL && (i == 0 || area > areas[i - 1] + NTOL)) { + areas.insert(areas.begin() + i, area); + angles.insert(angles.begin() + i, angle); + } + } + } - double interpolateAngle(double targetArea) - { - std::size_t size = areas.size(); - if (size < 2 || targetArea > areas[size - 1]) - return MIN_ANGLE; //max engage angle - convenient value to initially measure cut area - if (targetArea < areas[0]) - return MAX_ANGLE; // min engage angle + double interpolateAngle(double targetArea) + { + std::size_t size = areas.size(); + if (size < 2 || targetArea > areas[size - 1]) { + return MIN_ANGLE; // max engage angle - convenient value to initially measure cut area + } + if (targetArea < areas[0]) { + return MAX_ANGLE; // min engage angle + } - for (size_t i = 1; i < size; i++) - { - // find 2 subsequent points where target area is between - if (areas[i - 1] <= targetArea && areas[i] > targetArea) - { - // linear interpolation - double af = (targetArea - areas[i - 1]) / (areas[i] - areas[i - 1]); - double a = angles[i - 1] + af * (angles[i] - angles[i - 1]); - return a; - } - } - return MIN_ANGLE; - } + for (size_t i = 1; i < size; i++) { + // find 2 subsequent points where target area is between + if (areas[i - 1] <= targetArea && areas[i] > targetArea) { + // linear interpolation + double af = (targetArea - areas[i - 1]) / (areas[i] - areas[i - 1]); + double a = angles[i - 1] + af * (angles[i] - angles[i - 1]); + return a; + } + } + return MIN_ANGLE; + } - double clampAngle(double angle) - { - if (angle < MIN_ANGLE) - return MIN_ANGLE; - if (angle > MAX_ANGLE) - return MAX_ANGLE; - return angle; - } + double clampAngle(double angle) + { + if (angle < MIN_ANGLE) { + return MIN_ANGLE; + } + if (angle > MAX_ANGLE) { + return MAX_ANGLE; + } + return angle; + } - double getRandomAngle() - { - return MIN_ANGLE + (MAX_ANGLE - MIN_ANGLE) * double(rand()) / double(RAND_MAX); - } - size_t getPointCount() - { - return areas.size(); - } + double getRandomAngle() + { + return MIN_ANGLE + (MAX_ANGLE - MIN_ANGLE) * double(rand()) / double(RAND_MAX); + } + size_t getPointCount() + { + return areas.size(); + } - private: - vector angles; - vector areas; +private: + vector angles; + vector areas; }; //*************************************** @@ -1153,215 +1175,215 @@ class Interpolation class EngagePoint { - public: - struct EngageState - { - size_t currentPathIndex = 0; - size_t currentSegmentIndex = 0; - double segmentPos = 0; - double totalDistance = 0; - double currentPathLength = 0; - int passes = 0; +public: + struct EngageState + { + size_t currentPathIndex = 0; + size_t currentSegmentIndex = 0; + double segmentPos = 0; + double totalDistance = 0; + double currentPathLength = 0; + int passes = 0; - double metric = 0; // engage point metric + double metric = 0; // engage point metric - bool operator<(const EngageState &other) const - { - return (metric < other.metric); - } - }; - EngagePoint(const Paths &p_toolBoundPaths) - { - SetPaths(p_toolBoundPaths); + bool operator<(const EngageState& other) const + { + return (metric < other.metric); + } + }; + EngagePoint(const Paths& p_toolBoundPaths) + { + SetPaths(p_toolBoundPaths); - state.currentPathIndex = 0; - state.currentSegmentIndex = 0; - state.segmentPos = 0; - state.totalDistance = 0; - calculateCurrentPathLength(); - } + state.currentPathIndex = 0; + state.currentSegmentIndex = 0; + state.segmentPos = 0; + state.totalDistance = 0; + calculateCurrentPathLength(); + } - void SetPaths(const Paths &paths) - { - toolBoundPaths = paths; - state.currentPathIndex = 0; - state.currentSegmentIndex = 0; - state.segmentPos = 0; - state.totalDistance = 0; - state.passes = 0; - calculateCurrentPathLength(); - } + void SetPaths(const Paths& paths) + { + toolBoundPaths = paths; + state.currentPathIndex = 0; + state.currentSegmentIndex = 0; + state.segmentPos = 0; + state.totalDistance = 0; + state.passes = 0; + calculateCurrentPathLength(); + } - EngageState GetState() - { - return state; - } + EngageState GetState() + { + return state; + } - void SetState(const EngageState &new_state) - { - state = new_state; - } + void SetState(const EngageState& new_state) + { + state = new_state; + } - void ResetPasses() - { - state.passes = 0; - } - void moveToClosestPoint(const IntPoint &pt, double step) - { + void ResetPasses() + { + state.passes = 0; + } + void moveToClosestPoint(const IntPoint& pt, double step) + { - Path result; - IntPoint current = pt; - // chain paths according to distance in between - Paths toChain = toolBoundPaths; - toolBoundPaths.clear(); - // if(toChain.size()>0) { - // toolBoundPaths.push_back(toChain.front()); - // toChain.erase(toChain.begin()); - // } - while (PopPathWithClosestPoint(toChain, current, result)) - { - toolBoundPaths.push_back(result); - if (!result.empty()) - current = result.back(); - } + Path result; + IntPoint current = pt; + // chain paths according to distance in between + Paths toChain = toolBoundPaths; + toolBoundPaths.clear(); + // if(toChain.size()>0) { + // toolBoundPaths.push_back(toChain.front()); + // toChain.erase(toChain.begin()); + // } + while (PopPathWithClosestPoint(toChain, current, result)) { + toolBoundPaths.push_back(result); + if (!result.empty()) { + current = result.back(); + } + } - double minDistSq = __DBL_MAX__; - size_t minPathIndex = state.currentPathIndex; - size_t minSegmentIndex = state.currentSegmentIndex; - double minSegmentPos = state.segmentPos; - state.totalDistance = 0; - for (;;) - { - while (moveForward(step)) - { - double distSqrd = DistanceSqrd(pt, getCurrentPoint()); - if (distSqrd < minDistSq) - { - minDistSq = distSqrd; - minPathIndex = state.currentPathIndex; - minSegmentIndex = state.currentSegmentIndex; - minSegmentPos = state.segmentPos; - } - } - if (!nextPath()) - break; - } - state.currentPathIndex = minPathIndex; - state.currentSegmentIndex = minSegmentIndex; - state.segmentPos = minSegmentPos; - calculateCurrentPathLength(); - ResetPasses(); - } - bool nextEngagePoint(Adaptive2d *parent, ClearedArea &clearedArea, double step, double minCutArea, double maxCutArea, int maxPases = 2) - { - Perf_NextEngagePoint.Start(); - double prevArea = 0; // we want to make sure that we catch the point where the area is on raising slope - IntPoint initialPoint(-1000000000, -1000000000); - for (;;) - { - if (!moveForward(step)) - { - if (!nextPath()) - { - state.passes++; - if (state.passes >= maxPases) - { - Perf_NextEngagePoint.Stop(); - return false; // nothing more to cut - } - prevArea = 0; - } - } - IntPoint cpt = getCurrentPoint(); - double area = parent->CalcCutArea(clip, initialPoint, cpt, clearedArea); - if (area > minCutArea && area < maxCutArea && area > prevArea) - { - Perf_NextEngagePoint.Stop(); - return true; - } - prevArea = area; - } - } - IntPoint getCurrentPoint() - { - const Path *pth = &toolBoundPaths.at(state.currentPathIndex); - const IntPoint *p1 = &pth->at(state.currentSegmentIndex > 0 ? state.currentSegmentIndex - 1 : pth->size() - 1); - const IntPoint *p2 = &pth->at(state.currentSegmentIndex); - double segLength = sqrt(DistanceSqrd(*p1, *p2)); - return IntPoint(long(p1->X + state.segmentPos * double(p2->X - p1->X) / segLength), long(p1->Y + state.segmentPos * double(p2->Y - p1->Y) / segLength)); - } + double minDistSq = __DBL_MAX__; + size_t minPathIndex = state.currentPathIndex; + size_t minSegmentIndex = state.currentSegmentIndex; + double minSegmentPos = state.segmentPos; + state.totalDistance = 0; + for (;;) { + while (moveForward(step)) { + double distSqrd = DistanceSqrd(pt, getCurrentPoint()); + if (distSqrd < minDistSq) { + minDistSq = distSqrd; + minPathIndex = state.currentPathIndex; + minSegmentIndex = state.currentSegmentIndex; + minSegmentPos = state.segmentPos; + } + } + if (!nextPath()) { + break; + } + } + state.currentPathIndex = minPathIndex; + state.currentSegmentIndex = minSegmentIndex; + state.segmentPos = minSegmentPos; + calculateCurrentPathLength(); + ResetPasses(); + } + bool nextEngagePoint(Adaptive2d* parent, + ClearedArea& clearedArea, + double step, + double minCutArea, + double maxCutArea, + int maxPases = 2) + { + Perf_NextEngagePoint.Start(); + double prevArea = + 0; // we want to make sure that we catch the point where the area is on raising slope + IntPoint initialPoint(-1000000000, -1000000000); + for (;;) { + if (!moveForward(step)) { + if (!nextPath()) { + state.passes++; + if (state.passes >= maxPases) { + Perf_NextEngagePoint.Stop(); + return false; // nothing more to cut + } + prevArea = 0; + } + } + IntPoint cpt = getCurrentPoint(); + double area = parent->CalcCutArea(clip, initialPoint, cpt, clearedArea); + if (area > minCutArea && area < maxCutArea && area > prevArea) { + Perf_NextEngagePoint.Stop(); + return true; + } + prevArea = area; + } + } + IntPoint getCurrentPoint() + { + const Path* pth = &toolBoundPaths.at(state.currentPathIndex); + const IntPoint* p1 = &pth->at(state.currentSegmentIndex > 0 ? state.currentSegmentIndex - 1 + : pth->size() - 1); + const IntPoint* p2 = &pth->at(state.currentSegmentIndex); + double segLength = sqrt(DistanceSqrd(*p1, *p2)); + return IntPoint(long(p1->X + state.segmentPos * double(p2->X - p1->X) / segLength), + long(p1->Y + state.segmentPos * double(p2->Y - p1->Y) / segLength)); + } - DoublePoint getCurrentDir() - { - const Path *pth = &toolBoundPaths.at(state.currentPathIndex); - const IntPoint *p1 = &pth->at(state.currentSegmentIndex > 0 ? state.currentSegmentIndex - 1 : pth->size() - 1); - const IntPoint *p2 = &pth->at(state.currentSegmentIndex); - double segLength = sqrt(DistanceSqrd(*p1, *p2)); - return DoublePoint(double(p2->X - p1->X) / segLength, double(p2->Y - p1->Y) / segLength); - } + DoublePoint getCurrentDir() + { + const Path* pth = &toolBoundPaths.at(state.currentPathIndex); + const IntPoint* p1 = &pth->at(state.currentSegmentIndex > 0 ? state.currentSegmentIndex - 1 + : pth->size() - 1); + const IntPoint* p2 = &pth->at(state.currentSegmentIndex); + double segLength = sqrt(DistanceSqrd(*p1, *p2)); + return DoublePoint(double(p2->X - p1->X) / segLength, double(p2->Y - p1->Y) / segLength); + } - bool moveForward(double distance) - { - const Path *pth = &toolBoundPaths.at(state.currentPathIndex); - if (distance < NTOL) - throw std::invalid_argument("distance must be positive"); - state.totalDistance += distance; - double segmentLength = currentSegmentLength(); - while (state.segmentPos + distance > segmentLength) - { - state.currentSegmentIndex++; - if (state.currentSegmentIndex >= pth->size()) - { - state.currentSegmentIndex = 0; - } - distance = distance - (segmentLength - state.segmentPos); - state.segmentPos = 0; - segmentLength = currentSegmentLength(); - } - state.segmentPos += distance; - return state.totalDistance <= 1.2 * state.currentPathLength; - } + bool moveForward(double distance) + { + const Path* pth = &toolBoundPaths.at(state.currentPathIndex); + if (distance < NTOL) { + throw std::invalid_argument("distance must be positive"); + } + state.totalDistance += distance; + double segmentLength = currentSegmentLength(); + while (state.segmentPos + distance > segmentLength) { + state.currentSegmentIndex++; + if (state.currentSegmentIndex >= pth->size()) { + state.currentSegmentIndex = 0; + } + distance = distance - (segmentLength - state.segmentPos); + state.segmentPos = 0; + segmentLength = currentSegmentLength(); + } + state.segmentPos += distance; + return state.totalDistance <= 1.2 * state.currentPathLength; + } - bool nextPath() - { - state.currentPathIndex++; - state.currentSegmentIndex = 0; - state.segmentPos = 0; - state.totalDistance = 0; - if (state.currentPathIndex >= toolBoundPaths.size()) - { - state.currentPathIndex = 0; - calculateCurrentPathLength(); - return false; - } - calculateCurrentPathLength(); - return true; - } + bool nextPath() + { + state.currentPathIndex++; + state.currentSegmentIndex = 0; + state.segmentPos = 0; + state.totalDistance = 0; + if (state.currentPathIndex >= toolBoundPaths.size()) { + state.currentPathIndex = 0; + calculateCurrentPathLength(); + return false; + } + calculateCurrentPathLength(); + return true; + } - private: - Paths toolBoundPaths; - EngageState state; - Clipper clip; - void calculateCurrentPathLength() - { - const Path *pth = &toolBoundPaths.at(state.currentPathIndex); - size_t size = pth->size(); - state.currentPathLength = 0; - for (size_t i = 0; i < size; i++) - { - const IntPoint *p1 = &pth->at(i > 0 ? i - 1 : size - 1); - const IntPoint *p2 = &pth->at(i); - state.currentPathLength += sqrt(DistanceSqrd(*p1, *p2)); - } - } +private: + Paths toolBoundPaths; + EngageState state; + Clipper clip; + void calculateCurrentPathLength() + { + const Path* pth = &toolBoundPaths.at(state.currentPathIndex); + size_t size = pth->size(); + state.currentPathLength = 0; + for (size_t i = 0; i < size; i++) { + const IntPoint* p1 = &pth->at(i > 0 ? i - 1 : size - 1); + const IntPoint* p2 = &pth->at(i); + state.currentPathLength += sqrt(DistanceSqrd(*p1, *p2)); + } + } - double currentSegmentLength() - { - const Path *pth = &toolBoundPaths.at(state.currentPathIndex); - const IntPoint *p1 = &pth->at(state.currentSegmentIndex > 0 ? state.currentSegmentIndex - 1 : pth->size() - 1); - const IntPoint *p2 = &pth->at(state.currentSegmentIndex); - return sqrt(DistanceSqrd(*p1, *p2)); - } + double currentSegmentLength() + { + const Path* pth = &toolBoundPaths.at(state.currentPathIndex); + const IntPoint* p1 = &pth->at(state.currentSegmentIndex > 0 ? state.currentSegmentIndex - 1 + : pth->size() - 1); + const IntPoint* p2 = &pth->at(state.currentSegmentIndex); + return sqrt(DistanceSqrd(*p1, *p2)); + } }; //*************************************** @@ -1369,1801 +1391,1911 @@ class EngagePoint //*************************************** Adaptive2d::Adaptive2d() +{} + +double Adaptive2d::CalcCutArea(Clipper& clip, + const IntPoint& c1, + const IntPoint& c2, + ClearedArea& clearedArea, + bool preventConventional) { + + double dist = DistanceSqrd(c1, c2); + if (dist < NTOL) { + return 0; + } + + Perf_CalcCutAreaCirc.Start(); + + /// new alg + double rsqrd = toolRadiusScaled * toolRadiusScaled; + double area = 0; + Paths interPaths; + IntPoint clp; // to hold closest point + vector inters; // to hold intersection results + BoundBox c2BB(c2, toolRadiusScaled); + BoundBox c1BB(c1, toolRadiusScaled); + Paths& clearedBounded = clearedArea.GetBoundedClearedAreaClipped(c2); + for (const Path& path : clearedBounded) { + size_t size = path.size(); + if (size == 0) { + continue; + } + + //** bound box check + // construct bound box for path + BoundBox pathBB(path.front()); + for (const auto& pt : path) { + pathBB.AddPoint(pt); + } + if (!c2BB.CollidesWith(c2)) { + continue; // this path cannot colide with tool + } + //** end of BB check + + size_t curPtIndex = 0; + bool found = false; + // step 1: we find the starting point on the cleared path that is outside new tool shape + // (c2) + for (size_t i = 0; i < size; i++) { + if (DistanceSqrd(path[curPtIndex], c2) > rsqrd) { + found = true; + break; + } + curPtIndex++; + if (curPtIndex >= size) { + curPtIndex = 0; + } + } + if (!found) { + continue; // try another path + } + + // step 2: iterate through path from starting point and find the part of the path inside the + // c2 + size_t prevPtIndex = curPtIndex; + Path* interPath = NULL; + bool prev_inside = false; + const IntPoint* p1 = &path[prevPtIndex]; + double par; // to hold parameter output + for (size_t i = 0; i < size; i++) { + curPtIndex++; + if (curPtIndex >= size) { + curPtIndex = 0; + } + const IntPoint* p2 = &path[curPtIndex]; + BoundBox segBB(*p1, *p2); + if (!prev_inside) { // prev state: outside, find first point inside C2 + if (segBB.CollidesWith(c2BB) + && DistancePointToLineSegSquared(*p1, *p2, c2, clp, par) + <= rsqrd) { // current segment inside, start + prev_inside = true; + interPaths.push_back(Path()); + if (interPaths.size() > 1) { + break; // we will use poly clipping alg. if there are more intersecting + // paths + } + interPath = &interPaths.back(); + // current segment inside c2, prev point outside, find intersection: + if (Line2CircleIntersect(c2, toolRadiusScaled, *p1, *p2, inters)) { + interPath->push_back(IntPoint(long(inters[0].X), long(inters[0].Y))); + if (inters.size() > 1) { + interPath->push_back(IntPoint(long(inters[1].X), long(inters[1].Y))); + prev_inside = false; + } + else { + interPath->push_back(IntPoint(*p2)); + } + } + else { // no intersection - must be edge case, add p2 + interPath->push_back(IntPoint(*p2)); + } + } + } + else if (interPath != NULL) { // state: inside + if ((DistanceSqrd(c2, *p2) + <= rsqrd)) { // next point still inside, add it and continue, no state change + interPath->push_back(IntPoint(*p2)); + } + else { // prev point inside, current point outside, find intersection + if (Line2CircleIntersect(c2, toolRadiusScaled, *p1, *p2, inters)) { + if (inters.size() > 1) { + interPath->push_back(IntPoint(long(inters[1].X), long(inters[1].Y))); + } + else { + interPath->push_back(IntPoint(long(inters[0].X), long(inters[0].Y))); + } + } + prev_inside = false; + } + } + prevPtIndex = curPtIndex; + p1 = p2; + } + if (interPaths.size() > 1) { + break; // we will use poly clipping alg. if there are more intersecting paths with the + // tool (rare case) + } + } + Perf_CalcCutAreaCirc.Stop(); + if (interPaths.size() == 1 && interPaths.front().size() > 1) { + Perf_CalcCutAreaCirc.Start(); + Path* interPath = &interPaths.front(); + // interPath - now contains the part of cleared path inside the C2 + size_t ipc2_size = interPath->size(); + const IntPoint& fpc2 = interPath->front(); // first point + const IntPoint& lpc2 = interPath->back(); // last point + // path length + double interPathLen = 0; + for (size_t j = 1; j < ipc2_size; j++) { + interPathLen += sqrt(DistanceSqrd(interPath->at(j - 1), interPath->at(j))); + } + + Paths inPaths; + inPaths.reserve(200); + inPaths.push_back(*interPath); + Path pthToSubtract; + pthToSubtract.push_back(fpc2); + + double fi1 = atan2(fpc2.Y - c2.Y, fpc2.X - c2.X); + double fi2 = atan2(lpc2.Y - c2.Y, lpc2.X - c2.X); + double minFi = fi1; + double maxFi = fi2; + if (maxFi < minFi) { + maxFi += 2 * M_PI; + } + + if (preventConventional && interPathLen >= RESOLUTION_FACTOR) { + // detect conventional mode cut - we want only climb mode + IntPoint midPoint(long(c2.X + toolRadiusScaled * cos(0.5 * (maxFi + minFi))), + long(c2.Y + toolRadiusScaled * sin(0.5 * (maxFi + minFi)))); + if (PointSideOfLine(c1, c2, midPoint) < 0) { + area = __DBL_MAX__; + Perf_CalcCutAreaCirc.Stop(); + // #ifdef DEV_MODE + // cout << "Break: @(" << double(c2.X)/scaleFactor << "," << + // double(c2.Y)/scaleFactor << ") conventional mode" << endl; #endif + return area; + } + } + + double scanDistance = 2.5 * toolRadiusScaled; + // stepping through path discretized to stepDistance + double stepDistance = min(double(RESOLUTION_FACTOR), interPathLen / 24) + 1; + const IntPoint* prevPt = &interPath->front(); + double distance = 0; + for (size_t j = 1; j < ipc2_size; j++) { + const IntPoint* cpt = &interPath->at(j); + double segLen = sqrt(DistanceSqrd(*cpt, *prevPt)); + if (segLen < NTOL) { + continue; // skip point - segment too short + } + for (double pos_unclamped = 0.0; pos_unclamped < segLen + stepDistance; + pos_unclamped += stepDistance) { + double pos = pos_unclamped; + if (pos > segLen) { + distance += stepDistance - (pos - segLen); + pos = segLen; // make sure we get exact end point + } + else { + distance += stepDistance; + } + double dx = double(cpt->X - prevPt->X); + double dy = double(cpt->Y - prevPt->Y); + IntPoint segPoint(long(prevPt->X + dx * pos / segLen), + long(prevPt->Y + dy * pos / segLen)); + IntPoint scanPoint( + long(c2.X + + scanDistance * cos(minFi + distance * (maxFi - minFi) / interPathLen)), + long(c2.Y + + scanDistance * sin(minFi + distance * (maxFi - minFi) / interPathLen))); + + IntPoint intersC2(segPoint.X, segPoint.Y); + IntPoint intersC1(segPoint.X, segPoint.Y); + + // there should be intersection with C2 + if (Line2CircleIntersect(c2, toolRadiusScaled, segPoint, scanPoint, inters)) { + if (inters.size() > 1) { + intersC2.X = long(inters[1].X); + intersC2.Y = long(inters[1].Y); + } + else { + intersC2.X = long(inters[0].X); + intersC2.Y = long(inters[0].Y); + } + } + else { + pthToSubtract.push_back(segPoint); + } + + if (Line2CircleIntersect(c1, toolRadiusScaled, segPoint, scanPoint, inters)) { + if (inters.size() > 1) { + intersC1.X = long(inters[1].X); + intersC1.Y = long(inters[1].Y); + } + else { + intersC1.X = long(inters[0].X); + intersC1.Y = long(inters[0].Y); + } + if (DistanceSqrd(segPoint, intersC2) < DistanceSqrd(segPoint, intersC1)) { + pthToSubtract.push_back(intersC2); + } + else { + pthToSubtract.push_back(intersC1); + } + } + else { // add the segpoint if no intersection with C1 + pthToSubtract.push_back(segPoint); + } + } + prevPt = cpt; + } + + pthToSubtract.push_back(lpc2); // add last point + pthToSubtract.push_back(c2); + + double segArea = Area(pthToSubtract); + double A = (maxFi - minFi) * rsqrd / 2; // sector area + area += A - fabs(segArea); + Perf_CalcCutAreaCirc.Stop(); + } + else if (interPaths.size() > 1) { + Perf_CalcCutAreaClip.Start(); + // old way of calculating cut area based on polygon clipping + // used in case when there are multiple intersections of tool with cleared poly (very rare + // case, but important) + // 1. find difference between old and new tool shape + Path oldTool; + Path newTool; + TranslatePath(toolGeometry, oldTool, c1); + TranslatePath(toolGeometry, newTool, c2); + clip.Clear(); + clip.AddPath(newTool, PolyType::ptSubject, true); + clip.AddPath(oldTool, PolyType::ptClip, true); + Paths toolDiff; + clip.Execute(ClipType::ctDifference, toolDiff); + + // 2. difference to cleared + clip.Clear(); + clip.AddPaths(toolDiff, PolyType::ptSubject, true); + clip.AddPaths(clearedBounded, PolyType::ptClip, true); + Paths cutAreaPoly; + clip.Execute(ClipType::ctDifference, cutAreaPoly); + + // calculate resulting area + area = 0; + for (Path& path : cutAreaPoly) { + area += fabs(Area(path)); + } + Perf_CalcCutAreaClip.Stop(); + } + return area; } -double Adaptive2d::CalcCutArea(Clipper &clip, const IntPoint &c1, const IntPoint &c2, ClearedArea &clearedArea, bool preventConventional) +void Adaptive2d::ApplyStockToLeave(Paths& inputPaths) { - - double dist = DistanceSqrd(c1, c2); - if (dist < NTOL) - return 0; - - Perf_CalcCutAreaCirc.Start(); - - /// new alg - double rsqrd = toolRadiusScaled * toolRadiusScaled; - double area = 0; - Paths interPaths; - IntPoint clp; // to hold closest point - vector inters; // to hold intersection results - BoundBox c2BB(c2, toolRadiusScaled); - BoundBox c1BB(c1, toolRadiusScaled); - Paths &clearedBounded = clearedArea.GetBoundedClearedAreaClipped(c2); - for (const Path &path : clearedBounded) - { - size_t size = path.size(); - if (size == 0) - continue; - - //** bound box check - // construct bound box for path - BoundBox pathBB(path.front()); - for (const auto &pt : path) - pathBB.AddPoint(pt); - if (!c2BB.CollidesWith(c2)) - continue; // this path cannot colide with tool - //** end of BB check - - size_t curPtIndex = 0; - bool found = false; - // step 1: we find the starting point on the cleared path that is outside new tool shape (c2) - for (size_t i = 0; i < size; i++) - { - if (DistanceSqrd(path[curPtIndex], c2) > rsqrd) - { - found = true; - break; - } - curPtIndex++; - if (curPtIndex >= size) - curPtIndex = 0; - } - if (!found) - continue; // try another path - - // step 2: iterate through path from starting point and find the part of the path inside the c2 - size_t prevPtIndex = curPtIndex; - Path *interPath = NULL; - bool prev_inside = false; - const IntPoint *p1 = &path[prevPtIndex]; - double par; // to hold parameter output - for (size_t i = 0; i < size; i++) - { - curPtIndex++; - if (curPtIndex >= size) - curPtIndex = 0; - const IntPoint *p2 = &path[curPtIndex]; - BoundBox segBB(*p1, *p2); - if (!prev_inside) - { // prev state: outside, find first point inside C2 - if (segBB.CollidesWith(c2BB) && - DistancePointToLineSegSquared(*p1, *p2, c2, clp, par) <= rsqrd) - { // current segment inside, start - prev_inside = true; - interPaths.push_back(Path()); - if (interPaths.size() > 1) - break; // we will use poly clipping alg. if there are more intersecting paths - interPath = &interPaths.back(); - // current segment inside c2, prev point outside, find intersection: - if (Line2CircleIntersect(c2, toolRadiusScaled, *p1, *p2, inters)) - { - interPath->push_back(IntPoint(long(inters[0].X), long(inters[0].Y))); - if (inters.size() > 1) - { - interPath->push_back(IntPoint(long(inters[1].X), long(inters[1].Y))); - prev_inside = false; - } - else - { - interPath->push_back(IntPoint(*p2)); - } - } - else - { // no intersection - must be edge case, add p2 - interPath->push_back(IntPoint(*p2)); - } - } - } - else if (interPath != NULL) - { // state: inside - if ((DistanceSqrd(c2, *p2) <= rsqrd)) - { // next point still inside, add it and continue, no state change - interPath->push_back(IntPoint(*p2)); - } - else - { // prev point inside, current point outside, find intersection - if (Line2CircleIntersect(c2, toolRadiusScaled, *p1, *p2, inters)) - { - if (inters.size() > 1) - { - interPath->push_back(IntPoint(long(inters[1].X), long(inters[1].Y))); - } - else - { - interPath->push_back(IntPoint(long(inters[0].X), long(inters[0].Y))); - } - } - prev_inside = false; - } - } - prevPtIndex = curPtIndex; - p1 = p2; - } - if (interPaths.size() > 1) - break; // we will use poly clipping alg. if there are more intersecting paths with the tool (rare case) - } - Perf_CalcCutAreaCirc.Stop(); - if (interPaths.size() == 1 && interPaths.front().size() > 1) - { - Perf_CalcCutAreaCirc.Start(); - Path *interPath = &interPaths.front(); - // interPath - now contains the part of cleared path inside the C2 - size_t ipc2_size = interPath->size(); - const IntPoint &fpc2 = interPath->front(); // first point - const IntPoint &lpc2 = interPath->back(); // last point - // path length - double interPathLen = 0; - for (size_t j = 1; j < ipc2_size; j++) - interPathLen += sqrt(DistanceSqrd(interPath->at(j - 1), interPath->at(j))); - - Paths inPaths; - inPaths.reserve(200); - inPaths.push_back(*interPath); - Path pthToSubtract; - pthToSubtract.push_back(fpc2); - - double fi1 = atan2(fpc2.Y - c2.Y, fpc2.X - c2.X); - double fi2 = atan2(lpc2.Y - c2.Y, lpc2.X - c2.X); - double minFi = fi1; - double maxFi = fi2; - if (maxFi < minFi) - maxFi += 2 * M_PI; - - if (preventConventional && interPathLen >= RESOLUTION_FACTOR) - { - // detect conventional mode cut - we want only climb mode - IntPoint midPoint(long(c2.X + toolRadiusScaled * cos(0.5 * (maxFi + minFi))), long(c2.Y + toolRadiusScaled * sin(0.5 * (maxFi + minFi)))); - if (PointSideOfLine(c1, c2, midPoint) < 0) - { - area = __DBL_MAX__; - Perf_CalcCutAreaCirc.Stop(); - // #ifdef DEV_MODE - // cout << "Break: @(" << double(c2.X)/scaleFactor << "," << double(c2.Y)/scaleFactor << ") conventional mode" << endl; - // #endif - return area; - } - } - - double scanDistance = 2.5 * toolRadiusScaled; - // stepping through path discretized to stepDistance - double stepDistance = min(double(RESOLUTION_FACTOR), interPathLen / 24) + 1; - const IntPoint *prevPt = &interPath->front(); - double distance = 0; - for (size_t j = 1; j < ipc2_size; j++) - { - const IntPoint *cpt = &interPath->at(j); - double segLen = sqrt(DistanceSqrd(*cpt, *prevPt)); - if (segLen < NTOL) - continue; // skip point - segment too short - for (double pos_unclamped = 0.0; pos_unclamped < segLen + stepDistance; pos_unclamped += stepDistance) - { - double pos = pos_unclamped; - if (pos > segLen) - { - distance += stepDistance - (pos - segLen); - pos = segLen; // make sure we get exact end point - } - else - { - distance += stepDistance; - } - double dx = double(cpt->X - prevPt->X); - double dy = double(cpt->Y - prevPt->Y); - IntPoint segPoint(long(prevPt->X + dx * pos / segLen), long(prevPt->Y + dy * pos / segLen)); - IntPoint scanPoint(long(c2.X + scanDistance * cos(minFi + distance * (maxFi - minFi) / interPathLen)), - long(c2.Y + scanDistance * sin(minFi + distance * (maxFi - minFi) / interPathLen))); - - IntPoint intersC2(segPoint.X, segPoint.Y); - IntPoint intersC1(segPoint.X, segPoint.Y); - - // there should be intersection with C2 - if (Line2CircleIntersect(c2, toolRadiusScaled, segPoint, scanPoint, inters)) - { - if (inters.size() > 1) - { - intersC2.X = long(inters[1].X); - intersC2.Y = long(inters[1].Y); - } - else - { - intersC2.X = long(inters[0].X); - intersC2.Y = long(inters[0].Y); - } - } - else - { - pthToSubtract.push_back(segPoint); - } - - if (Line2CircleIntersect(c1, toolRadiusScaled, segPoint, scanPoint, inters)) - { - if (inters.size() > 1) - { - intersC1.X = long(inters[1].X); - intersC1.Y = long(inters[1].Y); - } - else - { - intersC1.X = long(inters[0].X); - intersC1.Y = long(inters[0].Y); - } - if (DistanceSqrd(segPoint, intersC2) < DistanceSqrd(segPoint, intersC1)) - { - pthToSubtract.push_back(intersC2); - } - else - { - pthToSubtract.push_back(intersC1); - } - } - else - { // add the segpoint if no intersection with C1 - pthToSubtract.push_back(segPoint); - } - } - prevPt = cpt; - } - - pthToSubtract.push_back(lpc2); // add last point - pthToSubtract.push_back(c2); - - double segArea = Area(pthToSubtract); - double A = (maxFi - minFi) * rsqrd / 2; // sector area - area += A - fabs(segArea); - Perf_CalcCutAreaCirc.Stop(); - } - else if (interPaths.size() > 1) - { - Perf_CalcCutAreaClip.Start(); - // old way of calculating cut area based on polygon clipping - // used in case when there are multiple intersections of tool with cleared poly (very rare case, but important) - // 1. find difference between old and new tool shape - Path oldTool; - Path newTool; - TranslatePath(toolGeometry, oldTool, c1); - TranslatePath(toolGeometry, newTool, c2); - clip.Clear(); - clip.AddPath(newTool, PolyType::ptSubject, true); - clip.AddPath(oldTool, PolyType::ptClip, true); - Paths toolDiff; - clip.Execute(ClipType::ctDifference, toolDiff); - - // 2. difference to cleared - clip.Clear(); - clip.AddPaths(toolDiff, PolyType::ptSubject, true); - clip.AddPaths(clearedBounded, PolyType::ptClip, true); - Paths cutAreaPoly; - clip.Execute(ClipType::ctDifference, cutAreaPoly); - - // calculate resulting area - area = 0; - for (Path &path : cutAreaPoly) - { - area += fabs(Area(path)); - } - Perf_CalcCutAreaClip.Stop(); - } - return area; -} - -void Adaptive2d::ApplyStockToLeave(Paths &inputPaths) -{ - ClipperOffset clipof; - if (stockToLeave > NTOL) - { - clipof.Clear(); - clipof.AddPaths(inputPaths, JoinType::jtRound, EndType::etClosedPolygon); - if (opType == OperationType::otClearingOutside || opType == OperationType::otProfilingOutside) - clipof.Execute(inputPaths, stockToLeave * scaleFactor); - else - clipof.Execute(inputPaths, -stockToLeave * scaleFactor); - } - else - { - // fix for clipper glitches - clipof.Clear(); - clipof.AddPaths(inputPaths, JoinType::jtRound, EndType::etClosedPolygon); - clipof.Execute(inputPaths, -1); - filterCloseValues(inputPaths); - clipof.Clear(); - clipof.AddPaths(inputPaths, JoinType::jtRound, EndType::etClosedPolygon); - clipof.Execute(inputPaths, 1); - filterCloseValues(inputPaths); - } + ClipperOffset clipof; + if (stockToLeave > NTOL) { + clipof.Clear(); + clipof.AddPaths(inputPaths, JoinType::jtRound, EndType::etClosedPolygon); + if (opType == OperationType::otClearingOutside + || opType == OperationType::otProfilingOutside) { + clipof.Execute(inputPaths, stockToLeave * scaleFactor); + } + else { + clipof.Execute(inputPaths, -stockToLeave * scaleFactor); + } + } + else { + // fix for clipper glitches + clipof.Clear(); + clipof.AddPaths(inputPaths, JoinType::jtRound, EndType::etClosedPolygon); + clipof.Execute(inputPaths, -1); + filterCloseValues(inputPaths); + clipof.Clear(); + clipof.AddPaths(inputPaths, JoinType::jtRound, EndType::etClosedPolygon); + clipof.Execute(inputPaths, 1); + filterCloseValues(inputPaths); + } } //******************************************** // Adaptive2d - Execute //******************************************** -std::list Adaptive2d::Execute(const DPaths &stockPaths, const DPaths &paths, std::function progressCallbackFn) +std::list Adaptive2d::Execute(const DPaths& stockPaths, + const DPaths& paths, + std::function progressCallbackFn) { - //********************************** - // Initializations - //********************************** + //********************************** + // Initializations + //********************************** - // keep the tolerance in workable range - if (tolerance < 0.01) - tolerance = 0.01; - if (tolerance > 0.2) - tolerance = 0.2; + // keep the tolerance in workable range + if (tolerance < 0.01) { + tolerance = 0.01; + } + if (tolerance > 0.2) { + tolerance = 0.2; + } - scaleFactor = RESOLUTION_FACTOR / tolerance; - long maxScaleFactor = toolDiameter<1.0 ? 10000: 1000; + scaleFactor = RESOLUTION_FACTOR / tolerance; + long maxScaleFactor = toolDiameter < 1.0 ? 10000 : 1000; - if (stepOverFactor * toolDiameter < 1.0) - scaleFactor *= 1.0 / (stepOverFactor * toolDiameter); + if (stepOverFactor * toolDiameter < 1.0) { + scaleFactor *= 1.0 / (stepOverFactor * toolDiameter); + } - if (scaleFactor > maxScaleFactor ) - scaleFactor = maxScaleFactor; - //scaleFactor = round(scaleFactor); + if (scaleFactor > maxScaleFactor) { + scaleFactor = maxScaleFactor; + } + // scaleFactor = round(scaleFactor); - current_region=0; - cout << "Tool Diameter: " << toolDiameter << endl; - cout << "Accuracy: " << round(10000.0/scaleFactor)/10 << " um" << endl; - cout << flush; + current_region = 0; + cout << "Tool Diameter: " << toolDiameter << endl; + cout << "Accuracy: " << round(10000.0 / scaleFactor) / 10 << " um" << endl; + cout << flush; - toolRadiusScaled = long(toolDiameter * scaleFactor / 2); - stepOverScaled = toolRadiusScaled * stepOverFactor; - progressCallback = &progressCallbackFn; - lastProgressTime = clock(); - stopProcessing = false; + toolRadiusScaled = long(toolDiameter * scaleFactor / 2); + stepOverScaled = toolRadiusScaled * stepOverFactor; + progressCallback = &progressCallbackFn; + lastProgressTime = clock(); + stopProcessing = false; - if(helixRampDiameter toolDiameter) - helixRampDiameter = toolDiameter; - if (helixRampDiameter < toolDiameter / 8) - helixRampDiameter = toolDiameter / 8; + if (helixRampDiameter < NTOL) { + helixRampDiameter = 0.75 * toolDiameter; + } + if (helixRampDiameter > toolDiameter) { + helixRampDiameter = toolDiameter; + } + if (helixRampDiameter < toolDiameter / 8) { + helixRampDiameter = toolDiameter / 8; + } - helixRampRadiusScaled = long(helixRampDiameter * scaleFactor / 2); - if(finishingProfile) - finishPassOffsetScaled = long(stepOverScaled / 10); + helixRampRadiusScaled = long(helixRampDiameter * scaleFactor / 2); + if (finishingProfile) { + finishPassOffsetScaled = long(stepOverScaled / 10); + } - ClipperOffset clipof; - Clipper clip; + ClipperOffset clipof; + Clipper clip; - // generate tool shape - clipof.Clear(); - Path p; - p << IntPoint(0, 0); - clipof.AddPath(p, JoinType::jtRound, EndType::etOpenRound); - Paths toolGeometryPaths; - clipof.Execute(toolGeometryPaths, toolRadiusScaled); - toolGeometry = toolGeometryPaths[0]; - //calculate reference area - Path slotCut; - TranslatePath(toolGeometryPaths[0], slotCut, IntPoint(toolRadiusScaled / 2, 0)); - clip.Clear(); - clip.AddPath(toolGeometryPaths[0], PolyType::ptSubject, true); - clip.AddPath(slotCut, PolyType::ptClip, true); - Paths crossing; - clip.Execute(ClipType::ctDifference, crossing); - referenceCutArea = fabs(Area(crossing[0])); - optimalCutAreaPD = 2 * stepOverFactor * referenceCutArea / toolRadiusScaled; + // generate tool shape + clipof.Clear(); + Path p; + p << IntPoint(0, 0); + clipof.AddPath(p, JoinType::jtRound, EndType::etOpenRound); + Paths toolGeometryPaths; + clipof.Execute(toolGeometryPaths, toolRadiusScaled); + toolGeometry = toolGeometryPaths[0]; + // calculate reference area + Path slotCut; + TranslatePath(toolGeometryPaths[0], slotCut, IntPoint(toolRadiusScaled / 2, 0)); + clip.Clear(); + clip.AddPath(toolGeometryPaths[0], PolyType::ptSubject, true); + clip.AddPath(slotCut, PolyType::ptClip, true); + Paths crossing; + clip.Execute(ClipType::ctDifference, crossing); + referenceCutArea = fabs(Area(crossing[0])); + optimalCutAreaPD = 2 * stepOverFactor * referenceCutArea / toolRadiusScaled; #ifdef DEV_MODE - cout << "optimalCutAreaPD:" << optimalCutAreaPD << " scaleFactor:" << scaleFactor << " toolRadiusScaled:" << toolRadiusScaled << " helixRampRadiusScaled:" << helixRampRadiusScaled << endl; + cout << "optimalCutAreaPD:" << optimalCutAreaPD << " scaleFactor:" << scaleFactor + << " toolRadiusScaled:" << toolRadiusScaled + << " helixRampRadiusScaled:" << helixRampRadiusScaled << endl; #endif - //****************************** - // Convert input paths to clipper - //****************************** - Paths converted; - for (size_t i = 0; i < paths.size(); i++) - { - Path cpth; - for (size_t j = 0; j < paths[i].size(); j++) - { - std::pair pt = paths[i][j]; - cpth.push_back(IntPoint(long(pt.first * scaleFactor), long(pt.second * scaleFactor))); - } - Path cpth2; - CleanPath(cpth,cpth2,FINISHING_CLEAN_PATH_TOLERANCE); - converted.push_back(cpth2); - } + //****************************** + // Convert input paths to clipper + //****************************** + Paths converted; + for (size_t i = 0; i < paths.size(); i++) { + Path cpth; + for (size_t j = 0; j < paths[i].size(); j++) { + std::pair pt = paths[i][j]; + cpth.push_back(IntPoint(long(pt.first * scaleFactor), long(pt.second * scaleFactor))); + } + Path cpth2; + CleanPath(cpth, cpth2, FINISHING_CLEAN_PATH_TOLERANCE); + converted.push_back(cpth2); + } - DeduplicatePaths(converted, inputPaths); - ConnectPaths(inputPaths, inputPaths); - SimplifyPolygons(inputPaths); - ApplyStockToLeave(inputPaths); + DeduplicatePaths(converted, inputPaths); + ConnectPaths(inputPaths, inputPaths); + SimplifyPolygons(inputPaths); + ApplyStockToLeave(inputPaths); - //************************* - // convert stock paths - //************************* - stockInputPaths.clear(); - for (size_t i = 0; i < stockPaths.size(); i++) - { - Path cpth; - for (size_t j = 0; j < stockPaths[i].size(); j++) - { - std::pair pt = stockPaths[i][j]; - cpth.push_back(IntPoint(long(pt.first * scaleFactor), long(pt.second * scaleFactor))); - } + //************************* + // convert stock paths + //************************* + stockInputPaths.clear(); + for (size_t i = 0; i < stockPaths.size(); i++) { + Path cpth; + for (size_t j = 0; j < stockPaths[i].size(); j++) { + std::pair pt = stockPaths[i][j]; + cpth.push_back(IntPoint(long(pt.first * scaleFactor), long(pt.second * scaleFactor))); + } - stockInputPaths.push_back(cpth); - } + stockInputPaths.push_back(cpth); + } - SimplifyPolygons(stockInputPaths); - //CleanPolygons(stockInputPaths,0.707); + SimplifyPolygons(stockInputPaths); + // CleanPolygons(stockInputPaths,0.707); - //*************************************** - // Resolve hierarchy and run processing - //*************************************** - double cornerRoundingOffset = 0.15 * toolRadiusScaled / 2; - if (opType == OperationType::otClearingInside || opType == OperationType::otClearingOutside) - { + //*************************************** + // Resolve hierarchy and run processing + //*************************************** + double cornerRoundingOffset = 0.15 * toolRadiusScaled / 2; + if (opType == OperationType::otClearingInside || opType == OperationType::otClearingOutside) { - // prepare stock boundary overshooted paths - clipof.Clear(); - clipof.AddPaths(stockInputPaths, JoinType::jtSquare, EndType::etClosedPolygon); - double overshootDistance = 4 * toolRadiusScaled + stockToLeave * scaleFactor; - if (forceInsideOut) - overshootDistance = 0; - Paths stockOvershoot; - clipof.Execute(stockOvershoot, overshootDistance); - ReversePaths(stockOvershoot); + // prepare stock boundary overshooted paths + clipof.Clear(); + clipof.AddPaths(stockInputPaths, JoinType::jtSquare, EndType::etClosedPolygon); + double overshootDistance = 4 * toolRadiusScaled + stockToLeave * scaleFactor; + if (forceInsideOut) { + overshootDistance = 0; + } + Paths stockOvershoot; + clipof.Execute(stockOvershoot, overshootDistance); + ReversePaths(stockOvershoot); - if (opType == OperationType::otClearingOutside) - { - // add stock paths, with overshooting - for (const auto& p : stockOvershoot) - inputPaths.push_back(p); - } - else if (opType == OperationType::otClearingInside) - { - // potential TODO: check if there are open paths, and try to close it through overshooted stock boundary - } + if (opType == OperationType::otClearingOutside) { + // add stock paths, with overshooting + for (const auto& p : stockOvershoot) { + inputPaths.push_back(p); + } + } + else if (opType == OperationType::otClearingInside) { + // potential TODO: check if there are open paths, and try to close it through + // overshooted stock boundary + } - clipof.Clear(); - clipof.AddPaths(inputPaths, JoinType::jtRound, EndType::etClosedPolygon); - Paths paths; - clipof.Execute(paths, -toolRadiusScaled - finishPassOffsetScaled - cornerRoundingOffset); - for (const auto ¤t : paths) - { - int nesting = getPathNestingLevel(current, paths); - if (nesting % 2 != 0 && (polyTreeNestingLimit == 0 || nesting <= polyTreeNestingLimit)) - { - Paths toolBoundPaths; - toolBoundPaths.push_back(current); - if (polyTreeNestingLimit != nesting) - { - appendDirectChildPaths(toolBoundPaths, current, paths); - } + clipof.Clear(); + clipof.AddPaths(inputPaths, JoinType::jtRound, EndType::etClosedPolygon); + Paths paths; + clipof.Execute(paths, -toolRadiusScaled - finishPassOffsetScaled - cornerRoundingOffset); + for (const auto& current : paths) { + int nesting = getPathNestingLevel(current, paths); + if (nesting % 2 != 0 + && (polyTreeNestingLimit == 0 || nesting <= polyTreeNestingLimit)) { + Paths toolBoundPaths; + toolBoundPaths.push_back(current); + if (polyTreeNestingLimit != nesting) { + appendDirectChildPaths(toolBoundPaths, current, paths); + } - // offset back outwards - corner rounding - clipof.Clear(); - clipof.AddPaths(toolBoundPaths, JoinType::jtRound, EndType::etClosedPolygon); - clipof.Execute(toolBoundPaths, cornerRoundingOffset); + // offset back outwards - corner rounding + clipof.Clear(); + clipof.AddPaths(toolBoundPaths, JoinType::jtRound, EndType::etClosedPolygon); + clipof.Execute(toolBoundPaths, cornerRoundingOffset); - // restore original bound paths - // bounding paths - i.e. area that must be cleared inside - // it's not the same as input paths due to filtering (nesting logic) and corner rounding - Paths boundPaths; - clipof.Clear(); - clipof.AddPaths(toolBoundPaths, JoinType::jtRound, EndType::etClosedPolygon); - clipof.Execute(boundPaths, toolRadiusScaled + finishPassOffsetScaled); - ProcessPolyNode(boundPaths, toolBoundPaths); - } - } - } + // restore original bound paths + // bounding paths - i.e. area that must be cleared inside + // it's not the same as input paths due to filtering (nesting logic) and corner + // rounding + Paths boundPaths; + clipof.Clear(); + clipof.AddPaths(toolBoundPaths, JoinType::jtRound, EndType::etClosedPolygon); + clipof.Execute(boundPaths, toolRadiusScaled + finishPassOffsetScaled); + ProcessPolyNode(boundPaths, toolBoundPaths); + } + } + } - if (opType == OperationType::otProfilingInside || opType == OperationType::otProfilingOutside) - { - double offset = opType == OperationType::otProfilingInside ? -2 * (helixRampRadiusScaled + toolRadiusScaled) - RESOLUTION_FACTOR : 2 * (helixRampRadiusScaled + toolRadiusScaled) + RESOLUTION_FACTOR; - for (const auto ¤t : inputPaths) - { - int nesting = getPathNestingLevel(current, inputPaths); - if (nesting % 2 != 0 && (polyTreeNestingLimit == 0 || nesting <= polyTreeNestingLimit)) - { - Paths profilePaths; - profilePaths.push_back(current); - if (polyTreeNestingLimit != nesting) - { - appendDirectChildPaths(profilePaths, current, inputPaths); - } - for (size_t i = 0; i < profilePaths.size(); i++) - { - double efOffset = i == 0 ? offset : -offset; - clipof.Clear(); - clipof.AddPath(profilePaths[i], JoinType::jtSquare, EndType::etClosedPolygon); - Paths off1; - clipof.Execute(off1, efOffset); - // make poly between original path and offset path - Paths boundPaths; - clip.Clear(); - if (efOffset < 0) - { - clip.AddPath(profilePaths[i], PolyType::ptSubject, true); - clip.AddPaths(off1, PolyType::ptClip, true); - } - else - { - clip.AddPaths(off1, PolyType::ptSubject, true); - clip.AddPath(profilePaths[i], PolyType::ptClip, true); - } - clip.Execute(ClipType::ctDifference, boundPaths, PolyFillType::pftEvenOdd); + if (opType == OperationType::otProfilingInside || opType == OperationType::otProfilingOutside) { + double offset = opType == OperationType::otProfilingInside + ? -2 * (helixRampRadiusScaled + toolRadiusScaled) - RESOLUTION_FACTOR + : 2 * (helixRampRadiusScaled + toolRadiusScaled) + RESOLUTION_FACTOR; + for (const auto& current : inputPaths) { + int nesting = getPathNestingLevel(current, inputPaths); + if (nesting % 2 != 0 + && (polyTreeNestingLimit == 0 || nesting <= polyTreeNestingLimit)) { + Paths profilePaths; + profilePaths.push_back(current); + if (polyTreeNestingLimit != nesting) { + appendDirectChildPaths(profilePaths, current, inputPaths); + } + for (size_t i = 0; i < profilePaths.size(); i++) { + double efOffset = i == 0 ? offset : -offset; + clipof.Clear(); + clipof.AddPath(profilePaths[i], JoinType::jtSquare, EndType::etClosedPolygon); + Paths off1; + clipof.Execute(off1, efOffset); + // make poly between original path and offset path + Paths boundPaths; + clip.Clear(); + if (efOffset < 0) { + clip.AddPath(profilePaths[i], PolyType::ptSubject, true); + clip.AddPaths(off1, PolyType::ptClip, true); + } + else { + clip.AddPaths(off1, PolyType::ptSubject, true); + clip.AddPath(profilePaths[i], PolyType::ptClip, true); + } + clip.Execute(ClipType::ctDifference, boundPaths, PolyFillType::pftEvenOdd); - /** tool bounds */ - Paths toolBoundPaths; - clipof.Clear(); - clipof.AddPaths(boundPaths, JoinType::jtRound, EndType::etClosedPolygon); - clipof.Execute(toolBoundPaths, -toolRadiusScaled - finishPassOffsetScaled - cornerRoundingOffset); + /** tool bounds */ + Paths toolBoundPaths; + clipof.Clear(); + clipof.AddPaths(boundPaths, JoinType::jtRound, EndType::etClosedPolygon); + clipof.Execute(toolBoundPaths, + -toolRadiusScaled - finishPassOffsetScaled + - cornerRoundingOffset); - /** offset back outwards - corner rounding */ - clipof.Clear(); - clipof.AddPaths(toolBoundPaths, JoinType::jtRound, EndType::etClosedPolygon); - clipof.Execute(toolBoundPaths, cornerRoundingOffset); + /** offset back outwards - corner rounding */ + clipof.Clear(); + clipof.AddPaths(toolBoundPaths, JoinType::jtRound, EndType::etClosedPolygon); + clipof.Execute(toolBoundPaths, cornerRoundingOffset); - // restore original bound paths - // bounding paths - i.e. area that must be cleared inside - // it's not the same as above due to corner rounding - clipof.Clear(); - clipof.AddPaths(toolBoundPaths, JoinType::jtRound, EndType::etClosedPolygon); - clipof.Execute(boundPaths, toolRadiusScaled + finishPassOffsetScaled); + // restore original bound paths + // bounding paths - i.e. area that must be cleared inside + // it's not the same as above due to corner rounding + clipof.Clear(); + clipof.AddPaths(toolBoundPaths, JoinType::jtRound, EndType::etClosedPolygon); + clipof.Execute(boundPaths, toolRadiusScaled + finishPassOffsetScaled); - ProcessPolyNode(boundPaths, toolBoundPaths); - } - } - } - } - return results; + ProcessPolyNode(boundPaths, toolBoundPaths); + } + } + } + } + return results; } -bool Adaptive2d::FindEntryPoint(TPaths &progressPaths, const Paths &toolBoundPaths, const Paths &boundPaths, - ClearedArea &clearedArea /*output-initial cleared area by helix*/, - IntPoint &entryPoint /*output*/, - IntPoint &toolPos, DoublePoint &toolDir) +bool Adaptive2d::FindEntryPoint(TPaths& progressPaths, + const Paths& toolBoundPaths, + const Paths& boundPaths, + ClearedArea& clearedArea /*output-initial cleared area by helix*/, + IntPoint& entryPoint /*output*/, + IntPoint& toolPos, + DoublePoint& toolDir) { - Paths incOffset; - Paths lastValidOffset; - Clipper clip; - ClipperOffset clipof; - bool found = false; - Paths clearedPaths; - Paths checkPaths = toolBoundPaths; - for (int iter = 0; iter < 10; iter++) - { - clipof.Clear(); - clipof.AddPaths(checkPaths, JoinType::jtSquare, EndType::etClosedPolygon); - double step = RESOLUTION_FACTOR; - double currentDelta = -1; - clipof.Execute(incOffset, currentDelta); - while (!incOffset.empty()) - { - clipof.Execute(incOffset, currentDelta); - if (!incOffset.empty()) - lastValidOffset = incOffset; - currentDelta -= step; - } - for (size_t i = 0; i < lastValidOffset.size(); i++) - { - if (!lastValidOffset[i].empty()) - { - entryPoint = Compute2DPolygonCentroid(lastValidOffset[i]); - found = true; - break; - } - } - // check if the start point is in any of the holes - // this may happen in case when toolBoundPaths are symmetric (boundary + holes) - // we need to break simetry and try again - for (size_t j = 0; j < checkPaths.size(); j++) - { - int pip = PointInPolygon(entryPoint, checkPaths[j]); - if ((j == 0 && pip == 0) || (j > 0 && pip != 0)) - { - found = false; - break; - } - } - // check if helix fits - if (found) - { - // make initial polygon cleared by helix ramp - clipof.Clear(); - Path p1; - p1.push_back(entryPoint); - clipof.AddPath(p1, JoinType::jtRound, EndType::etOpenRound); - clipof.Execute(clearedPaths, helixRampRadiusScaled + toolRadiusScaled); - CleanPolygons(clearedPaths); - // we got first cleared area - check if it is crossing boundary - clip.Clear(); - clip.AddPaths(clearedPaths, PolyType::ptSubject, true); - clip.AddPaths(boundPaths, PolyType::ptClip, true); - Paths crossing; - clip.Execute(ClipType::ctDifference, crossing); - if (!crossing.empty()) - { - // helix does not fit to the cutting area - found = false; - } - else - { - clearedArea.SetClearedPaths(clearedPaths); - } - } + Paths incOffset; + Paths lastValidOffset; + Clipper clip; + ClipperOffset clipof; + bool found = false; + Paths clearedPaths; + Paths checkPaths = toolBoundPaths; + for (int iter = 0; iter < 10; iter++) { + clipof.Clear(); + clipof.AddPaths(checkPaths, JoinType::jtSquare, EndType::etClosedPolygon); + double step = RESOLUTION_FACTOR; + double currentDelta = -1; + clipof.Execute(incOffset, currentDelta); + while (!incOffset.empty()) { + clipof.Execute(incOffset, currentDelta); + if (!incOffset.empty()) { + lastValidOffset = incOffset; + } + currentDelta -= step; + } + for (size_t i = 0; i < lastValidOffset.size(); i++) { + if (!lastValidOffset[i].empty()) { + entryPoint = Compute2DPolygonCentroid(lastValidOffset[i]); + found = true; + break; + } + } + // check if the start point is in any of the holes + // this may happen in case when toolBoundPaths are symmetric (boundary + holes) + // we need to break simetry and try again + for (size_t j = 0; j < checkPaths.size(); j++) { + int pip = PointInPolygon(entryPoint, checkPaths[j]); + if ((j == 0 && pip == 0) || (j > 0 && pip != 0)) { + found = false; + break; + } + } + // check if helix fits + if (found) { + // make initial polygon cleared by helix ramp + clipof.Clear(); + Path p1; + p1.push_back(entryPoint); + clipof.AddPath(p1, JoinType::jtRound, EndType::etOpenRound); + clipof.Execute(clearedPaths, helixRampRadiusScaled + toolRadiusScaled); + CleanPolygons(clearedPaths); + // we got first cleared area - check if it is crossing boundary + clip.Clear(); + clip.AddPaths(clearedPaths, PolyType::ptSubject, true); + clip.AddPaths(boundPaths, PolyType::ptClip, true); + Paths crossing; + clip.Execute(ClipType::ctDifference, crossing); + if (!crossing.empty()) { + // helix does not fit to the cutting area + found = false; + } + else { + clearedArea.SetClearedPaths(clearedPaths); + } + } - if (!found) - { // break simetry and try again - clip.Clear(); - clip.AddPaths(checkPaths, PolyType::ptSubject, true); - auto bounds = clip.GetBounds(); - clip.Clear(); - Path rect; - rect << IntPoint(bounds.left, bounds.bottom); - rect << IntPoint(bounds.left, (bounds.top + bounds.bottom) / 2); - rect << IntPoint((bounds.left + bounds.right) / 2, (bounds.top + bounds.bottom) / 2); - rect << IntPoint((bounds.left + bounds.right) / 2, bounds.bottom); - clip.AddPath(rect, PolyType::ptSubject, true); - clip.AddPaths(checkPaths, PolyType::ptClip, true); - clip.Execute(ClipType::ctIntersection, checkPaths); - } - if (found) - break; - } + if (!found) { // break simetry and try again + clip.Clear(); + clip.AddPaths(checkPaths, PolyType::ptSubject, true); + auto bounds = clip.GetBounds(); + clip.Clear(); + Path rect; + rect << IntPoint(bounds.left, bounds.bottom); + rect << IntPoint(bounds.left, (bounds.top + bounds.bottom) / 2); + rect << IntPoint((bounds.left + bounds.right) / 2, (bounds.top + bounds.bottom) / 2); + rect << IntPoint((bounds.left + bounds.right) / 2, bounds.bottom); + clip.AddPath(rect, PolyType::ptSubject, true); + clip.AddPaths(checkPaths, PolyType::ptClip, true); + clip.Execute(ClipType::ctIntersection, checkPaths); + } + if (found) { + break; + } + } - if (!found) - cerr << "Start point not found!" << endl; - if (found) - { - // visualize/progress for helix - clipof.Clear(); - Path hp; - hp << entryPoint; - clipof.AddPath(hp, JoinType::jtRound, EndType::etOpenRound); - Paths hps; - clipof.Execute(hps, helixRampRadiusScaled); - AddPathsToProgress(progressPaths, hps); + if (!found) { + cerr << "Start point not found!" << endl; + } + if (found) { + // visualize/progress for helix + clipof.Clear(); + Path hp; + hp << entryPoint; + clipof.AddPath(hp, JoinType::jtRound, EndType::etOpenRound); + Paths hps; + clipof.Execute(hps, helixRampRadiusScaled); + AddPathsToProgress(progressPaths, hps); - toolPos = IntPoint(entryPoint.X, entryPoint.Y - helixRampRadiusScaled); - toolDir = DoublePoint(1.0, 0.0); - } - return found; + toolPos = IntPoint(entryPoint.X, entryPoint.Y - helixRampRadiusScaled); + toolDir = DoublePoint(1.0, 0.0); + } + return found; } -bool Adaptive2d::FindEntryPointOutside(TPaths &progressPaths, const Paths &toolBoundPaths, const Paths &boundPaths, - ClearedArea &clearedArea /*output-initial cleared area by helix*/, - IntPoint &entryPoint /*output*/, - IntPoint &toolPos, DoublePoint &toolDir) +bool Adaptive2d::FindEntryPointOutside( + TPaths& progressPaths, + const Paths& toolBoundPaths, + const Paths& boundPaths, + ClearedArea& clearedArea /*output-initial cleared area by helix*/, + IntPoint& entryPoint /*output*/, + IntPoint& toolPos, + DoublePoint& toolDir) { - UNUSED(progressPaths); // to silence compiler warning - UNUSED(boundPaths); // to silence compiler warning + UNUSED(progressPaths); // to silence compiler warning + UNUSED(boundPaths); // to silence compiler warning - Clipper clip; - ClipperOffset clipof; - Paths clearedPaths; - // check if boundary shape to cut is outside the stock - for (const auto &pth : toolBoundPaths) - { - for (size_t i = 0; i < pth.size(); i++) - { - IntPoint checkPoint = pth[i]; - IntPoint lastPoint = i > 0 ? pth[i - 1] : pth.back(); - // if point is outside the stock - if (PointInPolygon(checkPoint, stockInputPaths.front()) == 0) - { + Clipper clip; + ClipperOffset clipof; + Paths clearedPaths; + // check if boundary shape to cut is outside the stock + for (const auto& pth : toolBoundPaths) { + for (size_t i = 0; i < pth.size(); i++) { + IntPoint checkPoint = pth[i]; + IntPoint lastPoint = i > 0 ? pth[i - 1] : pth.back(); + // if point is outside the stock + if (PointInPolygon(checkPoint, stockInputPaths.front()) == 0) { - clipof.Clear(); - clipof.AddPaths(stockInputPaths, JoinType::jtSquare, EndType::etClosedPolygon); - clipof.Execute(clearedPaths, 1000 * toolRadiusScaled); + clipof.Clear(); + clipof.AddPaths(stockInputPaths, JoinType::jtSquare, EndType::etClosedPolygon); + clipof.Execute(clearedPaths, 1000 * toolRadiusScaled); - clip.Clear(); - clip.AddPaths(clearedPaths, PolyType::ptSubject, true); - clip.AddPaths(stockInputPaths, PolyType::ptClip, true); - clip.Execute(ClipType::ctDifference, clearedPaths); - CleanPolygons(clearedPaths); - SimplifyPolygons(clearedPaths); - clearedArea.SetClearedPaths(clearedPaths); - entryPoint = checkPoint; - toolPos = entryPoint; - // find tool dir - double len = sqrt(DistanceSqrd(lastPoint, checkPoint)); - toolDir = DoublePoint((checkPoint.X - lastPoint.X) / len, (checkPoint.Y - lastPoint.Y) / len); - return true; - } - } - } - return false; + clip.Clear(); + clip.AddPaths(clearedPaths, PolyType::ptSubject, true); + clip.AddPaths(stockInputPaths, PolyType::ptClip, true); + clip.Execute(ClipType::ctDifference, clearedPaths); + CleanPolygons(clearedPaths); + SimplifyPolygons(clearedPaths); + clearedArea.SetClearedPaths(clearedPaths); + entryPoint = checkPoint; + toolPos = entryPoint; + // find tool dir + double len = sqrt(DistanceSqrd(lastPoint, checkPoint)); + toolDir = DoublePoint((checkPoint.X - lastPoint.X) / len, + (checkPoint.Y - lastPoint.Y) / len); + return true; + } + } + } + return false; } //************************************************************ // IsClearPath - returns true if path is clear from obstacles //*********************************************************** -bool Adaptive2d::IsClearPath(const Path &tp, ClearedArea &cleared, double safetyClearance) +bool Adaptive2d::IsClearPath(const Path& tp, ClearedArea& cleared, double safetyClearance) { - Perf_IsClearPath.Start(); - Clipper clip; - ClipperOffset clipof; - clipof.AddPath(tp, JoinType::jtRound, EndType::etOpenRound); - Paths toolShape; - clipof.Execute(toolShape, toolRadiusScaled + safetyClearance); - clip.AddPaths(toolShape, PolyType::ptSubject, true); - clip.AddPaths(cleared.GetCleared(), PolyType::ptClip, true); - Paths crossing; - clip.Execute(ClipType::ctDifference, crossing); - double collisionArea = 0; - for (auto &p : crossing) - { - collisionArea += fabs(Area(p)); - } - Perf_IsClearPath.Stop(); - return collisionArea < 1.0; + Perf_IsClearPath.Start(); + Clipper clip; + ClipperOffset clipof; + clipof.AddPath(tp, JoinType::jtRound, EndType::etOpenRound); + Paths toolShape; + clipof.Execute(toolShape, toolRadiusScaled + safetyClearance); + clip.AddPaths(toolShape, PolyType::ptSubject, true); + clip.AddPaths(cleared.GetCleared(), PolyType::ptClip, true); + Paths crossing; + clip.Execute(ClipType::ctDifference, crossing); + double collisionArea = 0; + for (auto& p : crossing) { + collisionArea += fabs(Area(p)); + } + Perf_IsClearPath.Stop(); + return collisionArea < 1.0; } -bool Adaptive2d::IsAllowedToCutTrough(const IntPoint &p1, const IntPoint &p2, ClearedArea &cleared, const Paths &toolBoundPaths, double areaFactor, bool skipBoundsCheck) +bool Adaptive2d::IsAllowedToCutTrough(const IntPoint& p1, + const IntPoint& p2, + ClearedArea& cleared, + const Paths& toolBoundPaths, + double areaFactor, + bool skipBoundsCheck) { - Perf_IsAllowedToCutTrough.Start(); + Perf_IsAllowedToCutTrough.Start(); - if (!skipBoundsCheck && !IsPointWithinCutRegion(toolBoundPaths, p2)) - { - // last point outside boundary - its not clear to cut - Perf_IsAllowedToCutTrough.Stop(); - return false; - } - else if (!skipBoundsCheck && !IsPointWithinCutRegion(toolBoundPaths, p1)) - { - // first point outside boundary - its not clear to cut - Perf_IsAllowedToCutTrough.Stop(); - return false; - } - else - { - Clipper clip; - double distance = sqrt(DistanceSqrd(p1, p2)); - double stepSize = min(0.5 * stepOverScaled, 8 * RESOLUTION_FACTOR); - if (distance < stepSize / 2) - { // not significant cut - Perf_IsAllowedToCutTrough.Stop(); - return true; - } - if (distance < stepSize) - { // adjust for numeric instability with small distances - areaFactor *= 2; - } + if (!skipBoundsCheck && !IsPointWithinCutRegion(toolBoundPaths, p2)) { + // last point outside boundary - its not clear to cut + Perf_IsAllowedToCutTrough.Stop(); + return false; + } + else if (!skipBoundsCheck && !IsPointWithinCutRegion(toolBoundPaths, p1)) { + // first point outside boundary - its not clear to cut + Perf_IsAllowedToCutTrough.Stop(); + return false; + } + else { + Clipper clip; + double distance = sqrt(DistanceSqrd(p1, p2)); + double stepSize = min(0.5 * stepOverScaled, 8 * RESOLUTION_FACTOR); + if (distance < stepSize / 2) { // not significant cut + Perf_IsAllowedToCutTrough.Stop(); + return true; + } + if (distance < stepSize) { // adjust for numeric instability with small distances + areaFactor *= 2; + } - IntPoint toolPos1 = p1; - long steps = long(distance / stepSize) + 1; - stepSize = distance / steps; - for (long i = 1; i <= steps; i++) - { - double p = double(i) / steps; - IntPoint toolPos2(long(p1.X + double(p2.X - p1.X) * p), long(p1.Y + double(p2.Y - p1.Y) * p)); - double area = CalcCutArea(clip, toolPos1, toolPos2, cleared, false); - // if we are cutting above optimal -> not clear to cut - if (area > areaFactor * stepSize * optimalCutAreaPD) - { - Perf_IsAllowedToCutTrough.Stop(); - return false; - } - //if tool is outside boundary -> its not clear to cut - if (!skipBoundsCheck && !IsPointWithinCutRegion(toolBoundPaths, toolPos2)) - { - Perf_IsAllowedToCutTrough.Stop(); - return false; - } - toolPos1 = toolPos2; - } - } - Perf_IsAllowedToCutTrough.Stop(); - return true; + IntPoint toolPos1 = p1; + long steps = long(distance / stepSize) + 1; + stepSize = distance / steps; + for (long i = 1; i <= steps; i++) { + double p = double(i) / steps; + IntPoint toolPos2(long(p1.X + double(p2.X - p1.X) * p), + long(p1.Y + double(p2.Y - p1.Y) * p)); + double area = CalcCutArea(clip, toolPos1, toolPos2, cleared, false); + // if we are cutting above optimal -> not clear to cut + if (area > areaFactor * stepSize * optimalCutAreaPD) { + Perf_IsAllowedToCutTrough.Stop(); + return false; + } + // if tool is outside boundary -> its not clear to cut + if (!skipBoundsCheck && !IsPointWithinCutRegion(toolBoundPaths, toolPos2)) { + Perf_IsAllowedToCutTrough.Stop(); + return false; + } + toolPos1 = toolPos2; + } + } + Perf_IsAllowedToCutTrough.Stop(); + return true; } -bool Adaptive2d::ResolveLinkPath(const IntPoint &startPoint, const IntPoint &endPoint, ClearedArea &clearedArea, Path &output) +bool Adaptive2d::ResolveLinkPath(const IntPoint& startPoint, + const IntPoint& endPoint, + ClearedArea& clearedArea, + Path& output) { - vector> queue; - queue.emplace_back(startPoint, endPoint); - Path checkPath; - double totalLength = 0; - double directDistance = sqrt(DistanceSqrd(startPoint, endPoint)); - Paths linkPaths; + vector> queue; + queue.emplace_back(startPoint, endPoint); + Path checkPath; + double totalLength = 0; + double directDistance = sqrt(DistanceSqrd(startPoint, endPoint)); + Paths linkPaths; - double scanStep = 2 * RESOLUTION_FACTOR; - if (scanStep > scaleFactor * 0.1) - scanStep = scaleFactor * 0.1; - if (scanStep < scaleFactor * 0.01) - scanStep = scaleFactor * 0.01; - long limit = 10000; + double scanStep = 2 * RESOLUTION_FACTOR; + if (scanStep > scaleFactor * 0.1) { + scanStep = scaleFactor * 0.1; + } + if (scanStep < scaleFactor * 0.01) { + scanStep = scaleFactor * 0.01; + } + long limit = 10000; - double clearance = stepOverScaled; - double offClearance = 2 * stepOverScaled; - if (offClearance > directDistance / 2) - { - offClearance = directDistance / 2; - clearance = 0; - } + double clearance = stepOverScaled; + double offClearance = 2 * stepOverScaled; + if (offClearance > directDistance / 2) { + offClearance = directDistance / 2; + clearance = 0; + } - long cnt = 0; + long cnt = 0; - // to hold CLP results - IntPoint clp; - size_t pindex; - size_t sindex; - double par; + // to hold CLP results + IntPoint clp; + size_t pindex; + size_t sindex; + double par; - // put a time limit on the resolving the link path - clock_t time_limit = (clock_t)(max(keepToolDownDistRatio, 3.0) * CLOCKS_PER_SEC / 6); + // put a time limit on the resolving the link path + clock_t time_limit = (clock_t)(max(keepToolDownDistRatio, 3.0) * CLOCKS_PER_SEC / 6); - clock_t time_out = clock() + time_limit; + clock_t time_out = clock() + time_limit; - while (!queue.empty()) - { - if (stopProcessing) - return false; - if (clock() > time_out) - { - cout << "Unable to resolve tool down linking path (limit reached)." << endl; - return false; - } + while (!queue.empty()) { + if (stopProcessing) { + return false; + } + if (clock() > time_out) { + cout << "Unable to resolve tool down linking path (limit reached)." << endl; + return false; + } - cnt++; - if (cnt > limit) - { - cout << "Unable to resolve tool down linking path @(" << endPoint.X / scaleFactor << "," << endPoint.Y / scaleFactor << ") (" << limit << " points limit reached)." << endl; - return false; - } - pair pointPair = queue.back(); - queue.pop_back(); + cnt++; + if (cnt > limit) { + cout << "Unable to resolve tool down linking path @(" << endPoint.X / scaleFactor << "," + << endPoint.Y / scaleFactor << ") (" << limit << " points limit reached)." << endl; + return false; + } + pair pointPair = queue.back(); + queue.pop_back(); - // check for self intersections - if found discard the link path - for (size_t i = 0; i < linkPaths.size(); i++) - { - if (linkPaths[i].front() != pointPair.first && linkPaths[i].back() != pointPair.first && linkPaths[i].front() != pointPair.second && linkPaths[i].back() != pointPair.second && IntersectionPoint(linkPaths[i].front(), linkPaths[i].back(), pointPair.first, pointPair.second, clp)) - { - cout << "Unable to resolve tool down linking path (self-intersects)." << endl; - return false; - } - } + // check for self intersections - if found discard the link path + for (size_t i = 0; i < linkPaths.size(); i++) { + if (linkPaths[i].front() != pointPair.first && linkPaths[i].back() != pointPair.first + && linkPaths[i].front() != pointPair.second + && linkPaths[i].back() != pointPair.second + && IntersectionPoint(linkPaths[i].front(), + linkPaths[i].back(), + pointPair.first, + pointPair.second, + clp)) { + cout << "Unable to resolve tool down linking path (self-intersects)." << endl; + return false; + } + } - DoublePoint direction = DirectionV(pointPair.first, pointPair.second); - checkPath.clear(); - if (pointPair.first == startPoint) - { - checkPath.push_back(IntPoint(pointPair.first.X + offClearance * direction.X, pointPair.first.Y + offClearance * direction.Y)); - } - else - { - checkPath.push_back(pointPair.first); - } - if (pointPair.second == endPoint) - { - checkPath.push_back(IntPoint(pointPair.second.X - offClearance * direction.X, pointPair.second.Y - offClearance * direction.Y)); - } - else - { - checkPath.push_back(pointPair.second); - } + DoublePoint direction = DirectionV(pointPair.first, pointPair.second); + checkPath.clear(); + if (pointPair.first == startPoint) { + checkPath.push_back(IntPoint(pointPair.first.X + offClearance * direction.X, + pointPair.first.Y + offClearance * direction.Y)); + } + else { + checkPath.push_back(pointPair.first); + } + if (pointPair.second == endPoint) { + checkPath.push_back(IntPoint(pointPair.second.X - offClearance * direction.X, + pointPair.second.Y - offClearance * direction.Y)); + } + else { + checkPath.push_back(pointPair.second); + } - if (IsClearPath(checkPath, clearedArea, clearance)) - { - totalLength += sqrt(DistanceSqrd(pointPair.first, pointPair.second)); - if (totalLength > keepToolDownDistRatio * directDistance) - { - return false; - } - Path link; - link.push_back(pointPair.first); - link.push_back(pointPair.second); - linkPaths.push_back(link); - } - else - { - if (sqrt(DistanceSqrd(pointPair.first, pointPair.second)) < 4) - { - //segment became too short but still not clear - return false; - } - DoublePoint pDir(-direction.Y, direction.X); - // find mid point - IntPoint midPoint(0.5 * double(pointPair.first.X + pointPair.second.X), 0.5 * double(pointPair.first.Y + pointPair.second.Y)); - for (long i = 1;; i++) - { - if (stopProcessing) - return false; - double offset = i * scanStep; - IntPoint checkPoint1(midPoint.X + offset * pDir.X, midPoint.Y + offset * pDir.Y); - IntPoint checkPoint2(midPoint.X - offset * pDir.X, midPoint.Y - offset * pDir.Y); + if (IsClearPath(checkPath, clearedArea, clearance)) { + totalLength += sqrt(DistanceSqrd(pointPair.first, pointPair.second)); + if (totalLength > keepToolDownDistRatio * directDistance) { + return false; + } + Path link; + link.push_back(pointPair.first); + link.push_back(pointPair.second); + linkPaths.push_back(link); + } + else { + if (sqrt(DistanceSqrd(pointPair.first, pointPair.second)) < 4) { + // segment became too short but still not clear + return false; + } + DoublePoint pDir(-direction.Y, direction.X); + // find mid point + IntPoint midPoint(0.5 * double(pointPair.first.X + pointPair.second.X), + 0.5 * double(pointPair.first.Y + pointPair.second.Y)); + for (long i = 1;; i++) { + if (stopProcessing) { + return false; + } + double offset = i * scanStep; + IntPoint checkPoint1(midPoint.X + offset * pDir.X, midPoint.Y + offset * pDir.Y); + IntPoint checkPoint2(midPoint.X - offset * pDir.X, midPoint.Y - offset * pDir.Y); - if (DistancePointToPathsSqrd(clearedArea.GetCleared(), checkPoint1, clp, pindex, sindex, par) < - DistancePointToPathsSqrd(clearedArea.GetCleared(), checkPoint2, clp, pindex, sindex, par)) - { - // exchange points - IntPoint tmp = checkPoint2; - checkPoint2 = checkPoint1; - checkPoint1 = tmp; - } + if (DistancePointToPathsSqrd(clearedArea.GetCleared(), + checkPoint1, + clp, + pindex, + sindex, + par) + < DistancePointToPathsSqrd(clearedArea.GetCleared(), + checkPoint2, + clp, + pindex, + sindex, + par)) { + // exchange points + IntPoint tmp = checkPoint2; + checkPoint2 = checkPoint1; + checkPoint1 = tmp; + } - checkPath.clear(); - checkPath.push_back(checkPoint1); - if (IsClearPath(checkPath, clearedArea, clearance + 1)) - { // check if point clear - queue.emplace_back(pointPair.first, checkPoint1); - queue.emplace_back(checkPoint1, pointPair.second); - break; - } - else - { // check the other side + checkPath.clear(); + checkPath.push_back(checkPoint1); + if (IsClearPath(checkPath, clearedArea, clearance + 1)) { // check if point clear + queue.emplace_back(pointPair.first, checkPoint1); + queue.emplace_back(checkPoint1, pointPair.second); + break; + } + else { // check the other side - checkPath.clear(); - checkPath.push_back(checkPoint2); - if (IsClearPath(checkPath, clearedArea, clearance + 1)) - { - queue.emplace_back(pointPair.first, checkPoint2); - queue.emplace_back(checkPoint2, pointPair.second); - break; - } - } - if (offset > keepToolDownDistRatio * directDistance) - return false; // can't find keep tool down link - } - } - } - if (linkPaths.empty()) - return false; - ConnectPaths(linkPaths, linkPaths); - output = linkPaths[0]; - return true; + checkPath.clear(); + checkPath.push_back(checkPoint2); + if (IsClearPath(checkPath, clearedArea, clearance + 1)) { + queue.emplace_back(pointPair.first, checkPoint2); + queue.emplace_back(checkPoint2, pointPair.second); + break; + } + } + if (offset > keepToolDownDistRatio * directDistance) { + return false; // can't find keep tool down link + } + } + } + } + if (linkPaths.empty()) { + return false; + } + ConnectPaths(linkPaths, linkPaths); + output = linkPaths[0]; + return true; } -bool Adaptive2d::MakeLeadPath(bool leadIn, const IntPoint &startPoint, const DoublePoint &startDir, const IntPoint &beaconPoint, - ClearedArea &clearedArea, const Paths &toolBoundPaths, Path &output) +bool Adaptive2d::MakeLeadPath(bool leadIn, + const IntPoint& startPoint, + const DoublePoint& startDir, + const IntPoint& beaconPoint, + ClearedArea& clearedArea, + const Paths& toolBoundPaths, + Path& output) { - IntPoint currentPoint = startPoint; - DoublePoint targetDir = DirectionV(currentPoint, beaconPoint); - double distanceToBeacon = sqrt(DistanceSqrd(startPoint, beaconPoint)); - double stepSize = 0.2 * stepOverScaled + 1; - double maxPathLen = stepOverScaled; - DoublePoint nextDir = startDir; - IntPoint nextPoint = IntPoint(currentPoint.X + nextDir.X * stepSize, currentPoint.Y + nextDir.Y * stepSize); - Path checkPath; - double adaptFactor = 0.4; - double alfa = M_PI / 64; - double pathLen = 0; - checkPath.push_back(nextPoint); - for (int i = 0; i < 10000; i++) - { - if (IsAllowedToCutTrough(IntPoint(currentPoint.X + RESOLUTION_FACTOR * nextDir.X, currentPoint.Y + RESOLUTION_FACTOR * nextDir.Y), nextPoint, clearedArea, toolBoundPaths)) - { - if (output.empty()) - output.push_back(currentPoint); - output.push_back(nextPoint); - currentPoint = nextPoint; - pathLen += stepSize; - targetDir = DirectionV(currentPoint, beaconPoint); - nextDir = DoublePoint(nextDir.X + adaptFactor * targetDir.X, nextDir.Y + adaptFactor * targetDir.Y); - NormalizeV(nextDir); - if (pathLen > maxPathLen) - break; - if (pathLen > distanceToBeacon / 2) - break; - } - else - { - nextDir = rotate(nextDir, leadIn ? -alfa : alfa); - } - nextPoint = IntPoint(currentPoint.X + nextDir.X * stepSize, currentPoint.Y + nextDir.Y * stepSize); - } - if (output.empty()) - output.push_back(startPoint); - return true; + IntPoint currentPoint = startPoint; + DoublePoint targetDir = DirectionV(currentPoint, beaconPoint); + double distanceToBeacon = sqrt(DistanceSqrd(startPoint, beaconPoint)); + double stepSize = 0.2 * stepOverScaled + 1; + double maxPathLen = stepOverScaled; + DoublePoint nextDir = startDir; + IntPoint nextPoint = + IntPoint(currentPoint.X + nextDir.X * stepSize, currentPoint.Y + nextDir.Y * stepSize); + Path checkPath; + double adaptFactor = 0.4; + double alfa = M_PI / 64; + double pathLen = 0; + checkPath.push_back(nextPoint); + for (int i = 0; i < 10000; i++) { + if (IsAllowedToCutTrough(IntPoint(currentPoint.X + RESOLUTION_FACTOR * nextDir.X, + currentPoint.Y + RESOLUTION_FACTOR * nextDir.Y), + nextPoint, + clearedArea, + toolBoundPaths)) { + if (output.empty()) { + output.push_back(currentPoint); + } + output.push_back(nextPoint); + currentPoint = nextPoint; + pathLen += stepSize; + targetDir = DirectionV(currentPoint, beaconPoint); + nextDir = DoublePoint(nextDir.X + adaptFactor * targetDir.X, + nextDir.Y + adaptFactor * targetDir.Y); + NormalizeV(nextDir); + if (pathLen > maxPathLen) { + break; + } + if (pathLen > distanceToBeacon / 2) { + break; + } + } + else { + nextDir = rotate(nextDir, leadIn ? -alfa : alfa); + } + nextPoint = + IntPoint(currentPoint.X + nextDir.X * stepSize, currentPoint.Y + nextDir.Y * stepSize); + } + if (output.empty()) { + output.push_back(startPoint); + } + return true; } -void Adaptive2d::AppendToolPath(TPaths &progressPaths, AdaptiveOutput &output, - const Path &passToolPath, ClearedArea &clearedBefore, - ClearedArea &clearedAfter, const Paths &toolBoundPaths) +void Adaptive2d::AppendToolPath(TPaths& progressPaths, + AdaptiveOutput& output, + const Path& passToolPath, + ClearedArea& clearedBefore, + ClearedArea& clearedAfter, + const Paths& toolBoundPaths) { - if (passToolPath.size() < 2) - return; - Perf_AppendToolPath.Start(); - UNUSED(progressPaths); // to silence compiler warning,var is occasionally used in dev. for debugging + if (passToolPath.size() < 2) { + return; + } + Perf_AppendToolPath.Start(); + UNUSED(progressPaths); // to silence compiler warning,var is occasionally used in dev. for + // debugging - IntPoint endPoint(passToolPath[0]); - // if there is a previous path - need to resolve linking move to new path - if (!output.AdaptivePaths.empty() && output.AdaptivePaths.back().second.size() > 1) - { - auto &lastTPath = output.AdaptivePaths.back(); + IntPoint endPoint(passToolPath[0]); + // if there is a previous path - need to resolve linking move to new path + if (!output.AdaptivePaths.empty() && output.AdaptivePaths.back().second.size() > 1) { + auto& lastTPath = output.AdaptivePaths.back(); - auto &lastPrevTPoint = lastTPath.second.at(lastTPath.second.size() - 2); - auto &lastTPoint = lastTPath.second.back(); + auto& lastPrevTPoint = lastTPath.second.at(lastTPath.second.size() - 2); + auto& lastTPoint = lastTPath.second.back(); - IntPoint startPrevPoint(long(lastPrevTPoint.first * scaleFactor), long(lastPrevTPoint.second * scaleFactor)); - IntPoint startPoint(long(lastTPoint.first * scaleFactor), long(lastTPoint.second * scaleFactor)); + IntPoint startPrevPoint(long(lastPrevTPoint.first * scaleFactor), + long(lastPrevTPoint.second * scaleFactor)); + IntPoint startPoint(long(lastTPoint.first * scaleFactor), + long(lastTPoint.second * scaleFactor)); - ClipperOffset clipof; - //first we try to cut through the linking move for short distances - bool linkFound = false; - double linkDistance = sqrt(DistanceSqrd(startPoint, endPoint)); - if (linkDistance < NTOL) - linkFound = true; + ClipperOffset clipof; + // first we try to cut through the linking move for short distances + bool linkFound = false; + double linkDistance = sqrt(DistanceSqrd(startPoint, endPoint)); + if (linkDistance < NTOL) { + linkFound = true; + } - if (!linkFound) - { - size_t clpPathIndex; - size_t clpSegmentIndex; - double clpParameter; - IntPoint clp; + if (!linkFound) { + size_t clpPathIndex; + size_t clpSegmentIndex; + double clpParameter; + IntPoint clp; - double beaconOffset = stepOverScaled; - if (beaconOffset > linkDistance) - { - beaconOffset = linkDistance; - } + double beaconOffset = stepOverScaled; + if (beaconOffset > linkDistance) { + beaconOffset = linkDistance; + } - double pathLen = PathLength(passToolPath); - if (beaconOffset > pathLen / 2) - { - beaconOffset = pathLen / 2; - } - if (beaconOffset > linkDistance / 2) - { - beaconOffset = linkDistance / 2; - } + double pathLen = PathLength(passToolPath); + if (beaconOffset > pathLen / 2) { + beaconOffset = pathLen / 2; + } + if (beaconOffset > linkDistance / 2) { + beaconOffset = linkDistance / 2; + } - DistancePointToPathsSqrd(toolBoundPaths, startPoint, clp, clpPathIndex, clpSegmentIndex, clpParameter); - DoublePoint startDir = GetPathDirectionV(toolBoundPaths[clpPathIndex], clpSegmentIndex); + DistancePointToPathsSqrd(toolBoundPaths, + startPoint, + clp, + clpPathIndex, + clpSegmentIndex, + clpParameter); + DoublePoint startDir = GetPathDirectionV(toolBoundPaths[clpPathIndex], clpSegmentIndex); - DistancePointToPathsSqrd(toolBoundPaths, endPoint, clp, clpPathIndex, clpSegmentIndex, clpParameter); - DoublePoint endDir = GetPathDirectionV(toolBoundPaths[clpPathIndex], clpSegmentIndex); + DistancePointToPathsSqrd(toolBoundPaths, + endPoint, + clp, + clpPathIndex, + clpSegmentIndex, + clpParameter); + DoublePoint endDir = GetPathDirectionV(toolBoundPaths[clpPathIndex], clpSegmentIndex); - IntPoint startBeacon(startPoint.X - beaconOffset * (startDir.Y - startDir.X), startPoint.Y + beaconOffset * (startDir.X + startDir.Y)); - IntPoint endBeacon(endPoint.X - beaconOffset * (endDir.X + endDir.Y), endPoint.Y + beaconOffset * (endDir.X - endDir.Y)); - Path leadOutPath; - MakeLeadPath(false, startPoint, startDir, startBeacon, clearedBefore, toolBoundPaths, leadOutPath); + IntPoint startBeacon(startPoint.X - beaconOffset * (startDir.Y - startDir.X), + startPoint.Y + beaconOffset * (startDir.X + startDir.Y)); + IntPoint endBeacon(endPoint.X - beaconOffset * (endDir.X + endDir.Y), + endPoint.Y + beaconOffset * (endDir.X - endDir.Y)); + Path leadOutPath; + MakeLeadPath(false, + startPoint, + startDir, + startBeacon, + clearedBefore, + toolBoundPaths, + leadOutPath); - Path leadInPath; - MakeLeadPath(true, endPoint, DoublePoint(-endDir.X, -endDir.Y), endBeacon, clearedBefore, toolBoundPaths, leadInPath); - ReversePath(leadInPath); + Path leadInPath; + MakeLeadPath(true, + endPoint, + DoublePoint(-endDir.X, -endDir.Y), + endBeacon, + clearedBefore, + toolBoundPaths, + leadInPath); + ReversePath(leadInPath); - Path linkPath; - MotionType linkType = MotionType::mtCutting; + Path linkPath; + MotionType linkType = MotionType::mtCutting; - // this is not needed: - //clearedBefore.ExpandCleared(leadInPath); - //clearedBefore.ExpandCleared(leadOutPath); + // this is not needed: + // clearedBefore.ExpandCleared(leadInPath); + // clearedBefore.ExpandCleared(leadOutPath); - if (ResolveLinkPath(leadOutPath.back(), leadInPath.front(), clearedBefore, linkPath)) - { - linkType = MotionType::mtLinkClear; - double remainingLeadInExtension = stepOverScaled / 2; - while (linkPath.size() >= 2 && remainingLeadInExtension > NTOL) - { - IntPoint p1 = linkPath.at(linkPath.size() - 2); - IntPoint p2 = linkPath.at(linkPath.size() - 1); - double l = sqrt(DistanceSqrd(p1, p2)); - if (l >= remainingLeadInExtension) - { - IntPoint splitPoint(p1.X + (p2.X - p1.X) * (l - remainingLeadInExtension) / l, p1.Y + (p2.Y - p1.Y) * (l - remainingLeadInExtension) / l); - linkPath.pop_back(); - linkPath.push_back(splitPoint); - leadInPath.insert(leadInPath.begin(), splitPoint); - remainingLeadInExtension = 0; - Path checkPath; - checkPath.push_back(p2); - checkPath.push_back(splitPoint); - if (!IsClearPath(checkPath, clearedBefore, 0)) - { - remainingLeadInExtension = stepOverScaled / 2; - } - } - else - { - linkPath.pop_back(); - leadInPath.insert(leadInPath.begin(), p1); - remainingLeadInExtension -= l; - if (remainingLeadInExtension < NTOL) - { - Path checkPath; - checkPath.push_back(p2); - checkPath.push_back(p1); - if (!IsClearPath(checkPath, clearedBefore, 0)) - { - remainingLeadInExtension = stepOverScaled / 2; - } - } - } - } - } - else - { - linkType = MotionType::mtLinkNotClear; - double dist = sqrt(DistanceSqrd(leadOutPath.back(), leadInPath.front())); - if (dist < 2 * stepOverScaled && IsAllowedToCutTrough( - IntPoint(leadOutPath.back().X + (leadInPath.front().X - leadOutPath.back().X) / dist, leadOutPath.back().Y + (leadInPath.front().Y - leadOutPath.back().Y) / dist), - IntPoint(leadInPath.front().X - (leadInPath.front().X - leadOutPath.back().X) / dist, leadInPath.front().Y - (leadInPath.front().Y - leadOutPath.back().Y) / dist), - clearedBefore, toolBoundPaths)) - linkType = MotionType::mtCutting; - // add direct linking move at clear height + if (ResolveLinkPath(leadOutPath.back(), leadInPath.front(), clearedBefore, linkPath)) { + linkType = MotionType::mtLinkClear; + double remainingLeadInExtension = stepOverScaled / 2; + while (linkPath.size() >= 2 && remainingLeadInExtension > NTOL) { + IntPoint p1 = linkPath.at(linkPath.size() - 2); + IntPoint p2 = linkPath.at(linkPath.size() - 1); + double l = sqrt(DistanceSqrd(p1, p2)); + if (l >= remainingLeadInExtension) { + IntPoint splitPoint( + p1.X + (p2.X - p1.X) * (l - remainingLeadInExtension) / l, + p1.Y + (p2.Y - p1.Y) * (l - remainingLeadInExtension) / l); + linkPath.pop_back(); + linkPath.push_back(splitPoint); + leadInPath.insert(leadInPath.begin(), splitPoint); + remainingLeadInExtension = 0; + Path checkPath; + checkPath.push_back(p2); + checkPath.push_back(splitPoint); + if (!IsClearPath(checkPath, clearedBefore, 0)) { + remainingLeadInExtension = stepOverScaled / 2; + } + } + else { + linkPath.pop_back(); + leadInPath.insert(leadInPath.begin(), p1); + remainingLeadInExtension -= l; + if (remainingLeadInExtension < NTOL) { + Path checkPath; + checkPath.push_back(p2); + checkPath.push_back(p1); + if (!IsClearPath(checkPath, clearedBefore, 0)) { + remainingLeadInExtension = stepOverScaled / 2; + } + } + } + } + } + else { + linkType = MotionType::mtLinkNotClear; + double dist = sqrt(DistanceSqrd(leadOutPath.back(), leadInPath.front())); + if (dist < 2 * stepOverScaled + && IsAllowedToCutTrough( + IntPoint(leadOutPath.back().X + + (leadInPath.front().X - leadOutPath.back().X) / dist, + leadOutPath.back().Y + + (leadInPath.front().Y - leadOutPath.back().Y) / dist), + IntPoint(leadInPath.front().X + - (leadInPath.front().X - leadOutPath.back().X) / dist, + leadInPath.front().Y + - (leadInPath.front().Y - leadOutPath.back().Y) / dist), + clearedBefore, + toolBoundPaths)) { + linkType = MotionType::mtCutting; + } + // add direct linking move at clear height - linkPath.clear(); - linkPath.push_back(leadOutPath.back()); - linkPath.push_back(leadInPath.front()); - } + linkPath.clear(); + linkPath.push_back(leadOutPath.back()); + linkPath.push_back(leadInPath.front()); + } - /* paths smoothing*/ - Paths linkPaths; - linkPaths.push_back(leadOutPath); - linkPaths.push_back(linkPath); - linkPaths.push_back(leadInPath); + /* paths smoothing*/ + Paths linkPaths; + linkPaths.push_back(leadOutPath); + linkPaths.push_back(linkPath); + linkPaths.push_back(leadInPath); - if (linkType == MotionType::mtLinkClear) - { - SmoothPaths(linkPaths, 0.1*stepOverScaled,1,4); - } + if (linkType == MotionType::mtLinkClear) { + SmoothPaths(linkPaths, 0.1 * stepOverScaled, 1, 4); + } - leadOutPath = linkPaths[0]; - linkPath = linkPaths[1]; - leadInPath = linkPaths[2]; + leadOutPath = linkPaths[0]; + linkPath = linkPaths[1]; + leadInPath = linkPaths[2]; - // add lead-out move - TPath linkPath1; - linkPath1.first = MotionType::mtCutting; - for (const auto &pt : leadOutPath) - { - linkPath1.second.emplace_back(double(pt.X) / scaleFactor, double(pt.Y) / scaleFactor); - } - output.AdaptivePaths.push_back(linkPath1); + // add lead-out move + TPath linkPath1; + linkPath1.first = MotionType::mtCutting; + for (const auto& pt : leadOutPath) { + linkPath1.second.emplace_back(double(pt.X) / scaleFactor, + double(pt.Y) / scaleFactor); + } + output.AdaptivePaths.push_back(linkPath1); - // add linking path - TPath linkPath2; - linkPath2.first = linkType; - for (const auto &pt : linkPath) - { - linkPath2.second.emplace_back(double(pt.X) / scaleFactor, double(pt.Y) / scaleFactor); - } - output.AdaptivePaths.push_back(linkPath2); + // add linking path + TPath linkPath2; + linkPath2.first = linkType; + for (const auto& pt : linkPath) { + linkPath2.second.emplace_back(double(pt.X) / scaleFactor, + double(pt.Y) / scaleFactor); + } + output.AdaptivePaths.push_back(linkPath2); - // add lead-in move - TPath linkPath3; - linkPath3.first = MotionType::mtCutting; - for (const auto &pt : leadInPath) - { - linkPath3.second.emplace_back(double(pt.X) / scaleFactor, double(pt.Y) / scaleFactor); - } + // add lead-in move + TPath linkPath3; + linkPath3.first = MotionType::mtCutting; + for (const auto& pt : leadInPath) { + linkPath3.second.emplace_back(double(pt.X) / scaleFactor, + double(pt.Y) / scaleFactor); + } - output.AdaptivePaths.push_back(linkPath3); + output.AdaptivePaths.push_back(linkPath3); - clearedAfter.ExpandCleared(leadInPath); - clearedAfter.ExpandCleared(leadOutPath); + clearedAfter.ExpandCleared(leadInPath); + clearedAfter.ExpandCleared(leadOutPath); - linkFound = true; - } - if (!linkFound) - { // nothing clear so far - check direct link with no interim points - either this is clear or we need to raise the tool - Path tp; - tp << startPoint; - tp << endPoint; - MotionType mt = IsClearPath(tp, clearedBefore) ? MotionType::mtLinkClear : MotionType::mtLinkNotClear; + linkFound = true; + } + if (!linkFound) { // nothing clear so far - check direct link with no interim points - + // either this is clear or we need to raise the tool + Path tp; + tp << startPoint; + tp << endPoint; + MotionType mt = IsClearPath(tp, clearedBefore) ? MotionType::mtLinkClear + : MotionType::mtLinkNotClear; - // make cutting move through small clear links - if (mt == MotionType::mtLinkClear && linkDistance < toolRadiusScaled) - { - mt = MotionType::mtCutting; - clearedAfter.ExpandCleared(tp); - } + // make cutting move through small clear links + if (mt == MotionType::mtLinkClear && linkDistance < toolRadiusScaled) { + mt = MotionType::mtCutting; + clearedAfter.ExpandCleared(tp); + } - TPath linkPath; - linkPath.first = mt; - linkPath.second.emplace_back(double(startPoint.X) / scaleFactor, double(startPoint.Y) / scaleFactor); - linkPath.second.emplace_back(double(endPoint.X) / scaleFactor, double(endPoint.Y) / scaleFactor); - output.AdaptivePaths.push_back(linkPath); - } - } - TPath cutPath; - cutPath.first = MotionType::mtCutting; - for (const auto &p : passToolPath) - { - DPoint nextT; - nextT.first = double(p.X) / scaleFactor; - nextT.second = double(p.Y) / scaleFactor; - cutPath.second.push_back(nextT); - } + TPath linkPath; + linkPath.first = mt; + linkPath.second.emplace_back(double(startPoint.X) / scaleFactor, + double(startPoint.Y) / scaleFactor); + linkPath.second.emplace_back(double(endPoint.X) / scaleFactor, + double(endPoint.Y) / scaleFactor); + output.AdaptivePaths.push_back(linkPath); + } + } + TPath cutPath; + cutPath.first = MotionType::mtCutting; + for (const auto& p : passToolPath) { + DPoint nextT; + nextT.first = double(p.X) / scaleFactor; + nextT.second = double(p.Y) / scaleFactor; + cutPath.second.push_back(nextT); + } - if (!cutPath.second.empty()) - output.AdaptivePaths.push_back(cutPath); - Perf_AppendToolPath.Stop(); + if (!cutPath.second.empty()) { + output.AdaptivePaths.push_back(cutPath); + } + Perf_AppendToolPath.Stop(); } -void Adaptive2d::CheckReportProgress(TPaths &progressPaths, bool force) +void Adaptive2d::CheckReportProgress(TPaths& progressPaths, bool force) { - if (!force && (clock() - lastProgressTime < PROGRESS_TICKS)) - return; // not yet - lastProgressTime = clock(); - if (progressPaths.empty()) - return; - if (progressCallback) - if ((*progressCallback)(progressPaths)) - stopProcessing = true; // call python function, if returns true signal stop processing - // clean the paths - keep the last point - if (progressPaths.back().second.empty()) - return; - TPath *lastPath = &progressPaths.back(); - DPoint *lastPoint = &lastPath->second.back(); - DPoint next(lastPoint->first, lastPoint->second); - while (progressPaths.size() > 1) - progressPaths.pop_back(); - while (!progressPaths.front().second.empty()) - progressPaths.front().second.pop_back(); - progressPaths.front().first = MotionType::mtCutting; - progressPaths.front().second.push_back(next); + if (!force && (clock() - lastProgressTime < PROGRESS_TICKS)) { + return; // not yet + } + lastProgressTime = clock(); + if (progressPaths.empty()) { + return; + } + if (progressCallback) { + if ((*progressCallback)(progressPaths)) { + stopProcessing = true; // call python function, if returns true signal stop processing + } + } + // clean the paths - keep the last point + if (progressPaths.back().second.empty()) { + return; + } + TPath* lastPath = &progressPaths.back(); + DPoint* lastPoint = &lastPath->second.back(); + DPoint next(lastPoint->first, lastPoint->second); + while (progressPaths.size() > 1) { + progressPaths.pop_back(); + } + while (!progressPaths.front().second.empty()) { + progressPaths.front().second.pop_back(); + } + progressPaths.front().first = MotionType::mtCutting; + progressPaths.front().second.push_back(next); } -void Adaptive2d::AddPathsToProgress(TPaths &progressPaths, Paths paths, MotionType mt) +void Adaptive2d::AddPathsToProgress(TPaths& progressPaths, Paths paths, MotionType mt) { - for (const auto &pth : paths) - { - if (!pth.empty()) - { - progressPaths.push_back(TPath()); - progressPaths.back().first = mt; - for (const auto pt : pth) - progressPaths.back().second.emplace_back(double(pt.X) / scaleFactor, double(pt.Y) / scaleFactor); - progressPaths.back().second.emplace_back(double(pth.front().X) / scaleFactor, double(pth.front().Y) / scaleFactor); - } - } + for (const auto& pth : paths) { + if (!pth.empty()) { + progressPaths.push_back(TPath()); + progressPaths.back().first = mt; + for (const auto pt : pth) { + progressPaths.back().second.emplace_back(double(pt.X) / scaleFactor, + double(pt.Y) / scaleFactor); + } + progressPaths.back().second.emplace_back(double(pth.front().X) / scaleFactor, + double(pth.front().Y) / scaleFactor); + } + } } -void Adaptive2d::AddPathToProgress(TPaths &progressPaths, const Path pth, MotionType mt) +void Adaptive2d::AddPathToProgress(TPaths& progressPaths, const Path pth, MotionType mt) { - if (!pth.empty()) - { - progressPaths.push_back(TPath()); - progressPaths.back().first = mt; - for (const auto pt : pth) - progressPaths.back().second.emplace_back(double(pt.X) / scaleFactor, double(pt.Y) / scaleFactor); - } + if (!pth.empty()) { + progressPaths.push_back(TPath()); + progressPaths.back().first = mt; + for (const auto pt : pth) { + progressPaths.back().second.emplace_back(double(pt.X) / scaleFactor, + double(pt.Y) / scaleFactor); + } + } } void Adaptive2d::ProcessPolyNode(Paths boundPaths, Paths toolBoundPaths) { - Perf_ProcessPolyNode.Start(); - current_region++; - cout << "** Processing region: " << current_region << endl; + Perf_ProcessPolyNode.Start(); + current_region++; + cout << "** Processing region: " << current_region << endl; - // node paths are already constrained to tool boundary path for adaptive path before finishing pass - Clipper clip; - ClipperOffset clipof; + // node paths are already constrained to tool boundary path for adaptive path before finishing + // pass + Clipper clip; + ClipperOffset clipof; - IntPoint entryPoint; - TPaths progressPaths; - progressPaths.reserve(10000); + IntPoint entryPoint; + TPaths progressPaths; + progressPaths.reserve(10000); - CleanPolygons(toolBoundPaths); - SimplifyPolygons(toolBoundPaths); + CleanPolygons(toolBoundPaths); + SimplifyPolygons(toolBoundPaths); - CleanPolygons(boundPaths); - SimplifyPolygons(boundPaths); + CleanPolygons(boundPaths); + SimplifyPolygons(boundPaths); - AddPathsToProgress(progressPaths, toolBoundPaths, MotionType::mtLinkClear); + AddPathsToProgress(progressPaths, toolBoundPaths, MotionType::mtLinkClear); - IntPoint toolPos; - DoublePoint toolDir; - ClearedArea cleared(toolRadiusScaled); - bool outsideEntry = false; - bool firstEngagePoint = true; - Paths engageBounds = toolBoundPaths; + IntPoint toolPos; + DoublePoint toolDir; + ClearedArea cleared(toolRadiusScaled); + bool outsideEntry = false; + bool firstEngagePoint = true; + Paths engageBounds = toolBoundPaths; - if (!forceInsideOut && FindEntryPointOutside(progressPaths, toolBoundPaths, boundPaths, cleared, entryPoint, toolPos, toolDir)) - { - if (!Orientation(engageBounds[0])) - ReversePath(engageBounds[0]); - // add initial offset of cleared area to engage paths - Paths outsideEngage; - clipof.Clear(); - clipof.AddPaths(stockInputPaths, JoinType::jtRound, EndType::etClosedPolygon); - clipof.Execute(outsideEngage, toolRadiusScaled - stepOverFactor * toolRadiusScaled); - CleanPolygons(outsideEngage); - ReversePaths(outsideEngage); - for (const auto& p : outsideEngage) - engageBounds.push_back(p); - outsideEntry = true; - } - else - { - if (!FindEntryPoint(progressPaths, toolBoundPaths, boundPaths, cleared, entryPoint, toolPos, toolDir)) - { - Perf_ProcessPolyNode.Stop(); - return; - } - } + if (!forceInsideOut + && FindEntryPointOutside(progressPaths, + toolBoundPaths, + boundPaths, + cleared, + entryPoint, + toolPos, + toolDir)) { + if (!Orientation(engageBounds[0])) { + ReversePath(engageBounds[0]); + } + // add initial offset of cleared area to engage paths + Paths outsideEngage; + clipof.Clear(); + clipof.AddPaths(stockInputPaths, JoinType::jtRound, EndType::etClosedPolygon); + clipof.Execute(outsideEngage, toolRadiusScaled - stepOverFactor * toolRadiusScaled); + CleanPolygons(outsideEngage); + ReversePaths(outsideEngage); + for (const auto& p : outsideEngage) { + engageBounds.push_back(p); + } + outsideEntry = true; + } + else { + if (!FindEntryPoint(progressPaths, + toolBoundPaths, + boundPaths, + cleared, + entryPoint, + toolPos, + toolDir)) { + Perf_ProcessPolyNode.Stop(); + return; + } + } - EngagePoint engage(engageBounds); // engage point stepping instance + EngagePoint engage(engageBounds); // engage point stepping instance - if (outsideEntry) - { - engage.moveToClosestPoint(toolPos, 2 * RESOLUTION_FACTOR); - engage.moveForward(RESOLUTION_FACTOR); - toolPos = engage.getCurrentPoint(); - toolDir = engage.getCurrentDir(); - entryPoint = toolPos; - } + if (outsideEntry) { + engage.moveToClosestPoint(toolPos, 2 * RESOLUTION_FACTOR); + engage.moveForward(RESOLUTION_FACTOR); + toolPos = engage.getCurrentPoint(); + toolDir = engage.getCurrentDir(); + entryPoint = toolPos; + } - //cout << "Entry point:" << double(entryPoint.X)/scaleFactor << "," << double(entryPoint.Y)/scaleFactor << endl; + // cout << "Entry point:" << double(entryPoint.X)/scaleFactor << "," << + // double(entryPoint.Y)/scaleFactor << endl; - AdaptiveOutput output; - output.HelixCenterPoint.first = double(entryPoint.X) / scaleFactor; - output.HelixCenterPoint.second = double(entryPoint.Y) / scaleFactor; + AdaptiveOutput output; + output.HelixCenterPoint.first = double(entryPoint.X) / scaleFactor; + output.HelixCenterPoint.second = double(entryPoint.Y) / scaleFactor; - long stepScaled = long(RESOLUTION_FACTOR); - IntPoint engagePoint; + long stepScaled = long(RESOLUTION_FACTOR); + IntPoint engagePoint; - IntPoint newToolPos; - DoublePoint newToolDir; + IntPoint newToolPos; + DoublePoint newToolDir; - CheckReportProgress(progressPaths, true); + CheckReportProgress(progressPaths, true); - IntPoint startPoint = toolPos; - output.StartPoint = DPoint(double(startPoint.X) / scaleFactor, double(startPoint.Y) / scaleFactor); + IntPoint startPoint = toolPos; + output.StartPoint = + DPoint(double(startPoint.X) / scaleFactor, double(startPoint.Y) / scaleFactor); - Path passToolPath; // to store pass toolpath - Path toClearPath; - IntPoint clp; // to store closest point - vector gyro; // used to average tool direction - vector angleHistory; // use to predict deflection angle - double angle = M_PI; - engagePoint = toolPos; - Interpolation interp; // interpolation instance + Path passToolPath; // to store pass toolpath + Path toClearPath; + IntPoint clp; // to store closest point + vector gyro; // used to average tool direction + vector angleHistory; // use to predict deflection angle + double angle = M_PI; + engagePoint = toolPos; + Interpolation interp; // interpolation instance - long total_iterations = 0; - long total_points = 0; - long total_exceeded = 0; - long total_output_points = 0; - long over_cut_count = 0; - long bad_engage_count = 0; - double prevDistFromStart = 0; - double refinement_factor = 1; - bool prevDistTrend = false; + long total_iterations = 0; + long total_points = 0; + long total_exceeded = 0; + long total_output_points = 0; + long over_cut_count = 0; + long bad_engage_count = 0; + double prevDistFromStart = 0; + double refinement_factor = 1; + bool prevDistTrend = false; - double perf_total_len = 0; + double perf_total_len = 0; #ifdef DEV_MODE - clock_t start_clock = clock(); + clock_t start_clock = clock(); #endif - ClearedArea clearedBeforePass(toolRadiusScaled); - clearedBeforePass.SetClearedPaths(cleared.GetCleared()); + ClearedArea clearedBeforePass(toolRadiusScaled); + clearedBeforePass.SetClearedPaths(cleared.GetCleared()); - //******************************* - // LOOP - PASSES - //******************************* - for (long pass = 0; pass < PASSES_LIMIT; pass++) - { - if (stopProcessing) - break; + //******************************* + // LOOP - PASSES + //******************************* + for (long pass = 0; pass < PASSES_LIMIT; pass++) { + if (stopProcessing) { + break; + } - passToolPath.clear(); - toClearPath.clear(); - angleHistory.clear(); + passToolPath.clear(); + toClearPath.clear(); + angleHistory.clear(); - // append a new path to progress info paths - if (progressPaths.empty()) - { - progressPaths.push_back(TPath()); - } - else - { - // append new path if previous not empty - if (!progressPaths.back().second.empty()) - progressPaths.push_back(TPath()); - } + // append a new path to progress info paths + if (progressPaths.empty()) { + progressPaths.push_back(TPath()); + } + else { + // append new path if previous not empty + if (!progressPaths.back().second.empty()) { + progressPaths.push_back(TPath()); + } + } - angle = M_PI / 4; // initial pass angle - bool recalcArea = false; - double cumulativeCutArea = 0; - // init gyro - gyro.clear(); - for (int i = 0; i < DIRECTION_SMOOTHING_BUFLEN; i++) - gyro.push_back(toolDir); + angle = M_PI / 4; // initial pass angle + bool recalcArea = false; + double cumulativeCutArea = 0; + // init gyro + gyro.clear(); + for (int i = 0; i < DIRECTION_SMOOTHING_BUFLEN; i++) { + gyro.push_back(toolDir); + } - size_t clpPathIndex; - size_t clpSegmentIndex; - double clpParameter; - double passLength = 0; - double noCutDistance=0; - clearedBeforePass.SetClearedPaths(cleared.GetCleared()); - //******************************* - // LOOP - POINTS - //******************************* - for (long point_index = 0; point_index < POINTS_PER_PASS_LIMIT; point_index++) - { - if (stopProcessing) - break; + size_t clpPathIndex; + size_t clpSegmentIndex; + double clpParameter; + double passLength = 0; + double noCutDistance = 0; + clearedBeforePass.SetClearedPaths(cleared.GetCleared()); + //******************************* + // LOOP - POINTS + //******************************* + for (long point_index = 0; point_index < POINTS_PER_PASS_LIMIT; point_index++) { + if (stopProcessing) { + break; + } - total_points++; - AverageDirection(gyro, toolDir); - Perf_DistanceToBoundary.Start(); + total_points++; + AverageDirection(gyro, toolDir); + Perf_DistanceToBoundary.Start(); - double distanceToBoundary = sqrt(DistancePointToPathsSqrd(toolBoundPaths, toolPos, clp, clpPathIndex, clpSegmentIndex, clpParameter)); - DoublePoint boundaryDir = GetPathDirectionV(toolBoundPaths[clpPathIndex], clpSegmentIndex); - double distBoundaryPointToEngage = sqrt(DistanceSqrd(clp, engagePoint)); + double distanceToBoundary = sqrt(DistancePointToPathsSqrd(toolBoundPaths, + toolPos, + clp, + clpPathIndex, + clpSegmentIndex, + clpParameter)); + DoublePoint boundaryDir = + GetPathDirectionV(toolBoundPaths[clpPathIndex], clpSegmentIndex); + double distBoundaryPointToEngage = sqrt(DistanceSqrd(clp, engagePoint)); - Perf_DistanceToBoundary.Stop(); - double distanceToEngage = sqrt(DistanceSqrd(toolPos, engagePoint)); + Perf_DistanceToBoundary.Stop(); + double distanceToEngage = sqrt(DistanceSqrd(toolPos, engagePoint)); - double targetAreaPD = optimalCutAreaPD; + double targetAreaPD = optimalCutAreaPD; - // set the step size - double slowDownDistance = max(double(toolRadiusScaled) / 4, RESOLUTION_FACTOR * 8); - if (distanceToBoundary < slowDownDistance || distanceToEngage < slowDownDistance) - { - stepScaled = long(RESOLUTION_FACTOR); - } - else if (fabs(angle) > NTOL) - { - stepScaled = long(RESOLUTION_FACTOR / fabs(angle)); - } - else - { - stepScaled = long(RESOLUTION_FACTOR * 4); - } + // set the step size + double slowDownDistance = max(double(toolRadiusScaled) / 4, RESOLUTION_FACTOR * 8); + if (distanceToBoundary < slowDownDistance || distanceToEngage < slowDownDistance) { + stepScaled = long(RESOLUTION_FACTOR); + } + else if (fabs(angle) > NTOL) { + stepScaled = long(RESOLUTION_FACTOR / fabs(angle)); + } + else { + stepScaled = long(RESOLUTION_FACTOR * 4); + } - // clamp the step size - for stability - if (stepScaled > min(long(toolRadiusScaled / 4), long(RESOLUTION_FACTOR * 8))) - stepScaled = min(long(toolRadiusScaled / 4), long(RESOLUTION_FACTOR * 8)); - if (stepScaled < RESOLUTION_FACTOR) - stepScaled = long(RESOLUTION_FACTOR); + // clamp the step size - for stability + if (stepScaled > min(long(toolRadiusScaled / 4), long(RESOLUTION_FACTOR * 8))) { + stepScaled = min(long(toolRadiusScaled / 4), long(RESOLUTION_FACTOR * 8)); + } + if (stepScaled < RESOLUTION_FACTOR) { + stepScaled = long(RESOLUTION_FACTOR); + } - //***************************** - // ANGLE vs AREA ITERATIONS - //***************************** - double predictedAngle = averageDV(angleHistory); - double maxError = AREA_ERROR_FACTOR * optimalCutAreaPD; - double area = 0; - double areaPD = 0; - interp.clear(); - /******************************/ - Perf_PointIterations.Start(); - int iteration; - double prev_error = __DBL_MAX__; - for (iteration = 0; iteration < MAX_ITERATIONS; iteration++) - { - total_iterations++; - if (iteration == 0) - angle = predictedAngle; - else if (iteration == 1) - angle = interp.MIN_ANGLE; // max engage - else if (iteration == 3) - angle = interp.MAX_ANGLE; // min engage - else if (interp.getPointCount() < 2) - angle = interp.getRandomAngle(); - else - angle = interp.interpolateAngle(targetAreaPD); - angle = interp.clampAngle(angle); + //***************************** + // ANGLE vs AREA ITERATIONS + //***************************** + double predictedAngle = averageDV(angleHistory); + double maxError = AREA_ERROR_FACTOR * optimalCutAreaPD; + double area = 0; + double areaPD = 0; + interp.clear(); + /******************************/ + Perf_PointIterations.Start(); + int iteration; + double prev_error = __DBL_MAX__; + for (iteration = 0; iteration < MAX_ITERATIONS; iteration++) { + total_iterations++; + if (iteration == 0) { + angle = predictedAngle; + } + else if (iteration == 1) { + angle = interp.MIN_ANGLE; // max engage + } + else if (iteration == 3) { + angle = interp.MAX_ANGLE; // min engage + } + else if (interp.getPointCount() < 2) { + angle = interp.getRandomAngle(); + } + else { + angle = interp.interpolateAngle(targetAreaPD); + } + angle = interp.clampAngle(angle); - newToolDir = rotate(toolDir, angle); - newToolPos = IntPoint(long(toolPos.X + newToolDir.X * stepScaled), long(toolPos.Y + newToolDir.Y * stepScaled)); + newToolDir = rotate(toolDir, angle); + newToolPos = IntPoint(long(toolPos.X + newToolDir.X * stepScaled), + long(toolPos.Y + newToolDir.Y * stepScaled)); - area = CalcCutArea(clip, toolPos, newToolPos, cleared); + area = CalcCutArea(clip, toolPos, newToolPos, cleared); - areaPD = area / double(stepScaled); // area per distance - interp.addPoint(areaPD, angle); + areaPD = area / double(stepScaled); // area per distance + interp.addPoint(areaPD, angle); double error = areaPD - targetAreaPD; // cout << " iter:" << iteration << " angle:" << angle << " area:" << areaPD // << " target:" << targetAreaPD << " error:" << error << " max:" << maxError // << endl; - if (fabs(error) < maxError) - { - angleHistory.push_back(angle); - if (angleHistory.size() > ANGLE_HISTORY_POINTS) - angleHistory.erase(angleHistory.begin()); - break; - } - if (iteration > 5 && fabs(error - prev_error) < 0.001) - break; - if (iteration == MAX_ITERATIONS - 1) - total_exceeded++; - prev_error = error; - } - Perf_PointIterations.Stop(); + if (fabs(error) < maxError) { + angleHistory.push_back(angle); + if (angleHistory.size() > ANGLE_HISTORY_POINTS) { + angleHistory.erase(angleHistory.begin()); + } + break; + } + if (iteration > 5 && fabs(error - prev_error) < 0.001) { + break; + } + if (iteration == MAX_ITERATIONS - 1) { + total_exceeded++; + } + prev_error = error; + } + Perf_PointIterations.Stop(); - recalcArea = false; - // approach end boundary tangentially - double relDistToBoundary = 4 * distanceToBoundary / stepOverScaled; - if (relDistToBoundary <= 1.0 && passLength > 2 * stepOverFactor && distanceToEngage > 2 * stepOverScaled && distBoundaryPointToEngage > 2 * stepOverScaled) - { - double wb = 1 - relDistToBoundary; - newToolDir = DoublePoint(newToolDir.X + wb * boundaryDir.X, newToolDir.Y + wb * boundaryDir.Y); - NormalizeV(newToolDir); - newToolPos = IntPoint(long(toolPos.X + newToolDir.X * stepScaled), long(toolPos.Y + newToolDir.Y * stepScaled)); - recalcArea = true; - } + recalcArea = false; + // approach end boundary tangentially + double relDistToBoundary = 4 * distanceToBoundary / stepOverScaled; + if (relDistToBoundary <= 1.0 && passLength > 2 * stepOverFactor + && distanceToEngage > 2 * stepOverScaled + && distBoundaryPointToEngage > 2 * stepOverScaled) { + double wb = 1 - relDistToBoundary; + newToolDir = DoublePoint(newToolDir.X + wb * boundaryDir.X, + newToolDir.Y + wb * boundaryDir.Y); + NormalizeV(newToolDir); + newToolPos = IntPoint(long(toolPos.X + newToolDir.X * stepScaled), + long(toolPos.Y + newToolDir.Y * stepScaled)); + recalcArea = true; + } - //********************************************** - // CHECK AND RECORD NEW TOOL POS - //********************************************** - long rotateStep = 0; - while (!IsPointWithinCutRegion(toolBoundPaths, newToolPos) && rotateStep < 180) - { - rotateStep++; - // if new tool pos. outside boundary rotate until back in - recalcArea = true; - newToolDir = rotate(newToolDir, M_PI / 90); - newToolPos = IntPoint(long(toolPos.X + newToolDir.X * stepScaled), long(toolPos.Y + newToolDir.Y * stepScaled)); - } - if (rotateStep >= 180) - { - #ifdef DEV_MODE - cerr << "Warning: unexpected number of rotate iterations." << endl; - #endif - break; - } - - if (recalcArea) - { - area = CalcCutArea(clip, toolPos, newToolPos, cleared); - } - - // safety condition - if (area > stepScaled * optimalCutAreaPD && areaPD > 2 * optimalCutAreaPD) - { - over_cut_count++; - break; - } - - // update cleared paths when trend of distance from start point changes sign (starts to get closer, or start to get farther) - double distFromStart = sqrt(DistanceSqrd(toolPos, startPoint)); - bool distanceTrend = distFromStart > prevDistFromStart ? true : false; - - if (distanceTrend != prevDistTrend) - { - cleared.ExpandCleared(toClearPath); - toClearPath.clear(); - } - prevDistTrend = distanceTrend; - prevDistFromStart = distFromStart; - - if (area > 0.5 * MIN_CUT_AREA_FACTOR * optimalCutAreaPD * RESOLUTION_FACTOR) - { // cut is ok - record it - noCutDistance=0; - if (toClearPath.empty()) - toClearPath.push_back(toolPos); - toClearPath.push_back(newToolPos); - - cumulativeCutArea += area; - - // append to toolpaths - if (passToolPath.empty()) - { - // in outside entry first successful cut defines the "helix center" and start point - // in this case helix diameter is 0 (straight line downwards) - if (output.AdaptivePaths.empty() && outsideEntry) - { - entryPoint = toolPos; - output.HelixCenterPoint.first = double(entryPoint.X) / scaleFactor; - output.HelixCenterPoint.second = double(entryPoint.Y) / scaleFactor; - output.StartPoint = DPoint(double(entryPoint.X) / scaleFactor, double(entryPoint.Y) / scaleFactor); - } - passToolPath.push_back(toolPos); - } - passToolPath.push_back(newToolPos); - perf_total_len += stepScaled; - passLength += stepScaled; - toolPos = newToolPos; - - // append to progress info paths - if (progressPaths.empty()) - progressPaths.push_back(TPath()); - progressPaths.back().second.emplace_back(double(newToolPos.X) / scaleFactor, double(newToolPos.Y) / scaleFactor); - - // append gyro - gyro.push_back(newToolDir); - gyro.erase(gyro.begin()); - CheckReportProgress(progressPaths); - } - else - { + //********************************************** + // CHECK AND RECORD NEW TOOL POS + //********************************************** + long rotateStep = 0; + while (!IsPointWithinCutRegion(toolBoundPaths, newToolPos) && rotateStep < 180) { + rotateStep++; + // if new tool pos. outside boundary rotate until back in + recalcArea = true; + newToolDir = rotate(newToolDir, M_PI / 90); + newToolPos = IntPoint(long(toolPos.X + newToolDir.X * stepScaled), + long(toolPos.Y + newToolDir.Y * stepScaled)); + } + if (rotateStep >= 180) { #ifdef DEV_MODE - // if(point_index==0) { - // engage_no_cut_count++; - // cout<<"Break:no cut #" << engage_no_cut_count << ", bad engage, pass:" << pass << " over_cut_count:" << over_cut_count << endl; - // } + cerr << "Warning: unexpected number of rotate iterations." << endl; #endif - //cout<<"Break: no cut @" << point_index << endl; - if(noCutDistance>stepOverScaled) break; - noCutDistance+=stepScaled; - } - } /* end of points loop*/ + break; + } - if (!toClearPath.empty()) - { - cleared.ExpandCleared(toClearPath); - toClearPath.clear(); - } - if (cumulativeCutArea > MIN_CUT_AREA_FACTOR * optimalCutAreaPD * RESOLUTION_FACTOR) - { - Path cleaned; - CleanPath(passToolPath, cleaned, CLEAN_PATH_TOLERANCE); - total_output_points += long(cleaned.size()); - AppendToolPath(progressPaths, output, cleaned, clearedBeforePass, cleared, toolBoundPaths); - CheckReportProgress(progressPaths); - bad_engage_count = 0; - engage.ResetPasses(); - } - else - { - bad_engage_count++; - } + if (recalcArea) { + area = CalcCutArea(clip, toolPos, newToolPos, cleared); + } - if (bad_engage_count > 10000) - { - cerr << "Break (next valid engage point not found)." << endl; - break; - } + // safety condition + if (area > stepScaled * optimalCutAreaPD && areaPD > 2 * optimalCutAreaPD) { + over_cut_count++; + break; + } - /*****NEXT ENGAGE POINT******/ - if (firstEngagePoint) - { - engage.moveToClosestPoint(newToolPos, stepScaled + 1); - firstEngagePoint = false; - } - else - { - double moveDistance = ENGAGE_SCAN_DISTANCE_FACTOR * stepOverScaled * refinement_factor; + // update cleared paths when trend of distance from start point changes sign (starts to + // get closer, or start to get farther) + double distFromStart = sqrt(DistanceSqrd(toolPos, startPoint)); + bool distanceTrend = distFromStart > prevDistFromStart ? true : false; - if (!engage.nextEngagePoint(this, cleared, moveDistance, - ENGAGE_AREA_THR_FACTOR * optimalCutAreaPD * RESOLUTION_FACTOR, - 4 * referenceCutArea * stepOverFactor)) - { - // check if there are any uncleared area left - Paths remaining; - for (const auto &p : cleared.GetCleared()) - { - if (!p.empty() && IsPointWithinCutRegion(toolBoundPaths, p.front()) && DistancePointToPathsSqrd(boundPaths, p.front(), clp, clpPathIndex, clpSegmentIndex, clpParameter) > 4 * toolRadiusScaled * toolRadiusScaled) - { - remaining.push_back(p); - } - }; - if (remaining.empty()) - { - cout << "All cleared." << endl; - break; - } - else - { - cout << "Clearing " << remaining.size() << " remaining internal path(s)." << endl; - } + if (distanceTrend != prevDistTrend) { + cleared.ExpandCleared(toClearPath); + toClearPath.clear(); + } + prevDistTrend = distanceTrend; + prevDistFromStart = distFromStart; - // try to find new engage point along the remaining - clipof.Clear(); - clipof.AddPaths(remaining, JoinType::jtRound, EndType::etClosedPolygon); - clipof.Execute(remaining, toolRadiusScaled - 0.5 * stepOverScaled); + if (area > 0.5 * MIN_CUT_AREA_FACTOR * optimalCutAreaPD + * RESOLUTION_FACTOR) { // cut is ok - record it + noCutDistance = 0; + if (toClearPath.empty()) { + toClearPath.push_back(toolPos); + } + toClearPath.push_back(newToolPos); - ReversePaths(remaining); - engage.SetPaths(remaining); - engage.moveToClosestPoint(newToolPos, stepScaled + 1); - if (!engage.nextEngagePoint(this, cleared, moveDistance, - ENGAGE_AREA_THR_FACTOR * optimalCutAreaPD * RESOLUTION_FACTOR, - 4 * referenceCutArea * stepOverFactor)) - break; - } - } - toolPos = engage.getCurrentPoint(); - toolDir = engage.getCurrentDir(); - } + cumulativeCutArea += area; - //********************************** - //* FINISHING PASS * - //********************************** - if(finishingProfile) { - Paths finishingPaths; - clipof.Clear(); - clipof.AddPaths(boundPaths, JoinType::jtRound, EndType::etClosedPolygon); - clipof.Execute(finishingPaths, -toolRadiusScaled); + // append to toolpaths + if (passToolPath.empty()) { + // in outside entry first successful cut defines the "helix center" and start + // point in this case helix diameter is 0 (straight line downwards) + if (output.AdaptivePaths.empty() && outsideEntry) { + entryPoint = toolPos; + output.HelixCenterPoint.first = double(entryPoint.X) / scaleFactor; + output.HelixCenterPoint.second = double(entryPoint.Y) / scaleFactor; + output.StartPoint = DPoint(double(entryPoint.X) / scaleFactor, + double(entryPoint.Y) / scaleFactor); + } + passToolPath.push_back(toolPos); + } + passToolPath.push_back(newToolPos); + perf_total_len += stepScaled; + passLength += stepScaled; + toolPos = newToolPos; - clipof.Clear(); - clipof.AddPaths(finishingPaths, JoinType::jtRound, EndType::etClosedPolygon); - clipof.Execute(toolBoundPaths, -1); + // append to progress info paths + if (progressPaths.empty()) { + progressPaths.push_back(TPath()); + } + progressPaths.back().second.emplace_back(double(newToolPos.X) / scaleFactor, + double(newToolPos.Y) / scaleFactor); - IntPoint lastPoint = toolPos; - Path finShiftedPath; - - bool allCutsAllowed = true; - while(!stopProcessing && PopPathWithClosestPoint(finishingPaths, lastPoint, finShiftedPath)) { - if(finShiftedPath.empty()) - continue; - // skip finishing passes outside the stock boundary - no sense to cut where is no material - bool allPointsOutside = true; - IntPoint p1 = finShiftedPath.front(); - for(const auto& pt : finShiftedPath) { - - // midpoint - if(IsPointWithinCutRegion(stockInputPaths, IntPoint((p1.X + pt.X) / 2, (p1.Y + pt.Y) / 2))) { - allPointsOutside = false; - break; - } - //current point - if(IsPointWithinCutRegion(stockInputPaths, pt)) { - allPointsOutside = false; - break; - } - - p1 = pt; - } - if(allPointsOutside) - continue; - - progressPaths.push_back(TPath()); - // show in progress cb - for(auto& pt : finShiftedPath) { - progressPaths.back().second.emplace_back(double(pt.X) / scaleFactor, double(pt.Y) / scaleFactor); - } - - if(!finShiftedPath.empty()) - finShiftedPath << finShiftedPath.front(); // make sure its closed - - Path finCleaned; - CleanPath(finShiftedPath, finCleaned, FINISHING_CLEAN_PATH_TOLERANCE); - - // sanity check for finishing paths - check the area of finishing cut - for(size_t i = 1; i < finCleaned.size(); i++) { - if(!IsAllowedToCutTrough(finCleaned.at(i - 1), finCleaned.at(i), cleared, toolBoundPaths, 2.0, true)) { - allCutsAllowed = false; - } - } - - // make sure it's closed - finCleaned.push_back(finCleaned.front()); - AppendToolPath(progressPaths, output, finCleaned, cleared, cleared, toolBoundPaths); - - cleared.ExpandCleared(finCleaned); - - if(!finCleaned.empty()) { - lastPoint.X = finCleaned.back().X; - lastPoint.Y = finCleaned.back().Y; - } - } - - Path returnPath; - returnPath << lastPoint; - returnPath << entryPoint; - output.ReturnMotionType = IsClearPath(returnPath, cleared) ? MotionType::mtLinkClear : MotionType::mtLinkNotClear; - - // dump performance results + // append gyro + gyro.push_back(newToolDir); + gyro.erase(gyro.begin()); + CheckReportProgress(progressPaths); + } + else { #ifdef DEV_MODE - Perf_ProcessPolyNode.Stop(); - Perf_ProcessPolyNode.DumpResults(); - Perf_PointIterations.DumpResults(); - Perf_CalcCutAreaCirc.DumpResults(); - Perf_CalcCutAreaClip.DumpResults(); - Perf_NextEngagePoint.DumpResults(); - Perf_ExpandCleared.DumpResults(); - Perf_DistanceToBoundary.DumpResults(); - Perf_AppendToolPath.DumpResults(); - Perf_IsAllowedToCutTrough.DumpResults(); - Perf_IsClearPath.DumpResults(); + // if(point_index==0) { + // engage_no_cut_count++; + // cout<<"Break:no cut #" << engage_no_cut_count << ", bad engage, pass:" << pass + // << " over_cut_count:" << over_cut_count << endl; + // } #endif - CheckReportProgress(progressPaths, true); + // cout<<"Break: no cut @" << point_index << endl; + if (noCutDistance > stepOverScaled) { + break; + } + noCutDistance += stepScaled; + } + } /* end of points loop*/ + + if (!toClearPath.empty()) { + cleared.ExpandCleared(toClearPath); + toClearPath.clear(); + } + if (cumulativeCutArea > MIN_CUT_AREA_FACTOR * optimalCutAreaPD * RESOLUTION_FACTOR) { + Path cleaned; + CleanPath(passToolPath, cleaned, CLEAN_PATH_TOLERANCE); + total_output_points += long(cleaned.size()); + AppendToolPath(progressPaths, + output, + cleaned, + clearedBeforePass, + cleared, + toolBoundPaths); + CheckReportProgress(progressPaths); + bad_engage_count = 0; + engage.ResetPasses(); + } + else { + bad_engage_count++; + } + + if (bad_engage_count > 10000) { + cerr << "Break (next valid engage point not found)." << endl; + break; + } + + /*****NEXT ENGAGE POINT******/ + if (firstEngagePoint) { + engage.moveToClosestPoint(newToolPos, stepScaled + 1); + firstEngagePoint = false; + } + else { + double moveDistance = ENGAGE_SCAN_DISTANCE_FACTOR * stepOverScaled * refinement_factor; + + if (!engage.nextEngagePoint(this, + cleared, + moveDistance, + ENGAGE_AREA_THR_FACTOR * optimalCutAreaPD + * RESOLUTION_FACTOR, + 4 * referenceCutArea * stepOverFactor)) { + // check if there are any uncleared area left + Paths remaining; + for (const auto& p : cleared.GetCleared()) { + if (!p.empty() && IsPointWithinCutRegion(toolBoundPaths, p.front()) + && DistancePointToPathsSqrd(boundPaths, + p.front(), + clp, + clpPathIndex, + clpSegmentIndex, + clpParameter) + > 4 * toolRadiusScaled * toolRadiusScaled) { + remaining.push_back(p); + } + }; + if (remaining.empty()) { + cout << "All cleared." << endl; + break; + } + else { + cout << "Clearing " << remaining.size() << " remaining internal path(s)." + << endl; + } + + // try to find new engage point along the remaining + clipof.Clear(); + clipof.AddPaths(remaining, JoinType::jtRound, EndType::etClosedPolygon); + clipof.Execute(remaining, toolRadiusScaled - 0.5 * stepOverScaled); + + ReversePaths(remaining); + engage.SetPaths(remaining); + engage.moveToClosestPoint(newToolPos, stepScaled + 1); + if (!engage.nextEngagePoint(this, + cleared, + moveDistance, + ENGAGE_AREA_THR_FACTOR * optimalCutAreaPD + * RESOLUTION_FACTOR, + 4 * referenceCutArea * stepOverFactor)) { + break; + } + } + } + toolPos = engage.getCurrentPoint(); + toolDir = engage.getCurrentDir(); + } + + //********************************** + //* FINISHING PASS * + //********************************** + if (finishingProfile) { + Paths finishingPaths; + clipof.Clear(); + clipof.AddPaths(boundPaths, JoinType::jtRound, EndType::etClosedPolygon); + clipof.Execute(finishingPaths, -toolRadiusScaled); + + clipof.Clear(); + clipof.AddPaths(finishingPaths, JoinType::jtRound, EndType::etClosedPolygon); + clipof.Execute(toolBoundPaths, -1); + + IntPoint lastPoint = toolPos; + Path finShiftedPath; + + bool allCutsAllowed = true; + while (!stopProcessing + && PopPathWithClosestPoint(finishingPaths, lastPoint, finShiftedPath)) { + if (finShiftedPath.empty()) { + continue; + } + // skip finishing passes outside the stock boundary - no sense to cut where is no + // material + bool allPointsOutside = true; + IntPoint p1 = finShiftedPath.front(); + for (const auto& pt : finShiftedPath) { + + // midpoint + if (IsPointWithinCutRegion(stockInputPaths, + IntPoint((p1.X + pt.X) / 2, (p1.Y + pt.Y) / 2))) { + allPointsOutside = false; + break; + } + // current point + if (IsPointWithinCutRegion(stockInputPaths, pt)) { + allPointsOutside = false; + break; + } + + p1 = pt; + } + if (allPointsOutside) { + continue; + } + + progressPaths.push_back(TPath()); + // show in progress cb + for (auto& pt : finShiftedPath) { + progressPaths.back().second.emplace_back(double(pt.X) / scaleFactor, + double(pt.Y) / scaleFactor); + } + + if (!finShiftedPath.empty()) { + finShiftedPath << finShiftedPath.front(); // make sure its closed + } + + Path finCleaned; + CleanPath(finShiftedPath, finCleaned, FINISHING_CLEAN_PATH_TOLERANCE); + + // sanity check for finishing paths - check the area of finishing cut + for (size_t i = 1; i < finCleaned.size(); i++) { + if (!IsAllowedToCutTrough(finCleaned.at(i - 1), + finCleaned.at(i), + cleared, + toolBoundPaths, + 2.0, + true)) { + allCutsAllowed = false; + } + } + + // make sure it's closed + finCleaned.push_back(finCleaned.front()); + AppendToolPath(progressPaths, output, finCleaned, cleared, cleared, toolBoundPaths); + + cleared.ExpandCleared(finCleaned); + + if (!finCleaned.empty()) { + lastPoint.X = finCleaned.back().X; + lastPoint.Y = finCleaned.back().Y; + } + } + + Path returnPath; + returnPath << lastPoint; + returnPath << entryPoint; + output.ReturnMotionType = + IsClearPath(returnPath, cleared) ? MotionType::mtLinkClear : MotionType::mtLinkNotClear; + + // dump performance results #ifdef DEV_MODE - double duration = ((double) (clock() - start_clock)) / CLOCKS_PER_SEC; - cout << "PolyNode perf:" << perf_total_len / double(scaleFactor) / duration << " mm/sec" - << " processed_points:" << total_points - << " output_points:" << total_output_points - << " total_iterations:" << total_iterations - << " iter_per_point:" << (double(total_iterations) / ((double(total_points) + 0.001))) - << " total_exceeded:" << total_exceeded << " (" << 100 * double(total_exceeded) / double(total_points) << "%)" - << endl; + Perf_ProcessPolyNode.Stop(); + Perf_ProcessPolyNode.DumpResults(); + Perf_PointIterations.DumpResults(); + Perf_CalcCutAreaCirc.DumpResults(); + Perf_CalcCutAreaClip.DumpResults(); + Perf_NextEngagePoint.DumpResults(); + Perf_ExpandCleared.DumpResults(); + Perf_DistanceToBoundary.DumpResults(); + Perf_AppendToolPath.DumpResults(); + Perf_IsAllowedToCutTrough.DumpResults(); + Perf_IsClearPath.DumpResults(); +#endif + CheckReportProgress(progressPaths, true); +#ifdef DEV_MODE + double duration = ((double)(clock() - start_clock)) / CLOCKS_PER_SEC; + cout << "PolyNode perf:" << perf_total_len / double(scaleFactor) / duration << " mm/sec" + << " processed_points:" << total_points << " output_points:" << total_output_points + << " total_iterations:" << total_iterations + << " iter_per_point:" << (double(total_iterations) / ((double(total_points) + 0.001))) + << " total_exceeded:" << total_exceeded << " (" + << 100 * double(total_exceeded) / double(total_points) << "%)" << endl; #else - (void)total_output_points; - (void)over_cut_count; - (void)total_exceeded; - (void)total_points; - (void)total_iterations; - (void)perf_total_len; + (void)total_output_points; + (void)over_cut_count; + (void)total_exceeded; + (void)total_points; + (void)total_iterations; + (void)perf_total_len; #endif - // warn about invalid paths being detected - if(!allCutsAllowed) { - cerr << "Warning: some cuts may be above optimal step-over. Please double check the results." << endl - << "Hint: try to modify accuracy and/or step-over." << endl; - } - } - results.push_back(output); + // warn about invalid paths being detected + if (!allCutsAllowed) { + cerr << "Warning: some cuts may be above optimal step-over. Please double check the " + "results." + << endl + << "Hint: try to modify accuracy and/or step-over." << endl; + } + } + results.push_back(output); } -} // namespace AdaptivePath +} // namespace AdaptivePath diff --git a/src/Mod/CAM/libarea/Adaptive.hpp b/src/Mod/CAM/libarea/Adaptive.hpp index e0e9ad04ab..497aa2792a 100644 --- a/src/Mod/CAM/libarea/Adaptive.hpp +++ b/src/Mod/CAM/libarea/Adaptive.hpp @@ -1,24 +1,24 @@ /************************************************************************** -* Copyright (c) 2018 Kresimir Tusek * -* * -* This file is part of the FreeCAD CAx development system. * -* * -* This library is free software; you can redistribute it and/or * -* modify it under the terms of the GNU Library General Public * -* License as published by the Free Software Foundation; either * -* version 2 of the License, or (at your option) any later version. * -* * -* This library is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU Library General Public License for more details. * -* * -* You should have received a copy of the GNU Library General Public * -* License along with this library; see the file COPYING.LIB. If not, * -* write to the Free Software Foundation, Inc., 59 Temple Place, * -* Suite 330, Boston, MA 02111-1307, USA * -* * -***************************************************************************/ + * Copyright (c) 2018 Kresimir Tusek * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ #include "clipper.hpp" #include @@ -42,7 +42,7 @@ // #define DEV_MODE -#define NTOL 1.0e-7 // numeric tolerance +#define NTOL 1.0e-7 // numeric tolerance namespace AdaptivePath { @@ -50,24 +50,25 @@ using namespace ClipperLib; enum MotionType { - mtCutting = 0, - mtLinkClear = 1, - mtLinkNotClear = 2, - mtLinkClearAtPrevPass = 3 + mtCutting = 0, + mtLinkClear = 1, + mtLinkNotClear = 2, + mtLinkClearAtPrevPass = 3 }; enum OperationType { - otClearingInside = 0, - otClearingOutside = 1, - otProfilingInside = 2, - otProfilingOutside = 3 + otClearingInside = 0, + otClearingOutside = 1, + otProfilingInside = 2, + otProfilingOutside = 3 }; typedef std::pair DPoint; typedef std::vector DPath; typedef std::vector DPaths; -typedef std::pair TPath; // first parameter is MotionType, must use int due to problem with serialization to JSON in python +typedef std::pair TPath; // first parameter is MotionType, must use int due to problem + // with serialization to JSON in python class ClearedArea; @@ -75,96 +76,134 @@ typedef std::vector TPaths; struct AdaptiveOutput { - DPoint HelixCenterPoint; - DPoint StartPoint; - TPaths AdaptivePaths; - int ReturnMotionType; // MotionType enum, problem with serialization if enum is used + DPoint HelixCenterPoint; + DPoint StartPoint; + TPaths AdaptivePaths; + int ReturnMotionType; // MotionType enum, problem with serialization if enum is used }; // used to isolate state -> enable potential adding of multi-threaded processing of separate regions class Adaptive2d { - public: - Adaptive2d(); - double toolDiameter = 5; - double helixRampDiameter = 0; - double stepOverFactor = 0.2; - double tolerance = 0.1; - double stockToLeave = 0; - bool forceInsideOut = true; - bool finishingProfile = true; - double keepToolDownDistRatio = 3.0; // keep tool down distance ratio - OperationType opType = OperationType::otClearingInside; +public: + Adaptive2d(); + double toolDiameter = 5; + double helixRampDiameter = 0; + double stepOverFactor = 0.2; + double tolerance = 0.1; + double stockToLeave = 0; + bool forceInsideOut = true; + bool finishingProfile = true; + double keepToolDownDistRatio = 3.0; // keep tool down distance ratio + OperationType opType = OperationType::otClearingInside; - std::list Execute(const DPaths &stockPaths, const DPaths &paths, std::function progressCallbackFn); + std::list Execute(const DPaths& stockPaths, + const DPaths& paths, + std::function progressCallbackFn); #ifdef DEV_MODE - /*for debugging*/ - std::function DrawCircleFn; - std::function DrawPathFn; - std::function ClearScreenFn; + /*for debugging*/ + std::function DrawCircleFn; + std::function DrawPathFn; + std::function ClearScreenFn; #endif - private: - std::list results; - Paths inputPaths; - Paths stockInputPaths; - int polyTreeNestingLimit = 0; - long scaleFactor = 100; - double stepOverScaled = 1; - long toolRadiusScaled = 10; - long finishPassOffsetScaled = 0; - long helixRampRadiusScaled = 0; - double referenceCutArea = 0; - double optimalCutAreaPD = 0; - bool stopProcessing = false; - int current_region=0; - clock_t lastProgressTime = 0; +private: + std::list results; + Paths inputPaths; + Paths stockInputPaths; + int polyTreeNestingLimit = 0; + long scaleFactor = 100; + double stepOverScaled = 1; + long toolRadiusScaled = 10; + long finishPassOffsetScaled = 0; + long helixRampRadiusScaled = 0; + double referenceCutArea = 0; + double optimalCutAreaPD = 0; + bool stopProcessing = false; + int current_region = 0; + clock_t lastProgressTime = 0; - std::function *progressCallback = NULL; - Path toolGeometry; // tool geometry at coord 0,0, should not be modified + std::function* progressCallback = NULL; + Path toolGeometry; // tool geometry at coord 0,0, should not be modified - void ProcessPolyNode(Paths boundPaths, Paths toolBoundPaths); - bool FindEntryPoint(TPaths &progressPaths, const Paths &toolBoundPaths, const Paths &bound, ClearedArea &cleared /*output*/, - IntPoint &entryPoint /*output*/, IntPoint &toolPos, DoublePoint &toolDir); - bool FindEntryPointOutside(TPaths &progressPaths, const Paths &toolBoundPaths, const Paths &bound, ClearedArea &cleared /*output*/, - IntPoint &entryPoint /*output*/, IntPoint &toolPos, DoublePoint &toolDir); - double CalcCutArea(Clipper &clip, const IntPoint &toolPos, const IntPoint &newToolPos, ClearedArea &clearedArea, bool preventConventionalMode = true); - void AppendToolPath(TPaths &progressPaths, AdaptiveOutput &output, const Path &passToolPath, ClearedArea &clearedAreaBefore, - ClearedArea &clearedAreaAfter, const Paths &toolBoundPaths); - bool IsClearPath(const Path &path, ClearedArea &clearedArea, double safetyDistanceScaled = 0); - bool IsAllowedToCutTrough(const IntPoint &p1, const IntPoint &p2, ClearedArea &clearedArea, const Paths &toolBoundPaths, double areaFactor = 1.5, bool skipBoundsCheck = false); - bool MakeLeadPath(bool leadIn, const IntPoint &startPoint, const DoublePoint &startDir, const IntPoint &beaconPoint, - ClearedArea &clearedArea, const Paths &toolBoundPaths, Path &output); + void ProcessPolyNode(Paths boundPaths, Paths toolBoundPaths); + bool FindEntryPoint(TPaths& progressPaths, + const Paths& toolBoundPaths, + const Paths& bound, + ClearedArea& cleared /*output*/, + IntPoint& entryPoint /*output*/, + IntPoint& toolPos, + DoublePoint& toolDir); + bool FindEntryPointOutside(TPaths& progressPaths, + const Paths& toolBoundPaths, + const Paths& bound, + ClearedArea& cleared /*output*/, + IntPoint& entryPoint /*output*/, + IntPoint& toolPos, + DoublePoint& toolDir); + double CalcCutArea(Clipper& clip, + const IntPoint& toolPos, + const IntPoint& newToolPos, + ClearedArea& clearedArea, + bool preventConventionalMode = true); + void AppendToolPath(TPaths& progressPaths, + AdaptiveOutput& output, + const Path& passToolPath, + ClearedArea& clearedAreaBefore, + ClearedArea& clearedAreaAfter, + const Paths& toolBoundPaths); + bool IsClearPath(const Path& path, ClearedArea& clearedArea, double safetyDistanceScaled = 0); + bool IsAllowedToCutTrough(const IntPoint& p1, + const IntPoint& p2, + ClearedArea& clearedArea, + const Paths& toolBoundPaths, + double areaFactor = 1.5, + bool skipBoundsCheck = false); + bool MakeLeadPath(bool leadIn, + const IntPoint& startPoint, + const DoublePoint& startDir, + const IntPoint& beaconPoint, + ClearedArea& clearedArea, + const Paths& toolBoundPaths, + Path& output); - bool ResolveLinkPath(const IntPoint &startPoint, const IntPoint &endPoint, ClearedArea &clearedArea, Path &output); + bool ResolveLinkPath(const IntPoint& startPoint, + const IntPoint& endPoint, + ClearedArea& clearedArea, + Path& output); - friend class EngagePoint; // for CalcCutArea + friend class EngagePoint; // for CalcCutArea - void CheckReportProgress(TPaths &progressPaths, bool force = false); - void AddPathsToProgress(TPaths &progressPaths, const Paths paths, MotionType mt = MotionType::mtCutting); - void AddPathToProgress(TPaths &progressPaths, const Path pth, MotionType mt = MotionType::mtCutting); - void ApplyStockToLeave(Paths &inputPaths); + void CheckReportProgress(TPaths& progressPaths, bool force = false); + void AddPathsToProgress(TPaths& progressPaths, + const Paths paths, + MotionType mt = MotionType::mtCutting); + void + AddPathToProgress(TPaths& progressPaths, const Path pth, MotionType mt = MotionType::mtCutting); + void ApplyStockToLeave(Paths& inputPaths); - private: // constants for fine tuning - const double RESOLUTION_FACTOR = 16.0; - const int MAX_ITERATIONS = 10; - const double AREA_ERROR_FACTOR = 0.05; /* how precise to match the cut area to optimal, reasonable value: 0.05 = 5%*/ - const size_t ANGLE_HISTORY_POINTS = 3; // used for angle prediction - const int DIRECTION_SMOOTHING_BUFLEN = 3; // gyro points - used for angle smoothing +private: // constants for fine tuning + const double RESOLUTION_FACTOR = 16.0; + const int MAX_ITERATIONS = 10; + const double AREA_ERROR_FACTOR = + 0.05; /* how precise to match the cut area to optimal, reasonable value: 0.05 = 5%*/ + const size_t ANGLE_HISTORY_POINTS = 3; // used for angle prediction + const int DIRECTION_SMOOTHING_BUFLEN = 3; // gyro points - used for angle smoothing - const double MIN_CUT_AREA_FACTOR = 0.1;// used for filtering out of insignificant cuts (should be < ENGAGE_AREA_THR_FACTOR) - const double ENGAGE_AREA_THR_FACTOR = 0.5; // influences minimal engage area - const double ENGAGE_SCAN_DISTANCE_FACTOR = 0.2; // influences the engage scan/stepping distance + const double MIN_CUT_AREA_FACTOR = + 0.1; // used for filtering out of insignificant cuts (should be < ENGAGE_AREA_THR_FACTOR) + const double ENGAGE_AREA_THR_FACTOR = 0.5; // influences minimal engage area + const double ENGAGE_SCAN_DISTANCE_FACTOR = 0.2; // influences the engage scan/stepping distance - const double CLEAN_PATH_TOLERANCE = 1.41; // should be >1 - const double FINISHING_CLEAN_PATH_TOLERANCE = 1.41; // should be >1 + const double CLEAN_PATH_TOLERANCE = 1.41; // should be >1 + const double FINISHING_CLEAN_PATH_TOLERANCE = 1.41; // should be >1 - const long PASSES_LIMIT = __LONG_MAX__; // limit used while debugging - const long POINTS_PER_PASS_LIMIT = __LONG_MAX__; // limit used while debugging - const clock_t PROGRESS_TICKS = CLOCKS_PER_SEC / 10; // progress report interval + const long PASSES_LIMIT = __LONG_MAX__; // limit used while debugging + const long POINTS_PER_PASS_LIMIT = __LONG_MAX__; // limit used while debugging + const clock_t PROGRESS_TICKS = CLOCKS_PER_SEC / 10; // progress report interval }; -} // namespace AdaptivePath -#endif \ No newline at end of file +} // namespace AdaptivePath +#endif diff --git a/src/Mod/CAM/libarea/Arc.cpp b/src/Mod/CAM/libarea/Arc.cpp index af65d52455..340250fe81 100644 --- a/src/Mod/CAM/libarea/Arc.cpp +++ b/src/Mod/CAM/libarea/Arc.cpp @@ -8,106 +8,124 @@ void CArc::SetDirWithPoint(const Point& p) { - double angs = atan2(m_s.y - m_c.y, m_s.x - m_c.x); - double ange = atan2(m_e.y - m_c.y, m_e.x - m_c.x); - double angp = atan2(p.y - m_c.y, p.x - m_c.x); - if(ange < angs)ange += 6.2831853071795864; - if(angp < angs - 0.0000000000001)angp += 6.2831853071795864; - if(angp > ange + 0.0000000000001)m_dir = false; - else m_dir = true; + double angs = atan2(m_s.y - m_c.y, m_s.x - m_c.x); + double ange = atan2(m_e.y - m_c.y, m_e.x - m_c.x); + double angp = atan2(p.y - m_c.y, p.x - m_c.x); + if (ange < angs) { + ange += 6.2831853071795864; + } + if (angp < angs - 0.0000000000001) { + angp += 6.2831853071795864; + } + if (angp > ange + 0.0000000000001) { + m_dir = false; + } + else { + m_dir = true; + } } -double CArc::IncludedAngle()const +double CArc::IncludedAngle() const { - double angs = atan2(m_s.y - m_c.y, m_s.x - m_c.x); - double ange = atan2(m_e.y - m_c.y, m_e.x - m_c.x); - if(m_dir) - { - // make sure ange > angs - if(ange < angs)ange += 6.2831853071795864; - } - else - { - // make sure angs > ange - if(angs < ange)angs += 6.2831853071795864; - } + double angs = atan2(m_s.y - m_c.y, m_s.x - m_c.x); + double ange = atan2(m_e.y - m_c.y, m_e.x - m_c.x); + if (m_dir) { + // make sure ange > angs + if (ange < angs) { + ange += 6.2831853071795864; + } + } + else { + // make sure angs > ange + if (angs < ange) { + angs += 6.2831853071795864; + } + } - return fabs(ange - angs); + return fabs(ange - angs); } -bool CArc::AlmostALine()const +bool CArc::AlmostALine() const { - Point mid_point = MidParam(0.5); - if(Line(m_s, m_e - m_s).Dist(mid_point) <= Point::tolerance) - return true; + Point mid_point = MidParam(0.5); + if (Line(m_s, m_e - m_s).Dist(mid_point) <= Point::tolerance) { + return true; + } - const double max_arc_radius = 1.0 / Point::tolerance; - double radius = m_c.dist(m_s); - if (radius > max_arc_radius) - { - return true; // We don't want to produce an arc whose radius is too large. - } + const double max_arc_radius = 1.0 / Point::tolerance; + double radius = m_c.dist(m_s); + if (radius > max_arc_radius) { + return true; // We don't want to produce an arc whose radius is too large. + } - return false; + return false; } -Point CArc::MidParam(double param)const { - /// returns a point which is 0-1 along arc - if(fabs(param) < 0.00000000000001) - return m_s; - if(fabs(param - 1.0) < 0.00000000000001) - return m_e; - - Point p; - Point v = m_s - m_c; - v.Rotate(param * IncludedAngle()); - p = v + m_c; - - return p; -} - -//segments - number of segments per full revolution! -//d_angle - determines the direction and the amount of the arc to draw -void CArc::GetSegments(void(*callbackfunc)(const double *p), double pixels_per_mm)const +Point CArc::MidParam(double param) const { - if(m_s == m_e) - return; + /// returns a point which is 0-1 along arc + if (fabs(param) < 0.00000000000001) { + return m_s; + } + if (fabs(param - 1.0) < 0.00000000000001) { + return m_e; + } - Point Va = m_s - m_c; - Point Vb = m_e - m_c; + Point p; + Point v = m_s - m_c; + v.Rotate(param * IncludedAngle()); + p = v + m_c; - double start_angle = atan2(Va.y, Va.x); - double end_angle = atan2(Vb.y, Vb.x); + return p; +} - if(m_dir) - { - if(start_angle > end_angle)end_angle += 6.28318530717958; - } - else - { - if(start_angle < end_angle)end_angle -= 6.28318530717958; - } +// segments - number of segments per full revolution! +// d_angle - determines the direction and the amount of the arc to draw +void CArc::GetSegments(void (*callbackfunc)(const double* p), double pixels_per_mm) const +{ + if (m_s == m_e) { + return; + } - double radius = m_c.dist(m_s); - double d_angle = end_angle - start_angle; - int segments = (int)(fabs(pixels_per_mm * radius * d_angle / 6.28318530717958 + 1)); + Point Va = m_s - m_c; + Point Vb = m_e - m_c; + + double start_angle = atan2(Va.y, Va.x); + double end_angle = atan2(Vb.y, Vb.x); + + if (m_dir) { + if (start_angle > end_angle) { + end_angle += 6.28318530717958; + } + } + else { + if (start_angle < end_angle) { + end_angle -= 6.28318530717958; + } + } + + double radius = m_c.dist(m_s); + double d_angle = end_angle - start_angle; + int segments = (int)(fabs(pixels_per_mm * radius * d_angle / 6.28318530717958 + 1)); double theta = d_angle / (double)segments; - while(theta>1.0){segments*=2;theta = d_angle / (double)segments;} + while (theta > 1.0) { + segments *= 2; + theta = d_angle / (double)segments; + } double tangential_factor = tan(theta); double radial_factor = 1 - cos(theta); double x = radius * cos(start_angle); double y = radius * sin(start_angle); - double pp[3] = {0.0, 0.0, 0.0}; + double pp[3] = {0.0, 0.0, 0.0}; - for(int i = 0; i < segments + 1; i++) - { - Point p = m_c + Point(x, y); - pp[0] = p.x; - pp[1] = p.y; - (*callbackfunc)(pp); + for (int i = 0; i < segments + 1; i++) { + Point p = m_c + Point(x, y); + pp[0] = p.x; + pp[1] = p.y; + (*callbackfunc)(pp); double tx = -y; double ty = x; @@ -115,10 +133,10 @@ void CArc::GetSegments(void(*callbackfunc)(const double *p), double pixels_per_m x += tx * tangential_factor; y += ty * tangential_factor; - double rx = - x; - double ry = - y; + double rx = -x; + double ry = -y; x += rx * radial_factor; y += ry * radial_factor; } -} \ No newline at end of file +} diff --git a/src/Mod/CAM/libarea/Arc.h b/src/Mod/CAM/libarea/Arc.h index a8955e67da..5c18f9dba5 100644 --- a/src/Mod/CAM/libarea/Arc.h +++ b/src/Mod/CAM/libarea/Arc.h @@ -6,20 +6,31 @@ #include "Point.h" -class CArc{ +class CArc +{ public: - Point m_s; - Point m_e; - Point m_c; - bool m_dir; // true - anti-clockwise, false - clockwise - int m_user_data; + Point m_s; + Point m_e; + Point m_c; + bool m_dir; // true - anti-clockwise, false - clockwise + int m_user_data; - CArc():m_dir(true), m_user_data(0){} - CArc(const Point& s, const Point& e, const Point& c, bool dir, int user_data):m_s(s), m_e(e), m_c(c), m_dir(dir), m_user_data(user_data){} + CArc() + : m_dir(true) + , m_user_data(0) + {} + CArc(const Point& s, const Point& e, const Point& c, bool dir, int user_data) + : m_s(s) + , m_e(e) + , m_c(c) + , m_dir(dir) + , m_user_data(user_data) + {} - void SetDirWithPoint(const Point& p); // set m_dir, such that this point lies between m_s and m_e - double IncludedAngle()const; // always > 0 - bool AlmostALine()const; - Point MidParam(double param)const; - void GetSegments(void(*callbackfunc)(const double *p), double pixels_per_mm)const; -}; \ No newline at end of file + void + SetDirWithPoint(const Point& p); // set m_dir, such that this point lies between m_s and m_e + double IncludedAngle() const; // always > 0 + bool AlmostALine() const; + Point MidParam(double param) const; + void GetSegments(void (*callbackfunc)(const double* p), double pixels_per_mm) const; +}; diff --git a/src/Mod/CAM/libarea/Area.cpp b/src/Mod/CAM/libarea/Area.cpp index 3b0f12b8c3..770c150479 100644 --- a/src/Mod/CAM/libarea/Area.cpp +++ b/src/Mod/CAM/libarea/Area.cpp @@ -22,180 +22,200 @@ double CArea::m_MakeOffsets_increment = 0.0; double CArea::m_split_processing_length = 0.0; bool CArea::m_set_processing_length_in_split = false; double CArea::m_after_MakeOffsets_length = 0.0; -//static const double PI = 3.1415926535897932; +// static const double PI = 3.1415926535897932; -#define _CAREA_PARAM_DEFINE(_class,_type,_name) \ - _type CArea::get_##_name() {return _class::_name;}\ - void CArea::set_##_name(_type _name) {_class::_name = _name;} +#define _CAREA_PARAM_DEFINE(_class, _type, _name) \ + _type CArea::get_##_name() \ + { \ + return _class::_name; \ + } \ + void CArea::set_##_name(_type _name) \ + { \ + _class::_name = _name; \ + } -#define CAREA_PARAM_DEFINE(_type,_name) \ - _type CArea::get_##_name() {return m_##_name;}\ - void CArea::set_##_name(_type _name) {m_##_name = _name;} +#define CAREA_PARAM_DEFINE(_type, _name) \ + _type CArea::get_##_name() \ + { \ + return m_##_name; \ + } \ + void CArea::set_##_name(_type _name) \ + { \ + m_##_name = _name; \ + } -_CAREA_PARAM_DEFINE(Point,double,tolerance) -CAREA_PARAM_DEFINE(bool,fit_arcs) -CAREA_PARAM_DEFINE(bool,clipper_simple) -CAREA_PARAM_DEFINE(double,clipper_clean_distance) -CAREA_PARAM_DEFINE(double,accuracy) -CAREA_PARAM_DEFINE(double,units) -CAREA_PARAM_DEFINE(short,min_arc_points) -CAREA_PARAM_DEFINE(short,max_arc_points) -CAREA_PARAM_DEFINE(double,clipper_scale) +_CAREA_PARAM_DEFINE(Point, double, tolerance) +CAREA_PARAM_DEFINE(bool, fit_arcs) +CAREA_PARAM_DEFINE(bool, clipper_simple) +CAREA_PARAM_DEFINE(double, clipper_clean_distance) +CAREA_PARAM_DEFINE(double, accuracy) +CAREA_PARAM_DEFINE(double, units) +CAREA_PARAM_DEFINE(short, min_arc_points) +CAREA_PARAM_DEFINE(short, max_arc_points) +CAREA_PARAM_DEFINE(double, clipper_scale) void CArea::append(const CCurve& curve) { - m_curves.push_back(curve); + m_curves.push_back(curve); } void CArea::move(CCurve&& curve) { - m_curves.push_back(std::move(curve)); + m_curves.push_back(std::move(curve)); } -void CArea::FitArcs(){ - for(std::list::iterator It = m_curves.begin(); It != m_curves.end(); It++) - { - CCurve& curve = *It; - curve.FitArcs(); - } -} - -Point CArea::NearestPoint(const Point& p)const +void CArea::FitArcs() { - double best_dist = 0.0; - Point best_point = Point(0, 0); - for(std::list::const_iterator It = m_curves.begin(); It != m_curves.end(); It++) - { - const CCurve& curve = *It; - Point near_point = curve.NearestPoint(p); - double dist = near_point.dist(p); - if(It == m_curves.begin() || dist < best_dist) - { - best_dist = dist; - best_point = near_point; - } - } - return best_point; + for (std::list::iterator It = m_curves.begin(); It != m_curves.end(); It++) { + CCurve& curve = *It; + curve.FitArcs(); + } } -void CArea::ChangeStartToNearest(const Point *point, double min_dist) +Point CArea::NearestPoint(const Point& p) const { - for(std::list::iterator It=m_curves.begin(),ItNext=It; - It != m_curves.end(); It=ItNext) - { + double best_dist = 0.0; + Point best_point = Point(0, 0); + for (std::list::const_iterator It = m_curves.begin(); It != m_curves.end(); It++) { + const CCurve& curve = *It; + Point near_point = curve.NearestPoint(p); + double dist = near_point.dist(p); + if (It == m_curves.begin() || dist < best_dist) { + best_dist = dist; + best_point = near_point; + } + } + return best_point; +} + +void CArea::ChangeStartToNearest(const Point* point, double min_dist) +{ + for (std::list::iterator It = m_curves.begin(), ItNext = It; It != m_curves.end(); + It = ItNext) { ++ItNext; - if(It->m_vertices.size()<=1) + if (It->m_vertices.size() <= 1) { m_curves.erase(It); + } } - if(m_curves.empty()) + if (m_curves.empty()) { return; + } std::list curves; Point p; - if(point) p =*point; - if(min_dist < Point::tolerance) + if (point) { + p = *point; + } + if (min_dist < Point::tolerance) { min_dist = Point::tolerance; + } - while(m_curves.size()) { - std::list::iterator It=m_curves.begin(); - std::list::iterator ItBest=It++; + while (m_curves.size()) { + std::list::iterator It = m_curves.begin(); + std::list::iterator ItBest = It++; Point best_point = ItBest->NearestPoint(p); double best_dist = p.dist(best_point); - for(; It != m_curves.end(); ++It) - { + for (; It != m_curves.end(); ++It) { const CCurve& curve = *It; Point near_point; double dist; - if(min_dist>Point::tolerance && !curve.IsClosed()) { + if (min_dist > Point::tolerance && !curve.IsClosed()) { double d1 = curve.m_vertices.front().m_p.dist(p); double d2 = curve.m_vertices.back().m_p.dist(p); - if(d1IsClosed()) { + if (ItBest->IsClosed()) { ItBest->ChangeStart(best_point); - }else{ + } + else { double dfront = ItBest->m_vertices.front().m_p.dist(best_point); double dback = ItBest->m_vertices.back().m_p.dist(best_point); - if(min_dist>Point::tolerance && dfront>min_dist && dback>min_dist) { + if (min_dist > Point::tolerance && dfront > min_dist && dback > min_dist) { ItBest->Break(best_point); m_curves.push_back(*ItBest); m_curves.back().ChangeEnd(best_point); ItBest->ChangeStart(best_point); - }else if(dfront>dback) + } + else if (dfront > dback) { ItBest->Reverse(); + } } - curves.splice(curves.end(),m_curves,ItBest); + curves.splice(curves.end(), m_curves, ItBest); p = curves.back().m_vertices.back().m_p; } - m_curves.splice(m_curves.end(),curves); + m_curves.splice(m_curves.end(), curves); } -void CArea::GetBox(CBox2D &box) +void CArea::GetBox(CBox2D& box) { - for(std::list::iterator It = m_curves.begin(); It != m_curves.end(); It++) - { - CCurve& curve = *It; - curve.GetBox(box); - } + for (std::list::iterator It = m_curves.begin(); It != m_curves.end(); It++) { + CCurve& curve = *It; + curve.GetBox(box); + } } void CArea::Reorder() { - // curves may have been added with wrong directions - // test all kurves to see which one are outsides and which are insides and - // make sure outsides are anti-clockwise and insides are clockwise + // curves may have been added with wrong directions + // test all kurves to see which one are outsides and which are insides and + // make sure outsides are anti-clockwise and insides are clockwise - // returns 0, if the curves are OK - // returns 1, if the curves are overlapping + // returns 0, if the curves are OK + // returns 1, if the curves are overlapping - CAreaOrderer ao; - for(std::list::iterator It = m_curves.begin(), ItNext=It; It != m_curves.end(); It=ItNext) - { + CAreaOrderer ao; + for (std::list::iterator It = m_curves.begin(), ItNext = It; It != m_curves.end(); + It = ItNext) { ++ItNext; - CCurve& curve = *It; - if(!It->IsClosed()) + CCurve& curve = *It; + if (!It->IsClosed()) { continue; - ao.Insert(make_shared(curve)); - if(m_set_processing_length_in_split) - { - CArea::m_processing_done += (m_split_processing_length / m_curves.size()); - } + } + ao.Insert(make_shared(curve)); + if (m_set_processing_length_in_split) { + CArea::m_processing_done += (m_split_processing_length / m_curves.size()); + } m_curves.erase(It); - } + } - if(ao.m_top_level) + if (ao.m_top_level) { ao.m_top_level->GetArea(*this); + } } class ZigZag { public: - CCurve zig; - CCurve zag; - ZigZag(const CCurve& Zig, const CCurve& Zag):zig(Zig), zag(Zag){} + CCurve zig; + CCurve zag; + ZigZag(const CCurve& Zig, const CCurve& Zag) + : zig(Zig) + , zag(Zag) + {} }; static double stepover_for_pocket = 0.0; static std::list zigzag_list_for_zigs; -static std::list *curve_list_for_zigs = NULL; +static std::list* curve_list_for_zigs = NULL; static bool rightward_for_zigs = true; static double sin_angle_for_zigs = 0.0; static double cos_angle_for_zigs = 0.0; @@ -203,253 +223,273 @@ static double sin_minus_angle_for_zigs = 0.0; static double cos_minus_angle_for_zigs = 0.0; static double one_over_units = 0.0; -static Point rotated_point(const Point &p) +static Point rotated_point(const Point& p) { - return Point(p.x * cos_angle_for_zigs - p.y * sin_angle_for_zigs, p.x * sin_angle_for_zigs + p.y * cos_angle_for_zigs); -} - -static Point unrotated_point(const Point &p) -{ - return Point(p.x * cos_minus_angle_for_zigs - p.y * sin_minus_angle_for_zigs, p.x * sin_minus_angle_for_zigs + p.y * cos_minus_angle_for_zigs); + return Point(p.x * cos_angle_for_zigs - p.y * sin_angle_for_zigs, + p.x * sin_angle_for_zigs + p.y * cos_angle_for_zigs); } -static CVertex rotated_vertex(const CVertex &v) +static Point unrotated_point(const Point& p) { - if(v.m_type) - { - return CVertex(v.m_type, rotated_point(v.m_p), rotated_point(v.m_c)); - } + return Point(p.x * cos_minus_angle_for_zigs - p.y * sin_minus_angle_for_zigs, + p.x * sin_minus_angle_for_zigs + p.y * cos_minus_angle_for_zigs); +} + +static CVertex rotated_vertex(const CVertex& v) +{ + if (v.m_type) { + return CVertex(v.m_type, rotated_point(v.m_p), rotated_point(v.m_c)); + } return CVertex(v.m_type, rotated_point(v.m_p), Point(0, 0)); } -static CVertex unrotated_vertex(const CVertex &v) +static CVertex unrotated_vertex(const CVertex& v) { - if(v.m_type) - { - return CVertex(v.m_type, unrotated_point(v.m_p), unrotated_point(v.m_c)); - } - return CVertex(v.m_type, unrotated_point(v.m_p), Point(0, 0)); + if (v.m_type) { + return CVertex(v.m_type, unrotated_point(v.m_p), unrotated_point(v.m_c)); + } + return CVertex(v.m_type, unrotated_point(v.m_p), Point(0, 0)); } -static void rotate_area(CArea &a) +static void rotate_area(CArea& a) { - for(std::list::iterator It = a.m_curves.begin(); It != a.m_curves.end(); It++) - { - CCurve& curve = *It; - for(std::list::iterator CIt = curve.m_vertices.begin(); CIt != curve.m_vertices.end(); CIt++) - { - CVertex& vt = *CIt; - vt = rotated_vertex(vt); - } - } + for (std::list::iterator It = a.m_curves.begin(); It != a.m_curves.end(); It++) { + CCurve& curve = *It; + for (std::list::iterator CIt = curve.m_vertices.begin(); + CIt != curve.m_vertices.end(); + CIt++) { + CVertex& vt = *CIt; + vt = rotated_vertex(vt); + } + } } -void test_y_point(int i, const Point& p, Point& best_p, bool &found, int &best_index, double y, bool left_not_right) +void test_y_point(int i, + const Point& p, + Point& best_p, + bool& found, + int& best_index, + double y, + bool left_not_right) { - // only consider points at y - if(fabs(p.y - y) < 0.002 * one_over_units) - { - if(found) - { - // equal high point - if(left_not_right) - { - // use the furthest left point - if(p.x < best_p.x) - { - best_p = p; - best_index = i; - } - } - else - { - // use the furthest right point - if(p.x > best_p.x) - { - best_p = p; - best_index = i; - } - } - } - else - { - best_p = p; - best_index = i; - found = true; - } - } + // only consider points at y + if (fabs(p.y - y) < 0.002 * one_over_units) { + if (found) { + // equal high point + if (left_not_right) { + // use the furthest left point + if (p.x < best_p.x) { + best_p = p; + best_index = i; + } + } + else { + // use the furthest right point + if (p.x > best_p.x) { + best_p = p; + best_index = i; + } + } + } + else { + best_p = p; + best_index = i; + found = true; + } + } } static void make_zig_curve(const CCurve& input_curve, double y0, double y) { - CCurve curve(input_curve); + CCurve curve(input_curve); - if(rightward_for_zigs) - { - if(curve.IsClockwise()) - curve.Reverse(); - } - else - { - if(!curve.IsClockwise()) - curve.Reverse(); - } + if (rightward_for_zigs) { + if (curve.IsClockwise()) { + curve.Reverse(); + } + } + else { + if (!curve.IsClockwise()) { + curve.Reverse(); + } + } // find a high point to start looking from - Point top_left; - int top_left_index = 0; - bool top_left_found = false; - Point top_right; - int top_right_index = 0; - bool top_right_found = false; - Point bottom_left; - int bottom_left_index = 0; - bool bottom_left_found = false; + Point top_left; + int top_left_index = 0; + bool top_left_found = false; + Point top_right; + int top_right_index = 0; + bool top_right_found = false; + Point bottom_left; + int bottom_left_index = 0; + bool bottom_left_found = false; - int i =0; - for(std::list::const_iterator VIt = curve.m_vertices.begin(); VIt != curve.m_vertices.end(); VIt++, i++) - { - const CVertex& vertex = *VIt; + int i = 0; + for (std::list::const_iterator VIt = curve.m_vertices.begin(); + VIt != curve.m_vertices.end(); + VIt++, i++) { + const CVertex& vertex = *VIt; - test_y_point(i, vertex.m_p, top_right, top_right_found, top_right_index, y, !rightward_for_zigs); - test_y_point(i, vertex.m_p, top_left, top_left_found, top_left_index, y, rightward_for_zigs); - test_y_point(i, vertex.m_p, bottom_left, bottom_left_found, bottom_left_index, y0, rightward_for_zigs); - } + test_y_point(i, + vertex.m_p, + top_right, + top_right_found, + top_right_index, + y, + !rightward_for_zigs); + test_y_point(i, + vertex.m_p, + top_left, + top_left_found, + top_left_index, + y, + rightward_for_zigs); + test_y_point(i, + vertex.m_p, + bottom_left, + bottom_left_found, + bottom_left_index, + y0, + rightward_for_zigs); + } - int start_index = 0; - int end_index = 0; - int zag_end_index = 0; + int start_index = 0; + int end_index = 0; + int zag_end_index = 0; - if(bottom_left_found)start_index = bottom_left_index; - else if(top_left_found)start_index = top_left_index; + if (bottom_left_found) { + start_index = bottom_left_index; + } + else if (top_left_found) { + start_index = top_left_index; + } - if(top_right_found) - { - end_index = top_right_index; - zag_end_index = top_left_index; - } - else - { - end_index = bottom_left_index; - zag_end_index = bottom_left_index; - } - if(end_index <= start_index)end_index += (i-1); - if(zag_end_index <= start_index)zag_end_index += (i-1); + if (top_right_found) { + end_index = top_right_index; + zag_end_index = top_left_index; + } + else { + end_index = bottom_left_index; + zag_end_index = bottom_left_index; + } + if (end_index <= start_index) { + end_index += (i - 1); + } + if (zag_end_index <= start_index) { + zag_end_index += (i - 1); + } CCurve zig, zag; - + bool zig_started = false; bool zig_finished = false; bool zag_finished = false; - - int v_index = 0; - for(int i = 0; i < 2; i++) - { - // process the curve twice because we don't know where it will start - if(zag_finished) - break; - for(std::list::const_iterator VIt = curve.m_vertices.begin(); VIt != curve.m_vertices.end(); VIt++) - { - if(i == 1 && VIt == curve.m_vertices.begin()) - { - continue; - } - const CVertex& vertex = *VIt; + int v_index = 0; + for (int i = 0; i < 2; i++) { + // process the curve twice because we don't know where it will start + if (zag_finished) { + break; + } + for (std::list::const_iterator VIt = curve.m_vertices.begin(); + VIt != curve.m_vertices.end(); + VIt++) { + if (i == 1 && VIt == curve.m_vertices.begin()) { + continue; + } - if(zig_finished) - { - zag.m_vertices.push_back(unrotated_vertex(vertex)); - if(v_index == zag_end_index) - { - zag_finished = true; - break; - } - } - else if(zig_started) - { - zig.m_vertices.push_back(unrotated_vertex(vertex)); - if(v_index == end_index) - { - zig_finished = true; - if(v_index == zag_end_index) - { - zag_finished = true; - break; - } - zag.m_vertices.push_back(unrotated_vertex(vertex)); - } - } - else - { - if(v_index == start_index) - { - zig.m_vertices.push_back(unrotated_vertex(vertex)); - zig_started = true; - } - } - v_index++; - } - } - - if(zig_finished) - zigzag_list_for_zigs.emplace_back(zig, zag); + const CVertex& vertex = *VIt; + + if (zig_finished) { + zag.m_vertices.push_back(unrotated_vertex(vertex)); + if (v_index == zag_end_index) { + zag_finished = true; + break; + } + } + else if (zig_started) { + zig.m_vertices.push_back(unrotated_vertex(vertex)); + if (v_index == end_index) { + zig_finished = true; + if (v_index == zag_end_index) { + zag_finished = true; + break; + } + zag.m_vertices.push_back(unrotated_vertex(vertex)); + } + } + else { + if (v_index == start_index) { + zig.m_vertices.push_back(unrotated_vertex(vertex)); + zig_started = true; + } + } + v_index++; + } + } + + if (zig_finished) { + zigzag_list_for_zigs.emplace_back(zig, zag); + } } -void make_zig(const CArea &a, double y0, double y) +void make_zig(const CArea& a, double y0, double y) { - for(std::list::const_iterator It = a.m_curves.begin(); It != a.m_curves.end(); It++) - { - const CCurve &curve = *It; - make_zig_curve(curve, y0, y); - } + for (std::list::const_iterator It = a.m_curves.begin(); It != a.m_curves.end(); It++) { + const CCurve& curve = *It; + make_zig_curve(curve, y0, y); + } } - -std::list< std::list > reorder_zig_list_list; - -void add_reorder_zig(ZigZag &zigzag) + +std::list> reorder_zig_list_list; + +void add_reorder_zig(ZigZag& zigzag) { // look in existing lists - // see if the zag is part of an existing zig - if(zigzag.zag.m_vertices.size() > 1) - { - const Point& zag_e = zigzag.zag.m_vertices.front().m_p; - bool zag_removed = false; - for(std::list< std::list >::iterator It = reorder_zig_list_list.begin(); It != reorder_zig_list_list.end() && !zag_removed; It++) - { - std::list &zigzag_list = *It; - for(std::list::iterator It2 = zigzag_list.begin(); It2 != zigzag_list.end() && !zag_removed; It2++) - { - const ZigZag& z = *It2; - for(std::list::const_iterator It3 = z.zig.m_vertices.begin(); It3 != z.zig.m_vertices.end() && !zag_removed; It3++) - { - const CVertex &v = *It3; - if((fabs(zag_e.x - v.m_p.x) < (0.002 * one_over_units)) && (fabs(zag_e.y - v.m_p.y) < (0.002 * one_over_units))) - { - // remove zag from zigzag - zigzag.zag.m_vertices.clear(); - zag_removed = true; - } - } - } - } - } + // see if the zag is part of an existing zig + if (zigzag.zag.m_vertices.size() > 1) { + const Point& zag_e = zigzag.zag.m_vertices.front().m_p; + bool zag_removed = false; + for (std::list>::iterator It = reorder_zig_list_list.begin(); + It != reorder_zig_list_list.end() && !zag_removed; + It++) { + std::list& zigzag_list = *It; + for (std::list::iterator It2 = zigzag_list.begin(); + It2 != zigzag_list.end() && !zag_removed; + It2++) { + const ZigZag& z = *It2; + for (std::list::const_iterator It3 = z.zig.m_vertices.begin(); + It3 != z.zig.m_vertices.end() && !zag_removed; + It3++) { + const CVertex& v = *It3; + if ((fabs(zag_e.x - v.m_p.x) < (0.002 * one_over_units)) + && (fabs(zag_e.y - v.m_p.y) < (0.002 * one_over_units))) { + // remove zag from zigzag + zigzag.zag.m_vertices.clear(); + zag_removed = true; + } + } + } + } + } - // see if the zigzag can join the end of an existing list - const Point& zig_s = zigzag.zig.m_vertices.front().m_p; - for(std::list< std::list >::iterator It = reorder_zig_list_list.begin(); It != reorder_zig_list_list.end(); It++) - { - std::list &zigzag_list = *It; - const ZigZag& last_zigzag = zigzag_list.back(); + // see if the zigzag can join the end of an existing list + const Point& zig_s = zigzag.zig.m_vertices.front().m_p; + for (std::list>::iterator It = reorder_zig_list_list.begin(); + It != reorder_zig_list_list.end(); + It++) { + std::list& zigzag_list = *It; + const ZigZag& last_zigzag = zigzag_list.back(); const Point& e = last_zigzag.zig.m_vertices.back().m_p; - if((fabs(zig_s.x - e.x) < (0.002 * one_over_units)) && (fabs(zig_s.y - e.y) < (0.002 * one_over_units))) - { + if ((fabs(zig_s.x - e.x) < (0.002 * one_over_units)) + && (fabs(zig_s.y - e.y) < (0.002 * one_over_units))) { zigzag_list.push_back(zigzag); - return; - } - } - + return; + } + } + // else add a new list std::list zigzag_list; zigzag_list.push_back(zigzag); @@ -458,475 +498,490 @@ void add_reorder_zig(ZigZag &zigzag) void reorder_zigs() { - for(std::list::iterator It = zigzag_list_for_zigs.begin(); It != zigzag_list_for_zigs.end(); It++) - { - ZigZag &zigzag = *It; + for (std::list::iterator It = zigzag_list_for_zigs.begin(); + It != zigzag_list_for_zigs.end(); + It++) { + ZigZag& zigzag = *It; add_reorder_zig(zigzag); - } - - zigzag_list_for_zigs.clear(); + } - for(std::list< std::list >::iterator It = reorder_zig_list_list.begin(); It != reorder_zig_list_list.end(); It++) - { - std::list &zigzag_list = *It; - if(zigzag_list.size() == 0)continue; + zigzag_list_for_zigs.clear(); - curve_list_for_zigs->push_back(CCurve()); - for(std::list::const_iterator It = zigzag_list.begin(); It != zigzag_list.end();) - { - const ZigZag &zigzag = *It; - for(std::list::const_iterator It2 = zigzag.zig.m_vertices.begin(); It2 != zigzag.zig.m_vertices.end(); It2++) - { - if(It2 == zigzag.zig.m_vertices.begin() && It != zigzag_list.begin())continue; // only add the first vertex if doing the first zig - const CVertex &v = *It2; - curve_list_for_zigs->back().m_vertices.push_back(v); - } + for (std::list>::iterator It = reorder_zig_list_list.begin(); + It != reorder_zig_list_list.end(); + It++) { + std::list& zigzag_list = *It; + if (zigzag_list.size() == 0) { + continue; + } - It++; - if(It == zigzag_list.end()) - { - for(std::list::const_iterator It2 = zigzag.zag.m_vertices.begin(); It2 != zigzag.zag.m_vertices.end(); It2++) - { - if(It2 == zigzag.zag.m_vertices.begin())continue; // don't add the first vertex of the zag - const CVertex &v = *It2; - curve_list_for_zigs->back().m_vertices.push_back(v); - } - } - } - } - reorder_zig_list_list.clear(); + curve_list_for_zigs->push_back(CCurve()); + for (std::list::const_iterator It = zigzag_list.begin(); It != zigzag_list.end();) { + const ZigZag& zigzag = *It; + for (std::list::const_iterator It2 = zigzag.zig.m_vertices.begin(); + It2 != zigzag.zig.m_vertices.end(); + It2++) { + if (It2 == zigzag.zig.m_vertices.begin() && It != zigzag_list.begin()) { + continue; // only add the first vertex if doing the first zig + } + const CVertex& v = *It2; + curve_list_for_zigs->back().m_vertices.push_back(v); + } + + It++; + if (It == zigzag_list.end()) { + for (std::list::const_iterator It2 = zigzag.zag.m_vertices.begin(); + It2 != zigzag.zag.m_vertices.end(); + It2++) { + if (It2 == zigzag.zag.m_vertices.begin()) { + continue; // don't add the first vertex of the zag + } + const CVertex& v = *It2; + curve_list_for_zigs->back().m_vertices.push_back(v); + } + } + } + } + reorder_zig_list_list.clear(); } -static void zigzag(const CArea &input_a) +static void zigzag(const CArea& input_a) { - if(input_a.m_curves.size() == 0) - { - CArea::m_processing_done += CArea::m_single_area_processing_length; - return; - } - + if (input_a.m_curves.size() == 0) { + CArea::m_processing_done += CArea::m_single_area_processing_length; + return; + } + one_over_units = 1 / CArea::m_units; - - CArea a(input_a); + + CArea a(input_a); rotate_area(a); - + CBox2D b; - a.GetBox(b); - + a.GetBox(b); + double x0 = b.MinX() - 1.0; double x1 = b.MaxX() + 1.0; double height = b.MaxY() - b.MinY(); int num_steps = int(height / stepover_for_pocket + 1); - double y = b.MinY();// + 0.1 * one_over_units; + double y = b.MinY(); // + 0.1 * one_over_units; Point null_point(0, 0); - rightward_for_zigs = true; + rightward_for_zigs = true; - if(CArea::m_please_abort) - return; + if (CArea::m_please_abort) { + return; + } - double step_percent_increment = 0.8 * CArea::m_single_area_processing_length / num_steps; + double step_percent_increment = 0.8 * CArea::m_single_area_processing_length / num_steps; - for(int i = 0; i &curve_list, const CAreaPocketParams ¶ms)const +void CArea::SplitAndMakePocketToolpath(std::list& curve_list, + const CAreaPocketParams& params) const { - CArea::m_processing_done = 0.0; + CArea::m_processing_done = 0.0; - double save_units = CArea::m_units; - CArea::m_units = 1.0; - std::list areas; - m_split_processing_length = 50.0; // jump to 50 percent after split - m_set_processing_length_in_split = true; - Split(areas); - m_set_processing_length_in_split = false; - CArea::m_processing_done = m_split_processing_length; - CArea::m_units = save_units; + double save_units = CArea::m_units; + CArea::m_units = 1.0; + std::list areas; + m_split_processing_length = 50.0; // jump to 50 percent after split + m_set_processing_length_in_split = true; + Split(areas); + m_set_processing_length_in_split = false; + CArea::m_processing_done = m_split_processing_length; + CArea::m_units = save_units; - if(areas.size() == 0) - return; + if (areas.size() == 0) { + return; + } - double single_area_length = 50.0 / areas.size(); + double single_area_length = 50.0 / areas.size(); - for(std::list::iterator It = areas.begin(); It != areas.end(); It++) - { - CArea::m_single_area_processing_length = single_area_length; - CArea &ar = *It; - ar.MakePocketToolpath(curve_list, params); - } + for (std::list::iterator It = areas.begin(); It != areas.end(); It++) { + CArea::m_single_area_processing_length = single_area_length; + CArea& ar = *It; + ar.MakePocketToolpath(curve_list, params); + } } -void CArea::MakePocketToolpath(std::list &curve_list, const CAreaPocketParams ¶ms)const +void CArea::MakePocketToolpath(std::list& curve_list, const CAreaPocketParams& params) const { - double radians_angle = params.zig_angle * PI / 180; - sin_angle_for_zigs = sin(-radians_angle); - cos_angle_for_zigs = cos(-radians_angle); - sin_minus_angle_for_zigs = sin(radians_angle); - cos_minus_angle_for_zigs = cos(radians_angle); - stepover_for_pocket = params.stepover; + double radians_angle = params.zig_angle * PI / 180; + sin_angle_for_zigs = sin(-radians_angle); + cos_angle_for_zigs = cos(-radians_angle); + sin_minus_angle_for_zigs = sin(radians_angle); + cos_minus_angle_for_zigs = cos(radians_angle); + stepover_for_pocket = params.stepover; - CArea a_offset = *this; - double current_offset = params.tool_radius + params.extra_offset; + CArea a_offset = *this; + double current_offset = params.tool_radius + params.extra_offset; - a_offset.Offset(current_offset); + a_offset.Offset(current_offset); - if(params.mode == ZigZagPocketMode || params.mode == ZigZagThenSingleOffsetPocketMode) - { - curve_list_for_zigs = &curve_list; - zigzag(a_offset); - } - else if(params.mode == SpiralPocketMode) - { - std::list m_areas; - a_offset.Split(m_areas); - if(CArea::m_please_abort) - return; - if(m_areas.size() == 0) - { - CArea::m_processing_done += CArea::m_single_area_processing_length; - return; - } + if (params.mode == ZigZagPocketMode || params.mode == ZigZagThenSingleOffsetPocketMode) { + curve_list_for_zigs = &curve_list; + zigzag(a_offset); + } + else if (params.mode == SpiralPocketMode) { + std::list m_areas; + a_offset.Split(m_areas); + if (CArea::m_please_abort) { + return; + } + if (m_areas.size() == 0) { + CArea::m_processing_done += CArea::m_single_area_processing_length; + return; + } - CArea::m_single_area_processing_length /= m_areas.size(); + CArea::m_single_area_processing_length /= m_areas.size(); - for(std::list::iterator It = m_areas.begin(); It != m_areas.end(); It++) - { - CArea &a2 = *It; - a2.MakeOnePocketCurve(curve_list, params); - } - } + for (std::list::iterator It = m_areas.begin(); It != m_areas.end(); It++) { + CArea& a2 = *It; + a2.MakeOnePocketCurve(curve_list, params); + } + } - if(params.mode == SingleOffsetPocketMode || params.mode == ZigZagThenSingleOffsetPocketMode) - { - // if there are already curves, attempt to start the offset from the current tool position - bool done = false; - if (!curve_list.empty() && !curve_list.back().m_vertices.empty()) { - // find the closest curve to the start point - const Point start = curve_list.back().m_vertices.back().m_p; - auto curve_itmin = a_offset.m_curves.begin(); - double dmin = Point::tolerance; - for (auto it = a_offset.m_curves.begin(); it != a_offset.m_curves.end(); it++) { - const double dist = it->NearestPoint(start).dist(start); - if (dist < dmin) { - dmin = dist; - curve_itmin = it; - } - } + if (params.mode == SingleOffsetPocketMode || params.mode == ZigZagThenSingleOffsetPocketMode) { + // if there are already curves, attempt to start the offset from the current tool position + bool done = false; + if (!curve_list.empty() && !curve_list.back().m_vertices.empty()) { + // find the closest curve to the start point + const Point start = curve_list.back().m_vertices.back().m_p; + auto curve_itmin = a_offset.m_curves.begin(); + double dmin = Point::tolerance; + for (auto it = a_offset.m_curves.begin(); it != a_offset.m_curves.end(); it++) { + const double dist = it->NearestPoint(start).dist(start); + if (dist < dmin) { + dmin = dist; + curve_itmin = it; + } + } - // if the start point is on that curve (within Point::tolerance), do the profile starting on that curve - if (dmin < Point::tolerance) { - // split the curve into two parts -- starting with this point, and ending with this point - CCurve startCurve; - CCurve endCurve; + // if the start point is on that curve (within Point::tolerance), do the profile + // starting on that curve + if (dmin < Point::tolerance) { + // split the curve into two parts -- starting with this point, and ending with this + // point + CCurve startCurve; + CCurve endCurve; - std::list spans; - curve_itmin->GetSpans(spans); - int imin = -1; - double dmin = std::numeric_limits::max(); - Point nmin; - Span smin; - { - int i = 0; - for (auto it = spans.begin(); it != spans.end(); i++, it++) { - const Point nearest = it->NearestPoint(start); - const double dist = nearest.dist(start); - if (dist < dmin) { - dmin = dist; - imin = i; - nmin = nearest; - smin = *it; - } - } - } - - startCurve.append(CVertex(nmin)); - endCurve.append(curve_itmin->m_vertices.front()); - { - int i =0; - for (auto it = spans.begin(); it != spans.end(); i++, it++) { - if (i < imin) { - endCurve.append(it->m_v); - } else if (i > imin) { - startCurve.append(it->m_v); - } else { - if (nmin != endCurve.m_vertices.back().m_p) { - endCurve.append(CVertex(smin.m_v.m_type, nmin, smin.m_v.m_c, smin.m_v.m_user_data)); - } - if (nmin != it->m_v.m_p) { - startCurve.append(CVertex(smin.m_v.m_type, it->m_v.m_p, smin.m_v.m_c, smin.m_v.m_user_data)); - } - } - } - } + std::list spans; + curve_itmin->GetSpans(spans); + int imin = -1; + double dmin = std::numeric_limits::max(); + Point nmin; + Span smin; + { + int i = 0; + for (auto it = spans.begin(); it != spans.end(); i++, it++) { + const Point nearest = it->NearestPoint(start); + const double dist = nearest.dist(start); + if (dist < dmin) { + dmin = dist; + imin = i; + nmin = nearest; + smin = *it; + } + } + } - // append curves to the curve list: start curve, other curves wrapping around, end curve - const auto appendCurve = [&curve_list](const CCurve &curve) { - if (curve_list.size() > 0 && curve_list.back().m_vertices.back().m_p == curve.m_vertices.front().m_p) { - auto it = curve.m_vertices.begin(); - for (it++; it != curve.m_vertices.end(); it++) { - curve_list.back().append(*it); - } - } else { - curve_list.push_back(curve); - } - }; + startCurve.append(CVertex(nmin)); + endCurve.append(curve_itmin->m_vertices.front()); + { + int i = 0; + for (auto it = spans.begin(); it != spans.end(); i++, it++) { + if (i < imin) { + endCurve.append(it->m_v); + } + else if (i > imin) { + startCurve.append(it->m_v); + } + else { + if (nmin != endCurve.m_vertices.back().m_p) { + endCurve.append(CVertex(smin.m_v.m_type, + nmin, + smin.m_v.m_c, + smin.m_v.m_user_data)); + } + if (nmin != it->m_v.m_p) { + startCurve.append(CVertex(smin.m_v.m_type, + it->m_v.m_p, + smin.m_v.m_c, + smin.m_v.m_user_data)); + } + } + } + } - if (startCurve.m_vertices.size() > 1) { - appendCurve(startCurve); - } - { - auto it = curve_itmin; - for(it++; it != a_offset.m_curves.end(); it++) { - appendCurve(*it); - } - } - for(auto it = a_offset.m_curves.begin(); it != curve_itmin; it++) { - appendCurve(*it); - } - if (endCurve.m_vertices.size() > 1) { - appendCurve(endCurve); - } + // append curves to the curve list: start curve, other curves wrapping around, end + // curve + const auto appendCurve = [&curve_list](const CCurve& curve) { + if (curve_list.size() > 0 + && curve_list.back().m_vertices.back().m_p + == curve.m_vertices.front().m_p) { + auto it = curve.m_vertices.begin(); + for (it++; it != curve.m_vertices.end(); it++) { + curve_list.back().append(*it); + } + } + else { + curve_list.push_back(curve); + } + }; + + if (startCurve.m_vertices.size() > 1) { + appendCurve(startCurve); + } + { + auto it = curve_itmin; + for (it++; it != a_offset.m_curves.end(); it++) { + appendCurve(*it); + } + } + for (auto it = a_offset.m_curves.begin(); it != curve_itmin; it++) { + appendCurve(*it); + } + if (endCurve.m_vertices.size() > 1) { + appendCurve(endCurve); + } - done = true; - } - } + done = true; + } + } - // add the single offset too - if (!done) - { - for(std::list::iterator It = a_offset.m_curves.begin(); It != a_offset.m_curves.end(); It++) - { - CCurve& curve = *It; - curve_list.push_back(curve); - } - } - } + // add the single offset too + if (!done) { + for (std::list::iterator It = a_offset.m_curves.begin(); + It != a_offset.m_curves.end(); + It++) { + CCurve& curve = *It; + curve_list.push_back(curve); + } + } + } } -void CArea::Split(std::list &m_areas)const +void CArea::Split(std::list& m_areas) const { - if(HolesLinked()) - { - for(std::list::const_iterator It = m_curves.begin(); It != m_curves.end(); It++) - { - const CCurve& curve = *It; - m_areas.emplace_back(); - m_areas.back().m_curves.push_back(curve); - } - } - else - { - CArea a = *this; - a.Reorder(); + if (HolesLinked()) { + for (std::list::const_iterator It = m_curves.begin(); It != m_curves.end(); It++) { + const CCurve& curve = *It; + m_areas.emplace_back(); + m_areas.back().m_curves.push_back(curve); + } + } + else { + CArea a = *this; + a.Reorder(); - if(CArea::m_please_abort) - return; + if (CArea::m_please_abort) { + return; + } - for(std::list::const_iterator It = a.m_curves.begin(); It != a.m_curves.end(); It++) - { - const CCurve& curve = *It; - if(curve.IsClockwise()) - { - if(m_areas.size() > 0) - m_areas.back().m_curves.push_back(curve); - } - else - { - m_areas.emplace_back(); - m_areas.back().m_curves.push_back(curve); - } - } - } + for (std::list::const_iterator It = a.m_curves.begin(); It != a.m_curves.end(); + It++) { + const CCurve& curve = *It; + if (curve.IsClockwise()) { + if (m_areas.size() > 0) { + m_areas.back().m_curves.push_back(curve); + } + } + else { + m_areas.emplace_back(); + m_areas.back().m_curves.push_back(curve); + } + } + } } -double CArea::GetArea(bool always_add)const +double CArea::GetArea(bool always_add) const { - // returns the area of the area - double area = 0.0; - for(std::list::const_iterator It = m_curves.begin(); It != m_curves.end(); It++) - { - const CCurve& curve = *It; - double a = curve.GetArea(); - if(always_add)area += fabs(a); - else area += a; - } - return area; + // returns the area of the area + double area = 0.0; + for (std::list::const_iterator It = m_curves.begin(); It != m_curves.end(); It++) { + const CCurve& curve = *It; + double a = curve.GetArea(); + if (always_add) { + area += fabs(a); + } + else { + area += a; + } + } + return area; } eOverlapType GetOverlapType(const CCurve& c1, const CCurve& c2) { - CArea a1; - a1.m_curves.push_back(c1); - CArea a2; - a2.m_curves.push_back(c2); + CArea a1; + a1.m_curves.push_back(c1); + CArea a2; + a2.m_curves.push_back(c2); - return GetOverlapType(a1, a2); + return GetOverlapType(a1, a2); } eOverlapType GetOverlapType(const CArea& a1, const CArea& a2) { - CArea A1(a1); + CArea A1(a1); - A1.Subtract(a2); - if(A1.m_curves.size() == 0) - { - return eInside; - } + A1.Subtract(a2); + if (A1.m_curves.size() == 0) { + return eInside; + } - CArea A2(a2); - A2.Subtract(a1); - if(A2.m_curves.size() == 0) - { - return eOutside; - } + CArea A2(a2); + A2.Subtract(a1); + if (A2.m_curves.size() == 0) { + return eOutside; + } - A1 = a1; - A1.Intersect(a2); - if(A1.m_curves.size() == 0) - { - return eSiblings; - } + A1 = a1; + A1.Intersect(a2); + if (A1.m_curves.size() == 0) { + return eSiblings; + } - return eCrossing; + return eCrossing; } bool IsInside(const Point& p, const CCurve& c) { - CArea a; - a.m_curves.push_back(c); - return IsInside(p, a); + CArea a; + a.m_curves.push_back(c); + return IsInside(p, a); } bool IsInside(const Point& p, const CArea& a) { - CArea a2; - CCurve c; - c.m_vertices.emplace_back(Point(p.x - 0.01, p.y - 0.01)); - c.m_vertices.emplace_back(Point(p.x + 0.01, p.y - 0.01)); - c.m_vertices.emplace_back(Point(p.x + 0.01, p.y + 0.01)); - c.m_vertices.emplace_back(Point(p.x - 0.01, p.y + 0.01)); - c.m_vertices.emplace_back(Point(p.x - 0.01, p.y - 0.01)); - a2.m_curves.push_back(c); - a2.Intersect(a); - if(fabs(a2.GetArea()) < 0.0004) - return false; - return true; + CArea a2; + CCurve c; + c.m_vertices.emplace_back(Point(p.x - 0.01, p.y - 0.01)); + c.m_vertices.emplace_back(Point(p.x + 0.01, p.y - 0.01)); + c.m_vertices.emplace_back(Point(p.x + 0.01, p.y + 0.01)); + c.m_vertices.emplace_back(Point(p.x - 0.01, p.y + 0.01)); + c.m_vertices.emplace_back(Point(p.x - 0.01, p.y - 0.01)); + a2.m_curves.push_back(c); + a2.Intersect(a); + if (fabs(a2.GetArea()) < 0.0004) { + return false; + } + return true; } -void CArea::SpanIntersections(const Span& span, std::list &pts)const +void CArea::SpanIntersections(const Span& span, std::list& pts) const { - // this returns all the intersections of this area with the given span, ordered along the span + // this returns all the intersections of this area with the given span, ordered along the span - // get all points where this area's curves intersect the span - std::list pts2; - for(std::list::const_iterator It = m_curves.begin(); It != m_curves.end(); It++) - { - const CCurve &c = *It; - c.SpanIntersections(span, pts2); - } + // get all points where this area's curves intersect the span + std::list pts2; + for (std::list::const_iterator It = m_curves.begin(); It != m_curves.end(); It++) { + const CCurve& c = *It; + c.SpanIntersections(span, pts2); + } - // order them along the span - std::multimap ordered_points; - for(std::list::iterator It = pts2.begin(); It != pts2.end(); It++) - { - Point &p = *It; - double t; - if(span.On(p, &t)) - { - ordered_points.insert(std::make_pair(t, p)); - } - } + // order them along the span + std::multimap ordered_points; + for (std::list::iterator It = pts2.begin(); It != pts2.end(); It++) { + Point& p = *It; + double t; + if (span.On(p, &t)) { + ordered_points.insert(std::make_pair(t, p)); + } + } - // add them to the given list of points - for(std::multimap::iterator It = ordered_points.begin(); It != ordered_points.end(); It++) - { - Point p = It->second; - pts.push_back(p); - } + // add them to the given list of points + for (std::multimap::iterator It = ordered_points.begin(); + It != ordered_points.end(); + It++) { + Point p = It->second; + pts.push_back(p); + } } -void CArea::CurveIntersections(const CCurve& curve, std::list &pts)const +void CArea::CurveIntersections(const CCurve& curve, std::list& pts) const { - // this returns all the intersections of this area with the given curve, ordered along the curve - std::list spans; - curve.GetSpans(spans); - for(std::list::iterator It = spans.begin(); It != spans.end(); It++) - { - Span& span = *It; - std::list pts2; - SpanIntersections(span, pts2); - for(std::list::iterator It = pts2.begin(); It != pts2.end(); It++) - { - Point &pt = *It; - if(pts.size() == 0) - { - pts.push_back(pt); - } - else - { - if(pt != pts.back())pts.push_back(pt); - } - } - } + // this returns all the intersections of this area with the given curve, ordered along the curve + std::list spans; + curve.GetSpans(spans); + for (std::list::iterator It = spans.begin(); It != spans.end(); It++) { + Span& span = *It; + std::list pts2; + SpanIntersections(span, pts2); + for (std::list::iterator It = pts2.begin(); It != pts2.end(); It++) { + Point& pt = *It; + if (pts.size() == 0) { + pts.push_back(pt); + } + else { + if (pt != pts.back()) { + pts.push_back(pt); + } + } + } + } } class ThickLine { public: - CArea m_area; - CCurve m_curve; + CArea m_area; + CCurve m_curve; - ThickLine(const CCurve& curve) - { - m_curve = curve; - m_area.append(curve); - m_area.Thicken(0.001); - } + ThickLine(const CCurve& curve) + { + m_curve = curve; + m_area.append(curve); + m_area.Thicken(0.001); + } }; -void CArea::InsideCurves(const CCurve& curve, std::list &curves_inside)const +void CArea::InsideCurves(const CCurve& curve, std::list& curves_inside) const { - //1. find the intersectionpoints between these two curves. - std::list pts; - CurveIntersections(curve, pts); + // 1. find the intersectionpoints between these two curves. + std::list pts; + CurveIntersections(curve, pts); - //2.separate curve2 in multiple curves between these intersections. - std::list separate_curves; - curve.ExtractSeparateCurves(pts, separate_curves); + // 2.separate curve2 in multiple curves between these intersections. + std::list separate_curves; + curve.ExtractSeparateCurves(pts, separate_curves); - //3. if the midpoint of a separate curve lies in a1, then we return it. - for(std::list::iterator It = separate_curves.begin(); It != separate_curves.end(); It++) - { - CCurve &curve = *It; - double length = curve.Perim(); - Point mid_point = curve.PerimToPoint(length * 0.5); - if(IsInside(mid_point, *this))curves_inside.push_back(curve); - } + // 3. if the midpoint of a separate curve lies in a1, then we return it. + for (std::list::iterator It = separate_curves.begin(); It != separate_curves.end(); + It++) { + CCurve& curve = *It; + double length = curve.Perim(); + Point mid_point = curve.PerimToPoint(length * 0.5); + if (IsInside(mid_point, *this)) { + curves_inside.push_back(curve); + } + } } diff --git a/src/Mod/CAM/libarea/Area.h b/src/Mod/CAM/libarea/Area.h index 9010806d2f..471975984f 100644 --- a/src/Mod/CAM/libarea/Area.h +++ b/src/Mod/CAM/libarea/Area.h @@ -11,113 +11,124 @@ enum PocketMode { - SpiralPocketMode, - ZigZagPocketMode, - SingleOffsetPocketMode, - ZigZagThenSingleOffsetPocketMode, + SpiralPocketMode, + ZigZagPocketMode, + SingleOffsetPocketMode, + ZigZagThenSingleOffsetPocketMode, }; struct CAreaPocketParams { - double tool_radius; - double extra_offset; - double stepover; - bool from_center; - PocketMode mode; - double zig_angle; - bool only_cut_first_offset; - CAreaPocketParams(double Tool_radius, double Extra_offset, double Stepover, bool From_center, PocketMode Mode, double Zig_angle) - { - tool_radius = Tool_radius; - extra_offset = Extra_offset; - stepover = Stepover; - from_center = From_center; - mode = Mode; - zig_angle = Zig_angle; - only_cut_first_offset = false; - } + double tool_radius; + double extra_offset; + double stepover; + bool from_center; + PocketMode mode; + double zig_angle; + bool only_cut_first_offset; + CAreaPocketParams(double Tool_radius, + double Extra_offset, + double Stepover, + bool From_center, + PocketMode Mode, + double Zig_angle) + { + tool_radius = Tool_radius; + extra_offset = Extra_offset; + stepover = Stepover; + from_center = From_center; + mode = Mode; + zig_angle = Zig_angle; + only_cut_first_offset = false; + } }; class CArea { public: - std::list m_curves; - static double m_accuracy; - static double m_units; // 1.0 for mm, 25.4 for inches. All points are multiplied by this before going to the engine - static bool m_clipper_simple; - static double m_clipper_clean_distance; - static bool m_fit_arcs; + std::list m_curves; + static double m_accuracy; + static double m_units; // 1.0 for mm, 25.4 for inches. All points are multiplied by this before + // going to the engine + static bool m_clipper_simple; + static double m_clipper_clean_distance; + static bool m_fit_arcs; static int m_min_arc_points; static int m_max_arc_points; - static double m_processing_done; // 0.0 to 100.0, set inside MakeOnePocketCurve - static double m_single_area_processing_length; - static double m_after_MakeOffsets_length; - static double m_MakeOffsets_increment; - static double m_split_processing_length; - static bool m_set_processing_length_in_split; - static bool m_please_abort; // the user sets this from another thread, to tell MakeOnePocketCurve to finish with no result. + static double m_processing_done; // 0.0 to 100.0, set inside MakeOnePocketCurve + static double m_single_area_processing_length; + static double m_after_MakeOffsets_length; + static double m_MakeOffsets_increment; + static double m_split_processing_length; + static bool m_set_processing_length_in_split; + static bool m_please_abort; // the user sets this from another thread, to tell + // MakeOnePocketCurve to finish with no result. static double m_clipper_scale; - void append(const CCurve& curve); - void move(CCurve&& curve); - void Subtract(const CArea& a2); - void Intersect(const CArea& a2); - void Union(const CArea& a2); - static CArea UniteCurves(std::list &curves); - void Xor(const CArea& a2); - void Offset(double inwards_value); - void OffsetWithClipper(double offset, - ClipperLib::JoinType joinType=ClipperLib::jtRound, - ClipperLib::EndType endType=ClipperLib::etOpenRound, - double miterLimit = 5.0, - double roundPrecision = 0.0); - void Thicken(double value); - void FitArcs(); - unsigned int num_curves(){return static_cast(m_curves.size());} - Point NearestPoint(const Point& p)const; - void GetBox(CBox2D &box); - void Reorder(); - void MakePocketToolpath(std::list &toolpath, const CAreaPocketParams ¶ms)const; - void SplitAndMakePocketToolpath(std::list &toolpath, const CAreaPocketParams ¶ms)const; - void MakeOnePocketCurve(std::list &curve_list, const CAreaPocketParams ¶ms)const; - static bool HolesLinked(); - void Split(std::list &m_areas)const; - double GetArea(bool always_add = false)const; - void SpanIntersections(const Span& span, std::list &pts)const; - void CurveIntersections(const CCurve& curve, std::list &pts)const; - void InsideCurves(const CCurve& curve, std::list &curves_inside)const; + void append(const CCurve& curve); + void move(CCurve&& curve); + void Subtract(const CArea& a2); + void Intersect(const CArea& a2); + void Union(const CArea& a2); + static CArea UniteCurves(std::list& curves); + void Xor(const CArea& a2); + void Offset(double inwards_value); + void OffsetWithClipper(double offset, + ClipperLib::JoinType joinType = ClipperLib::jtRound, + ClipperLib::EndType endType = ClipperLib::etOpenRound, + double miterLimit = 5.0, + double roundPrecision = 0.0); + void Thicken(double value); + void FitArcs(); + unsigned int num_curves() + { + return static_cast(m_curves.size()); + } + Point NearestPoint(const Point& p) const; + void GetBox(CBox2D& box); + void Reorder(); + void MakePocketToolpath(std::list& toolpath, const CAreaPocketParams& params) const; + void SplitAndMakePocketToolpath(std::list& toolpath, + const CAreaPocketParams& params) const; + void MakeOnePocketCurve(std::list& curve_list, const CAreaPocketParams& params) const; + static bool HolesLinked(); + void Split(std::list& m_areas) const; + double GetArea(bool always_add = false) const; + void SpanIntersections(const Span& span, std::list& pts) const; + void CurveIntersections(const CCurve& curve, std::list& pts) const; + void InsideCurves(const CCurve& curve, std::list& curves_inside) const; - void ChangeStartToNearest(const Point *pstart=NULL, double min_dist=1.0); + void ChangeStartToNearest(const Point* pstart = NULL, double min_dist = 1.0); - //Avoid outside direct accessing static member variable because of Windows DLL issue -#define CAREA_PARAM_DECLARE(_type,_name) \ - static _type get_##_name();\ + // Avoid outside direct accessing static member variable because of Windows DLL issue +#define CAREA_PARAM_DECLARE(_type, _name) \ + static _type get_##_name(); \ static void set_##_name(_type _name); - CAREA_PARAM_DECLARE(double,tolerance) - CAREA_PARAM_DECLARE(bool,fit_arcs) - CAREA_PARAM_DECLARE(bool,clipper_simple) - CAREA_PARAM_DECLARE(double,clipper_clean_distance) - CAREA_PARAM_DECLARE(double,accuracy) - CAREA_PARAM_DECLARE(double,units) - CAREA_PARAM_DECLARE(short,min_arc_points) - CAREA_PARAM_DECLARE(short,max_arc_points) - CAREA_PARAM_DECLARE(double,clipper_scale) + CAREA_PARAM_DECLARE(double, tolerance) + CAREA_PARAM_DECLARE(bool, fit_arcs) + CAREA_PARAM_DECLARE(bool, clipper_simple) + CAREA_PARAM_DECLARE(double, clipper_clean_distance) + CAREA_PARAM_DECLARE(double, accuracy) + CAREA_PARAM_DECLARE(double, units) + CAREA_PARAM_DECLARE(short, min_arc_points) + CAREA_PARAM_DECLARE(short, max_arc_points) + CAREA_PARAM_DECLARE(double, clipper_scale) // Following functions is add to operate on possible open curves - void PopulateClipper(ClipperLib::Clipper &c, ClipperLib::PolyType type) const; - void Clip(ClipperLib::ClipType op, - const CArea *a, + void PopulateClipper(ClipperLib::Clipper& c, ClipperLib::PolyType type) const; + void Clip(ClipperLib::ClipType op, + const CArea* a, ClipperLib::PolyFillType subjFillType = ClipperLib::pftEvenOdd, ClipperLib::PolyFillType clipFillType = ClipperLib::pftEvenOdd); }; enum eOverlapType { - eOutside, - eInside, - eSiblings, - eCrossing, + eOutside, + eInside, + eSiblings, + eCrossing, }; eOverlapType GetOverlapType(const CCurve& c1, const CCurve& c2); @@ -125,4 +136,4 @@ eOverlapType GetOverlapType(const CArea& a1, const CArea& a2); bool IsInside(const Point& p, const CCurve& c); bool IsInside(const Point& p, const CArea& a); -#endif // #define AREA_HEADER +#endif // #define AREA_HEADER diff --git a/src/Mod/CAM/libarea/AreaClipper.cpp b/src/Mod/CAM/libarea/AreaClipper.cpp index 1ee608bbba..13ff32267a 100644 --- a/src/Mod/CAM/libarea/AreaClipper.cpp +++ b/src/Mod/CAM/libarea/AreaClipper.cpp @@ -9,565 +9,613 @@ using namespace ClipperLib; #define TPolygon Path #define TPolyPolygon Paths -bool CArea::HolesLinked(){ return false; } +bool CArea::HolesLinked() +{ + return false; +} -//static const double PI = 3.1415926535897932; +// static const double PI = 3.1415926535897932; double CArea::m_clipper_scale = 10000.0; class DoubleAreaPoint { public: - double X, Y; + double X, Y; - DoubleAreaPoint(double x, double y){X = x; Y = y;} - DoubleAreaPoint(const IntPoint& p){X = (double)(p.X) / CArea::m_clipper_scale; Y = (double)(p.Y) / CArea::m_clipper_scale;} - IntPoint int_point(){return IntPoint((long64)(X * CArea::m_clipper_scale), (long64)(Y * CArea::m_clipper_scale));} + DoubleAreaPoint(double x, double y) + { + X = x; + Y = y; + } + DoubleAreaPoint(const IntPoint& p) + { + X = (double)(p.X) / CArea::m_clipper_scale; + Y = (double)(p.Y) / CArea::m_clipper_scale; + } + IntPoint int_point() + { + return IntPoint((long64)(X * CArea::m_clipper_scale), (long64)(Y * CArea::m_clipper_scale)); + } }; static std::list pts_for_AddVertex; static void AddPoint(const DoubleAreaPoint& p) { - pts_for_AddVertex.push_back(p); + pts_for_AddVertex.push_back(p); } static void AddVertex(const CVertex& vertex, const CVertex* prev_vertex) { - if(vertex.m_type == 0 || prev_vertex == NULL) - { - AddPoint(DoubleAreaPoint(vertex.m_p.x * CArea::m_units, vertex.m_p.y * CArea::m_units)); - } - else - { - if(vertex.m_p != prev_vertex->m_p) - { - double phi,dphi,dx,dy; - int Segments; - int i; - double ang1,ang2,phit; + if (vertex.m_type == 0 || prev_vertex == NULL) { + AddPoint(DoubleAreaPoint(vertex.m_p.x * CArea::m_units, vertex.m_p.y * CArea::m_units)); + } + else { + if (vertex.m_p != prev_vertex->m_p) { + double phi, dphi, dx, dy; + int Segments; + int i; + double ang1, ang2, phit; - dx = (prev_vertex->m_p.x - vertex.m_c.x) * CArea::m_units; - dy = (prev_vertex->m_p.y - vertex.m_c.y) * CArea::m_units; + dx = (prev_vertex->m_p.x - vertex.m_c.x) * CArea::m_units; + dy = (prev_vertex->m_p.y - vertex.m_c.y) * CArea::m_units; - ang1=atan2(dy,dx); - if (ang1<0) ang1+=2.0*PI; - dx = (vertex.m_p.x - vertex.m_c.x) * CArea::m_units; - dy = (vertex.m_p.y - vertex.m_c.y) * CArea::m_units; - ang2=atan2(dy,dx); - if (ang2<0) ang2+=2.0*PI; + ang1 = atan2(dy, dx); + if (ang1 < 0) { + ang1 += 2.0 * PI; + } + dx = (vertex.m_p.x - vertex.m_c.x) * CArea::m_units; + dy = (vertex.m_p.y - vertex.m_c.y) * CArea::m_units; + ang2 = atan2(dy, dx); + if (ang2 < 0) { + ang2 += 2.0 * PI; + } - if (vertex.m_type == -1) - { //clockwise - if (ang2 > ang1) - phit=2.0*PI-ang2+ ang1; - else - phit=ang1-ang2; - } - else - { //counter_clockwise - if (ang1 > ang2) - phit=-(2.0*PI-ang1+ ang2); - else - phit=-(ang2-ang1); - } + if (vertex.m_type == -1) { // clockwise + if (ang2 > ang1) { + phit = 2.0 * PI - ang2 + ang1; + } + else { + phit = ang1 - ang2; + } + } + else { // counter_clockwise + if (ang1 > ang2) { + phit = -(2.0 * PI - ang1 + ang2); + } + else { + phit = -(ang2 - ang1); + } + } - //what is the delta phi to get an accuracy of aber - double radius = sqrt(dx*dx + dy*dy); - dphi=2*acos((radius-CArea::m_accuracy)/radius); + // what is the delta phi to get an accuracy of aber + double radius = sqrt(dx * dx + dy * dy); + dphi = 2 * acos((radius - CArea::m_accuracy) / radius); - //set the number of segments - if (phit > 0) - Segments=(int)ceil(phit/dphi); - else - Segments=(int)ceil(-phit/dphi); + // set the number of segments + if (phit > 0) { + Segments = (int)ceil(phit / dphi); + } + else { + Segments = (int)ceil(-phit / dphi); + } - if (Segments < CArea::m_min_arc_points) - Segments = CArea::m_min_arc_points; - // if (Segments > CArea::m_max_arc_points) - // Segments=CArea::m_max_arc_points; + if (Segments < CArea::m_min_arc_points) { + Segments = CArea::m_min_arc_points; + } + // if (Segments > CArea::m_max_arc_points) + // Segments=CArea::m_max_arc_points; - dphi=phit/(Segments); + dphi = phit / (Segments); - double px = prev_vertex->m_p.x * CArea::m_units; - double py = prev_vertex->m_p.y * CArea::m_units; + double px = prev_vertex->m_p.x * CArea::m_units; + double py = prev_vertex->m_p.y * CArea::m_units; - for (i=1; i<=Segments; i++) - { - dx = px - vertex.m_c.x * CArea::m_units; - dy = py - vertex.m_c.y * CArea::m_units; - phi=atan2(dy,dx); + for (i = 1; i <= Segments; i++) { + dx = px - vertex.m_c.x * CArea::m_units; + dy = py - vertex.m_c.y * CArea::m_units; + phi = atan2(dy, dx); - double nx = vertex.m_c.x * CArea::m_units + radius * cos(phi-dphi); - double ny = vertex.m_c.y * CArea::m_units + radius * sin(phi-dphi); + double nx = vertex.m_c.x * CArea::m_units + radius * cos(phi - dphi); + double ny = vertex.m_c.y * CArea::m_units + radius * sin(phi - dphi); - AddPoint(DoubleAreaPoint(nx, ny)); + AddPoint(DoubleAreaPoint(nx, ny)); - px = nx; - py = ny; - } - } - } + px = nx; + py = ny; + } + } + } } -static void MakeLoop(const DoubleAreaPoint &pt0, const DoubleAreaPoint &pt1, const DoubleAreaPoint &pt2, double radius) +static void MakeLoop(const DoubleAreaPoint& pt0, + const DoubleAreaPoint& pt1, + const DoubleAreaPoint& pt2, + double radius) { - Point p0(pt0.X, pt0.Y); - Point p1(pt1.X, pt1.Y); - Point p2(pt2.X, pt2.Y); - Point forward0 = p1 - p0; - Point right0(forward0.y, -forward0.x); - right0.normalize(); - Point forward1 = p2 - p1; - Point right1(forward1.y, -forward1.x); - right1.normalize(); + Point p0(pt0.X, pt0.Y); + Point p1(pt1.X, pt1.Y); + Point p2(pt2.X, pt2.Y); + Point forward0 = p1 - p0; + Point right0(forward0.y, -forward0.x); + right0.normalize(); + Point forward1 = p2 - p1; + Point right1(forward1.y, -forward1.x); + right1.normalize(); - int arc_dir = (radius > 0) ? 1 : -1; + int arc_dir = (radius > 0) ? 1 : -1; - CVertex v0(0, p1 + right0 * radius, Point(0, 0)); - CVertex v1(arc_dir, p1 + right1 * radius, p1); - CVertex v2(0, p2 + right1 * radius, Point(0, 0)); + CVertex v0(0, p1 + right0 * radius, Point(0, 0)); + CVertex v1(arc_dir, p1 + right1 * radius, p1); + CVertex v2(0, p2 + right1 * radius, Point(0, 0)); - double save_units = CArea::m_units; - CArea::m_units = 1.0; + double save_units = CArea::m_units; + CArea::m_units = 1.0; - AddVertex(v1, &v0); - AddVertex(v2, &v1); + AddVertex(v1, &v0); + AddVertex(v2, &v1); - CArea::m_units = save_units; + CArea::m_units = save_units; } -static void OffsetWithLoops(const TPolyPolygon &pp, TPolyPolygon &pp_new, double inwards_value) +static void OffsetWithLoops(const TPolyPolygon& pp, TPolyPolygon& pp_new, double inwards_value) { - Clipper c; + Clipper c; c.StrictlySimple(CArea::m_clipper_simple); - bool inwards = (inwards_value > 0); - bool reverse = false; - double radius = -fabs(inwards_value); + bool inwards = (inwards_value > 0); + bool reverse = false; + double radius = -fabs(inwards_value); - if(inwards) - { - // add a large square on the outside, to be removed later - TPolygon p; - p.push_back(DoubleAreaPoint(-10000.0, -10000.0).int_point()); - p.push_back(DoubleAreaPoint(-10000.0, 10000.0).int_point()); - p.push_back(DoubleAreaPoint(10000.0, 10000.0).int_point()); - p.push_back(DoubleAreaPoint(10000.0, -10000.0).int_point()); - c.AddPath(p, ptSubject, true); - } - else - { - reverse = true; - } + if (inwards) { + // add a large square on the outside, to be removed later + TPolygon p; + p.push_back(DoubleAreaPoint(-10000.0, -10000.0).int_point()); + p.push_back(DoubleAreaPoint(-10000.0, 10000.0).int_point()); + p.push_back(DoubleAreaPoint(10000.0, 10000.0).int_point()); + p.push_back(DoubleAreaPoint(10000.0, -10000.0).int_point()); + c.AddPath(p, ptSubject, true); + } + else { + reverse = true; + } - for(unsigned int i = 0; i < pp.size(); i++) - { - const TPolygon& p = pp[i]; + for (unsigned int i = 0; i < pp.size(); i++) { + const TPolygon& p = pp[i]; - pts_for_AddVertex.clear(); + pts_for_AddVertex.clear(); - if(p.size() > 2) - { - if(reverse) - { - for(std::size_t j = p.size()-1; j > 1; j--)MakeLoop(p[j], p[j-1], p[j-2], radius); - MakeLoop(p[1], p[0], p[p.size()-1], radius); - MakeLoop(p[0], p[p.size()-1], p[p.size()-2], radius); - } - else - { - MakeLoop(p[p.size()-2], p[p.size()-1], p[0], radius); - MakeLoop(p[p.size()-1], p[0], p[1], radius); - for(std::size_t j = 2; j < p.size(); j++)MakeLoop(p[j-2], p[j-1], p[j], radius); - } + if (p.size() > 2) { + if (reverse) { + for (std::size_t j = p.size() - 1; j > 1; j--) { + MakeLoop(p[j], p[j - 1], p[j - 2], radius); + } + MakeLoop(p[1], p[0], p[p.size() - 1], radius); + MakeLoop(p[0], p[p.size() - 1], p[p.size() - 2], radius); + } + else { + MakeLoop(p[p.size() - 2], p[p.size() - 1], p[0], radius); + MakeLoop(p[p.size() - 1], p[0], p[1], radius); + for (std::size_t j = 2; j < p.size(); j++) { + MakeLoop(p[j - 2], p[j - 1], p[j], radius); + } + } - TPolygon loopy_polygon; - loopy_polygon.reserve(pts_for_AddVertex.size()); - for(std::list::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++) - { - loopy_polygon.push_back(It->int_point()); - } - c.AddPath(loopy_polygon, ptSubject, true); - pts_for_AddVertex.clear(); - } - } + TPolygon loopy_polygon; + loopy_polygon.reserve(pts_for_AddVertex.size()); + for (std::list::iterator It = pts_for_AddVertex.begin(); + It != pts_for_AddVertex.end(); + It++) { + loopy_polygon.push_back(It->int_point()); + } + c.AddPath(loopy_polygon, ptSubject, true); + pts_for_AddVertex.clear(); + } + } - //c.ForceOrientation(false); - c.Execute(ctUnion, pp_new, pftNonZero, pftNonZero); + // c.ForceOrientation(false); + c.Execute(ctUnion, pp_new, pftNonZero, pftNonZero); - if(inwards) - { - // remove the large square - if(pp_new.size() > 0) - { - pp_new.erase(pp_new.begin()); - } - } - else - { - // reverse all the resulting polygons - TPolyPolygon copy = pp_new; - pp_new.clear(); - pp_new.resize(copy.size()); - for(unsigned int i = 0; i < copy.size(); i++) - { - const TPolygon& p = copy[i]; - TPolygon p_new; - p_new.resize(p.size()); - std::size_t size_minus_one = p.size() - 1; - for(std::size_t j = 0; j < p.size(); j++)p_new[j] = p[size_minus_one - j]; - pp_new[i] = p_new; - } - } + if (inwards) { + // remove the large square + if (pp_new.size() > 0) { + pp_new.erase(pp_new.begin()); + } + } + else { + // reverse all the resulting polygons + TPolyPolygon copy = pp_new; + pp_new.clear(); + pp_new.resize(copy.size()); + for (unsigned int i = 0; i < copy.size(); i++) { + const TPolygon& p = copy[i]; + TPolygon p_new; + p_new.resize(p.size()); + std::size_t size_minus_one = p.size() - 1; + for (std::size_t j = 0; j < p.size(); j++) { + p_new[j] = p[size_minus_one - j]; + } + pp_new[i] = p_new; + } + } } -static void MakeObround(const Point &pt0, const CVertex &vt1, double radius) +static void MakeObround(const Point& pt0, const CVertex& vt1, double radius) { - Span span(pt0, vt1); - Point forward0 = span.GetVector(0.0); - Point forward1 = span.GetVector(1.0); - Point right0(forward0.y, -forward0.x); - Point right1(forward1.y, -forward1.x); - right0.normalize(); - right1.normalize(); + Span span(pt0, vt1); + Point forward0 = span.GetVector(0.0); + Point forward1 = span.GetVector(1.0); + Point right0(forward0.y, -forward0.x); + Point right1(forward1.y, -forward1.x); + right0.normalize(); + right1.normalize(); - CVertex v0(pt0 + right0 * radius); - CVertex v1(vt1.m_type, vt1.m_p + right1 * radius, vt1.m_c); - CVertex v2(1, vt1.m_p + right1 * -radius, vt1.m_p); - CVertex v3(-vt1.m_type, pt0 + right0 * -radius, vt1.m_c); - CVertex v4(1, pt0 + right0 * radius, pt0); + CVertex v0(pt0 + right0 * radius); + CVertex v1(vt1.m_type, vt1.m_p + right1 * radius, vt1.m_c); + CVertex v2(1, vt1.m_p + right1 * -radius, vt1.m_p); + CVertex v3(-vt1.m_type, pt0 + right0 * -radius, vt1.m_c); + CVertex v4(1, pt0 + right0 * radius, pt0); - double save_units = CArea::m_units; - CArea::m_units = 1.0; + double save_units = CArea::m_units; + CArea::m_units = 1.0; - AddVertex(v0, NULL); - AddVertex(v1, &v0); - AddVertex(v2, &v1); - AddVertex(v3, &v2); - AddVertex(v4, &v3); + AddVertex(v0, NULL); + AddVertex(v1, &v0); + AddVertex(v2, &v1); + AddVertex(v3, &v2); + AddVertex(v4, &v3); - CArea::m_units = save_units; + CArea::m_units = save_units; } -static void OffsetSpansWithObrounds(const CArea& area, TPolyPolygon &pp_new, double radius) +static void OffsetSpansWithObrounds(const CArea& area, TPolyPolygon& pp_new, double radius) { - Clipper c; - c.StrictlySimple(CArea::m_clipper_simple); - pp_new.clear(); + Clipper c; + c.StrictlySimple(CArea::m_clipper_simple); + pp_new.clear(); - for(std::list::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); It++) - { - c.Clear(); - c.AddPaths(pp_new, ptSubject, true); - pp_new.clear(); - pts_for_AddVertex.clear(); + for (std::list::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); + It++) { + c.Clear(); + c.AddPaths(pp_new, ptSubject, true); + pp_new.clear(); + pts_for_AddVertex.clear(); - const CCurve& curve = *It; - const CVertex* prev_vertex = NULL; - for(std::list::const_iterator It2 = curve.m_vertices.begin(); It2 != curve.m_vertices.end(); It2++) - { - const CVertex& vertex = *It2; - if(prev_vertex) - { - MakeObround(prev_vertex->m_p, vertex, radius); + const CCurve& curve = *It; + const CVertex* prev_vertex = NULL; + for (std::list::const_iterator It2 = curve.m_vertices.begin(); + It2 != curve.m_vertices.end(); + It2++) { + const CVertex& vertex = *It2; + if (prev_vertex) { + MakeObround(prev_vertex->m_p, vertex, radius); - TPolygon loopy_polygon; - loopy_polygon.reserve(pts_for_AddVertex.size()); - for(std::list::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++) - { - loopy_polygon.push_back(It->int_point()); - } - c.AddPath(loopy_polygon, ptSubject, true); - pts_for_AddVertex.clear(); - } - prev_vertex = &vertex; - } - c.Execute(ctUnion, pp_new, pftNonZero, pftNonZero); - } + TPolygon loopy_polygon; + loopy_polygon.reserve(pts_for_AddVertex.size()); + for (std::list::iterator It = pts_for_AddVertex.begin(); + It != pts_for_AddVertex.end(); + It++) { + loopy_polygon.push_back(It->int_point()); + } + c.AddPath(loopy_polygon, ptSubject, true); + pts_for_AddVertex.clear(); + } + prev_vertex = &vertex; + } + c.Execute(ctUnion, pp_new, pftNonZero, pftNonZero); + } - // reverse all the resulting polygons - TPolyPolygon copy = pp_new; - pp_new.clear(); - pp_new.resize(copy.size()); - for(unsigned int i = 0; i < copy.size(); i++) - { - const TPolygon& p = copy[i]; - TPolygon p_new; - p_new.resize(p.size()); - std::size_t size_minus_one = p.size() - 1; - for(std::size_t j = 0; j < p.size(); j++)p_new[j] = p[size_minus_one - j]; - pp_new[i] = p_new; - } + // reverse all the resulting polygons + TPolyPolygon copy = pp_new; + pp_new.clear(); + pp_new.resize(copy.size()); + for (unsigned int i = 0; i < copy.size(); i++) { + const TPolygon& p = copy[i]; + TPolygon p_new; + p_new.resize(p.size()); + std::size_t size_minus_one = p.size() - 1; + for (std::size_t j = 0; j < p.size(); j++) { + p_new[j] = p[size_minus_one - j]; + } + pp_new[i] = p_new; + } } -static void MakePoly(const CCurve& curve, TPolygon &p, bool reverse = false) +static void MakePoly(const CCurve& curve, TPolygon& p, bool reverse = false) { - pts_for_AddVertex.clear(); - const CVertex* prev_vertex = NULL; + pts_for_AddVertex.clear(); + const CVertex* prev_vertex = NULL; - if(!curve.m_vertices.size()) + if (!curve.m_vertices.size()) { return; - if(!curve.IsClosed()) AddVertex(curve.m_vertices.front(),NULL); + } + if (!curve.IsClosed()) { + AddVertex(curve.m_vertices.front(), NULL); + } - for (std::list::const_iterator It2 = curve.m_vertices.begin(); It2 != curve.m_vertices.end(); It2++) - { - const CVertex& vertex = *It2; - if (prev_vertex)AddVertex(vertex, prev_vertex); - prev_vertex = &vertex; - } + for (std::list::const_iterator It2 = curve.m_vertices.begin(); + It2 != curve.m_vertices.end(); + It2++) { + const CVertex& vertex = *It2; + if (prev_vertex) { + AddVertex(vertex, prev_vertex); + } + prev_vertex = &vertex; + } - p.resize(pts_for_AddVertex.size()); - if(reverse) - { - std::size_t i = pts_for_AddVertex.size() - 1;// clipper wants them the opposite way to CArea - for(std::list::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++, i--) - { + p.resize(pts_for_AddVertex.size()); + if (reverse) { + std::size_t i = + pts_for_AddVertex.size() - 1; // clipper wants them the opposite way to CArea + for (std::list::iterator It = pts_for_AddVertex.begin(); + It != pts_for_AddVertex.end(); + It++, i--) { + p[i] = It->int_point(); + } + } + else { + unsigned int i = 0; + for (std::list::iterator It = pts_for_AddVertex.begin(); + It != pts_for_AddVertex.end(); + It++, i++) { p[i] = It->int_point(); } } - else - { - unsigned int i = 0; - for (std::list::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++, i++) - { - p[i] = It->int_point(); - } - } } -static void MakePolyPoly( const CArea& area, TPolyPolygon &pp, bool reverse = true ){ - pp.clear(); - - for(std::list::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); It++) - { - pp.push_back(TPolygon()); - MakePoly(*It,pp.back(),reverse); - } -} - -static void SetFromResult( CCurve& curve, TPolygon& p, bool reverse = true, bool is_closed = true ) +static void MakePolyPoly(const CArea& area, TPolyPolygon& pp, bool reverse = true) { - if(CArea::m_clipper_clean_distance >= Point::tolerance) - CleanPolygon(p,CArea::m_clipper_clean_distance); + pp.clear(); - for(unsigned int j = 0; j < p.size(); j++) - { - const IntPoint &pt = p[j]; + for (std::list::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); + It++) { + pp.push_back(TPolygon()); + MakePoly(*It, pp.back(), reverse); + } +} + +static void SetFromResult(CCurve& curve, TPolygon& p, bool reverse = true, bool is_closed = true) +{ + if (CArea::m_clipper_clean_distance >= Point::tolerance) { + CleanPolygon(p, CArea::m_clipper_clean_distance); + } + + for (unsigned int j = 0; j < p.size(); j++) { + const IntPoint& pt = p[j]; DoubleAreaPoint dp(pt); CVertex vertex(0, Point(dp.X / CArea::m_units, dp.Y / CArea::m_units), Point(0.0, 0.0)); - if(reverse)curve.m_vertices.push_front(vertex); - else curve.m_vertices.push_back(vertex); + if (reverse) { + curve.m_vertices.push_front(vertex); + } + else { + curve.m_vertices.push_back(vertex); + } } - if(is_closed) { + if (is_closed) { // make a copy of the first point at the end - if(reverse)curve.m_vertices.push_front(curve.m_vertices.back()); - else curve.m_vertices.push_back(curve.m_vertices.front()); + if (reverse) { + curve.m_vertices.push_front(curve.m_vertices.back()); + } + else { + curve.m_vertices.push_back(curve.m_vertices.front()); + } } - if(CArea::m_fit_arcs)curve.FitArcs(); + if (CArea::m_fit_arcs) { + curve.FitArcs(); + } } -static void SetFromResult( CArea& area, TPolyPolygon& pp, bool reverse=true, bool is_closed=true, bool clear=true) +static void SetFromResult(CArea& area, + TPolyPolygon& pp, + bool reverse = true, + bool is_closed = true, + bool clear = true) { - // delete existing geometry - if(clear) - area.m_curves.clear(); + // delete existing geometry + if (clear) { + area.m_curves.clear(); + } - for(unsigned int i = 0; i < pp.size(); i++) - { - TPolygon& p = pp[i]; + for (unsigned int i = 0; i < pp.size(); i++) { + TPolygon& p = pp[i]; - area.m_curves.emplace_back(); - CCurve &curve = area.m_curves.back(); - SetFromResult(curve, p, reverse, is_closed); + area.m_curves.emplace_back(); + CCurve& curve = area.m_curves.back(); + SetFromResult(curve, p, reverse, is_closed); } } void CArea::Subtract(const CArea& a2) { - Clipper c; + Clipper c; c.StrictlySimple(CArea::m_clipper_simple); - TPolyPolygon pp1, pp2; - MakePolyPoly(*this, pp1); - MakePolyPoly(a2, pp2); - c.AddPaths(pp1, ptSubject, true); - c.AddPaths(pp2, ptClip, true); - TPolyPolygon solution; - c.Execute(ctDifference, solution); - SetFromResult(*this, solution); + TPolyPolygon pp1, pp2; + MakePolyPoly(*this, pp1); + MakePolyPoly(a2, pp2); + c.AddPaths(pp1, ptSubject, true); + c.AddPaths(pp2, ptClip, true); + TPolyPolygon solution; + c.Execute(ctDifference, solution); + SetFromResult(*this, solution); } void CArea::Intersect(const CArea& a2) { - Clipper c; + Clipper c; c.StrictlySimple(CArea::m_clipper_simple); - TPolyPolygon pp1, pp2; - MakePolyPoly(*this, pp1); - MakePolyPoly(a2, pp2); - c.AddPaths(pp1, ptSubject, true); - c.AddPaths(pp2, ptClip, true); - TPolyPolygon solution; - c.Execute(ctIntersection, solution); - SetFromResult(*this, solution); + TPolyPolygon pp1, pp2; + MakePolyPoly(*this, pp1); + MakePolyPoly(a2, pp2); + c.AddPaths(pp1, ptSubject, true); + c.AddPaths(pp2, ptClip, true); + TPolyPolygon solution; + c.Execute(ctIntersection, solution); + SetFromResult(*this, solution); } void CArea::Union(const CArea& a2) { - Clipper c; + Clipper c; c.StrictlySimple(CArea::m_clipper_simple); - TPolyPolygon pp1, pp2; - MakePolyPoly(*this, pp1); - MakePolyPoly(a2, pp2); - c.AddPaths(pp1, ptSubject, true); - c.AddPaths(pp2, ptClip, true); - TPolyPolygon solution; - c.Execute(ctUnion, solution); - SetFromResult(*this, solution); + TPolyPolygon pp1, pp2; + MakePolyPoly(*this, pp1); + MakePolyPoly(a2, pp2); + c.AddPaths(pp1, ptSubject, true); + c.AddPaths(pp2, ptClip, true); + TPolyPolygon solution; + c.Execute(ctUnion, solution); + SetFromResult(*this, solution); } // static -CArea CArea::UniteCurves(std::list &curves) +CArea CArea::UniteCurves(std::list& curves) { - Clipper c; + Clipper c; c.StrictlySimple(CArea::m_clipper_simple); - TPolyPolygon pp; + TPolyPolygon pp; - for (std::list::iterator It = curves.begin(); It != curves.end(); It++) - { - CCurve &curve = *It; - TPolygon p; - MakePoly(curve, p); - pp.push_back(p); - } + for (std::list::iterator It = curves.begin(); It != curves.end(); It++) { + CCurve& curve = *It; + TPolygon p; + MakePoly(curve, p); + pp.push_back(p); + } - c.AddPaths(pp, ptSubject, true); - TPolyPolygon solution; - c.Execute(ctUnion, solution, pftNonZero, pftNonZero); - CArea area; - SetFromResult(area, solution); - return area; + c.AddPaths(pp, ptSubject, true); + TPolyPolygon solution; + c.Execute(ctUnion, solution, pftNonZero, pftNonZero); + CArea area; + SetFromResult(area, solution); + return area; } void CArea::Xor(const CArea& a2) { - Clipper c; + Clipper c; c.StrictlySimple(CArea::m_clipper_simple); - TPolyPolygon pp1, pp2; - MakePolyPoly(*this, pp1); - MakePolyPoly(a2, pp2); - c.AddPaths(pp1, ptSubject, true); - c.AddPaths(pp2, ptClip, true); - TPolyPolygon solution; - c.Execute(ctXor, solution); - SetFromResult(*this, solution); + TPolyPolygon pp1, pp2; + MakePolyPoly(*this, pp1); + MakePolyPoly(a2, pp2); + c.AddPaths(pp1, ptSubject, true); + c.AddPaths(pp2, ptClip, true); + TPolyPolygon solution; + c.Execute(ctXor, solution); + SetFromResult(*this, solution); } void CArea::Offset(double inwards_value) { - TPolyPolygon pp, pp2; - MakePolyPoly(*this, pp, false); - OffsetWithLoops(pp, pp2, inwards_value * m_units); - SetFromResult(*this, pp2, false); - this->Reorder(); + TPolyPolygon pp, pp2; + MakePolyPoly(*this, pp, false); + OffsetWithLoops(pp, pp2, inwards_value * m_units); + SetFromResult(*this, pp2, false); + this->Reorder(); } -void CArea::PopulateClipper(Clipper &c, PolyType type) const +void CArea::PopulateClipper(Clipper& c, PolyType type) const { int skipped = 0; - for (std::list::const_iterator It = m_curves.begin(); It != m_curves.end(); It++) - { - const CCurve &curve = *It; + for (std::list::const_iterator It = m_curves.begin(); It != m_curves.end(); It++) { + const CCurve& curve = *It; bool closed = curve.IsClosed(); - if(!closed) { - if(type == ptClip){ + if (!closed) { + if (type == ptClip) { ++skipped; continue; } } - TPolygon p; - MakePoly(curve, p, false); + TPolygon p; + MakePoly(curve, p, false); c.AddPath(p, type, closed); - } - if(skipped) + } + if (skipped) { std::cout << "libarea: warning skipped " << skipped << " open wires" << std::endl; + } } -void CArea::Clip(ClipType op, const CArea *a, - PolyFillType subjFillType, - PolyFillType clipFillType) +void CArea::Clip(ClipType op, const CArea* a, PolyFillType subjFillType, PolyFillType clipFillType) { - Clipper c; + Clipper c; c.StrictlySimple(CArea::m_clipper_simple); - PopulateClipper(c,ptSubject); - if(a) a->PopulateClipper(c,ptClip); + PopulateClipper(c, ptSubject); + if (a) { + a->PopulateClipper(c, ptClip); + } PolyTree tree; - c.Execute(op, tree, subjFillType,clipFillType); - TPolyPolygon solution; - ClosedPathsFromPolyTree(tree,solution); - SetFromResult(*this, solution); + c.Execute(op, tree, subjFillType, clipFillType); + TPolyPolygon solution; + ClosedPathsFromPolyTree(tree, solution); + SetFromResult(*this, solution); solution.clear(); - OpenPathsFromPolyTree(tree,solution); - SetFromResult(*this, solution, false, false, false); + OpenPathsFromPolyTree(tree, solution); + SetFromResult(*this, solution, false, false, false); } -void CArea::OffsetWithClipper(double offset, - JoinType joinType/* =jtRound */, - EndType endType/* =etOpenRound */, - double miterLimit/* = 5.0 */, - double roundPrecision/* = 0.0 */) +void CArea::OffsetWithClipper(double offset, + JoinType joinType /* =jtRound */, + EndType endType /* =etOpenRound */, + double miterLimit /* = 5.0 */, + double roundPrecision /* = 0.0 */) { - offset *= m_units*m_clipper_scale; - if(roundPrecision == 0.0) { + offset *= m_units * m_clipper_scale; + if (roundPrecision == 0.0) { // Clipper roundPrecision definition: https://goo.gl/4odfQh - double dphi=acos(1.0-m_accuracy*m_clipper_scale/fabs(offset)); - int Segments=(int)ceil(PI/dphi); - if (Segments < 2*CArea::m_min_arc_points) - Segments = 2*CArea::m_min_arc_points; + double dphi = acos(1.0 - m_accuracy * m_clipper_scale / fabs(offset)); + int Segments = (int)ceil(PI / dphi); + if (Segments < 2 * CArea::m_min_arc_points) { + Segments = 2 * CArea::m_min_arc_points; + } // if (Segments > CArea::m_max_arc_points) // Segments=CArea::m_max_arc_points; - dphi = PI/Segments; - roundPrecision = (1.0-cos(dphi))*fabs(offset); - }else + dphi = PI / Segments; + roundPrecision = (1.0 - cos(dphi)) * fabs(offset); + } + else { roundPrecision *= m_clipper_scale; + } - ClipperOffset clipper(miterLimit,roundPrecision); - TPolyPolygon pp, pp2; - MakePolyPoly(*this, pp, false); - int i=0; - for(const CCurve &c : m_curves) - clipper.AddPath(pp[i++],joinType,c.IsClosed()?etClosedPolygon:endType); - clipper.Execute(pp2,(long64)(offset)); - SetFromResult(*this, pp2, false); + ClipperOffset clipper(miterLimit, roundPrecision); + TPolyPolygon pp, pp2; + MakePolyPoly(*this, pp, false); + int i = 0; + for (const CCurve& c : m_curves) { + clipper.AddPath(pp[i++], joinType, c.IsClosed() ? etClosedPolygon : endType); + } + clipper.Execute(pp2, (long64)(offset)); + SetFromResult(*this, pp2, false); this->Reorder(); } void CArea::Thicken(double value) { - TPolyPolygon pp; - OffsetSpansWithObrounds(*this, pp, value * m_units); - SetFromResult(*this, pp, false); - this->Reorder(); + TPolyPolygon pp; + OffsetSpansWithObrounds(*this, pp, value * m_units); + SetFromResult(*this, pp, false); + this->Reorder(); } -void UnFitArcs(CCurve &curve) +void UnFitArcs(CCurve& curve) { - pts_for_AddVertex.clear(); - const CVertex* prev_vertex = NULL; - for(std::list::const_iterator It2 = curve.m_vertices.begin(); It2 != curve.m_vertices.end(); It2++) - { - const CVertex& vertex = *It2; - AddVertex(vertex, prev_vertex); - prev_vertex = &vertex; - } + pts_for_AddVertex.clear(); + const CVertex* prev_vertex = NULL; + for (std::list::const_iterator It2 = curve.m_vertices.begin(); + It2 != curve.m_vertices.end(); + It2++) { + const CVertex& vertex = *It2; + AddVertex(vertex, prev_vertex); + prev_vertex = &vertex; + } - curve.m_vertices.clear(); + curve.m_vertices.clear(); - for(std::list::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++) - { - DoubleAreaPoint &pt = *It; - CVertex vertex(0, Point(pt.X / CArea::m_units, pt.Y / CArea::m_units), Point(0.0, 0.0)); - curve.m_vertices.push_back(vertex); - } + for (std::list::iterator It = pts_for_AddVertex.begin(); + It != pts_for_AddVertex.end(); + It++) { + DoubleAreaPoint& pt = *It; + CVertex vertex(0, Point(pt.X / CArea::m_units, pt.Y / CArea::m_units), Point(0.0, 0.0)); + curve.m_vertices.push_back(vertex); + } } diff --git a/src/Mod/CAM/libarea/AreaDxf.cpp b/src/Mod/CAM/libarea/AreaDxf.cpp index 8d05a1850e..227af1d39d 100644 --- a/src/Mod/CAM/libarea/AreaDxf.cpp +++ b/src/Mod/CAM/libarea/AreaDxf.cpp @@ -5,23 +5,28 @@ #include "AreaDxf.h" #include "Area.h" -AreaDxfRead::AreaDxfRead(CArea* area, const char* filepath):CDxfRead(filepath), m_area(area){} +AreaDxfRead::AreaDxfRead(CArea* area, const char* filepath) + : CDxfRead(filepath) + , m_area(area) +{} void AreaDxfRead::StartCurveIfNecessary(const Base::Vector3d& startPoint) const { - Point ps(startPoint.x, startPoint.y); - if(m_area->m_curves.empty() || m_area->m_curves.back().m_vertices.empty() || m_area->m_curves.back().m_vertices.back().m_p != ps) - { - // start a new curve - m_area->m_curves.emplace_back(); - m_area->m_curves.back().m_vertices.emplace_back(ps); - } + Point ps(startPoint.x, startPoint.y); + if (m_area->m_curves.empty() || m_area->m_curves.back().m_vertices.empty() + || m_area->m_curves.back().m_vertices.back().m_p != ps) { + // start a new curve + m_area->m_curves.emplace_back(); + m_area->m_curves.back().m_vertices.emplace_back(ps); + } } -void AreaDxfRead::OnReadLine(const Base::Vector3d& start, const Base::Vector3d& end, bool /*hidden*/) +void AreaDxfRead::OnReadLine(const Base::Vector3d& start, + const Base::Vector3d& end, + bool /*hidden*/) { - StartCurveIfNecessary(start); - m_area->m_curves.back().m_vertices.emplace_back(Point(end.x, end.y)); + StartCurveIfNecessary(start); + m_area->m_curves.back().m_vertices.emplace_back(Point(end.x, end.y)); } void AreaDxfRead::OnReadArc(const Base::Vector3d& start, @@ -30,7 +35,7 @@ void AreaDxfRead::OnReadArc(const Base::Vector3d& start, bool dir, bool /*hidden*/) { - StartCurveIfNecessary(start); + StartCurveIfNecessary(start); m_area->m_curves.back().m_vertices.emplace_back(dir ? 1 : 0, Point(end.x, end.y), Point(center.x, center.y)); diff --git a/src/Mod/CAM/libarea/AreaDxf.h b/src/Mod/CAM/libarea/AreaDxf.h index b3b815697a..575c605f89 100644 --- a/src/Mod/CAM/libarea/AreaDxf.h +++ b/src/Mod/CAM/libarea/AreaDxf.h @@ -10,14 +10,20 @@ class CSketch; class CArea; class CCurve; -class AreaDxfRead : public CDxfRead{ +class AreaDxfRead: public CDxfRead +{ void StartCurveIfNecessary(const Base::Vector3d& startPoint) const; public: - CArea* m_area; - AreaDxfRead(CArea* area, const char* filepath); + CArea* m_area; + AreaDxfRead(CArea* area, const char* filepath); - // AreaDxfRead's virtual functions - void OnReadLine(const Base::Vector3d& start, const Base::Vector3d& end, bool /*hidden*/) override; - void OnReadArc(const Base::Vector3d& start, const Base::Vector3d& end, const Base::Vector3d& center, bool dir, bool /*hidden*/) override; + // AreaDxfRead's virtual functions + void + OnReadLine(const Base::Vector3d& start, const Base::Vector3d& end, bool /*hidden*/) override; + void OnReadArc(const Base::Vector3d& start, + const Base::Vector3d& end, + const Base::Vector3d& center, + bool dir, + bool /*hidden*/) override; }; diff --git a/src/Mod/CAM/libarea/AreaOrderer.cpp b/src/Mod/CAM/libarea/AreaOrderer.cpp index 8d1d47e6e7..cb17d26a84 100644 --- a/src/Mod/CAM/libarea/AreaOrderer.cpp +++ b/src/Mod/CAM/libarea/AreaOrderer.cpp @@ -36,132 +36,137 @@ using namespace std; CAreaOrderer* CInnerCurves::area_orderer = NULL; CInnerCurves::CInnerCurves(shared_ptr pOuter, shared_ptr curve) -:m_pOuter(pOuter) -,m_curve(curve) -{ -} + : m_pOuter(pOuter) + , m_curve(curve) +{} CInnerCurves::~CInnerCurves() -{ -} +{} void CInnerCurves::Insert(shared_ptr pcurve) { - std::list > outside_of_these; - std::list > crossing_these; + std::list> outside_of_these; + std::list> crossing_these; - // check all inner curves - for(shared_ptr c : m_inner_curves) { + // check all inner curves + for (shared_ptr c : m_inner_curves) { - switch(GetOverlapType(*pcurve, *(c->m_curve))) - { - case eOutside: - outside_of_these.push_back(c); - break; + switch (GetOverlapType(*pcurve, *(c->m_curve))) { + case eOutside: + outside_of_these.push_back(c); + break; - case eInside: - // insert in this inner curve - c->Insert(pcurve); - return; + case eInside: + // insert in this inner curve + c->Insert(pcurve); + return; - case eSiblings: - break; + case eSiblings: + break; - case eCrossing: - crossing_these.push_back(c); - break; - } - } + case eCrossing: + crossing_these.push_back(c); + break; + } + } - // add as a new inner - shared_ptr new_item(new CInnerCurves(shared_from_this(), pcurve)); - this->m_inner_curves.insert(new_item); + // add as a new inner + shared_ptr new_item(new CInnerCurves(shared_from_this(), pcurve)); + this->m_inner_curves.insert(new_item); - for(const shared_ptr& c : outside_of_these) { - // move items - c->m_pOuter = new_item; - new_item->m_inner_curves.insert(c); - this->m_inner_curves.erase(c); - } + for (const shared_ptr& c : outside_of_these) { + // move items + c->m_pOuter = new_item; + new_item->m_inner_curves.insert(c); + this->m_inner_curves.erase(c); + } - for(const shared_ptr& c : crossing_these) { - // unite these - new_item->Unite(c); - this->m_inner_curves.erase(c); - } + for (const shared_ptr& c : crossing_these) { + // unite these + new_item->Unite(c); + this->m_inner_curves.erase(c); + } } -void CInnerCurves::GetArea(CArea &area, bool outside, bool use_curve) +void CInnerCurves::GetArea(CArea& area, bool outside, bool use_curve) { - if(use_curve && m_curve) - { - area.m_curves.push_back(*m_curve); - outside = !outside; - } + if (use_curve && m_curve) { + area.m_curves.push_back(*m_curve); + outside = !outside; + } - std::list > do_after; + std::list> do_after; - for(shared_ptr c: m_inner_curves) { - area.m_curves.push_back(*c->m_curve); - if(!outside)area.m_curves.back().Reverse(); + for (shared_ptr c : m_inner_curves) { + area.m_curves.push_back(*c->m_curve); + if (!outside) { + area.m_curves.back().Reverse(); + } - if(outside)c->GetArea(area, !outside, false); - else do_after.push_back(c); - } + if (outside) { + c->GetArea(area, !outside, false); + } + else { + do_after.push_back(c); + } + } - for(shared_ptr c : do_after) - c->GetArea(area, !outside, false); + for (shared_ptr c : do_after) { + c->GetArea(area, !outside, false); + } } void CInnerCurves::Unite(shared_ptr c) { - // unite all the curves in c, with this one - shared_ptr new_area(new CArea()); - new_area->m_curves.push_back(*m_curve); + // unite all the curves in c, with this one + shared_ptr new_area(new CArea()); + new_area->m_curves.push_back(*m_curve); m_unite_area = new_area; - CArea a2; - c->GetArea(a2); + CArea a2; + c->GetArea(a2); - m_unite_area->Union(a2); - m_unite_area->Reorder(); - for(std::list::iterator It = m_unite_area->m_curves.begin(); It != m_unite_area->m_curves.end(); It++) - { - CCurve &curve = *It; - if(It == m_unite_area->m_curves.begin()) - m_curve = make_shared(curve); - else - { - if(curve.IsClockwise())curve.Reverse(); - Insert(std::make_shared(curve)); - } - } + m_unite_area->Union(a2); + m_unite_area->Reorder(); + for (std::list::iterator It = m_unite_area->m_curves.begin(); + It != m_unite_area->m_curves.end(); + It++) { + CCurve& curve = *It; + if (It == m_unite_area->m_curves.begin()) { + m_curve = make_shared(curve); + } + else { + if (curve.IsClockwise()) { + curve.Reverse(); + } + Insert(std::make_shared(curve)); + } + } } CAreaOrderer::CAreaOrderer() - :m_top_level(make_shared()) -{ -} + : m_top_level(make_shared()) +{} void CAreaOrderer::Insert(shared_ptr pcurve) { - CInnerCurves::area_orderer = this; + CInnerCurves::area_orderer = this; - // make them all anti-clockwise as they come in - if(pcurve->IsClockwise())pcurve->Reverse(); + // make them all anti-clockwise as they come in + if (pcurve->IsClockwise()) { + pcurve->Reverse(); + } - m_top_level->Insert(pcurve); + m_top_level->Insert(pcurve); } -CArea CAreaOrderer::ResultArea()const +CArea CAreaOrderer::ResultArea() const { - CArea a; + CArea a; - if(m_top_level) - { - m_top_level->GetArea(a); - } + if (m_top_level) { + m_top_level->GetArea(a); + } - return a; + return a; } - diff --git a/src/Mod/CAM/libarea/AreaOrderer.h b/src/Mod/CAM/libarea/AreaOrderer.h index 05fd964340..98326a3ccc 100644 --- a/src/Mod/CAM/libarea/AreaOrderer.h +++ b/src/Mod/CAM/libarea/AreaOrderer.h @@ -40,19 +40,20 @@ class CAreaOrderer; class CInnerCurves: public std::enable_shared_from_this { std::shared_ptr m_pOuter; - std::shared_ptr m_curve; // always empty if top level - std::set > m_inner_curves; - std::shared_ptr m_unite_area; // new curves made by uniting are stored here + std::shared_ptr m_curve; // always empty if top level + std::set> m_inner_curves; + std::shared_ptr m_unite_area; // new curves made by uniting are stored here public: - static CAreaOrderer* area_orderer; - CInnerCurves(std::shared_ptr pOuter, std::shared_ptr curve); - CInnerCurves(){} - ~CInnerCurves(); + static CAreaOrderer* area_orderer; + CInnerCurves(std::shared_ptr pOuter, std::shared_ptr curve); + CInnerCurves() + {} + ~CInnerCurves(); - void Insert(std::shared_ptr pcurve); - void GetArea(CArea &area, bool outside = true, bool use_curve = true); - void Unite(std::shared_ptr c); + void Insert(std::shared_ptr pcurve); + void GetArea(CArea& area, bool outside = true, bool use_curve = true); + void Unite(std::shared_ptr c); }; class CAreaOrderer @@ -60,8 +61,8 @@ class CAreaOrderer public: std::shared_ptr m_top_level; - CAreaOrderer(); + CAreaOrderer(); - void Insert(std::shared_ptr pcurve); - CArea ResultArea()const; + void Insert(std::shared_ptr pcurve); + CArea ResultArea() const; }; diff --git a/src/Mod/CAM/libarea/AreaPocket.cpp b/src/Mod/CAM/libarea/AreaPocket.cpp index e4ebde685a..961562324a 100644 --- a/src/Mod/CAM/libarea/AreaPocket.cpp +++ b/src/Mod/CAM/libarea/AreaPocket.cpp @@ -14,66 +14,77 @@ static const CAreaPocketParams* pocket_params = NULL; class IslandAndOffset { public: - const CCurve* island; - CArea offset; - std::list island_inners; - std::list touching_offsets; + const CCurve* island; + CArea offset; + std::list island_inners; + std::list touching_offsets; - IslandAndOffset(const CCurve* Island) - { - island = Island; + IslandAndOffset(const CCurve* Island) + { + island = Island; - offset.m_curves.push_back(*island); - offset.m_curves.back().Reverse(); + offset.m_curves.push_back(*island); + offset.m_curves.back().Reverse(); - offset.Offset(-pocket_params->stepover); + offset.Offset(-pocket_params->stepover); - if(offset.m_curves.size() > 1) - { - for(std::list::iterator It = offset.m_curves.begin(); It != offset.m_curves.end(); It++) - { - if(It == offset.m_curves.begin())continue; - island_inners.push_back(*It); - island_inners.back().Reverse(); - } - offset.m_curves.resize(1); - } - } + if (offset.m_curves.size() > 1) { + for (std::list::iterator It = offset.m_curves.begin(); + It != offset.m_curves.end(); + It++) { + if (It == offset.m_curves.begin()) { + continue; + } + island_inners.push_back(*It); + island_inners.back().Reverse(); + } + offset.m_curves.resize(1); + } + } }; class CurveTree { - static std::list to_do_list_for_MakeOffsets; - void MakeOffsets2(); - static std::list islands_added; + static std::list to_do_list_for_MakeOffsets; + void MakeOffsets2(); + static std::list islands_added; public: - Point point_on_parent; - CCurve curve; - std::list inners; - std::list offset_islands; - CurveTree(const CCurve &c) - { - curve = c; - } - ~CurveTree(){} + Point point_on_parent; + CCurve curve; + std::list inners; + std::list offset_islands; + CurveTree(const CCurve& c) + { + curve = c; + } + ~CurveTree() + {} - void MakeOffsets(); + void MakeOffsets(); }; std::list CurveTree::islands_added; class GetCurveItem { public: - CurveTree* curve_tree; - std::list::iterator EndIt; - static std::list to_do_list; + CurveTree* curve_tree; + std::list::iterator EndIt; + static std::list to_do_list; - GetCurveItem(CurveTree* ct, std::list::iterator EIt):curve_tree(ct), EndIt(EIt){} + GetCurveItem(CurveTree* ct, std::list::iterator EIt) + : curve_tree(ct) + , EndIt(EIt) + {} - void GetCurve(CCurve& output); - CVertex& back(){std::list::iterator It = EndIt; It--; return *It;} + void GetCurve(CCurve& output); + CVertex& back() + { + std::list::iterator It = EndIt; + It--; + return *It; + } }; std::list GetCurveItem::to_do_list; @@ -81,374 +92,436 @@ std::list CurveTree::to_do_list_for_MakeOffsets; void GetCurveItem::GetCurve(CCurve& output) { - // walk around the curve adding spans to output until we get to an inner's point_on_parent - // then add a line from the inner's point_on_parent to inner's start point, then GetCurve from inner + // walk around the curve adding spans to output until we get to an inner's point_on_parent + // then add a line from the inner's point_on_parent to inner's start point, then GetCurve from + // inner - // add start point - if(CArea::m_please_abort) - return; - output.m_vertices.insert(this->EndIt, CVertex(curve_tree->curve.m_vertices.front())); + // add start point + if (CArea::m_please_abort) { + return; + } + output.m_vertices.insert(this->EndIt, CVertex(curve_tree->curve.m_vertices.front())); - std::list inners_to_visit; - for(std::list::iterator It2 = curve_tree->inners.begin(); It2 != curve_tree->inners.end(); It2++) - { - inners_to_visit.push_back(*It2); - } + std::list inners_to_visit; + for (std::list::iterator It2 = curve_tree->inners.begin(); + It2 != curve_tree->inners.end(); + It2++) { + inners_to_visit.push_back(*It2); + } - const CVertex* prev_vertex = NULL; + const CVertex* prev_vertex = NULL; - for(std::list::iterator It = curve_tree->curve.m_vertices.begin(); It != curve_tree->curve.m_vertices.end(); It++) - { - const CVertex& vertex = *It; - if(prev_vertex) - { - Span span(prev_vertex->m_p, vertex); + for (std::list::iterator It = curve_tree->curve.m_vertices.begin(); + It != curve_tree->curve.m_vertices.end(); + It++) { + const CVertex& vertex = *It; + if (prev_vertex) { + Span span(prev_vertex->m_p, vertex); - // order inners on this span - std::multimap ordered_inners; - for(std::list::iterator It2 = inners_to_visit.begin(); It2 != inners_to_visit.end();) - { - CurveTree *inner = *It2; - double t; - if(span.On(inner->point_on_parent, &t)) - { - ordered_inners.insert(std::make_pair(t, inner)); - It2 = inners_to_visit.erase(It2); - } - else - { - It2++; - } - if(CArea::m_please_abort) - return; - } + // order inners on this span + std::multimap ordered_inners; + for (std::list::iterator It2 = inners_to_visit.begin(); + It2 != inners_to_visit.end();) { + CurveTree* inner = *It2; + double t; + if (span.On(inner->point_on_parent, &t)) { + ordered_inners.insert(std::make_pair(t, inner)); + It2 = inners_to_visit.erase(It2); + } + else { + It2++; + } + if (CArea::m_please_abort) { + return; + } + } - if(CArea::m_please_abort) - return; - for(std::multimap::iterator It2 = ordered_inners.begin(); It2 != ordered_inners.end(); It2++) - { - CurveTree& inner = *(It2->second); - if(inner.point_on_parent.dist(back().m_p) > 0.01/CArea::m_units) - { - output.m_vertices.insert(this->EndIt, CVertex(vertex.m_type, inner.point_on_parent, vertex.m_c)); - } - if(CArea::m_please_abort) - return; + if (CArea::m_please_abort) { + return; + } + for (std::multimap::iterator It2 = ordered_inners.begin(); + It2 != ordered_inners.end(); + It2++) { + CurveTree& inner = *(It2->second); + if (inner.point_on_parent.dist(back().m_p) > 0.01 / CArea::m_units) { + output.m_vertices.insert( + this->EndIt, + CVertex(vertex.m_type, inner.point_on_parent, vertex.m_c)); + } + if (CArea::m_please_abort) { + return; + } - // vertex add after GetCurve - std::list::iterator VIt = output.m_vertices.insert(this->EndIt, CVertex(inner.point_on_parent)); + // vertex add after GetCurve + std::list::iterator VIt = + output.m_vertices.insert(this->EndIt, CVertex(inner.point_on_parent)); - //inner.GetCurve(output); - GetCurveItem::to_do_list.emplace_back(&inner, VIt); - } + // inner.GetCurve(output); + GetCurveItem::to_do_list.emplace_back(&inner, VIt); + } - if(back().m_p != vertex.m_p)output.m_vertices.insert(this->EndIt, vertex); - } - prev_vertex = &vertex; - } + if (back().m_p != vertex.m_p) { + output.m_vertices.insert(this->EndIt, vertex); + } + } + prev_vertex = &vertex; + } - if(CArea::m_please_abort) - return; - for(std::list::iterator It2 = inners_to_visit.begin(); It2 != inners_to_visit.end(); It2++) - { - CurveTree &inner = *(*It2); - if(inner.point_on_parent != back().m_p) - { - output.m_vertices.insert(this->EndIt, CVertex(inner.point_on_parent)); - } - if(CArea::m_please_abort) - return; + if (CArea::m_please_abort) { + return; + } + for (std::list::iterator It2 = inners_to_visit.begin(); + It2 != inners_to_visit.end(); + It2++) { + CurveTree& inner = *(*It2); + if (inner.point_on_parent != back().m_p) { + output.m_vertices.insert(this->EndIt, CVertex(inner.point_on_parent)); + } + if (CArea::m_please_abort) { + return; + } - // vertex add after GetCurve - std::list::iterator VIt = output.m_vertices.insert(this->EndIt, CVertex(inner.point_on_parent)); + // vertex add after GetCurve + std::list::iterator VIt = + output.m_vertices.insert(this->EndIt, CVertex(inner.point_on_parent)); - //inner.GetCurve(output); - GetCurveItem::to_do_list.emplace_back(&inner, VIt); - - } + // inner.GetCurve(output); + GetCurveItem::to_do_list.emplace_back(&inner, VIt); + } } class IslandAndOffsetLink { public: - const IslandAndOffset* island_and_offset; - CurveTree* add_to; - IslandAndOffsetLink(const IslandAndOffset* i, CurveTree* a){island_and_offset = i; add_to = a;} + const IslandAndOffset* island_and_offset; + CurveTree* add_to; + IslandAndOffsetLink(const IslandAndOffset* i, CurveTree* a) + { + island_and_offset = i; + add_to = a; + } }; -static Point GetNearestPoint(CurveTree* curve_tree, std::list &islands_added, const CCurve &test_curve, CurveTree** best_curve_tree) +static Point GetNearestPoint(CurveTree* curve_tree, + std::list& islands_added, + const CCurve& test_curve, + CurveTree** best_curve_tree) { - // find nearest point to test_curve, from curve and all the islands in - double best_dist; - Point best_point = curve_tree->curve.NearestPoint(test_curve, &best_dist); - *best_curve_tree = curve_tree; - for(std::list::iterator It = islands_added.begin(); It != islands_added.end(); It++) - { - CurveTree* island = *It; - double dist; - Point p = island->curve.NearestPoint(test_curve, &dist); - if(dist < best_dist) - { - *best_curve_tree = island; - best_point = p; - best_dist = dist; - } - } + // find nearest point to test_curve, from curve and all the islands in + double best_dist; + Point best_point = curve_tree->curve.NearestPoint(test_curve, &best_dist); + *best_curve_tree = curve_tree; + for (std::list::iterator It = islands_added.begin(); It != islands_added.end(); + It++) { + CurveTree* island = *It; + double dist; + Point p = island->curve.NearestPoint(test_curve, &dist); + if (dist < best_dist) { + *best_curve_tree = island; + best_point = p; + best_dist = dist; + } + } - return best_point; + return best_point; } void CurveTree::MakeOffsets2() { - // make offsets + // make offsets - if(CArea::m_please_abort) - return; - CArea smaller; - smaller.m_curves.push_back(curve); - smaller.Offset(pocket_params->stepover); + if (CArea::m_please_abort) { + return; + } + CArea smaller; + smaller.m_curves.push_back(curve); + smaller.Offset(pocket_params->stepover); - if(CArea::m_please_abort) - return; + if (CArea::m_please_abort) { + return; + } - // test islands - for(std::list::iterator It = offset_islands.begin(); It != offset_islands.end();) - { - const IslandAndOffset* island_and_offset = *It; + // test islands + for (std::list::iterator It = offset_islands.begin(); + It != offset_islands.end();) { + const IslandAndOffset* island_and_offset = *It; - if(GetOverlapType(island_and_offset->offset, smaller) == eInside) - It++; // island is still inside - else - { - inners.push_back(new CurveTree(*island_and_offset->island)); - islands_added.push_back(inners.back()); - inners.back()->point_on_parent = curve.NearestPoint(*island_and_offset->island); - if(CArea::m_please_abort) - return; - Point island_point = island_and_offset->island->NearestPoint(inners.back()->point_on_parent); - if(CArea::m_please_abort) - return; - inners.back()->curve.ChangeStart(island_point); - if(CArea::m_please_abort) - return; + if (GetOverlapType(island_and_offset->offset, smaller) == eInside) { + It++; // island is still inside + } + else { + inners.push_back(new CurveTree(*island_and_offset->island)); + islands_added.push_back(inners.back()); + inners.back()->point_on_parent = curve.NearestPoint(*island_and_offset->island); + if (CArea::m_please_abort) { + return; + } + Point island_point = + island_and_offset->island->NearestPoint(inners.back()->point_on_parent); + if (CArea::m_please_abort) { + return; + } + inners.back()->curve.ChangeStart(island_point); + if (CArea::m_please_abort) { + return; + } - // add the island offset's inner curves - for(std::list::const_iterator It2 = island_and_offset->island_inners.begin(); It2 != island_and_offset->island_inners.end(); It2++) - { - const CCurve& island_inner = *It2; - inners.back()->inners.push_back(new CurveTree(island_inner)); - inners.back()->inners.back()->point_on_parent = inners.back()->curve.NearestPoint(island_inner); - if(CArea::m_please_abort) - return; - Point island_point = island_inner.NearestPoint(inners.back()->inners.back()->point_on_parent); - if(CArea::m_please_abort) - return; - inners.back()->inners.back()->curve.ChangeStart(island_point); - to_do_list_for_MakeOffsets.push_back(inners.back()->inners.back()); // do it later, in a while loop - if(CArea::m_please_abort) - return; - } + // add the island offset's inner curves + for (std::list::const_iterator It2 = island_and_offset->island_inners.begin(); + It2 != island_and_offset->island_inners.end(); + It2++) { + const CCurve& island_inner = *It2; + inners.back()->inners.push_back(new CurveTree(island_inner)); + inners.back()->inners.back()->point_on_parent = + inners.back()->curve.NearestPoint(island_inner); + if (CArea::m_please_abort) { + return; + } + Point island_point = + island_inner.NearestPoint(inners.back()->inners.back()->point_on_parent); + if (CArea::m_please_abort) { + return; + } + inners.back()->inners.back()->curve.ChangeStart(island_point); + to_do_list_for_MakeOffsets.push_back( + inners.back()->inners.back()); // do it later, in a while loop + if (CArea::m_please_abort) { + return; + } + } - smaller.Subtract(island_and_offset->offset); + smaller.Subtract(island_and_offset->offset); - std::set added; + std::set added; - std::list touching_list; - for(std::list::const_iterator It2 = island_and_offset->touching_offsets.begin(); It2 != island_and_offset->touching_offsets.end(); It2++) - { - const IslandAndOffset* touching = *It2; - touching_list.emplace_back(touching, inners.back()); - added.insert(touching); - } + std::list touching_list; + for (std::list::const_iterator It2 = + island_and_offset->touching_offsets.begin(); + It2 != island_and_offset->touching_offsets.end(); + It2++) { + const IslandAndOffset* touching = *It2; + touching_list.emplace_back(touching, inners.back()); + added.insert(touching); + } - while(touching_list.size() > 0) - { - IslandAndOffsetLink touching = touching_list.front(); - touching_list.pop_front(); - touching.add_to->inners.push_back(new CurveTree(*touching.island_and_offset->island)); - islands_added.push_back(touching.add_to->inners.back()); - touching.add_to->inners.back()->point_on_parent = touching.add_to->curve.NearestPoint(*touching.island_and_offset->island); - Point island_point = touching.island_and_offset->island->NearestPoint(touching.add_to->inners.back()->point_on_parent); - touching.add_to->inners.back()->curve.ChangeStart(island_point); - smaller.Subtract(touching.island_and_offset->offset); + while (touching_list.size() > 0) { + IslandAndOffsetLink touching = touching_list.front(); + touching_list.pop_front(); + touching.add_to->inners.push_back( + new CurveTree(*touching.island_and_offset->island)); + islands_added.push_back(touching.add_to->inners.back()); + touching.add_to->inners.back()->point_on_parent = + touching.add_to->curve.NearestPoint(*touching.island_and_offset->island); + Point island_point = touching.island_and_offset->island->NearestPoint( + touching.add_to->inners.back()->point_on_parent); + touching.add_to->inners.back()->curve.ChangeStart(island_point); + smaller.Subtract(touching.island_and_offset->offset); - // add the island offset's inner curves - for(std::list::const_iterator It2 = touching.island_and_offset->island_inners.begin(); It2 != touching.island_and_offset->island_inners.end(); It2++) - { - const CCurve& island_inner = *It2; - touching.add_to->inners.back()->inners.push_back(new CurveTree(island_inner)); - touching.add_to->inners.back()->inners.back()->point_on_parent = touching.add_to->inners.back()->curve.NearestPoint(island_inner); - if(CArea::m_please_abort) - return; - Point island_point = island_inner.NearestPoint(touching.add_to->inners.back()->inners.back()->point_on_parent); - if(CArea::m_please_abort) - return; - touching.add_to->inners.back()->inners.back()->curve.ChangeStart(island_point); - to_do_list_for_MakeOffsets.push_back(touching.add_to->inners.back()->inners.back()); // do it later, in a while loop - if(CArea::m_please_abort) - return; - } + // add the island offset's inner curves + for (std::list::const_iterator It2 = + touching.island_and_offset->island_inners.begin(); + It2 != touching.island_and_offset->island_inners.end(); + It2++) { + const CCurve& island_inner = *It2; + touching.add_to->inners.back()->inners.push_back(new CurveTree(island_inner)); + touching.add_to->inners.back()->inners.back()->point_on_parent = + touching.add_to->inners.back()->curve.NearestPoint(island_inner); + if (CArea::m_please_abort) { + return; + } + Point island_point = island_inner.NearestPoint( + touching.add_to->inners.back()->inners.back()->point_on_parent); + if (CArea::m_please_abort) { + return; + } + touching.add_to->inners.back()->inners.back()->curve.ChangeStart(island_point); + to_do_list_for_MakeOffsets.push_back( + touching.add_to->inners.back() + ->inners.back()); // do it later, in a while loop + if (CArea::m_please_abort) { + return; + } + } - for(std::list::const_iterator It2 = touching.island_and_offset->touching_offsets.begin(); It2 != touching.island_and_offset->touching_offsets.end(); It2++) - { - if(added.find(*It2)==added.end() && ((*It2) != island_and_offset)) - { - touching_list.emplace_back(*It2, touching.add_to->inners.back()); - added.insert(*It2); - } - } - } + for (std::list::const_iterator It2 = + touching.island_and_offset->touching_offsets.begin(); + It2 != touching.island_and_offset->touching_offsets.end(); + It2++) { + if (added.find(*It2) == added.end() && ((*It2) != island_and_offset)) { + touching_list.emplace_back(*It2, touching.add_to->inners.back()); + added.insert(*It2); + } + } + } - if(CArea::m_please_abort) - return; - It = offset_islands.erase(It); + if (CArea::m_please_abort) { + return; + } + It = offset_islands.erase(It); - for(std::set::iterator It2 = added.begin(); It2 != added.end(); It2++) - { - const IslandAndOffset* i = *It2; - offset_islands.remove(i); - } + for (std::set::iterator It2 = added.begin(); It2 != added.end(); + It2++) { + const IslandAndOffset* i = *It2; + offset_islands.remove(i); + } - if(offset_islands.size() == 0)break; - It = offset_islands.begin(); - } - } + if (offset_islands.size() == 0) { + break; + } + It = offset_islands.begin(); + } + } - CArea::m_processing_done += CArea::m_MakeOffsets_increment; - if(CArea::m_processing_done > CArea::m_after_MakeOffsets_length)CArea::m_processing_done = CArea::m_after_MakeOffsets_length; + CArea::m_processing_done += CArea::m_MakeOffsets_increment; + if (CArea::m_processing_done > CArea::m_after_MakeOffsets_length) { + CArea::m_processing_done = CArea::m_after_MakeOffsets_length; + } - std::list separate_areas; - smaller.Split(separate_areas); - if(CArea::m_please_abort) - return; - for(std::list::iterator It = separate_areas.begin(); It != separate_areas.end(); It++) - { - CArea& separate_area = *It; - CCurve& first_curve = separate_area.m_curves.front(); + std::list separate_areas; + smaller.Split(separate_areas); + if (CArea::m_please_abort) { + return; + } + for (std::list::iterator It = separate_areas.begin(); It != separate_areas.end(); It++) { + CArea& separate_area = *It; + CCurve& first_curve = separate_area.m_curves.front(); - CurveTree* nearest_curve_tree = NULL; - Point near_point = GetNearestPoint(this, islands_added, first_curve, &nearest_curve_tree); + CurveTree* nearest_curve_tree = NULL; + Point near_point = GetNearestPoint(this, islands_added, first_curve, &nearest_curve_tree); - nearest_curve_tree->inners.push_back(new CurveTree(first_curve)); + nearest_curve_tree->inners.push_back(new CurveTree(first_curve)); - for(std::list::iterator It = offset_islands.begin(); It != offset_islands.end();It++) - { - const IslandAndOffset* island_and_offset = *It; - if(GetOverlapType(island_and_offset->offset, separate_area) == eInside) - nearest_curve_tree->inners.back()->offset_islands.push_back(island_and_offset); - if(CArea::m_please_abort) - return; - } + for (std::list::iterator It = offset_islands.begin(); + It != offset_islands.end(); + It++) { + const IslandAndOffset* island_and_offset = *It; + if (GetOverlapType(island_and_offset->offset, separate_area) == eInside) { + nearest_curve_tree->inners.back()->offset_islands.push_back(island_and_offset); + } + if (CArea::m_please_abort) { + return; + } + } - nearest_curve_tree->inners.back()->point_on_parent = near_point; + nearest_curve_tree->inners.back()->point_on_parent = near_point; - if(CArea::m_please_abort) - return; - Point first_curve_point = first_curve.NearestPoint(nearest_curve_tree->inners.back()->point_on_parent); - if(CArea::m_please_abort) - return; - nearest_curve_tree->inners.back()->curve.ChangeStart(first_curve_point); - if(CArea::m_please_abort) - return; - to_do_list_for_MakeOffsets.push_back(nearest_curve_tree->inners.back()); // do it later, in a while loop - if(CArea::m_please_abort) - return; - } + if (CArea::m_please_abort) { + return; + } + Point first_curve_point = + first_curve.NearestPoint(nearest_curve_tree->inners.back()->point_on_parent); + if (CArea::m_please_abort) { + return; + } + nearest_curve_tree->inners.back()->curve.ChangeStart(first_curve_point); + if (CArea::m_please_abort) { + return; + } + to_do_list_for_MakeOffsets.push_back( + nearest_curve_tree->inners.back()); // do it later, in a while loop + if (CArea::m_please_abort) { + return; + } + } } void CurveTree::MakeOffsets() { - to_do_list_for_MakeOffsets.push_back(this); - islands_added.clear(); + to_do_list_for_MakeOffsets.push_back(this); + islands_added.clear(); - while(to_do_list_for_MakeOffsets.size() > 0) - { - CurveTree* curve_tree = to_do_list_for_MakeOffsets.front(); - to_do_list_for_MakeOffsets.pop_front(); - curve_tree->MakeOffsets2(); - } + while (to_do_list_for_MakeOffsets.size() > 0) { + CurveTree* curve_tree = to_do_list_for_MakeOffsets.front(); + to_do_list_for_MakeOffsets.pop_front(); + curve_tree->MakeOffsets2(); + } } -void recur(std::list &arealist, const CArea& a1, const CAreaPocketParams ¶ms, int level) +void recur(std::list& arealist, const CArea& a1, const CAreaPocketParams& params, int level) { - //if(level > 3)return; + // if(level > 3)return; // this makes arealist by recursively offsetting a1 inwards - - if(a1.m_curves.size() == 0) - return; - - if(params.from_center) - arealist.push_front(a1); - else - arealist.push_back(a1); + + if (a1.m_curves.size() == 0) { + return; + } + + if (params.from_center) { + arealist.push_front(a1); + } + else { + arealist.push_back(a1); + } CArea a_offset = a1; a_offset.Offset(params.stepover); - + // split curves into new areas - if(CArea::HolesLinked()) - { - for(std::list::iterator It = a_offset.m_curves.begin(); It != a_offset.m_curves.end(); It++) - { + if (CArea::HolesLinked()) { + for (std::list::iterator It = a_offset.m_curves.begin(); + It != a_offset.m_curves.end(); + It++) { CArea a2; - a2.m_curves.push_back(*It); + a2.m_curves.push_back(*It); recur(arealist, a2, params, level + 1); - } - } - else - { + } + } + else { // split curves into new areas - a_offset.Reorder(); + a_offset.Reorder(); CArea* a2 = NULL; - - for(std::list::iterator It = a_offset.m_curves.begin(); It != a_offset.m_curves.end(); It++) - { - CCurve& curve = *It; - if(curve.IsClockwise()) - { - if(a2 != NULL) - a2->m_curves.push_back(curve); - } - else - { - if(a2 != NULL) - recur(arealist, *a2, params, level + 1); - else - a2 = new CArea(); + + for (std::list::iterator It = a_offset.m_curves.begin(); + It != a_offset.m_curves.end(); + It++) { + CCurve& curve = *It; + if (curve.IsClockwise()) { + if (a2 != NULL) { + a2->m_curves.push_back(curve); + } + } + else { + if (a2 != NULL) { + recur(arealist, *a2, params, level + 1); + } + else { + a2 = new CArea(); + } a2->m_curves.push_back(curve); - } - } + } + } - if(a2 != NULL) - recur(arealist, *a2, params, level + 1); - } + if (a2 != NULL) { + recur(arealist, *a2, params, level + 1); + } + } } -void MarkOverlappingOffsetIslands(std::list &offset_islands) +void MarkOverlappingOffsetIslands(std::list& offset_islands) { - for(std::list::iterator It1 = offset_islands.begin(); It1 != offset_islands.end(); It1++) - { - std::list::iterator It2 = It1; - It2++; - for(;It2 != offset_islands.end(); It2++) - { - IslandAndOffset &o1 = *It1; - IslandAndOffset &o2 = *It2; + for (std::list::iterator It1 = offset_islands.begin(); + It1 != offset_islands.end(); + It1++) { + std::list::iterator It2 = It1; + It2++; + for (; It2 != offset_islands.end(); It2++) { + IslandAndOffset& o1 = *It1; + IslandAndOffset& o2 = *It2; - if(GetOverlapType(o1.offset, o2.offset) == eCrossing) - { - o1.touching_offsets.push_back(&o2); - o2.touching_offsets.push_back(&o1); - } - } - } + if (GetOverlapType(o1.offset, o2.offset) == eCrossing) { + o1.touching_offsets.push_back(&o2); + o2.touching_offsets.push_back(&o1); + } + } + } } -void CArea::MakeOnePocketCurve(std::list &curve_list, const CAreaPocketParams ¶ms)const +void CArea::MakeOnePocketCurve(std::list& curve_list, const CAreaPocketParams& params) const { - if(CArea::m_please_abort) - return; + if (CArea::m_please_abort) { + return; + } #if 0 // simple offsets with feed or rapid joins CArea area_for_feed_possible = *this; @@ -491,73 +564,71 @@ void CArea::MakeOnePocketCurve(std::list &curve_list, const CAreaPocketP } } #else - pocket_params = ¶ms; - if(m_curves.size() == 0) - { - CArea::m_processing_done += CArea::m_single_area_processing_length; - return; - } - CurveTree top_level(m_curves.front()); + pocket_params = ¶ms; + if (m_curves.size() == 0) { + CArea::m_processing_done += CArea::m_single_area_processing_length; + return; + } + CurveTree top_level(m_curves.front()); - std::list offset_islands; + std::list offset_islands; - for(std::list::const_iterator It = m_curves.begin(); It != m_curves.end(); It++) - { - const CCurve& c = *It; - if(It != m_curves.begin()) - { - IslandAndOffset island_and_offset(&c); - offset_islands.push_back(island_and_offset); - top_level.offset_islands.push_back(&(offset_islands.back())); - if(m_please_abort) - return; - } - } + for (std::list::const_iterator It = m_curves.begin(); It != m_curves.end(); It++) { + const CCurve& c = *It; + if (It != m_curves.begin()) { + IslandAndOffset island_and_offset(&c); + offset_islands.push_back(island_and_offset); + top_level.offset_islands.push_back(&(offset_islands.back())); + if (m_please_abort) { + return; + } + } + } - MarkOverlappingOffsetIslands(offset_islands); + MarkOverlappingOffsetIslands(offset_islands); - CArea::m_processing_done += CArea::m_single_area_processing_length * 0.1; + CArea::m_processing_done += CArea::m_single_area_processing_length * 0.1; - double MakeOffsets_processing_length = CArea::m_single_area_processing_length * 0.8; - CArea::m_after_MakeOffsets_length = CArea::m_processing_done + MakeOffsets_processing_length; - double guess_num_offsets = sqrt(GetArea(true)) * 0.5 / params.stepover; - CArea::m_MakeOffsets_increment = MakeOffsets_processing_length / guess_num_offsets; + double MakeOffsets_processing_length = CArea::m_single_area_processing_length * 0.8; + CArea::m_after_MakeOffsets_length = CArea::m_processing_done + MakeOffsets_processing_length; + double guess_num_offsets = sqrt(GetArea(true)) * 0.5 / params.stepover; + CArea::m_MakeOffsets_increment = MakeOffsets_processing_length / guess_num_offsets; - top_level.MakeOffsets(); - if(CArea::m_please_abort) - return; - CArea::m_processing_done = CArea::m_after_MakeOffsets_length; + top_level.MakeOffsets(); + if (CArea::m_please_abort) { + return; + } + CArea::m_processing_done = CArea::m_after_MakeOffsets_length; - curve_list.emplace_back(); - CCurve& output = curve_list.back(); + curve_list.emplace_back(); + CCurve& output = curve_list.back(); - GetCurveItem::to_do_list.emplace_back(&top_level, output.m_vertices.end()); + GetCurveItem::to_do_list.emplace_back(&top_level, output.m_vertices.end()); - while(GetCurveItem::to_do_list.size() > 0) - { - GetCurveItem item = GetCurveItem::to_do_list.front(); - item.GetCurve(output); - GetCurveItem::to_do_list.pop_front(); - } + while (GetCurveItem::to_do_list.size() > 0) { + GetCurveItem item = GetCurveItem::to_do_list.front(); + item.GetCurve(output); + GetCurveItem::to_do_list.pop_front(); + } - // delete curve_trees non-recursively - std::list CurveTreeDestructList; - for(std::list::iterator It = top_level.inners.begin(); It != top_level.inners.end(); It++) - { - CurveTreeDestructList.push_back(*It); - } - while(CurveTreeDestructList.size() > 0) - { - CurveTree* curve_tree = CurveTreeDestructList.front(); - CurveTreeDestructList.pop_front(); - for(std::list::iterator It = curve_tree->inners.begin(); It != curve_tree->inners.end(); It++) - { - CurveTreeDestructList.push_back(*It); - } - delete curve_tree; - } + // delete curve_trees non-recursively + std::list CurveTreeDestructList; + for (std::list::iterator It = top_level.inners.begin(); + It != top_level.inners.end(); + It++) { + CurveTreeDestructList.push_back(*It); + } + while (CurveTreeDestructList.size() > 0) { + CurveTree* curve_tree = CurveTreeDestructList.front(); + CurveTreeDestructList.pop_front(); + for (std::list::iterator It = curve_tree->inners.begin(); + It != curve_tree->inners.end(); + It++) { + CurveTreeDestructList.push_back(*It); + } + delete curve_tree; + } - CArea::m_processing_done += CArea::m_single_area_processing_length * 0.1; + CArea::m_processing_done += CArea::m_single_area_processing_length * 0.1; #endif } - diff --git a/src/Mod/CAM/libarea/Box2D.h b/src/Mod/CAM/libarea/Box2D.h index fc1c0e9749..23ee202ac7 100644 --- a/src/Mod/CAM/libarea/Box2D.h +++ b/src/Mod/CAM/libarea/Box2D.h @@ -28,67 +28,133 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma once -#include // for memcpy() prototype -#include // for sqrt() prototype +#include // for memcpy() prototype +#include // for sqrt() prototype -class CBox2D{ +class CBox2D +{ public: - Point m_minxy; - Point m_maxxy; - bool m_valid; + Point m_minxy; + Point m_maxxy; + bool m_valid; - CBox2D():m_valid(false){} - CBox2D(const Point& minxy, const Point& maxxy):m_minxy(minxy), m_maxxy(maxxy), m_valid(true){} + CBox2D() + : m_valid(false) + {} + CBox2D(const Point& minxy, const Point& maxxy) + : m_minxy(minxy) + , m_maxxy(maxxy) + , m_valid(true) + {} - bool operator==( const CBox2D & rhs ) const - { - if(m_minxy != rhs.m_minxy)return false; - if(m_maxxy != rhs.m_maxxy)return false; - if (m_valid != rhs.m_valid) return(false); + bool operator==(const CBox2D& rhs) const + { + if (m_minxy != rhs.m_minxy) { + return false; + } + if (m_maxxy != rhs.m_maxxy) { + return false; + } + if (m_valid != rhs.m_valid) { + return (false); + } - return(true); - } + return (true); + } - bool operator!=( const CBox2D & rhs ) const { return(! (*this == rhs)); } + bool operator!=(const CBox2D& rhs) const + { + return (!(*this == rhs)); + } - void Insert(const Point &p){ // insert a point - if(m_valid){ - if(p.x < m_minxy.x)m_minxy.x = p.x; - if(p.y < m_minxy.y)m_minxy.y = p.y; - if(p.x > m_maxxy.x)m_maxxy.x = p.x; - if(p.y > m_maxxy.y)m_maxxy.y = p.y; - } - else - { - m_valid = true; - m_minxy = p; - m_maxxy = p; - } - } + void Insert(const Point& p) + { // insert a point + if (m_valid) { + if (p.x < m_minxy.x) { + m_minxy.x = p.x; + } + if (p.y < m_minxy.y) { + m_minxy.y = p.y; + } + if (p.x > m_maxxy.x) { + m_maxxy.x = p.x; + } + if (p.y > m_maxxy.y) { + m_maxxy.y = p.y; + } + } + else { + m_valid = true; + m_minxy = p; + m_maxxy = p; + } + } - void Insert(const CBox2D& b){ - if(b.m_valid){ - if(m_valid){ - if(b.m_minxy.x < m_minxy.x)m_minxy.x = b.m_minxy.x; - if(b.m_minxy.y < m_minxy.y)m_minxy.y = b.m_minxy.y; - if(b.m_maxxy.x > m_maxxy.x)m_maxxy.x = b.m_maxxy.x; - if(b.m_maxxy.y > m_maxxy.y)m_maxxy.y = b.m_maxxy.y; - } - else{ - m_valid = b.m_valid; - m_minxy = b.m_minxy; - m_maxxy = b.m_maxxy; - } - } - } - Point Centre() const {return (m_minxy + m_maxxy) * 0.5;} - double Width() const {if(m_valid)return m_maxxy.x - m_minxy.x; else return 0.0;} - double Height() const {if(m_valid)return m_maxxy.y - m_minxy.y; else return 0.0;} - double Radius() const {return sqrt(Width() * Width() + Height() * Height()) /2;} - double MinX() const { return(m_minxy.x); } - double MaxX() const { return(m_maxxy.x); } - double MinY() const { return(m_minxy.y); } - double MaxY() const { return(m_maxxy.y); } + void Insert(const CBox2D& b) + { + if (b.m_valid) { + if (m_valid) { + if (b.m_minxy.x < m_minxy.x) { + m_minxy.x = b.m_minxy.x; + } + if (b.m_minxy.y < m_minxy.y) { + m_minxy.y = b.m_minxy.y; + } + if (b.m_maxxy.x > m_maxxy.x) { + m_maxxy.x = b.m_maxxy.x; + } + if (b.m_maxxy.y > m_maxxy.y) { + m_maxxy.y = b.m_maxxy.y; + } + } + else { + m_valid = b.m_valid; + m_minxy = b.m_minxy; + m_maxxy = b.m_maxxy; + } + } + } + Point Centre() const + { + return (m_minxy + m_maxxy) * 0.5; + } + double Width() const + { + if (m_valid) { + return m_maxxy.x - m_minxy.x; + } + else { + return 0.0; + } + } + double Height() const + { + if (m_valid) { + return m_maxxy.y - m_minxy.y; + } + else { + return 0.0; + } + } + double Radius() const + { + return sqrt(Width() * Width() + Height() * Height()) / 2; + } + double MinX() const + { + return (m_minxy.x); + } + double MaxX() const + { + return (m_maxxy.x); + } + double MinY() const + { + return (m_minxy.y); + } + double MaxY() const + { + return (m_maxxy.y); + } }; - diff --git a/src/Mod/CAM/libarea/CMakeLists.txt b/src/Mod/CAM/libarea/CMakeLists.txt index 34eb218b6e..e7ba218d3f 100644 --- a/src/Mod/CAM/libarea/CMakeLists.txt +++ b/src/Mod/CAM/libarea/CMakeLists.txt @@ -1,4 +1,4 @@ -# Turn compiler warnings on for gcc +# Turn compiler warnings on for gcc if (CMAKE_BUILD_TOOL MATCHES "make") MESSAGE(STATUS "setting gcc options: -Wall -Werror -Wno-deprecated -pedantic-errors") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") diff --git a/src/Mod/CAM/libarea/Circle.cpp b/src/Mod/CAM/libarea/Circle.cpp index ff973d89b4..7839f7f177 100644 --- a/src/Mod/CAM/libarea/Circle.cpp +++ b/src/Mod/CAM/libarea/Circle.cpp @@ -31,76 +31,79 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Circle::Circle(const Point& p0, const Point& p1, const Point& p2) { - // from TangentCircles in http://code.google.com/p/heekscad/source/browse/trunk/src/Geom.cpp + // from TangentCircles in http://code.google.com/p/heekscad/source/browse/trunk/src/Geom.cpp - // set default values, in case this fails - m_radius = 0.0; - m_c = Point(0, 0); + // set default values, in case this fails + m_radius = 0.0; + m_c = Point(0, 0); - double x1 = p0.x; - double y1 = p0.y; - double x2 = p1.x; - double y2 = p1.y; - double x3 = p2.x; - double y3 = p2.y; + double x1 = p0.x; + double y1 = p0.y; + double x2 = p1.x; + double y2 = p1.y; + double x3 = p2.x; + double y3 = p2.y; - double a = 2 * (x1 - x2); - double b = 2 * (y1 - y2); - double d = (x1 * x1 + y1 * y1) - (x2 * x2 + y2 * y2); + double a = 2 * (x1 - x2); + double b = 2 * (y1 - y2); + double d = (x1 * x1 + y1 * y1) - (x2 * x2 + y2 * y2); - double A = 2 * (x1 - x3); - double B = 2 * (y1 - y3); - double D = (x1 * x1 + y1 * y1) - (x3 * x3 + y3 * y3); + double A = 2 * (x1 - x3); + double B = 2 * (y1 - y3); + double D = (x1 * x1 + y1 * y1) - (x3 * x3 + y3 * y3); - double aBmbA = (a*B - b*A); // aB - bA + double aBmbA = (a * B - b * A); // aB - bA - // x = k + Kr where - double k = (B*d - b*D) / aBmbA; + // x = k + Kr where + double k = (B * d - b * D) / aBmbA; - // y = l + Lr where - double l = (-A*d + a*D)/ aBmbA; + // y = l + Lr where + double l = (-A * d + a * D) / aBmbA; - double qa = -1; - double qb = 0.0; - double qc = k*k + x1*x1 -2*k*x1 + l*l + y1*y1 - 2*l*y1; + double qa = -1; + double qb = 0.0; + double qc = k * k + x1 * x1 - 2 * k * x1 + l * l + y1 * y1 - 2 * l * y1; - // solve the quadratic equation, r = (-b +- sqrt(b*b - 4*a*c))/(2 * a) - for(int qs = 0; qs<2; qs++){ - double bb = qb*qb; - double ac4 = 4*qa*qc; - if(ac4 <= bb){ - double r = (-qb + ((qs == 0) ? 1 : -1) * sqrt(bb - ac4))/(2 * qa); - double x = k; - double y = l; + // solve the quadratic equation, r = (-b +- sqrt(b*b - 4*a*c))/(2 * a) + for (int qs = 0; qs < 2; qs++) { + double bb = qb * qb; + double ac4 = 4 * qa * qc; + if (ac4 <= bb) { + double r = (-qb + ((qs == 0) ? 1 : -1) * sqrt(bb - ac4)) / (2 * qa); + double x = k; + double y = l; - // set the circle - if(r >= 0.0){ - m_c = Point(x, y); - m_radius = r; - } - } - } + // set the circle + if (r >= 0.0) { + m_c = Point(x, y); + m_radius = r; + } + } + } } bool Circle::PointIsOn(const Point& p, double accuracy) { - double rp = p.dist(m_c); - bool on = fabs(m_radius - rp) < accuracy; - return on; + double rp = p.dist(m_c); + bool on = fabs(m_radius - rp) < accuracy; + return on; } bool Circle::LineIsOn(const Point& p0, const Point& p1, double accuracy) { - // checks the points are on the arc, to the given accuracy, and the mid point of the line. + // checks the points are on the arc, to the given accuracy, and the mid point of the line. - if(!PointIsOn(p0, accuracy)) - return false; - if(!PointIsOn(p1, accuracy)) - return false; + if (!PointIsOn(p0, accuracy)) { + return false; + } + if (!PointIsOn(p1, accuracy)) { + return false; + } - Point mid = Point((p0 + p1)/2); - if(!PointIsOn(mid, accuracy)) - return false; + Point mid = Point((p0 + p1) / 2); + if (!PointIsOn(mid, accuracy)) { + return false; + } - return true; -} \ No newline at end of file + return true; +} diff --git a/src/Mod/CAM/libarea/Circle.h b/src/Mod/CAM/libarea/Circle.h index 19a147a1bb..1cfdfda2f5 100644 --- a/src/Mod/CAM/libarea/Circle.h +++ b/src/Mod/CAM/libarea/Circle.h @@ -31,14 +31,18 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Point.h" -class Circle{ +class Circle +{ public: - Point m_c; - double m_radius; + Point m_c; + double m_radius; - Circle(const Point& c, double radius):m_c(c), m_radius(radius){} - Circle(const Point& p0, const Point& p1, const Point& p2); // circle through three points - - bool PointIsOn(const Point& p, double accuracy); - bool LineIsOn(const Point& p0, const Point& p1, double accuracy); -}; \ No newline at end of file + Circle(const Point& c, double radius) + : m_c(c) + , m_radius(radius) + {} + Circle(const Point& p0, const Point& p1, const Point& p2); // circle through three points + + bool PointIsOn(const Point& p, double accuracy); + bool LineIsOn(const Point& p0, const Point& p1, double accuracy); +}; diff --git a/src/Mod/CAM/libarea/Curve.cpp b/src/Mod/CAM/libarea/Curve.cpp index ac920381f0..1258ee2abd 100644 --- a/src/Mod/CAM/libarea/Curve.cpp +++ b/src/Mod/CAM/libarea/Curve.cpp @@ -8,258 +8,280 @@ #include "Area.h" #include "kurve/geometry.h" -const Point operator*(const double &d, const Point &p){ return p * d;} +const Point operator*(const double& d, const Point& p) +{ + return p * d; +} double Point::tolerance = 0.001; -//static const double PI = 3.1415926535897932; duplicated in kurve/geometry.h +// static const double PI = 3.1415926535897932; duplicated in kurve/geometry.h -//This function is moved from header here to solve windows DLL not export -//static variable problem -bool Point::operator==(const Point& p)const{ - return fabs(x-p.x) 0.000000000000001) - *this = (*this) / len; - return len; + double len = length(); + if (fabs(len) > 0.000000000000001) { + *this = (*this) / len; + } + return len; } -Line::Line(const Point& P0, const Point& V):p0(P0), v(V) +Line::Line(const Point& P0, const Point& V) + : p0(P0) + , v(V) +{} + +double Line::Dist(const Point& p) const { + Point vn = v; + vn.normalize(); + double d1 = p0 * vn; + double d2 = p * vn; + Point pn = p0 + vn * (d2 - d1); + + return pn.dist(p); } -double Line::Dist(const Point& p)const -{ - Point vn = v; - vn.normalize(); - double d1 = p0 * vn; - double d2 = p * vn; - Point pn = p0 + vn * (d2 - d1); +CVertex::CVertex(int type, const Point& p, const Point& c, int user_data) + : m_type(type) + , m_p(p) + , m_c(c) + , m_user_data(user_data) +{} - return pn.dist(p); -} - -CVertex::CVertex(int type, const Point& p, const Point& c, int user_data):m_type(type), m_p(p), m_c(c), m_user_data(user_data) -{ -} - -CVertex::CVertex(const Point& p, int user_data):m_type(0), m_p(p), m_c(0.0, 0.0), m_user_data(user_data) -{ -} +CVertex::CVertex(const Point& p, int user_data) + : m_type(0) + , m_p(p) + , m_c(0.0, 0.0) + , m_user_data(user_data) +{} void CCurve::append(const CVertex& vertex) { - m_vertices.push_back(vertex); + m_vertices.push_back(vertex); } -bool CCurve::CheckForArc(const CVertex& prev_vt, std::list& might_be_an_arc, CArc &arc_returned) +bool CCurve::CheckForArc(const CVertex& prev_vt, + std::list& might_be_an_arc, + CArc& arc_returned) { - // this examines the vertices in might_be_an_arc - // if they do fit an arc, set arc to be the arc that they fit and return true - // returns true, if arc added - if(might_be_an_arc.size() < 2) - return false; + // this examines the vertices in might_be_an_arc + // if they do fit an arc, set arc to be the arc that they fit and return true + // returns true, if arc added + if (might_be_an_arc.size() < 2) { + return false; + } - // find middle point - std::size_t num = might_be_an_arc.size(); - std::size_t i = 0; - const CVertex* mid_vt = NULL; - std::size_t mid_i = (num-1)/2; - for(std::list::iterator It = might_be_an_arc.begin(); It != might_be_an_arc.end(); It++, i++) - { - if(i == mid_i) - { - mid_vt = *It; - break; - } - } + // find middle point + std::size_t num = might_be_an_arc.size(); + std::size_t i = 0; + const CVertex* mid_vt = NULL; + std::size_t mid_i = (num - 1) / 2; + for (std::list::iterator It = might_be_an_arc.begin(); + It != might_be_an_arc.end(); + It++, i++) { + if (i == mid_i) { + mid_vt = *It; + break; + } + } - if (mid_vt == NULL) - return false; + if (mid_vt == NULL) { + return false; + } - // create a circle to test - Point p0(prev_vt.m_p); - Point p1(mid_vt->m_p); - Point p2(might_be_an_arc.back()->m_p); - Circle c(p0, p1, p2); + // create a circle to test + Point p0(prev_vt.m_p); + Point p1(mid_vt->m_p); + Point p2(might_be_an_arc.back()->m_p); + Circle c(p0, p1, p2); - const CVertex* current_vt = &prev_vt; + const CVertex* current_vt = &prev_vt; // It seems that ClipperLib's offset ArcTolerance (same as m_accuracy here) // is not exactly what's documented at https://goo.gl/4odfQh. Test shows the // maximum arc distance deviate at about 2.2*ArcTolerance units. The maximum // deviance seems to always occur at the end of arc. - double accuracy = CArea::m_accuracy * 2.3 / CArea::m_units; - for(std::list::iterator It = might_be_an_arc.begin(); It != might_be_an_arc.end(); It++) - { - const CVertex* vt = *It; + double accuracy = CArea::m_accuracy * 2.3 / CArea::m_units; + for (std::list::iterator It = might_be_an_arc.begin(); + It != might_be_an_arc.end(); + It++) { + const CVertex* vt = *It; - if(!c.LineIsOn(current_vt->m_p, vt->m_p, accuracy)) - return false; - current_vt = vt; - } + if (!c.LineIsOn(current_vt->m_p, vt->m_p, accuracy)) { + return false; + } + current_vt = vt; + } - CArc arc; - arc.m_c = c.m_c; - arc.m_s = prev_vt.m_p; - arc.m_e = might_be_an_arc.back()->m_p; - arc.SetDirWithPoint(might_be_an_arc.front()->m_p); - arc.m_user_data = might_be_an_arc.back()->m_user_data; + CArc arc; + arc.m_c = c.m_c; + arc.m_s = prev_vt.m_p; + arc.m_e = might_be_an_arc.back()->m_p; + arc.SetDirWithPoint(might_be_an_arc.front()->m_p); + arc.m_user_data = might_be_an_arc.back()->m_user_data; - double angs = atan2(arc.m_s.y - arc.m_c.y, arc.m_s.x - arc.m_c.x); - double ange = atan2(arc.m_e.y - arc.m_c.y, arc.m_e.x - arc.m_c.x); - if(arc.m_dir) - { - // make sure ange > angs - if(ange < angs)ange += 6.2831853071795864; - } - else - { - // make sure angs > ange - if(angs < ange)angs += 6.2831853071795864; - } + double angs = atan2(arc.m_s.y - arc.m_c.y, arc.m_s.x - arc.m_c.x); + double ange = atan2(arc.m_e.y - arc.m_c.y, arc.m_e.x - arc.m_c.x); + if (arc.m_dir) { + // make sure ange > angs + if (ange < angs) { + ange += 6.2831853071795864; + } + } + else { + // make sure angs > ange + if (angs < ange) { + angs += 6.2831853071795864; + } + } - if(arc.IncludedAngle() >= 3.15) // We don't want full arcs, so limit to about 180 degrees - return false; + if (arc.IncludedAngle() >= 3.15) { // We don't want full arcs, so limit to about 180 degrees + return false; + } - for(std::list::iterator It = might_be_an_arc.begin(); It != might_be_an_arc.end(); It++) - { - const CVertex* vt = *It; - double angp = atan2(vt->m_p.y - arc.m_c.y, vt->m_p.x - arc.m_c.x); - if(arc.m_dir) - { - // make sure angp > angs - if(angp < angs)angp += 6.2831853071795864; - if(angp > ange) - return false; - } - else - { - // make sure angp > ange - if(angp < ange)angp += 6.2831853071795864; - if(angp > angs) - return false; - } - } + for (std::list::iterator It = might_be_an_arc.begin(); + It != might_be_an_arc.end(); + It++) { + const CVertex* vt = *It; + double angp = atan2(vt->m_p.y - arc.m_c.y, vt->m_p.x - arc.m_c.x); + if (arc.m_dir) { + // make sure angp > angs + if (angp < angs) { + angp += 6.2831853071795864; + } + if (angp > ange) { + return false; + } + } + else { + // make sure angp > ange + if (angp < ange) { + angp += 6.2831853071795864; + } + if (angp > angs) { + return false; + } + } + } - arc_returned = arc; - return true; + arc_returned = arc; + return true; } -void CCurve::AddArcOrLines(bool check_for_arc, std::list &new_vertices, std::list& might_be_an_arc, CArc &arc, bool &arc_found, bool &arc_added) +void CCurve::AddArcOrLines(bool check_for_arc, + std::list& new_vertices, + std::list& might_be_an_arc, + CArc& arc, + bool& arc_found, + bool& arc_added) { - if(check_for_arc && CheckForArc(new_vertices.back(), might_be_an_arc, arc)) - { - arc_found = true; - } - else - { - if(arc_found) - { - if(arc.AlmostALine()) - { - new_vertices.emplace_back(arc.m_e, arc.m_user_data); - } - else - { - new_vertices.emplace_back(arc.m_dir ? 1:-1, arc.m_e, arc.m_c, arc.m_user_data); - } + if (check_for_arc && CheckForArc(new_vertices.back(), might_be_an_arc, arc)) { + arc_found = true; + } + else { + if (arc_found) { + if (arc.AlmostALine()) { + new_vertices.emplace_back(arc.m_e, arc.m_user_data); + } + else { + new_vertices.emplace_back(arc.m_dir ? 1 : -1, arc.m_e, arc.m_c, arc.m_user_data); + } - arc_added = true; - arc_found = false; - const CVertex* back_vt = might_be_an_arc.back(); - might_be_an_arc.clear(); - if(check_for_arc)might_be_an_arc.push_back(back_vt); - } - else - { - const CVertex* back_vt = might_be_an_arc.back(); - if(check_for_arc)might_be_an_arc.pop_back(); - for(std::list::iterator It = might_be_an_arc.begin(); It != might_be_an_arc.end(); It++) - { - const CVertex* v = *It; - if(It != might_be_an_arc.begin() || (new_vertices.size() == 0) || (new_vertices.back().m_p != v->m_p)) - { - new_vertices.push_back(*v); - } - } - might_be_an_arc.clear(); - if(check_for_arc)might_be_an_arc.push_back(back_vt); - } - } + arc_added = true; + arc_found = false; + const CVertex* back_vt = might_be_an_arc.back(); + might_be_an_arc.clear(); + if (check_for_arc) { + might_be_an_arc.push_back(back_vt); + } + } + else { + const CVertex* back_vt = might_be_an_arc.back(); + if (check_for_arc) { + might_be_an_arc.pop_back(); + } + for (std::list::iterator It = might_be_an_arc.begin(); + It != might_be_an_arc.end(); + It++) { + const CVertex* v = *It; + if (It != might_be_an_arc.begin() || (new_vertices.size() == 0) + || (new_vertices.back().m_p != v->m_p)) { + new_vertices.push_back(*v); + } + } + might_be_an_arc.clear(); + if (check_for_arc) { + might_be_an_arc.push_back(back_vt); + } + } + } } void CCurve::FitArcs(bool retry) { - std::list new_vertices; + std::list new_vertices; - std::list might_be_an_arc; - CArc arc; - bool arc_found = false; - bool arc_added = false; - int i = 0; - for(std::list::iterator It = m_vertices.begin(); It != m_vertices.end(); It++, i++) - { - CVertex& vt = *It; - if(vt.m_type || i == 0) - { - if (i != 0) - { - AddArcOrLines(false, new_vertices, might_be_an_arc, arc, arc_found, arc_added); - } - new_vertices.push_back(vt); - } - else - { - might_be_an_arc.push_back(&vt); + std::list might_be_an_arc; + CArc arc; + bool arc_found = false; + bool arc_added = false; + int i = 0; + for (std::list::iterator It = m_vertices.begin(); It != m_vertices.end(); It++, i++) { + CVertex& vt = *It; + if (vt.m_type || i == 0) { + if (i != 0) { + AddArcOrLines(false, new_vertices, might_be_an_arc, arc, arc_found, arc_added); + } + new_vertices.push_back(vt); + } + else { + might_be_an_arc.push_back(&vt); - if(might_be_an_arc.size() == 1) - { - } - else - { - AddArcOrLines(true, new_vertices, might_be_an_arc, arc, arc_found, arc_added); - } - } - } + if (might_be_an_arc.size() == 1) {} + else { + AddArcOrLines(true, new_vertices, might_be_an_arc, arc, arc_found, arc_added); + } + } + } - if(might_be_an_arc.size() > 0) { + if (might_be_an_arc.size() > 0) { // check if the last edge can form an arc with the starting edge - if(!retry && - m_vertices.size()>2 && - m_vertices.begin()->m_type==0 && - IsClosed()) - { - std::list tmp; + if (!retry && m_vertices.size() > 2 && m_vertices.begin()->m_type == 0 && IsClosed()) { + std::list tmp; auto it = m_vertices.begin(); tmp.push_back(&(*it++)); // this condition check is to skip the situation when both the // starting and ending has already been fitted with some arc - if(!arc_found || it->m_type==0) { + if (!arc_found || it->m_type == 0) { tmp.push_back(&(*it)); CArc tmpArc; auto itEnd = m_vertices.end(); --itEnd; --itEnd; - if(CheckForArc(*itEnd,tmp,tmpArc)) { - if(arc_found) { + if (CheckForArc(*itEnd, tmp, tmpArc)) { + if (arc_found) { // this means the last edge has already been fitted with // some arc, so we move the first edge to the end - + // Must pop first, because this is a closed curve, // meaning the last point must be equal to the first // point. m_vertices.pop_front(); m_vertices.push_back(m_vertices.front()); - }else{ + } + else { m_vertices.push_front(CVertex(new_vertices.back().m_p)); m_vertices.pop_back(); } @@ -271,1065 +293,1080 @@ void CCurve::FitArcs(bool retry) AddArcOrLines(false, new_vertices, might_be_an_arc, arc, arc_found, arc_added); } - if(arc_added) - { - for(auto *v : might_be_an_arc) + if (arc_added) { + for (auto* v : might_be_an_arc) { new_vertices.push_back(*v); + } m_vertices.swap(new_vertices); - } + } } void CCurve::UnFitArcs() { - std::list new_pts; + std::list new_pts; - const CVertex* prev_vertex = NULL; - for(std::list::const_iterator It2 = m_vertices.begin(); It2 != m_vertices.end(); It2++) - { - const CVertex& vertex = *It2; - if(vertex.m_type == 0 || prev_vertex == NULL) - { - new_pts.push_back(vertex.m_p * CArea::m_units); - } - else - { - if(vertex.m_p != prev_vertex->m_p) - { - double phi,dphi,dx,dy; - int Segments; - int i; - double ang1,ang2,phit; + const CVertex* prev_vertex = NULL; + for (std::list::const_iterator It2 = m_vertices.begin(); It2 != m_vertices.end(); + It2++) { + const CVertex& vertex = *It2; + if (vertex.m_type == 0 || prev_vertex == NULL) { + new_pts.push_back(vertex.m_p * CArea::m_units); + } + else { + if (vertex.m_p != prev_vertex->m_p) { + double phi, dphi, dx, dy; + int Segments; + int i; + double ang1, ang2, phit; - dx = (prev_vertex->m_p.x - vertex.m_c.x) * CArea::m_units; - dy = (prev_vertex->m_p.y - vertex.m_c.y) * CArea::m_units; + dx = (prev_vertex->m_p.x - vertex.m_c.x) * CArea::m_units; + dy = (prev_vertex->m_p.y - vertex.m_c.y) * CArea::m_units; - ang1=atan2(dy,dx); - if (ang1<0) ang1+=2.0*PI; - dx = (vertex.m_p.x - vertex.m_c.x) * CArea::m_units; - dy = (vertex.m_p.y - vertex.m_c.y) * CArea::m_units; - ang2=atan2(dy,dx); - if (ang2<0) ang2+=2.0*PI; + ang1 = atan2(dy, dx); + if (ang1 < 0) { + ang1 += 2.0 * PI; + } + dx = (vertex.m_p.x - vertex.m_c.x) * CArea::m_units; + dy = (vertex.m_p.y - vertex.m_c.y) * CArea::m_units; + ang2 = atan2(dy, dx); + if (ang2 < 0) { + ang2 += 2.0 * PI; + } - if (vertex.m_type == -1) - { //clockwise - if (ang2 > ang1) - phit=2.0*PI-ang2+ ang1; - else - phit=ang1-ang2; - } - else - { //counter_clockwise - if (ang1 > ang2) - phit=-(2.0*PI-ang1+ ang2); - else - phit=-(ang2-ang1); - } + if (vertex.m_type == -1) { // clockwise + if (ang2 > ang1) { + phit = 2.0 * PI - ang2 + ang1; + } + else { + phit = ang1 - ang2; + } + } + else { // counter_clockwise + if (ang1 > ang2) { + phit = -(2.0 * PI - ang1 + ang2); + } + else { + phit = -(ang2 - ang1); + } + } - //what is the delta phi to get an accuracy of aber - double radius = sqrt(dx*dx + dy*dy); - dphi=2*acos((radius-CArea::m_accuracy)/radius); + // what is the delta phi to get an accuracy of aber + double radius = sqrt(dx * dx + dy * dy); + dphi = 2 * acos((radius - CArea::m_accuracy) / radius); - //set the number of segments - if (phit > 0) - Segments=(int)ceil(phit/dphi); - else - Segments=(int)ceil(-phit/dphi); + // set the number of segments + if (phit > 0) { + Segments = (int)ceil(phit / dphi); + } + else { + Segments = (int)ceil(-phit / dphi); + } - if (Segments < 1) - Segments=1; - if (Segments > 100) - Segments=100; + if (Segments < 1) { + Segments = 1; + } + if (Segments > 100) { + Segments = 100; + } - dphi=phit/(Segments); + dphi = phit / (Segments); - double px = prev_vertex->m_p.x * CArea::m_units; - double py = prev_vertex->m_p.y * CArea::m_units; + double px = prev_vertex->m_p.x * CArea::m_units; + double py = prev_vertex->m_p.y * CArea::m_units; - for (i=1; i<=Segments; i++) - { - dx = px - vertex.m_c.x * CArea::m_units; - dy = py - vertex.m_c.y * CArea::m_units; - phi=atan2(dy,dx); + for (i = 1; i <= Segments; i++) { + dx = px - vertex.m_c.x * CArea::m_units; + dy = py - vertex.m_c.y * CArea::m_units; + phi = atan2(dy, dx); - double nx = vertex.m_c.x * CArea::m_units + radius * cos(phi-dphi); - double ny = vertex.m_c.y * CArea::m_units + radius * sin(phi-dphi); + double nx = vertex.m_c.x * CArea::m_units + radius * cos(phi - dphi); + double ny = vertex.m_c.y * CArea::m_units + radius * sin(phi - dphi); - new_pts.emplace_back(nx, ny); + new_pts.emplace_back(nx, ny); - px = nx; - py = ny; - } - } - } - prev_vertex = &vertex; - } + px = nx; + py = ny; + } + } + } + prev_vertex = &vertex; + } - m_vertices.clear(); + m_vertices.clear(); - for(std::list::iterator It = new_pts.begin(); It != new_pts.end(); It++) - { - Point &pt = *It; - CVertex vertex(0, pt / CArea::m_units, Point(0.0, 0.0)); - m_vertices.push_back(vertex); - } + for (std::list::iterator It = new_pts.begin(); It != new_pts.end(); It++) { + Point& pt = *It; + CVertex vertex(0, pt / CArea::m_units, Point(0.0, 0.0)); + m_vertices.push_back(vertex); + } } -Point CCurve::NearestPoint(const Point& p)const +Point CCurve::NearestPoint(const Point& p) const { - double best_dist = 0.0; - Point best_point = Point(0, 0); - bool best_point_valid = false; - Point prev_p = Point(0, 0); - bool prev_p_valid = false; - bool first_span = true; - for(std::list::const_iterator It = m_vertices.begin(); It != m_vertices.end(); It++) - { - const CVertex& vertex = *It; - if(prev_p_valid) - { - Point near_point = Span(prev_p, vertex, first_span).NearestPoint(p); - first_span = false; - double dist = near_point.dist(p); - if(!best_point_valid || dist < best_dist) - { - best_dist = dist; - best_point = near_point; - best_point_valid = true; - } - } - prev_p = vertex.m_p; - prev_p_valid = true; - } - return best_point; + double best_dist = 0.0; + Point best_point = Point(0, 0); + bool best_point_valid = false; + Point prev_p = Point(0, 0); + bool prev_p_valid = false; + bool first_span = true; + for (std::list::const_iterator It = m_vertices.begin(); It != m_vertices.end(); It++) { + const CVertex& vertex = *It; + if (prev_p_valid) { + Point near_point = Span(prev_p, vertex, first_span).NearestPoint(p); + first_span = false; + double dist = near_point.dist(p); + if (!best_point_valid || dist < best_dist) { + best_dist = dist; + best_point = near_point; + best_point_valid = true; + } + } + prev_p = vertex.m_p; + prev_p_valid = true; + } + return best_point; } -Point CCurve::NearestPoint(const CCurve& c, double *d)const +Point CCurve::NearestPoint(const CCurve& c, double* d) const { - double best_dist = 0.0; - Point best_point = Point(0, 0); - bool best_point_valid = false; - Point prev_p = Point(0, 0); - bool prev_p_valid = false; - bool first_span = true; - for(std::list::const_iterator It = c.m_vertices.begin(); It != c.m_vertices.end(); It++) - { - const CVertex& vertex = *It; - if(prev_p_valid) - { - double dist; - Point near_point = NearestPoint(Span(prev_p, vertex, first_span), &dist); - first_span = false; - if(!best_point_valid || dist < best_dist) - { - best_dist = dist; - best_point = near_point; - best_point_valid = true; - } - } - prev_p = vertex.m_p; - prev_p_valid = true; - } - if(d)*d = best_dist; - return best_point; + double best_dist = 0.0; + Point best_point = Point(0, 0); + bool best_point_valid = false; + Point prev_p = Point(0, 0); + bool prev_p_valid = false; + bool first_span = true; + for (std::list::const_iterator It = c.m_vertices.begin(); It != c.m_vertices.end(); + It++) { + const CVertex& vertex = *It; + if (prev_p_valid) { + double dist; + Point near_point = NearestPoint(Span(prev_p, vertex, first_span), &dist); + first_span = false; + if (!best_point_valid || dist < best_dist) { + best_dist = dist; + best_point = near_point; + best_point_valid = true; + } + } + prev_p = vertex.m_p; + prev_p_valid = true; + } + if (d) { + *d = best_dist; + } + return best_point; } -void CCurve::GetBox(CBox2D &box) +void CCurve::GetBox(CBox2D& box) { - Point prev_p = Point(0, 0); - bool prev_p_valid = false; - for(std::list::iterator It = m_vertices.begin(); It != m_vertices.end(); It++) - { - CVertex& vertex = *It; - if(prev_p_valid) - { - Span(prev_p, vertex).GetBox(box); - } - prev_p = vertex.m_p; - prev_p_valid = true; - } + Point prev_p = Point(0, 0); + bool prev_p_valid = false; + for (std::list::iterator It = m_vertices.begin(); It != m_vertices.end(); It++) { + CVertex& vertex = *It; + if (prev_p_valid) { + Span(prev_p, vertex).GetBox(box); + } + prev_p = vertex.m_p; + prev_p_valid = true; + } } void CCurve::Reverse() { - std::list new_vertices; + std::list new_vertices; - CVertex* prev_v = NULL; + CVertex* prev_v = NULL; - for(std::list::reverse_iterator It = m_vertices.rbegin(); It != m_vertices.rend(); It++) - { - CVertex &v = *It; - int type = 0; - Point cp(0.0, 0.0); - if(prev_v) - { - type = -prev_v->m_type; - cp = prev_v->m_c; - } - CVertex new_v(type, v.m_p, cp); - new_vertices.push_back(new_v); - prev_v = &v; - } + for (std::list::reverse_iterator It = m_vertices.rbegin(); It != m_vertices.rend(); + It++) { + CVertex& v = *It; + int type = 0; + Point cp(0.0, 0.0); + if (prev_v) { + type = -prev_v->m_type; + cp = prev_v->m_c; + } + CVertex new_v(type, v.m_p, cp); + new_vertices.push_back(new_v); + prev_v = &v; + } - m_vertices.swap(new_vertices); + m_vertices.swap(new_vertices); } -double CCurve::GetArea()const +double CCurve::GetArea() const { - double area = 0.0; - Point prev_p = Point(0, 0); - bool prev_p_valid = false; - for(std::list::const_iterator It = m_vertices.begin(); It != m_vertices.end(); It++) - { - const CVertex& vertex = *It; - if(prev_p_valid) - { - area += Span(prev_p, vertex).GetArea(); - } - prev_p = vertex.m_p; - prev_p_valid = true; - } - return area; + double area = 0.0; + Point prev_p = Point(0, 0); + bool prev_p_valid = false; + for (std::list::const_iterator It = m_vertices.begin(); It != m_vertices.end(); It++) { + const CVertex& vertex = *It; + if (prev_p_valid) { + area += Span(prev_p, vertex).GetArea(); + } + prev_p = vertex.m_p; + prev_p_valid = true; + } + return area; } -bool CCurve::IsClosed()const +bool CCurve::IsClosed() const { - if(m_vertices.size() == 0) - return false; - return m_vertices.front().m_p == m_vertices.back().m_p; + if (m_vertices.size() == 0) { + return false; + } + return m_vertices.front().m_p == m_vertices.back().m_p; } -void CCurve::ChangeStart(const Point &p) { - CCurve new_curve; - - bool started = false; - bool finished = false; - int start_span = 0; - bool closed = IsClosed(); - - for(int i = 0; i < (closed ? 2:1); i++) - { - const Point *prev_p = NULL; - - int span_index = 0; - for(std::list::const_iterator VIt = m_vertices.begin(); VIt != m_vertices.end() && !finished; VIt++) - { - const CVertex& vertex = *VIt; - - if(prev_p) - { - Span span(*prev_p, vertex); - if(span.On(p)) - { - if(started) - { - if(p == *prev_p || span_index != start_span) - { - new_curve.m_vertices.push_back(vertex); - } - else - { - if(p == vertex.m_p)new_curve.m_vertices.push_back(vertex); - else - { - CVertex v(vertex); - v.m_p = p; - new_curve.m_vertices.push_back(v); - } - finished = true; - } - } - else - { - new_curve.m_vertices.emplace_back(p); - started = true; - start_span = span_index; - if(p != vertex.m_p)new_curve.m_vertices.push_back(vertex); - } - } - else - { - if(started) - { - new_curve.m_vertices.push_back(vertex); - } - } - span_index++; - } - prev_p = &(vertex.m_p); - } - } - - if(started) - { - m_vertices.swap(new_curve.m_vertices); - } -} - -void CCurve::Break(const Point &p) { - // inserts a point, if it lies on the curve - const Point *prev_p = NULL; - - for(std::list::iterator VIt = m_vertices.begin(); VIt != m_vertices.end(); VIt++) - { - CVertex& vertex = *VIt; - - if(p == vertex.m_p)break; // point is already on a vertex - - if(prev_p) - { - Span span(*prev_p, vertex); - if(span.On(p)) - { - CVertex v(vertex); - v.m_p = p; - m_vertices.insert(VIt, v); - break; - } - } - prev_p = &(vertex.m_p); - } -} - -void CCurve::ExtractSeparateCurves(const std::list &ordered_points, std::list &separate_curves)const +void CCurve::ChangeStart(const Point& p) { - // returns separate curves for this curve split at points - // the points must be in order along this curve, already, and lie on this curve - const Point *prev_p = NULL; + CCurve new_curve; - if(ordered_points.size() == 0) - { - separate_curves.push_back(*this); - return; - } + bool started = false; + bool finished = false; + int start_span = 0; + bool closed = IsClosed(); - CCurve current_curve; + for (int i = 0; i < (closed ? 2 : 1); i++) { + const Point* prev_p = NULL; - std::list::const_iterator PIt = ordered_points.begin(); - Point point = *PIt; + int span_index = 0; + for (std::list::const_iterator VIt = m_vertices.begin(); + VIt != m_vertices.end() && !finished; + VIt++) { + const CVertex& vertex = *VIt; - for(std::list::const_iterator VIt = m_vertices.begin(); VIt != m_vertices.end(); VIt++) - { - const CVertex& vertex = *VIt; - if(prev_p)// not the first vertex - { - Span span(*prev_p, vertex); - while((PIt != ordered_points.end()) && span.On(point)) - { - CVertex v(vertex); - v.m_p = point; - current_curve.m_vertices.push_back(v); - if(current_curve.m_vertices.size() > 1)// don't add single point curves - separate_curves.push_back(current_curve); // add the curve - current_curve = CCurve();// make a new curve - current_curve.m_vertices.push_back(v); // add it's first point - PIt++; - if(PIt != ordered_points.end())point = *PIt; // increment the point - } + if (prev_p) { + Span span(*prev_p, vertex); + if (span.On(p)) { + if (started) { + if (p == *prev_p || span_index != start_span) { + new_curve.m_vertices.push_back(vertex); + } + else { + if (p == vertex.m_p) { + new_curve.m_vertices.push_back(vertex); + } + else { + CVertex v(vertex); + v.m_p = p; + new_curve.m_vertices.push_back(v); + } + finished = true; + } + } + else { + new_curve.m_vertices.emplace_back(p); + started = true; + start_span = span_index; + if (p != vertex.m_p) { + new_curve.m_vertices.push_back(vertex); + } + } + } + else { + if (started) { + new_curve.m_vertices.push_back(vertex); + } + } + span_index++; + } + prev_p = &(vertex.m_p); + } + } - // add the end of span - if(current_curve.m_vertices.back().m_p != vertex.m_p) - current_curve.m_vertices.push_back(vertex); - } - if((current_curve.m_vertices.size() == 0) || (current_curve.m_vertices.back().m_p != vertex.m_p)) - { - // very first vertex, start the current curve - current_curve.m_vertices.push_back(vertex); - } - prev_p = &(vertex.m_p); - } + if (started) { + m_vertices.swap(new_curve.m_vertices); + } +} - // add whatever is left - if(current_curve.m_vertices.size() > 1)// don't add single point curves - separate_curves.push_back(current_curve); // add the curve +void CCurve::Break(const Point& p) +{ + // inserts a point, if it lies on the curve + const Point* prev_p = NULL; + + for (std::list::iterator VIt = m_vertices.begin(); VIt != m_vertices.end(); VIt++) { + CVertex& vertex = *VIt; + + if (p == vertex.m_p) { + break; // point is already on a vertex + } + + if (prev_p) { + Span span(*prev_p, vertex); + if (span.On(p)) { + CVertex v(vertex); + v.m_p = p; + m_vertices.insert(VIt, v); + break; + } + } + prev_p = &(vertex.m_p); + } +} + +void CCurve::ExtractSeparateCurves(const std::list& ordered_points, + std::list& separate_curves) const +{ + // returns separate curves for this curve split at points + // the points must be in order along this curve, already, and lie on this curve + const Point* prev_p = NULL; + + if (ordered_points.size() == 0) { + separate_curves.push_back(*this); + return; + } + + CCurve current_curve; + + std::list::const_iterator PIt = ordered_points.begin(); + Point point = *PIt; + + for (std::list::const_iterator VIt = m_vertices.begin(); VIt != m_vertices.end(); + VIt++) { + const CVertex& vertex = *VIt; + if (prev_p) // not the first vertex + { + Span span(*prev_p, vertex); + while ((PIt != ordered_points.end()) && span.On(point)) { + CVertex v(vertex); + v.m_p = point; + current_curve.m_vertices.push_back(v); + if (current_curve.m_vertices.size() > 1) { // don't add single point curves + separate_curves.push_back(current_curve); // add the curve + } + current_curve = CCurve(); // make a new curve + current_curve.m_vertices.push_back(v); // add it's first point + PIt++; + if (PIt != ordered_points.end()) { + point = *PIt; // increment the point + } + } + + // add the end of span + if (current_curve.m_vertices.back().m_p != vertex.m_p) { + current_curve.m_vertices.push_back(vertex); + } + } + if ((current_curve.m_vertices.size() == 0) + || (current_curve.m_vertices.back().m_p != vertex.m_p)) { + // very first vertex, start the current curve + current_curve.m_vertices.push_back(vertex); + } + prev_p = &(vertex.m_p); + } + + // add whatever is left + if (current_curve.m_vertices.size() > 1) { // don't add single point curves + separate_curves.push_back(current_curve); // add the curve + } } +void CCurve::RemoveTinySpans() +{ + CCurve new_curve; -void CCurve::RemoveTinySpans() { - CCurve new_curve; + std::list::const_iterator VIt = m_vertices.begin(); + new_curve.m_vertices.push_back(*VIt); + VIt++; - std::list::const_iterator VIt = m_vertices.begin(); - new_curve.m_vertices.push_back(*VIt); - VIt++; + for (; VIt != m_vertices.end(); VIt++) { + const CVertex& vertex = *VIt; - for(; VIt != m_vertices.end(); VIt++) - { - const CVertex& vertex = *VIt; - - if(vertex.m_type != 0 || new_curve.m_vertices.back().m_p.dist(vertex.m_p) > Point::tolerance) - { - new_curve.m_vertices.push_back(vertex); - } - } + if (vertex.m_type != 0 + || new_curve.m_vertices.back().m_p.dist(vertex.m_p) > Point::tolerance) { + new_curve.m_vertices.push_back(vertex); + } + } m_vertices.swap(new_curve.m_vertices); } -void CCurve::ChangeEnd(const Point &p) { - // changes the end position of the Kurve, doesn't keep closed kurves closed - CCurve new_curve; +void CCurve::ChangeEnd(const Point& p) +{ + // changes the end position of the Kurve, doesn't keep closed kurves closed + CCurve new_curve; - const Point *prev_p = NULL; + const Point* prev_p = NULL; - for(std::list::const_iterator VIt = m_vertices.begin(); VIt != m_vertices.end(); VIt++) - { - const CVertex& vertex = *VIt; + for (std::list::const_iterator VIt = m_vertices.begin(); VIt != m_vertices.end(); + VIt++) { + const CVertex& vertex = *VIt; - if(prev_p) - { - Span span(*prev_p, vertex); - if(span.On(p)) - { - CVertex v(vertex); - v.m_p = p; - new_curve.m_vertices.push_back(v); - break; - } - else - { - if(p != vertex.m_p)new_curve.m_vertices.push_back(vertex); - } - } - else - { - new_curve.m_vertices.push_back(vertex); - } - prev_p = &(vertex.m_p); - } + if (prev_p) { + Span span(*prev_p, vertex); + if (span.On(p)) { + CVertex v(vertex); + v.m_p = p; + new_curve.m_vertices.push_back(v); + break; + } + else { + if (p != vertex.m_p) { + new_curve.m_vertices.push_back(vertex); + } + } + } + else { + new_curve.m_vertices.push_back(vertex); + } + prev_p = &(vertex.m_p); + } - m_vertices.swap(new_curve.m_vertices); + m_vertices.swap(new_curve.m_vertices); } -Point CCurve::NearestPoint(const Span& p, double *d)const +Point CCurve::NearestPoint(const Span& p, double* d) const { - double best_dist = 0.0; - Point best_point = Point(0, 0); - bool best_point_valid = false; - Point prev_p = Point(0, 0); - bool prev_p_valid = false; - bool first_span = true; - for(std::list::const_iterator It = m_vertices.begin(); It != m_vertices.end(); It++) - { - const CVertex& vertex = *It; - if(prev_p_valid) - { - double dist; - Point near_point = Span(prev_p, vertex, first_span).NearestPoint(p, &dist); - first_span = false; - if(!best_point_valid || dist < best_dist) - { - best_dist = dist; - best_point = near_point; - best_point_valid = true; - } - } - prev_p = vertex.m_p; - prev_p_valid = true; - } - if(d)*d = best_dist; - return best_point; + double best_dist = 0.0; + Point best_point = Point(0, 0); + bool best_point_valid = false; + Point prev_p = Point(0, 0); + bool prev_p_valid = false; + bool first_span = true; + for (std::list::const_iterator It = m_vertices.begin(); It != m_vertices.end(); It++) { + const CVertex& vertex = *It; + if (prev_p_valid) { + double dist; + Point near_point = Span(prev_p, vertex, first_span).NearestPoint(p, &dist); + first_span = false; + if (!best_point_valid || dist < best_dist) { + best_dist = dist; + best_point = near_point; + best_point_valid = true; + } + } + prev_p = vertex.m_p; + prev_p_valid = true; + } + if (d) { + *d = best_dist; + } + return best_point; } static geoff_geometry::Kurve MakeKurve(const CCurve& curve) { - geoff_geometry::Kurve k; - for(std::list::const_iterator It = curve.m_vertices.begin(); It != curve.m_vertices.end(); It++) - { - const CVertex& v = *It; - k.Add(geoff_geometry::spVertex(v.m_type, geoff_geometry::Point(v.m_p.x, v.m_p.y), geoff_geometry::Point(v.m_c.x, v.m_c.y))); - } - return k; + geoff_geometry::Kurve k; + for (std::list::const_iterator It = curve.m_vertices.begin(); + It != curve.m_vertices.end(); + It++) { + const CVertex& v = *It; + k.Add(geoff_geometry::spVertex(v.m_type, + geoff_geometry::Point(v.m_p.x, v.m_p.y), + geoff_geometry::Point(v.m_c.x, v.m_c.y))); + } + return k; } static CCurve MakeCCurve(const geoff_geometry::Kurve& k) { - CCurve c; - int n = k.nSpans(); - for(int i = 0; i<= n; i++) - { - geoff_geometry::spVertex spv; - k.Get(i, spv); - c.append(CVertex(spv.type, Point(spv.p.x, spv.p.y), Point(spv.pc.x, spv.pc.y))); - } - return c; + CCurve c; + int n = k.nSpans(); + for (int i = 0; i <= n; i++) { + geoff_geometry::spVertex spv; + k.Get(i, spv); + c.append(CVertex(spv.type, Point(spv.p.x, spv.p.y), Point(spv.pc.x, spv.pc.y))); + } + return c; } static geoff_geometry::Span MakeSpan(const Span& span) { - return geoff_geometry::Span(span.m_v.m_type, geoff_geometry::Point(span.m_p.x, span.m_p.y), geoff_geometry::Point(span.m_v.m_p.x, span.m_v.m_p.y), geoff_geometry::Point(span.m_v.m_c.x, span.m_v.m_c.y)); + return geoff_geometry::Span(span.m_v.m_type, + geoff_geometry::Point(span.m_p.x, span.m_p.y), + geoff_geometry::Point(span.m_v.m_p.x, span.m_v.m_p.y), + geoff_geometry::Point(span.m_v.m_c.x, span.m_v.m_c.y)); } bool CCurve::Offset(double leftwards_value) { - // use the kurve code donated by Geoff Hawkesford, to offset the curve as an open curve - // returns true for success, false for failure - bool success = true; + // use the kurve code donated by Geoff Hawkesford, to offset the curve as an open curve + // returns true for success, false for failure + bool success = true; - CCurve save_curve = *this; + CCurve save_curve = *this; - try - { - geoff_geometry::Kurve k = MakeKurve(*this); - geoff_geometry::Kurve kOffset; - int ret = 0; - k.OffsetMethod1(kOffset, fabs(leftwards_value), (leftwards_value > 0) ? 1:-1, 1, ret); - success = (ret == 0); - if(success)*this = MakeCCurve(kOffset); - } - catch(...) - { - success = false; - } + try { + geoff_geometry::Kurve k = MakeKurve(*this); + geoff_geometry::Kurve kOffset; + int ret = 0; + k.OffsetMethod1(kOffset, fabs(leftwards_value), (leftwards_value > 0) ? 1 : -1, 1, ret); + success = (ret == 0); + if (success) { + *this = MakeCCurve(kOffset); + } + } + catch (...) { + success = false; + } - if(!success) - { - if(this->IsClosed()) - { - double inwards_offset = leftwards_value; - bool cw = false; - if(this->IsClockwise()) - { - inwards_offset = -inwards_offset; - cw = true; - } - CArea a; - a.append(*this); - a.Offset(inwards_offset); - if(a.m_curves.size() == 1) - { - Span* start_span = NULL; - if(this->m_vertices.size() > 1) - { - std::list::iterator It = m_vertices.begin(); - CVertex &v0 = *It; - It++; - CVertex &v1 = *It; - start_span = new Span(v0.m_p, v1, true); - } - *this = a.m_curves.front(); - if(this->IsClockwise() != cw)this->Reverse(); - if(start_span) - { - Point forward = start_span->GetVector(0.0); - Point left(-forward.y, forward.x); - Point offset_start = start_span->m_p + left * leftwards_value; - this->ChangeStart(this->NearestPoint(offset_start)); - delete start_span; - } - success = true; - } - } - } + if (!success) { + if (this->IsClosed()) { + double inwards_offset = leftwards_value; + bool cw = false; + if (this->IsClockwise()) { + inwards_offset = -inwards_offset; + cw = true; + } + CArea a; + a.append(*this); + a.Offset(inwards_offset); + if (a.m_curves.size() == 1) { + Span* start_span = NULL; + if (this->m_vertices.size() > 1) { + std::list::iterator It = m_vertices.begin(); + CVertex& v0 = *It; + It++; + CVertex& v1 = *It; + start_span = new Span(v0.m_p, v1, true); + } + *this = a.m_curves.front(); + if (this->IsClockwise() != cw) { + this->Reverse(); + } + if (start_span) { + Point forward = start_span->GetVector(0.0); + Point left(-forward.y, forward.x); + Point offset_start = start_span->m_p + left * leftwards_value; + this->ChangeStart(this->NearestPoint(offset_start)); + delete start_span; + } + success = true; + } + } + } - return success; + return success; } -void CCurve::GetSpans(std::list &spans)const +void CCurve::GetSpans(std::list& spans) const { - const Point *prev_p = NULL; - for(std::list::const_iterator It = m_vertices.begin(); It != m_vertices.end(); It++) - { - const CVertex& vertex = *It; - if(prev_p) - { - spans.emplace_back(*prev_p, vertex); - } - prev_p = &(vertex.m_p); - } + const Point* prev_p = NULL; + for (std::list::const_iterator It = m_vertices.begin(); It != m_vertices.end(); It++) { + const CVertex& vertex = *It; + if (prev_p) { + spans.emplace_back(*prev_p, vertex); + } + prev_p = &(vertex.m_p); + } } void CCurve::OffsetForward(double forwards_value, bool refit_arcs) { - // for drag-knife compensation + // for drag-knife compensation - // replace arcs with lines - UnFitArcs(); + // replace arcs with lines + UnFitArcs(); - std::list spans; - GetSpans(spans); + std::list spans; + GetSpans(spans); - m_vertices.clear(); + m_vertices.clear(); - // shift all the spans - for(std::list::iterator It = spans.begin(); It != spans.end(); It++) - { - Span &span = *It; - Point v = span.GetVector(0.0); - v.normalize(); - Point shift = v * forwards_value; - span.m_p = span.m_p + shift; - span.m_v.m_p = span.m_v.m_p + shift; - } + // shift all the spans + for (std::list::iterator It = spans.begin(); It != spans.end(); It++) { + Span& span = *It; + Point v = span.GetVector(0.0); + v.normalize(); + Point shift = v * forwards_value; + span.m_p = span.m_p + shift; + span.m_v.m_p = span.m_v.m_p + shift; + } - // loop through the shifted spans - for(std::list::iterator It = spans.begin(); It != spans.end();) - { - Span &span = *It; - Point v = span.GetVector(0.0); - v.normalize(); + // loop through the shifted spans + for (std::list::iterator It = spans.begin(); It != spans.end();) { + Span& span = *It; + Point v = span.GetVector(0.0); + v.normalize(); - // add the span - if(It == spans.begin())m_vertices.push_back(span.m_p); - m_vertices.push_back(span.m_v.m_p); + // add the span + if (It == spans.begin()) { + m_vertices.push_back(span.m_p); + } + m_vertices.push_back(span.m_v.m_p); - It++; - if(It != spans.end()) - { - Span &next_span = *It; - Point nv = next_span.GetVector(0.0); - nv.normalize(); - double sin_angle = v ^ nv; - bool sharp_corner = ( fabs(sin_angle) > 0.5 ); // angle > 30 degrees + It++; + if (It != spans.end()) { + Span& next_span = *It; + Point nv = next_span.GetVector(0.0); + nv.normalize(); + double sin_angle = v ^ nv; + bool sharp_corner = (fabs(sin_angle) > 0.5); // angle > 30 degrees - if(sharp_corner) - { - // add an arc to the start of the next span - int arc_type = ((sin_angle > 0) ? 1 : (-1)); - Point centre = span.m_v.m_p - v * forwards_value; - m_vertices.emplace_back(arc_type, next_span.m_p, centre); - } - } - } + if (sharp_corner) { + // add an arc to the start of the next span + int arc_type = ((sin_angle > 0) ? 1 : (-1)); + Point centre = span.m_v.m_p - v * forwards_value; + m_vertices.emplace_back(arc_type, next_span.m_p, centre); + } + } + } - if(refit_arcs) - FitArcs(); // find the arcs again - else - UnFitArcs(); // convert those little arcs added to lines + if (refit_arcs) { + FitArcs(); // find the arcs again + } + else { + UnFitArcs(); // convert those little arcs added to lines + } } -double CCurve::Perim()const +double CCurve::Perim() const { - const Point *prev_p = NULL; - double perim = 0.0; - for(std::list::const_iterator It = m_vertices.begin(); It != m_vertices.end(); It++) - { - const CVertex& vertex = *It; - if(prev_p) - { - Span span(*prev_p, vertex); - perim += span.Length(); - } - prev_p = &(vertex.m_p); - } + const Point* prev_p = NULL; + double perim = 0.0; + for (std::list::const_iterator It = m_vertices.begin(); It != m_vertices.end(); It++) { + const CVertex& vertex = *It; + if (prev_p) { + Span span(*prev_p, vertex); + perim += span.Length(); + } + prev_p = &(vertex.m_p); + } - return perim; + return perim; } -Point CCurve::PerimToPoint(double perim)const +Point CCurve::PerimToPoint(double perim) const { - if(m_vertices.size() == 0) - return Point(0, 0); + if (m_vertices.size() == 0) { + return Point(0, 0); + } - const Point *prev_p = NULL; - double kperim = 0.0; - for(std::list::const_iterator It = m_vertices.begin(); It != m_vertices.end(); It++) - { - const CVertex& vertex = *It; - if(prev_p) - { - Span span(*prev_p, vertex); - double length = span.Length(); - if(perim < kperim + length) - { - Point p = span.MidPerim(perim - kperim); - return p; - } - kperim += length; - } - prev_p = &(vertex.m_p); - } + const Point* prev_p = NULL; + double kperim = 0.0; + for (std::list::const_iterator It = m_vertices.begin(); It != m_vertices.end(); It++) { + const CVertex& vertex = *It; + if (prev_p) { + Span span(*prev_p, vertex); + double length = span.Length(); + if (perim < kperim + length) { + Point p = span.MidPerim(perim - kperim); + return p; + } + kperim += length; + } + prev_p = &(vertex.m_p); + } - return m_vertices.back().m_p; + return m_vertices.back().m_p; } -double CCurve::PointToPerim(const Point& p)const +double CCurve::PointToPerim(const Point& p) const { - double best_dist = 0.0; - double perim_at_best_dist = 0.0; - //Point best_point = Point(0, 0); - bool best_dist_found = false; + double best_dist = 0.0; + double perim_at_best_dist = 0.0; + // Point best_point = Point(0, 0); + bool best_dist_found = false; - double perim = 0.0; + double perim = 0.0; - const Point *prev_p = NULL; - bool first_span = true; - for(std::list::const_iterator It = m_vertices.begin(); It != m_vertices.end(); It++) - { - const CVertex& vertex = *It; - if(prev_p) - { - Span span(*prev_p, vertex, first_span); - Point near_point = span.NearestPoint(p); - first_span = false; - double dist = near_point.dist(p); - if(!best_dist_found || dist < best_dist) - { - best_dist = dist; - Span span_to_point(*prev_p, CVertex(span.m_v.m_type, near_point, span.m_v.m_c)); - perim_at_best_dist = perim + span_to_point.Length(); - best_dist_found = true; - } - perim += span.Length(); - } - prev_p = &(vertex.m_p); - } - return perim_at_best_dist; + const Point* prev_p = NULL; + bool first_span = true; + for (std::list::const_iterator It = m_vertices.begin(); It != m_vertices.end(); It++) { + const CVertex& vertex = *It; + if (prev_p) { + Span span(*prev_p, vertex, first_span); + Point near_point = span.NearestPoint(p); + first_span = false; + double dist = near_point.dist(p); + if (!best_dist_found || dist < best_dist) { + best_dist = dist; + Span span_to_point(*prev_p, CVertex(span.m_v.m_type, near_point, span.m_v.m_c)); + perim_at_best_dist = perim + span_to_point.Length(); + best_dist_found = true; + } + perim += span.Length(); + } + prev_p = &(vertex.m_p); + } + return perim_at_best_dist; } void CCurve::operator+=(const CCurve& curve) { - for(std::list::const_iterator It = curve.m_vertices.begin(); It != curve.m_vertices.end(); It++) - { - const CVertex &vt = *It; - if(It == curve.m_vertices.begin()) - { - if((m_vertices.size() == 0) || (It->m_p != m_vertices.back().m_p)) - { - m_vertices.emplace_back(It->m_p); - } - } - else - { - m_vertices.push_back(vt); - } - } + for (std::list::const_iterator It = curve.m_vertices.begin(); + It != curve.m_vertices.end(); + It++) { + const CVertex& vt = *It; + if (It == curve.m_vertices.begin()) { + if ((m_vertices.size() == 0) || (It->m_p != m_vertices.back().m_p)) { + m_vertices.emplace_back(It->m_p); + } + } + else { + m_vertices.push_back(vt); + } + } } -void CCurve::CurveIntersections(const CCurve& c, std::list &pts)const +void CCurve::CurveIntersections(const CCurve& c, std::list& pts) const { - CArea a; - a.append(*this); - a.CurveIntersections(c, pts); + CArea a; + a.append(*this); + a.CurveIntersections(c, pts); } -void CCurve::SpanIntersections(const Span& s, std::list &pts)const +void CCurve::SpanIntersections(const Span& s, std::list& pts) const { - std::list spans; - GetSpans(spans); - for(std::list::iterator It = spans.begin(); It != spans.end(); It++) - { - Span& span = *It; - std::list pts2; - span.Intersect(s, pts2); - for(std::list::iterator It = pts2.begin(); It != pts2.end(); It++) - { - Point &pt = *It; - if(pts.size() == 0) - { - pts.push_back(pt); - } - else - { - if(pt != pts.back())pts.push_back(pt); - } - } - } + std::list spans; + GetSpans(spans); + for (std::list::iterator It = spans.begin(); It != spans.end(); It++) { + Span& span = *It; + std::list pts2; + span.Intersect(s, pts2); + for (std::list::iterator It = pts2.begin(); It != pts2.end(); It++) { + Point& pt = *It; + if (pts.size() == 0) { + pts.push_back(pt); + } + else { + if (pt != pts.back()) { + pts.push_back(pt); + } + } + } + } } const Point Span::null_point = Point(0, 0); const CVertex Span::null_vertex = CVertex(Point(0, 0)); -Span::Span():m_start_span(false), m_p(null_point), m_v(null_vertex){} +Span::Span() + : m_start_span(false) + , m_p(null_point) + , m_v(null_vertex) +{} -Point Span::NearestPointNotOnSpan(const Point& p)const +Point Span::NearestPointNotOnSpan(const Point& p) const { - if(m_v.m_type == 0) - { - Point Vs = (m_v.m_p - m_p); - Vs.normalize(); - double dp = (p - m_p) * Vs; - return (Vs * dp) + m_p; - } - else - { - double radius = m_p.dist(m_v.m_c); - double r = p.dist(m_v.m_c); - if(r < Point::tolerance) - return m_p; - Point vc = (m_v.m_c - p); - return p + vc * ((r - radius) / r); - } + if (m_v.m_type == 0) { + Point Vs = (m_v.m_p - m_p); + Vs.normalize(); + double dp = (p - m_p) * Vs; + return (Vs * dp) + m_p; + } + else { + double radius = m_p.dist(m_v.m_c); + double r = p.dist(m_v.m_c); + if (r < Point::tolerance) { + return m_p; + } + Point vc = (m_v.m_c - p); + return p + vc * ((r - radius) / r); + } } -Point Span::NearestPoint(const Point& p)const +Point Span::NearestPoint(const Point& p) const { - Point np = NearestPointNotOnSpan(p); - double t = Parameter(np); - if(t >= 0.0 && t <= 1.0) - return np; + Point np = NearestPointNotOnSpan(p); + double t = Parameter(np); + if (t >= 0.0 && t <= 1.0) { + return np; + } - double d1 = p.dist(this->m_p); - double d2 = p.dist(this->m_v.m_p); + double d1 = p.dist(this->m_p); + double d2 = p.dist(this->m_v.m_p); - if(d1 < d2) - return this->m_p; - else return m_v.m_p; + if (d1 < d2) { + return this->m_p; + } + else { + return m_v.m_p; + } } -Point Span::MidPerim(double d)const { - /// returns a point which is 0-d along span - Point p; - if(m_v.m_type == 0) { - Point vs = m_v.m_p - m_p; - vs.normalize(); - p = vs * d + m_p; - } - else { - Point v = m_p - m_v.m_c; - double radius = v.length(); - v.Rotate(d * m_v.m_type / radius); - p = v + m_v.m_c; - } - return p; -} - -Point Span::MidParam(double param)const { - /// returns a point which is 0-1 along span - if(fabs(param) < 0.00000000000001) - return m_p; - if(fabs(param - 1.0) < 0.00000000000001) - return m_v.m_p; - - Point p; - if(m_v.m_type == 0) { - Point vs = m_v.m_p - m_p; - p = vs * param + m_p; - } - else { - Point v = m_p - m_v.m_c; - v.Rotate(param * IncludedAngle()); - p = v + m_v.m_c; - } - return p; -} - -Point Span::NearestPointToSpan(const Span& p, double &d)const +Point Span::MidPerim(double d) const { - Point midpoint = MidParam(0.5); - Point np = p.NearestPoint(m_p); - Point best_point = m_p; - double dist = np.dist(m_p); - if(p.m_start_span)dist -= (CArea::m_accuracy * 2); // give start of curve most priority - Point npm = p.NearestPoint(midpoint); - double dm = npm.dist(midpoint) - CArea::m_accuracy; // lie about midpoint distance to give midpoints priority - if(dm < dist){dist = dm; best_point = midpoint;} - Point np2 = p.NearestPoint(m_v.m_p); - double dp2 = np2.dist(m_v.m_p); - if(dp2 < dist){dist = dp2; best_point = m_v.m_p;} - d = dist; - return best_point; + /// returns a point which is 0-d along span + Point p; + if (m_v.m_type == 0) { + Point vs = m_v.m_p - m_p; + vs.normalize(); + p = vs * d + m_p; + } + else { + Point v = m_p - m_v.m_c; + double radius = v.length(); + v.Rotate(d * m_v.m_type / radius); + p = v + m_v.m_c; + } + return p; } -Point Span::NearestPoint(const Span& p, double *d)const +Point Span::MidParam(double param) const { - double best_dist; - Point best_point = this->NearestPointToSpan(p, best_dist); + /// returns a point which is 0-1 along span + if (fabs(param) < 0.00000000000001) { + return m_p; + } + if (fabs(param - 1.0) < 0.00000000000001) { + return m_v.m_p; + } - // try the other way round too - double best_dist2; - Point best_point2 = p.NearestPointToSpan(*this, best_dist2); - if(best_dist2 < best_dist) - { - best_point = NearestPoint(best_point2); - best_dist = best_dist2; - } - - if(d)*d = best_dist; - return best_point; + Point p; + if (m_v.m_type == 0) { + Point vs = m_v.m_p - m_p; + p = vs * param + m_p; + } + else { + Point v = m_p - m_v.m_c; + v.Rotate(param * IncludedAngle()); + p = v + m_v.m_c; + } + return p; } -static int GetQuadrant(const Point& v){ - // 0 = [+,+], 1 = [-,+], 2 = [-,-], 3 = [+,-] - if(v.x > 0) - { - if(v.y > 0) - return 0; - return 3; - } - if(v.y > 0) - return 1; - return 2; +Point Span::NearestPointToSpan(const Span& p, double& d) const +{ + Point midpoint = MidParam(0.5); + Point np = p.NearestPoint(m_p); + Point best_point = m_p; + double dist = np.dist(m_p); + if (p.m_start_span) { + dist -= (CArea::m_accuracy * 2); // give start of curve most priority + } + Point npm = p.NearestPoint(midpoint); + double dm = npm.dist(midpoint) + - CArea::m_accuracy; // lie about midpoint distance to give midpoints priority + if (dm < dist) { + dist = dm; + best_point = midpoint; + } + Point np2 = p.NearestPoint(m_v.m_p); + double dp2 = np2.dist(m_v.m_p); + if (dp2 < dist) { + dist = dp2; + best_point = m_v.m_p; + } + d = dist; + return best_point; +} + +Point Span::NearestPoint(const Span& p, double* d) const +{ + double best_dist; + Point best_point = this->NearestPointToSpan(p, best_dist); + + // try the other way round too + double best_dist2; + Point best_point2 = p.NearestPointToSpan(*this, best_dist2); + if (best_dist2 < best_dist) { + best_point = NearestPoint(best_point2); + best_dist = best_dist2; + } + + if (d) { + *d = best_dist; + } + return best_point; +} + +static int GetQuadrant(const Point& v) +{ + // 0 = [+,+], 1 = [-,+], 2 = [-,-], 3 = [+,-] + if (v.x > 0) { + if (v.y > 0) { + return 0; + } + return 3; + } + if (v.y > 0) { + return 1; + } + return 2; } static Point QuadrantEndPoint(int i) { - if(i >3)i-=4; - switch(i) - { - case 0: - return Point(0.0,1.0); - case 1: - return Point(-1.0,0.0); - case 2: - return Point(0.0,-1.0); - default: - return Point(1.0,0.0); - } + if (i > 3) { + i -= 4; + } + switch (i) { + case 0: + return Point(0.0, 1.0); + case 1: + return Point(-1.0, 0.0); + case 2: + return Point(0.0, -1.0); + default: + return Point(1.0, 0.0); + } } -void Span::GetBox(CBox2D &box) +void Span::GetBox(CBox2D& box) { - box.Insert(m_p); - box.Insert(m_v.m_p); + box.Insert(m_p); + box.Insert(m_v.m_p); - if(this->m_v.m_type) - { - // arc, add quadrant points - Point vs = m_p - m_v.m_c; - Point ve = m_v.m_p - m_v.m_c; - int qs = GetQuadrant(vs); - int qe = GetQuadrant(ve); - if(m_v.m_type == -1) - { - // swap qs and qe - int t=qs; - qs = qe; - qe = t; - } + if (this->m_v.m_type) { + // arc, add quadrant points + Point vs = m_p - m_v.m_c; + Point ve = m_v.m_p - m_v.m_c; + int qs = GetQuadrant(vs); + int qe = GetQuadrant(ve); + if (m_v.m_type == -1) { + // swap qs and qe + int t = qs; + qs = qe; + qe = t; + } - if(qe 1. - 1.0e-10) - return 0; - if(inc_ang < -1. + 1.0e-10) - inc_ang = PI; - else { // dot product, v1 . v2 = cos ang - if(inc_ang > 1.0) inc_ang = 1.0; - inc_ang = acos(inc_ang); // 0 to pi radians - - if(dir * (v0 ^ v1) < 0) inc_ang = 2 * PI - inc_ang ; // cp - } - return dir * inc_ang; -} - -double Span::IncludedAngle()const +double IncludedAngle(const Point& v0, const Point& v1, int dir) { - if(m_v.m_type) - { - Point vs = ~(m_p - m_v.m_c); - Point ve = ~(m_v.m_p - m_v.m_c); - if(m_v.m_type == -1) - { - vs = -vs; - ve = -ve; - } - vs.normalize(); - ve.normalize(); + // returns the absolute included angle between 2 vectors in the direction of dir ( 1=acw -1=cw) + double inc_ang = v0 * v1; + if (inc_ang > 1. - 1.0e-10) { + return 0; + } + if (inc_ang < -1. + 1.0e-10) { + inc_ang = PI; + } + else { // dot product, v1 . v2 = cos ang + if (inc_ang > 1.0) { + inc_ang = 1.0; + } + inc_ang = acos(inc_ang); // 0 to pi radians - return ::IncludedAngle(vs, ve, m_v.m_type); - } - - return 0.0; + if (dir * (v0 ^ v1) < 0) { + inc_ang = 2 * PI - inc_ang; // cp + } + } + return dir * inc_ang; } -double Span::GetArea()const +double Span::IncludedAngle() const { - if(m_v.m_type) - { - double angle = IncludedAngle(); - double radius = m_p.dist(m_v.m_c); - return ( 0.5 * ((m_v.m_c.x - m_p.x) * (m_v.m_c.y + m_p.y) - (m_v.m_c.x - m_v.m_p.x) * (m_v.m_c.y + m_v.m_p.y) - angle * radius * radius)); - } + if (m_v.m_type) { + Point vs = ~(m_p - m_v.m_c); + Point ve = ~(m_v.m_p - m_v.m_c); + if (m_v.m_type == -1) { + vs = -vs; + ve = -ve; + } + vs.normalize(); + ve.normalize(); - return 0.5 * (m_v.m_p.x - m_p.x) * (m_p.y + m_v.m_p.y); + return ::IncludedAngle(vs, ve, m_v.m_type); + } + + return 0.0; } -double Span::Parameter(const Point& p)const +double Span::GetArea() const { - double t; - if(m_v.m_type == 0) { - Point v0 = p - m_p; - Point vs = m_v.m_p - m_p; - double length = vs.length(); - vs.normalize(); - t = vs * v0; - t = t / length; - } - else - { - // true if p lies on arc span sp (p must be on circle of span) - Point vs = ~(m_p - m_v.m_c); - Point v = ~(p - m_v.m_c); - vs.normalize(); - v.normalize(); - if(m_v.m_type == -1){ - vs = -vs; - v = -v; - } - double ang = ::IncludedAngle(vs, v, m_v.m_type); - double angle = IncludedAngle(); - t = ang / angle; - } - return t; + if (m_v.m_type) { + double angle = IncludedAngle(); + double radius = m_p.dist(m_v.m_c); + return (0.5 + * ((m_v.m_c.x - m_p.x) * (m_v.m_c.y + m_p.y) + - (m_v.m_c.x - m_v.m_p.x) * (m_v.m_c.y + m_v.m_p.y) - angle * radius * radius)); + } + + return 0.5 * (m_v.m_p.x - m_p.x) * (m_p.y + m_v.m_p.y); } -bool Span::On(const Point& p, double* t)const +double Span::Parameter(const Point& p) const { - if(p != NearestPoint(p)) - return false; - if(t)*t = Parameter(p); - return true; + double t; + if (m_v.m_type == 0) { + Point v0 = p - m_p; + Point vs = m_v.m_p - m_p; + double length = vs.length(); + vs.normalize(); + t = vs * v0; + t = t / length; + } + else { + // true if p lies on arc span sp (p must be on circle of span) + Point vs = ~(m_p - m_v.m_c); + Point v = ~(p - m_v.m_c); + vs.normalize(); + v.normalize(); + if (m_v.m_type == -1) { + vs = -vs; + v = -v; + } + double ang = ::IncludedAngle(vs, v, m_v.m_type); + double angle = IncludedAngle(); + t = ang / angle; + } + return t; } -double Span::Length()const +bool Span::On(const Point& p, double* t) const { - if(m_v.m_type) { - double radius = m_p.dist(m_v.m_c); - return fabs(IncludedAngle()) * radius; - } - - return m_p.dist(m_v.m_p); + if (p != NearestPoint(p)) { + return false; + } + if (t) { + *t = Parameter(p); + } + return true; } -Point Span::GetVector(double fraction)const +double Span::Length() const { - /// returns the direction vector at point which is 0-1 along span - if(m_v.m_type == 0){ - Point v(m_p, m_v.m_p); - v.normalize(); - return v; - } + if (m_v.m_type) { + double radius = m_p.dist(m_v.m_c); + return fabs(IncludedAngle()) * radius; + } - Point p= MidParam(fraction); - Point v(m_v.m_c, p); - v.normalize(); - if(m_v.m_type == 1) - { - return Point(-v.y, v.x); - } - else - { - return Point(v.y, -v.x); - } + return m_p.dist(m_v.m_p); } -void Span::Intersect(const Span& s, std::list &pts)const +Point Span::GetVector(double fraction) const { - // finds all the intersection points between two spans and puts them in the given list - geoff_geometry::Point pInt1, pInt2; - double t[4]; - int num_int = MakeSpan(*this).Intof(MakeSpan(s), pInt1, pInt2, t); - if(num_int > 0)pts.emplace_back(pInt1.x, pInt1.y); - if(num_int > 1)pts.emplace_back(pInt2.x, pInt2.y); + /// returns the direction vector at point which is 0-1 along span + if (m_v.m_type == 0) { + Point v(m_p, m_v.m_p); + v.normalize(); + return v; + } + + Point p = MidParam(fraction); + Point v(m_v.m_c, p); + v.normalize(); + if (m_v.m_type == 1) { + return Point(-v.y, v.x); + } + else { + return Point(v.y, -v.x); + } } -void tangential_arc(const Point &p0, const Point &p1, const Point &v0, Point &c, int &dir) +void Span::Intersect(const Span& s, std::list& pts) const { - geoff_geometry::Point gp0(p0.x, p0.y); - geoff_geometry::Point gp1(p1.x, p1.y); - geoff_geometry::Vector2d gv0(v0.x, v0.y); - geoff_geometry::Point gc; - geoff_geometry::tangential_arc(gp0, gp1, gv0, gc, dir); - c = Point(gc.x, gc.y); + // finds all the intersection points between two spans and puts them in the given list + geoff_geometry::Point pInt1, pInt2; + double t[4]; + int num_int = MakeSpan(*this).Intof(MakeSpan(s), pInt1, pInt2, t); + if (num_int > 0) { + pts.emplace_back(pInt1.x, pInt1.y); + } + if (num_int > 1) { + pts.emplace_back(pInt2.x, pInt2.y); + } +} + +void tangential_arc(const Point& p0, const Point& p1, const Point& v0, Point& c, int& dir) +{ + geoff_geometry::Point gp0(p0.x, p0.y); + geoff_geometry::Point gp1(p1.x, p1.y); + geoff_geometry::Vector2d gv0(v0.x, v0.y); + geoff_geometry::Point gc; + geoff_geometry::tangential_arc(gp0, gp1, gv0, gc, dir); + c = Point(gc.x, gc.y); } diff --git a/src/Mod/CAM/libarea/Curve.h b/src/Mod/CAM/libarea/Curve.h index c85fe833fc..f6f62eee14 100644 --- a/src/Mod/CAM/libarea/Curve.h +++ b/src/Mod/CAM/libarea/Curve.h @@ -35,15 +35,16 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Point.h" #include "Box2D.h" -class Line{ +class Line +{ public: - Point p0; - Point v; + Point p0; + Point v; - // constructors - Line(const Point& P0, const Point& V); + // constructors + Line(const Point& P0, const Point& V); - double Dist(const Point& p)const; + double Dist(const Point& p) const; }; class CArc; @@ -51,80 +52,102 @@ class CArc; class CVertex { public: - int m_type; // 0 - line ( or start point ), 1 - anti-clockwise arc, -1 - clockwise arc - Point m_p; // end point - Point m_c; // centre point in absolute coordinates - int m_user_data; + int m_type; // 0 - line ( or start point ), 1 - anti-clockwise arc, -1 - clockwise arc + Point m_p; // end point + Point m_c; // centre point in absolute coordinates + int m_user_data; - CVertex():m_type(0), m_p(Point(0, 0)), m_c(Point(0,0)), m_user_data(0){} - CVertex(int type, const Point& p, const Point& c, int user_data = 0); - CVertex(const Point& p, int user_data = 0); + CVertex() + : m_type(0) + , m_p(Point(0, 0)) + , m_c(Point(0, 0)) + , m_user_data(0) + {} + CVertex(int type, const Point& p, const Point& c, int user_data = 0); + CVertex(const Point& p, int user_data = 0); }; class Span { - Point NearestPointNotOnSpan(const Point& p)const; - double Parameter(const Point& p)const; - Point NearestPointToSpan(const Span& p, double &d)const; + Point NearestPointNotOnSpan(const Point& p) const; + double Parameter(const Point& p) const; + Point NearestPointToSpan(const Span& p, double& d) const; - static const Point null_point; - static const CVertex null_vertex; + static const Point null_point; + static const CVertex null_vertex; public: - bool m_start_span; - Point m_p; - CVertex m_v; - Span(); - Span(const Point& p, const CVertex& v, bool start_span = false):m_start_span(start_span), m_p(p), m_v(v){} - Point NearestPoint(const Point& p)const; - Point NearestPoint(const Span& p, double *d = NULL)const; - void GetBox(CBox2D &box); - double IncludedAngle()const; - double GetArea()const; - bool On(const Point& p, double* t = NULL)const; - Point MidPerim(double d)const; - Point MidParam(double param)const; - double Length()const; - Point GetVector(double fraction)const; - void Intersect(const Span& s, std::list &pts)const; // finds all the intersection points between two spans + bool m_start_span; + Point m_p; + CVertex m_v; + Span(); + Span(const Point& p, const CVertex& v, bool start_span = false) + : m_start_span(start_span) + , m_p(p) + , m_v(v) + {} + Point NearestPoint(const Point& p) const; + Point NearestPoint(const Span& p, double* d = NULL) const; + void GetBox(CBox2D& box); + double IncludedAngle() const; + double GetArea() const; + bool On(const Point& p, double* t = NULL) const; + Point MidPerim(double d) const; + Point MidParam(double param) const; + double Length() const; + Point GetVector(double fraction) const; + void + Intersect(const Span& s, + std::list& pts) const; // finds all the intersection points between two spans }; class CCurve { - // a closed curve, please make sure you add an end point, the same as the start point + // a closed curve, please make sure you add an end point, the same as the start point protected: - void AddArcOrLines(bool check_for_arc, std::list &new_vertices, std::list& might_be_an_arc, CArc &arc, bool &arc_found, bool &arc_added); - static bool CheckForArc(const CVertex& prev_vt, std::list& might_be_an_arc, CArc &arc); + void AddArcOrLines(bool check_for_arc, + std::list& new_vertices, + std::list& might_be_an_arc, + CArc& arc, + bool& arc_found, + bool& arc_added); + static bool + CheckForArc(const CVertex& prev_vt, std::list& might_be_an_arc, CArc& arc); public: - std::list m_vertices; - void append(const CVertex& vertex); + std::list m_vertices; + void append(const CVertex& vertex); - void FitArcs(bool retry=false); - void UnFitArcs(); - Point NearestPoint(const Point& p)const; - Point NearestPoint(const CCurve& p, double *d = NULL)const; - Point NearestPoint(const Span& p, double *d = NULL)const; - void GetBox(CBox2D &box); - void Reverse(); - double GetArea()const; - bool IsClockwise()const{return GetArea()>0;} - bool IsClosed()const; - void ChangeStart(const Point &p); - void ChangeEnd(const Point &p); - bool Offset(double leftwards_value); - void OffsetForward(double forwards_value, bool refit_arcs = true); // for drag-knife compensation - void Break(const Point &p); - void ExtractSeparateCurves(const std::list &ordered_points, std::list &separate_curves)const; - double Perim()const; - Point PerimToPoint(double perim)const; - double PointToPerim(const Point& p)const; - void GetSpans(std::list &spans)const; - void RemoveTinySpans(); - void operator+=(const CCurve& p); - void SpanIntersections(const Span& s, std::list &pts)const; - void CurveIntersections(const CCurve& c, std::list &pts)const; + void FitArcs(bool retry = false); + void UnFitArcs(); + Point NearestPoint(const Point& p) const; + Point NearestPoint(const CCurve& p, double* d = NULL) const; + Point NearestPoint(const Span& p, double* d = NULL) const; + void GetBox(CBox2D& box); + void Reverse(); + double GetArea() const; + bool IsClockwise() const + { + return GetArea() > 0; + } + bool IsClosed() const; + void ChangeStart(const Point& p); + void ChangeEnd(const Point& p); + bool Offset(double leftwards_value); + void OffsetForward(double forwards_value, + bool refit_arcs = true); // for drag-knife compensation + void Break(const Point& p); + void ExtractSeparateCurves(const std::list& ordered_points, + std::list& separate_curves) const; + double Perim() const; + Point PerimToPoint(double perim) const; + double PointToPerim(const Point& p) const; + void GetSpans(std::list& spans) const; + void RemoveTinySpans(); + void operator+=(const CCurve& p); + void SpanIntersections(const Span& s, std::list& pts) const; + void CurveIntersections(const CCurve& c, std::list& pts) const; }; -void tangential_arc(const Point &p0, const Point &p1, const Point &v0, Point &c, int &dir); +void tangential_arc(const Point& p0, const Point& p1, const Point& v0, Point& c, int& dir); diff --git a/src/Mod/CAM/libarea/Point.h b/src/Mod/CAM/libarea/Point.h index 280ed77dad..086f16faae 100644 --- a/src/Mod/CAM/libarea/Point.h +++ b/src/Mod/CAM/libarea/Point.h @@ -32,44 +32,96 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "kurve/geometry.h" -class Point{ +class Point +{ public: - // can be a position, or a vector - double x, y; + // can be a position, or a vector + double x, y; - Point():x(0.0), y(0.0){} - Point(double X, double Y):x(X), y(Y){} - Point(const double* p):x(p[0]), y(p[1]){} - Point(const Point& p0, const Point& p1):x(p1.x - p0.x), y(p1.y - p0.y){} // vector from p0 to p1 + Point() + : x(0.0) + , y(0.0) + {} + Point(double X, double Y) + : x(X) + , y(Y) + {} + Point(const double* p) + : x(p[0]) + , y(p[1]) + {} + Point(const Point& p0, const Point& p1) + : x(p1.x - p0.x) + , y(p1.y - p0.y) + {} // vector from p0 to p1 - static double tolerance; + static double tolerance; - const Point operator+(const Point& p)const{return Point(x + p.x, y + p.y);} - const Point operator-(const Point& p)const{return Point(x - p.x, y - p.y);} - const Point operator*(double d)const{return Point(x * d, y * d);} - const Point operator/(double d)const{return Point(x / d, y / d);} - bool operator==(const Point& p)const; - bool operator!=(const Point &p)const{ return !(*this == p);} - double dist(const Point &p)const{double dx = p.x - x; double dy = p.y - y; return sqrt(dx*dx + dy*dy);} - double length()const; + const Point operator+(const Point& p) const + { + return Point(x + p.x, y + p.y); + } + const Point operator-(const Point& p) const + { + return Point(x - p.x, y - p.y); + } + const Point operator*(double d) const + { + return Point(x * d, y * d); + } + const Point operator/(double d) const + { + return Point(x / d, y / d); + } + bool operator==(const Point& p) const; + bool operator!=(const Point& p) const + { + return !(*this == p); + } + double dist(const Point& p) const + { + double dx = p.x - x; + double dy = p.y - y; + return sqrt(dx * dx + dy * dy); + } + double length() const; double normalize(); - double operator*(const Point &p)const{return (x * p.x + y * p.y);}// dot product - double operator^(const Point &p)const{return (x * p.y - y * p.x);}// cross product m0.m1.sin a = v0 ^ v1 - Point operator~(void)const{return Point(-y, x);}// perp to left - Point operator-(void)const{return Point(-x, -y);}// v1 = -v0; (unary minus) - void Rotate(double cosa, double sina){// rotate vector by angle - double temp = -y * sina + x * cosa; - y = x * sina + cosa * y; - x = temp; - } - void Rotate(double angle){if(fabs(angle) < 1.0e-09)return; Rotate(cos(angle), sin(angle));} - void Transform(const geoff_geometry::Matrix &m) - { - geoff_geometry::Point p(x,y); - p = p.Transform(m); - x = p.x; - y = p.y; - } + double operator*(const Point& p) const + { + return (x * p.x + y * p.y); + } // dot product + double operator^(const Point& p) const + { + return (x * p.y - y * p.x); + } // cross product m0.m1.sin a = v0 ^ v1 + Point operator~(void) const + { + return Point(-y, x); + } // perp to left + Point operator-(void) const + { + return Point(-x, -y); + } // v1 = -v0; (unary minus) + void Rotate(double cosa, double sina) + { // rotate vector by angle + double temp = -y * sina + x * cosa; + y = x * sina + cosa * y; + x = temp; + } + void Rotate(double angle) + { + if (fabs(angle) < 1.0e-09) { + return; + } + Rotate(cos(angle), sin(angle)); + } + void Transform(const geoff_geometry::Matrix& m) + { + geoff_geometry::Point p(x, y); + p = p.Transform(m); + x = p.x; + y = p.y; + } }; -const Point operator*(const double &d, const Point &p); +const Point operator*(const double& d, const Point& p); diff --git a/src/Mod/CAM/libarea/PythonStuff.cpp b/src/Mod/CAM/libarea/PythonStuff.cpp index 87f54a8712..eb0db089dc 100644 --- a/src/Mod/CAM/libarea/PythonStuff.cpp +++ b/src/Mod/CAM/libarea/PythonStuff.cpp @@ -10,12 +10,12 @@ #include "kurve/geometry.h" #include "Adaptive.hpp" -#if defined (_POSIX_C_SOURCE) -# undef _POSIX_C_SOURCE +#if defined(_POSIX_C_SOURCE) +#undef _POSIX_C_SOURCE #endif -#if defined (_XOPEN_SOURCE) -# undef _XOPEN_SOURCE +#if defined(_XOPEN_SOURCE) +#undef _XOPEN_SOURCE #endif #if _DEBUG @@ -32,8 +32,8 @@ #define BOOST_BIND_GLOBAL_PLACEHOLDERS -//#include -//#include +// #include +// #include #include #include #include @@ -48,333 +48,370 @@ using namespace ClipperLib; namespace bp = boost::python; -boost::python::list getVertices(const CCurve& curve) { - boost::python::list vlist; - BOOST_FOREACH(const CVertex& vertex, curve.m_vertices) { - vlist.append(vertex); - } - return vlist; -} - -boost::python::list getCurves(const CArea& area) { - boost::python::list clist; - BOOST_FOREACH(const CCurve& curve, area.m_curves) { - clist.append(curve); - } - return clist; -} - -boost::python::tuple transformed_point(const geoff_geometry::Matrix &matrix, double x, double y, double z) +boost::python::list getVertices(const CCurve& curve) { - geoff_geometry::Point3d p(x,y,z); - p = p.Transform(matrix); + boost::python::list vlist; + BOOST_FOREACH (const CVertex& vertex, curve.m_vertices) { + vlist.append(vertex); + } + return vlist; +} - return bp::make_tuple(p.x,p.y,p.z); +boost::python::list getCurves(const CArea& area) +{ + boost::python::list clist; + BOOST_FOREACH (const CCurve& curve, area.m_curves) { + clist.append(curve); + } + return clist; +} + +boost::python::tuple +transformed_point(const geoff_geometry::Matrix& matrix, double x, double y, double z) +{ + geoff_geometry::Point3d p(x, y, z); + p = p.Transform(matrix); + + return bp::make_tuple(p.x, p.y, p.z); } static void print_curve(const CCurve& c) { - std::size_t nvertices = c.m_vertices.size(); + std::size_t nvertices = c.m_vertices.size(); #if defined SIZEOF_SIZE_T && SIZEOF_SIZE_T == 4 - printf("number of vertices = %d\n", nvertices); + printf("number of vertices = %d\n", nvertices); #elif defined(_WIN32) - printf("number of vertices = %Iu\n", nvertices); + printf("number of vertices = %Iu\n", nvertices); #else - printf("number of vertices = %lu\n", nvertices); + printf("number of vertices = %lu\n", nvertices); #endif - int i = 0; - for(std::list::const_iterator It = c.m_vertices.begin(); It != c.m_vertices.end(); It++, i++) - { - const CVertex& vertex = *It; - printf("vertex %d type = %d, x = %g, y = %g", i+1, vertex.m_type, vertex.m_p.x / CArea::get_units(), vertex.m_p.y / CArea::get_units()); - if(vertex.m_type)printf(", xc = %g, yc = %g", vertex.m_c.x / CArea::get_units(), vertex.m_c.y / CArea::get_units()); - printf("\n"); - } + int i = 0; + for (std::list::const_iterator It = c.m_vertices.begin(); It != c.m_vertices.end(); + It++, i++) { + const CVertex& vertex = *It; + printf("vertex %d type = %d, x = %g, y = %g", + i + 1, + vertex.m_type, + vertex.m_p.x / CArea::get_units(), + vertex.m_p.y / CArea::get_units()); + if (vertex.m_type) { + printf(", xc = %g, yc = %g", + vertex.m_c.x / CArea::get_units(), + vertex.m_c.y / CArea::get_units()); + } + printf("\n"); + } } -static void print_area(const CArea &a) +static void print_area(const CArea& a) { - for(std::list::const_iterator It = a.m_curves.begin(); It != a.m_curves.end(); It++) - { - const CCurve& curve = *It; - print_curve(curve); - } + for (std::list::const_iterator It = a.m_curves.begin(); It != a.m_curves.end(); It++) { + const CCurve& curve = *It; + print_curve(curve); + } } static unsigned int num_vertices(const CCurve& curve) { - return static_cast(curve.m_vertices.size()); + return static_cast(curve.m_vertices.size()); } static CVertex FirstVertex(const CCurve& curve) { - return curve.m_vertices.front(); + return curve.m_vertices.front(); } static CVertex LastVertex(const CCurve& curve) { - return curve.m_vertices.back(); + return curve.m_vertices.back(); } static void set_units(double units) { - CArea::set_units(units); + CArea::set_units(units); } static double get_units() { - return CArea::get_units(); + return CArea::get_units(); } static bool holes_linked() { - return CArea::HolesLinked(); + return CArea::HolesLinked(); } static CArea AreaFromDxf(const char* filepath) { - CArea area; - AreaDxfRead dxf(&area, filepath); - dxf.DoRead(); - return area; + CArea area; + AreaDxfRead dxf(&area, filepath); + dxf.DoRead(); + return area; } static void append_point(CCurve& c, const Point& p) { - c.m_vertices.emplace_back(p); + c.m_vertices.emplace_back(p); } static boost::python::tuple nearest_point_to_curve(CCurve& c1, const CCurve& c2) { - double dist; - Point p = c1.NearestPoint(c2, &dist); + double dist; + Point p = c1.NearestPoint(c2, &dist); - return bp::make_tuple(p, dist); + return bp::make_tuple(p, dist); } -boost::python::list MakePocketToolpath(const CArea& a, double tool_radius, double extra_offset, double stepover, bool from_center, bool use_zig_zag, double zig_angle) +boost::python::list MakePocketToolpath(const CArea& a, + double tool_radius, + double extra_offset, + double stepover, + bool from_center, + bool use_zig_zag, + double zig_angle) { - std::list toolpath; + std::list toolpath; - CAreaPocketParams params(tool_radius, extra_offset, stepover, from_center, use_zig_zag ? ZigZagPocketMode : SpiralPocketMode, zig_angle); - a.SplitAndMakePocketToolpath(toolpath, params); + CAreaPocketParams params(tool_radius, + extra_offset, + stepover, + from_center, + use_zig_zag ? ZigZagPocketMode : SpiralPocketMode, + zig_angle); + a.SplitAndMakePocketToolpath(toolpath, params); - boost::python::list clist; - BOOST_FOREACH(const CCurve& c, toolpath) { - clist.append(c); + boost::python::list clist; + BOOST_FOREACH (const CCurve& c, toolpath) { + clist.append(c); } - return clist; + return clist; } boost::python::list SplitArea(const CArea& a) { - std::list areas; - a.Split(areas); + std::list areas; + a.Split(areas); - boost::python::list alist; - BOOST_FOREACH(const CArea& a, areas) { - alist.append(a); + boost::python::list alist; + BOOST_FOREACH (const CArea& a, areas) { + alist.append(a); } - return alist; + return alist; } void dxfArea(CArea& area, const char* /*str*/) { - area = CArea(); + area = CArea(); } boost::python::list getCurveSpans(const CCurve& c) { - boost::python::list span_list; - const Point *prev_p = NULL; + boost::python::list span_list; + const Point* prev_p = NULL; - for(std::list::const_iterator VIt = c.m_vertices.begin(); VIt != c.m_vertices.end(); VIt++) - { - const CVertex& vertex = *VIt; + for (std::list::const_iterator VIt = c.m_vertices.begin(); VIt != c.m_vertices.end(); + VIt++) { + const CVertex& vertex = *VIt; - if(prev_p) - { - span_list.append(Span(*prev_p, vertex)); - } - prev_p = &(vertex.m_p); - } + if (prev_p) { + span_list.append(Span(*prev_p, vertex)); + } + prev_p = &(vertex.m_p); + } - return span_list; + return span_list; } Span getFirstCurveSpan(const CCurve& c) { - if(c.m_vertices.size() < 2) - return Span(); + if (c.m_vertices.size() < 2) { + return Span(); + } - std::list::const_iterator VIt = c.m_vertices.begin(); - const Point &p = (*VIt).m_p; - VIt++; - return Span(p, *VIt, true); + std::list::const_iterator VIt = c.m_vertices.begin(); + const Point& p = (*VIt).m_p; + VIt++; + return Span(p, *VIt, true); } Span getLastCurveSpan(const CCurve& c) { - if(c.m_vertices.size() < 2) - return Span(); + if (c.m_vertices.size() < 2) { + return Span(); + } - std::list::const_reverse_iterator VIt = c.m_vertices.rbegin(); - const CVertex &v = (*VIt); - VIt++; + std::list::const_reverse_iterator VIt = c.m_vertices.rbegin(); + const CVertex& v = (*VIt); + VIt++; - return Span((*VIt).m_p, v, c.m_vertices.size() == 2); + return Span((*VIt).m_p, v, c.m_vertices.size() == 2); } -bp::tuple TangentialArc(const Point &p0, const Point &p1, const Point &v0) +bp::tuple TangentialArc(const Point& p0, const Point& p1, const Point& v0) { - Point c; - int dir; - tangential_arc(p0, p1, v0, c, dir); + Point c; + int dir; + tangential_arc(p0, p1, v0, c, dir); - return bp::make_tuple(c, dir); + return bp::make_tuple(c, dir); } -boost::python::list spanIntersect(const Span& span1, const Span& span2) { - boost::python::list plist; - std::list pts; - span1.Intersect(span2, pts); - BOOST_FOREACH(const Point& p, pts) { - plist.append(p); +boost::python::list spanIntersect(const Span& span1, const Span& span2) +{ + boost::python::list plist; + std::list pts; + span1.Intersect(span2, pts); + BOOST_FOREACH (const Point& p, pts) { + plist.append(p); } - return plist; + return plist; } -//Matrix(boost::python::list &l){} -std::shared_ptr matrix_constructor(const boost::python::list& lst) { - double m[16] = {1,0,0,0,0,1,0,0, 0,0,1,0, 0,0,0,1}; +// Matrix(boost::python::list &l){} +std::shared_ptr matrix_constructor(const boost::python::list& lst) +{ + double m[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; - boost::python::ssize_t n = boost::python::len(lst); - int j = 0; - for(boost::python::ssize_t i=0;i(elem.attr("__float__")()); - j++; - if(j>=16)break; - } - - return std::shared_ptr( new geoff_geometry::Matrix(m) ); -} - -boost::python::list InsideCurves(const CArea& a, const CCurve& curve) { - boost::python::list plist; - - std::list curves_inside; - a.InsideCurves(curve, curves_inside); - BOOST_FOREACH(const CCurve& c, curves_inside) { - plist.append(c); + boost::python::ssize_t n = boost::python::len(lst); + int j = 0; + for (boost::python::ssize_t i = 0; i < n; i++) { + boost::python::object elem = lst[i]; + m[j] = boost::python::extract(elem.attr("__float__")()); + j++; + if (j >= 16) { + break; + } } - return plist; + + return std::shared_ptr(new geoff_geometry::Matrix(m)); } -boost::python::list CurveIntersections(const CCurve& c1, const CCurve& c2) { - boost::python::list plist; +boost::python::list InsideCurves(const CArea& a, const CCurve& curve) +{ + boost::python::list plist; - std::list pts; - c1.CurveIntersections(c2, pts); - BOOST_FOREACH(const Point& p, pts) { - plist.append(p); + std::list curves_inside; + a.InsideCurves(curve, curves_inside); + BOOST_FOREACH (const CCurve& c, curves_inside) { + plist.append(c); } - return plist; + return plist; } -boost::python::list AreaIntersections(const CArea& a, const CCurve& c2) { - boost::python::list plist; +boost::python::list CurveIntersections(const CCurve& c1, const CCurve& c2) +{ + boost::python::list plist; - std::list pts; - a.CurveIntersections(c2, pts); - BOOST_FOREACH(const Point& p, pts) { - plist.append(p); + std::list pts; + c1.CurveIntersections(c2, pts); + BOOST_FOREACH (const Point& p, pts) { + plist.append(p); } - return plist; + return plist; +} + +boost::python::list AreaIntersections(const CArea& a, const CCurve& c2) +{ + boost::python::list plist; + + std::list pts; + a.CurveIntersections(c2, pts); + BOOST_FOREACH (const Point& p, pts) { + plist.append(p); + } + return plist; } double AreaGetArea(const CArea& a) { - return a.GetArea(); + return a.GetArea(); } - // Adaptive2d.Execute wrapper -bp::list AdaptiveExecute(AdaptivePath::Adaptive2d& ada,const boost::python::list &stock_paths, const boost::python::list &in_paths, boost::python::object progressCallbackFn) { - bp::list out_list; +bp::list AdaptiveExecute(AdaptivePath::Adaptive2d& ada, + const boost::python::list& stock_paths, + const boost::python::list& in_paths, + boost::python::object progressCallbackFn) +{ + bp::list out_list; - // convert stock paths - AdaptivePath::DPaths stock_dpaths; - for(bp::ssize_t i=0;i(stock_paths[i]); - AdaptivePath::DPath dpath; - for(bp::ssize_t j=0;j(in_path[j]); - dpath.push_back(pair(bp::extract(in_point[0]),bp::extract(in_point[1]))); - } - stock_dpaths.push_back(dpath); - } + // convert stock paths + AdaptivePath::DPaths stock_dpaths; + for (bp::ssize_t i = 0; i < bp::len(stock_paths); i++) { + bp::list in_path = bp::extract(stock_paths[i]); + AdaptivePath::DPath dpath; + for (bp::ssize_t j = 0; j < bp::len(in_path); j++) { + bp::list in_point = bp::extract(in_path[j]); + dpath.push_back(pair(bp::extract(in_point[0]), + bp::extract(in_point[1]))); + } + stock_dpaths.push_back(dpath); + } - // convert inputs - AdaptivePath::DPaths dpaths; - for(bp::ssize_t i=0;i(in_paths[i]); - AdaptivePath::DPath dpath; - for(bp::ssize_t j=0;j(in_path[j]); - dpath.push_back(pair(bp::extract(in_point[0]),bp::extract(in_point[1]))); - } - dpaths.push_back(dpath); - } - // Execute with callback - std::list result=ada.Execute(stock_dpaths,dpaths,[progressCallbackFn](AdaptivePath::TPaths tp)->bool { - bp::list out_paths; - for(const auto & in_pair : tp) { - bp::list path; - for(const auto & in_pt : in_pair.second) { - path.append(bp::make_tuple(in_pt.first,in_pt.second)); - } - out_paths.append(bp::make_tuple(in_pair.first,path)); - } - return bp::extract(progressCallbackFn(out_paths)); - }); - // convert outputs back - BOOST_FOREACH(const auto & res, result) { - out_list.append(res); - } - return out_list; + // convert inputs + AdaptivePath::DPaths dpaths; + for (bp::ssize_t i = 0; i < bp::len(in_paths); i++) { + bp::list in_path = bp::extract(in_paths[i]); + AdaptivePath::DPath dpath; + for (bp::ssize_t j = 0; j < bp::len(in_path); j++) { + bp::list in_point = bp::extract(in_path[j]); + dpath.push_back(pair(bp::extract(in_point[0]), + bp::extract(in_point[1]))); + } + dpaths.push_back(dpath); + } + // Execute with callback + std::list result = + ada.Execute(stock_dpaths, dpaths, [progressCallbackFn](AdaptivePath::TPaths tp) -> bool { + bp::list out_paths; + for (const auto& in_pair : tp) { + bp::list path; + for (const auto& in_pt : in_pair.second) { + path.append(bp::make_tuple(in_pt.first, in_pt.second)); + } + out_paths.append(bp::make_tuple(in_pair.first, path)); + } + return bp::extract(progressCallbackFn(out_paths)); + }); + // convert outputs back + BOOST_FOREACH (const auto& res, result) { + out_list.append(res); + } + return out_list; } - // Converts a std::pair instance to a Python tuple. - template - struct std_pair_to_tuple - { +// Converts a std::pair instance to a Python tuple. +template +struct std_pair_to_tuple +{ static PyObject* convert(std::pair const& p) { - return boost::python::incref( - boost::python::make_tuple(p.first, p.second).ptr()); + return boost::python::incref(boost::python::make_tuple(p.first, p.second).ptr()); } - static PyTypeObject const *get_pytype () { - return &PyTuple_Type; - } - }; + static PyTypeObject const* get_pytype() + { + return &PyTuple_Type; + } +}; - boost::python::list AdaptiveOutput_AdaptivePaths(const AdaptivePath::AdaptiveOutput &ado) { - bp::list olist; - for(auto & ap : ado.AdaptivePaths) { - bp::list op; - for(auto & pt : ap.second) { - op.append(bp::make_tuple(pt.first, pt.second)); - } - olist.append(bp::make_tuple(ap.first, op)); - } - return olist; - } +boost::python::list AdaptiveOutput_AdaptivePaths(const AdaptivePath::AdaptiveOutput& ado) +{ + bp::list olist; + for (auto& ap : ado.AdaptivePaths) { + bp::list op; + for (auto& pt : ap.second) { + op.append(bp::make_tuple(pt.first, pt.second)); + } + olist.append(bp::make_tuple(ap.first, op)); + } + return olist; +} -BOOST_PYTHON_MODULE(area) { - bp::class_("Point") +BOOST_PYTHON_MODULE(area) +{ + bp::class_("Point") .def(bp::init()) .def(bp::init()) .def(bp::other() * bp::self) @@ -391,14 +428,13 @@ BOOST_PYTHON_MODULE(area) { .def("dist", &Point::dist) .def("length", &Point::length) .def("normalize", &Point::normalize) - .def("Rotate", static_cast< void (Point::*)(double, double) >(&Point::Rotate)) - .def("Rotate", static_cast< void (Point::*)(double) >(&Point::Rotate)) + .def("Rotate", static_cast(&Point::Rotate)) + .def("Rotate", static_cast(&Point::Rotate)) .def_readwrite("x", &Point::x) .def_readwrite("y", &Point::y) - .def("Transform", &Point::Transform) - ; + .def("Transform", &Point::Transform); - bp::class_("Vertex") + bp::class_("Vertex") .def(bp::init()) .def(bp::init()) .def(bp::init()) @@ -406,94 +442,91 @@ BOOST_PYTHON_MODULE(area) { .def_readwrite("type", &CVertex::m_type) .def_readwrite("p", &CVertex::m_p) .def_readwrite("c", &CVertex::m_c) - .def_readwrite("user_data", &CVertex::m_user_data) - ; + .def_readwrite("user_data", &CVertex::m_user_data); - bp::class_("Span") + bp::class_("Span") .def(bp::init()) .def(bp::init()) - .def("NearestPoint", static_cast< Point (Span::*)(const Point& p)const >(&Span::NearestPoint)) - .def("NearestPoint", static_cast< Point (Span::*)(const Span& p, double *d)const >(&Span::NearestPoint)) - .def("GetBox", &Span::GetBox) - .def("IncludedAngle", &Span::IncludedAngle) - .def("GetArea", &Span::GetArea) - .def("On", &Span::On) - .def("MidPerim", &Span::MidPerim) - .def("MidParam", &Span::MidParam) - .def("Length", &Span::Length) - .def("GetVector", &Span::GetVector) - .def("Intersect", &spanIntersect) + .def("NearestPoint", + static_cast(&Span::NearestPoint)) + .def("NearestPoint", + static_cast(&Span::NearestPoint)) + .def("GetBox", &Span::GetBox) + .def("IncludedAngle", &Span::IncludedAngle) + .def("GetArea", &Span::GetArea) + .def("On", &Span::On) + .def("MidPerim", &Span::MidPerim) + .def("MidParam", &Span::MidParam) + .def("Length", &Span::Length) + .def("GetVector", &Span::GetVector) + .def("Intersect", &spanIntersect) .def_readwrite("p", &Span::m_p) - .def_readwrite("v", &Span::m_v) - ; + .def_readwrite("v", &Span::m_v); - bp::class_("Curve") + bp::class_("Curve") .def(bp::init()) .def("getVertices", &getVertices) - .def("append",&CCurve::append) - .def("append",&append_point) + .def("append", &CCurve::append) + .def("append", &append_point) .def("text", &print_curve) - .def("NearestPoint", static_cast< Point (CCurve::*)(const Point& p)const >(&CCurve::NearestPoint)) - .def("NearestPoint", &nearest_point_to_curve) - .def("Reverse", &CCurve::Reverse) - .def("getNumVertices", &num_vertices) - .def("FirstVertex", &FirstVertex) - .def("LastVertex", &LastVertex) - .def("GetArea", &CCurve::GetArea) - .def("IsClockwise", &CCurve::IsClockwise) - .def("IsClosed", &CCurve::IsClosed) - .def("ChangeStart",&CCurve::ChangeStart) - .def("ChangeEnd",&CCurve::ChangeEnd) - .def("Offset",&CCurve::Offset) - .def("OffsetForward",&CCurve::OffsetForward) - .def("GetSpans",&getCurveSpans) - .def("GetFirstSpan",&getFirstCurveSpan) - .def("GetLastSpan",&getLastCurveSpan) - .def("Break",&CCurve::Break) - .def("Perim",&CCurve::Perim) - .def("PerimToPoint",&CCurve::PerimToPoint) - .def("PointToPerim",&CCurve::PointToPerim) - .def("FitArcs",&CCurve::FitArcs) - .def("UnFitArcs",&CCurve::UnFitArcs) - .def("Intersections",&CurveIntersections) - ; + .def("NearestPoint", + static_cast(&CCurve::NearestPoint)) + .def("NearestPoint", &nearest_point_to_curve) + .def("Reverse", &CCurve::Reverse) + .def("getNumVertices", &num_vertices) + .def("FirstVertex", &FirstVertex) + .def("LastVertex", &LastVertex) + .def("GetArea", &CCurve::GetArea) + .def("IsClockwise", &CCurve::IsClockwise) + .def("IsClosed", &CCurve::IsClosed) + .def("ChangeStart", &CCurve::ChangeStart) + .def("ChangeEnd", &CCurve::ChangeEnd) + .def("Offset", &CCurve::Offset) + .def("OffsetForward", &CCurve::OffsetForward) + .def("GetSpans", &getCurveSpans) + .def("GetFirstSpan", &getFirstCurveSpan) + .def("GetLastSpan", &getLastCurveSpan) + .def("Break", &CCurve::Break) + .def("Perim", &CCurve::Perim) + .def("PerimToPoint", &CCurve::PerimToPoint) + .def("PointToPerim", &CCurve::PointToPerim) + .def("FitArcs", &CCurve::FitArcs) + .def("UnFitArcs", &CCurve::UnFitArcs) + .def("Intersections", &CurveIntersections); - bp::class_("Box") + bp::class_("Box") .def(bp::init()) - .def("MinX", &CBox2D::MinX) - .def("MaxX", &CBox2D::MaxX) - .def("MinY", &CBox2D::MinY) - .def("MaxY", &CBox2D::MaxY) - ; + .def("MinX", &CBox2D::MinX) + .def("MaxX", &CBox2D::MaxX) + .def("MinY", &CBox2D::MinY) + .def("MaxY", &CBox2D::MaxY); - bp::class_("Area") + bp::class_("Area") .def(bp::init()) .def("getCurves", &getCurves) - .def("append",&CArea::append) - .def("Subtract",&CArea::Subtract) - .def("Intersect",&CArea::Intersect) - .def("Union",&CArea::Union) - .def("Offset",&CArea::Offset) - .def("FitArcs",&CArea::FitArcs) + .def("append", &CArea::append) + .def("Subtract", &CArea::Subtract) + .def("Intersect", &CArea::Intersect) + .def("Union", &CArea::Union) + .def("Offset", &CArea::Offset) + .def("FitArcs", &CArea::FitArcs) .def("text", &print_area) - .def("num_curves", &CArea::num_curves) - .def("NearestPoint", &CArea::NearestPoint) - .def("GetBox", &CArea::GetBox) - .def("Reorder", &CArea::Reorder) - .def("MakePocketToolpath", &MakePocketToolpath) - .def("Split", &SplitArea) - .def("InsideCurves", &InsideCurves) - .def("Thicken", &CArea::Thicken) - .def("Intersections",&AreaIntersections) - .def("GetArea",&AreaGetArea) - ; + .def("num_curves", &CArea::num_curves) + .def("NearestPoint", &CArea::NearestPoint) + .def("GetBox", &CArea::GetBox) + .def("Reorder", &CArea::Reorder) + .def("MakePocketToolpath", &MakePocketToolpath) + .def("Split", &SplitArea) + .def("InsideCurves", &InsideCurves) + .def("Thicken", &CArea::Thicken) + .def("Intersections", &AreaIntersections) + .def("GetArea", &AreaGetArea); - bp::class_ > ("Matrix") + bp::class_>("Matrix") .def(bp::init()) - .def("__init__", bp::make_constructor(&matrix_constructor)) - .def("TransformedPoint", &transformed_point) - .def("Multiply", &geoff_geometry::Matrix::Multiply) - ; + .def("__init__", bp::make_constructor(&matrix_constructor)) + .def("TransformedPoint", &transformed_point) + .def("Multiply", &geoff_geometry::Matrix::Multiply); bp::def("set_units", set_units); bp::def("get_units", get_units); @@ -502,46 +535,46 @@ BOOST_PYTHON_MODULE(area) { bp::def("TangentialArc", TangentialArc); - using namespace AdaptivePath; + using namespace AdaptivePath; - boost::python::to_python_converter, std_pair_to_tuple,true>(); + boost::python:: + to_python_converter, std_pair_to_tuple, true>(); - bp::enum_("AdaptiveMotionType") - .value("Cutting", MotionType::mtCutting) - .value("LinkClear", MotionType::mtLinkClear) - .value("LinkNotClear", MotionType::mtLinkNotClear) - .value("LinkClearAtPrevPass", MotionType::mtLinkClearAtPrevPass); + bp::enum_("AdaptiveMotionType") + .value("Cutting", MotionType::mtCutting) + .value("LinkClear", MotionType::mtLinkClear) + .value("LinkNotClear", MotionType::mtLinkNotClear) + .value("LinkClearAtPrevPass", MotionType::mtLinkClearAtPrevPass); - bp::enum_("AdaptiveOperationType") - .value("ClearingInside", OperationType::otClearingInside) - .value("ClearingOutside", OperationType::otClearingOutside) - .value("ProfilingInside", OperationType::otProfilingInside) - .value("ProfilingOutside", OperationType::otProfilingOutside); - - bp::class_ ("AdaptiveOutput") - .def(bp::init<>()) - .add_property("HelixCenterPoint", bp::make_getter(&AdaptiveOutput::HelixCenterPoint, bp::return_value_policy())) - .add_property("StartPoint", bp::make_getter(&AdaptiveOutput::StartPoint, bp::return_value_policy())) - .add_property("AdaptivePaths", &AdaptiveOutput_AdaptivePaths) - .def_readonly("ReturnMotionType",&AdaptiveOutput::ReturnMotionType); - - bp::class_("Adaptive2d") - .def(bp::init<>()) - .def("Execute",&AdaptiveExecute) - .def_readwrite("stepOverFactor", &Adaptive2d::stepOverFactor) - .def_readwrite("toolDiameter", &Adaptive2d::toolDiameter) - .def_readwrite("stockToLeave", &Adaptive2d::stockToLeave) - .def_readwrite("helixRampDiameter", &Adaptive2d::helixRampDiameter) - .def_readwrite("forceInsideOut", &Adaptive2d::forceInsideOut) - .def_readwrite("finishingProfile", &Adaptive2d::finishingProfile) - //.def_readwrite("polyTreeNestingLimit", &Adaptive2d::polyTreeNestingLimit) - .def_readwrite("tolerance", &Adaptive2d::tolerance) - .def_readwrite("keepToolDownDistRatio", &Adaptive2d::keepToolDownDistRatio) - .def_readwrite("opType", &Adaptive2d::opType); + bp::enum_("AdaptiveOperationType") + .value("ClearingInside", OperationType::otClearingInside) + .value("ClearingOutside", OperationType::otClearingOutside) + .value("ProfilingInside", OperationType::otProfilingInside) + .value("ProfilingOutside", OperationType::otProfilingOutside); + bp::class_("AdaptiveOutput") + .def(bp::init<>()) + .add_property("HelixCenterPoint", + bp::make_getter(&AdaptiveOutput::HelixCenterPoint, + bp::return_value_policy())) + .add_property("StartPoint", + bp::make_getter(&AdaptiveOutput::StartPoint, + bp::return_value_policy())) + .add_property("AdaptivePaths", &AdaptiveOutput_AdaptivePaths) + .def_readonly("ReturnMotionType", &AdaptiveOutput::ReturnMotionType); + bp::class_("Adaptive2d") + .def(bp::init<>()) + .def("Execute", &AdaptiveExecute) + .def_readwrite("stepOverFactor", &Adaptive2d::stepOverFactor) + .def_readwrite("toolDiameter", &Adaptive2d::toolDiameter) + .def_readwrite("stockToLeave", &Adaptive2d::stockToLeave) + .def_readwrite("helixRampDiameter", &Adaptive2d::helixRampDiameter) + .def_readwrite("forceInsideOut", &Adaptive2d::forceInsideOut) + .def_readwrite("finishingProfile", &Adaptive2d::finishingProfile) + //.def_readwrite("polyTreeNestingLimit", &Adaptive2d::polyTreeNestingLimit) + .def_readwrite("tolerance", &Adaptive2d::tolerance) + .def_readwrite("keepToolDownDistRatio", &Adaptive2d::keepToolDownDistRatio) + .def_readwrite("opType", &Adaptive2d::opType); } - - - diff --git a/src/Mod/CAM/libarea/PythonStuff.h b/src/Mod/CAM/libarea/PythonStuff.h index e5690ebd21..5d6e3c3cd4 100644 --- a/src/Mod/CAM/libarea/PythonStuff.h +++ b/src/Mod/CAM/libarea/PythonStuff.h @@ -7,4 +7,3 @@ extern void Message(const char*); void PythonInit(); void PythonFinish(); - diff --git a/src/Mod/CAM/libarea/clipper.cpp b/src/Mod/CAM/libarea/clipper.cpp index 0af5d2443e..7a70ca79c0 100644 --- a/src/Mod/CAM/libarea/clipper.cpp +++ b/src/Mod/CAM/libarea/clipper.cpp @@ -1,42 +1,42 @@ /******************************************************************************* -* * -* Author : Angus Johnson * -* Version : 6.2.0 * -* Date : 2 October 2014 * -* Website : http://www.angusj.com * -* Copyright : Angus Johnson 2010-2014 * -* * -* License: * -* Use, modification & distribution is subject to Boost Software License Ver 1. * -* http://www.boost.org/LICENSE_1_0.txt * -* * -* Attributions: * -* The code in this library is an extension of Bala Vatti's clipping algorithm: * -* "A generic solution to polygon clipping" * -* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * -* http://portal.acm.org/citation.cfm?id=129906 * -* * -* Computer graphics and geometric modeling: implementation and algorithms * -* By Max K. Agoston * -* Springer; 1 edition (January 4, 2005) * -* http://books.google.com/books?q=vatti+clipping+agoston * -* * -* See also: * -* "Polygon Offsetting by Computing Winding Numbers" * -* Paper no. DETC2005-85513 pp. 565-575 * -* ASME 2005 International Design Engineering Technical Conferences * -* and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24-28, 2005 , Long Beach, California, USA * -* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * -* * -*******************************************************************************/ + * * + * Author : Angus Johnson * + * Version : 6.2.0 * + * Date : 2 October 2014 * + * Website : http://www.angusj.com * + * Copyright : Angus Johnson 2010-2014 * + * * + * License: * + * Use, modification & distribution is subject to Boost Software License Ver 1. * + * http://www.boost.org/LICENSE_1_0.txt * + * * + * Attributions: * + * The code in this library is an extension of Bala Vatti's clipping algorithm: * + * "A generic solution to polygon clipping" * + * Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * + * http://portal.acm.org/citation.cfm?id=129906 * + * * + * Computer graphics and geometric modeling: implementation and algorithms * + * By Max K. Agoston * + * Springer; 1 edition (January 4, 2005) * + * http://books.google.com/books?q=vatti+clipping+agoston * + * * + * See also: * + * "Polygon Offsetting by Computing Winding Numbers" * + * Paper no. DETC2005-85513 pp. 565-575 * + * ASME 2005 International Design Engineering Technical Conferences * + * and Computers and Information in Engineering Conference (IDETC/CIE2005) * + * September 24-28, 2005 , Long Beach, California, USA * + * http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * + * * + *******************************************************************************/ /******************************************************************************* -* * -* This is a translation of the Delphi Clipper library and the naming style * -* used has retained a Delphi flavour. * -* * -*******************************************************************************/ + * * + * This is a translation of the Delphi Clipper library and the naming style * + * used has retained a Delphi flavour. * + * * + *******************************************************************************/ #include "clipper.hpp" #include @@ -48,85 +48,96 @@ #include #include -namespace ClipperLib { +namespace ClipperLib +{ static double const pi = 3.141592653589793238; -static double const two_pi = pi *2; +static double const two_pi = pi * 2; static double const def_arc_tolerance = 0.25; -enum Direction { dRightToLeft, dLeftToRight }; +enum Direction +{ + dRightToLeft, + dLeftToRight +}; -static int const Unassigned = -1; //edge not currently 'owning' a solution -static int const Skip = -2; //edge that would otherwise close a path +static int const Unassigned = -1; // edge not currently 'owning' a solution +static int const Skip = -2; // edge that would otherwise close a path #define HORIZONTAL (-1.0E+40) #define TOLERANCE (1.0e-20) #define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) -struct TEdge { - IntPoint Bot{0,0}; - IntPoint Curr{0,0}; - IntPoint Top{0,0}; - IntPoint Delta{0,0}; - double Dx = 0.0; - PolyType PolyTyp = ptSubject; - EdgeSide Side = esLeft; - int WindDelta = 0; //1 or -1 depending on winding direction - int WindCnt = 0; - int WindCnt2 = 0; //winding count of the opposite polytype - int OutIdx = 0; - TEdge *Next = nullptr; - TEdge *Prev = nullptr; - TEdge *NextInLML = nullptr; - TEdge *NextInAEL = nullptr; - TEdge *PrevInAEL = nullptr; - TEdge *NextInSEL = nullptr; - TEdge *PrevInSEL = nullptr; +struct TEdge +{ + IntPoint Bot {0, 0}; + IntPoint Curr {0, 0}; + IntPoint Top {0, 0}; + IntPoint Delta {0, 0}; + double Dx = 0.0; + PolyType PolyTyp = ptSubject; + EdgeSide Side = esLeft; + int WindDelta = 0; // 1 or -1 depending on winding direction + int WindCnt = 0; + int WindCnt2 = 0; // winding count of the opposite polytype + int OutIdx = 0; + TEdge* Next = nullptr; + TEdge* Prev = nullptr; + TEdge* NextInLML = nullptr; + TEdge* NextInAEL = nullptr; + TEdge* PrevInAEL = nullptr; + TEdge* NextInSEL = nullptr; + TEdge* PrevInSEL = nullptr; }; -struct IntersectNode { - TEdge *Edge1; - TEdge *Edge2; - IntPoint Pt; +struct IntersectNode +{ + TEdge* Edge1; + TEdge* Edge2; + IntPoint Pt; }; -struct LocalMinimum { - cInt Y; - TEdge *LeftBound; - TEdge *RightBound; +struct LocalMinimum +{ + cInt Y; + TEdge* LeftBound; + TEdge* RightBound; }; struct OutPt; -struct OutRec { - int Idx; - bool IsHole; - bool IsOpen; - OutRec *FirstLeft; //see comments in clipper.pas - PolyNode *PolyNd; - OutPt *Pts; - OutPt *BottomPt; +struct OutRec +{ + int Idx; + bool IsHole; + bool IsOpen; + OutRec* FirstLeft; // see comments in clipper.pas + PolyNode* PolyNd; + OutPt* Pts; + OutPt* BottomPt; }; -struct OutPt { - int Idx; - IntPoint Pt; - OutPt *Next; - OutPt *Prev; +struct OutPt +{ + int Idx; + IntPoint Pt; + OutPt* Next; + OutPt* Prev; }; -struct Join { - OutPt *OutPt1; - OutPt *OutPt2; - IntPoint OffPt; +struct Join +{ + OutPt* OutPt1; + OutPt* OutPt2; + IntPoint OffPt; }; struct LocMinSorter { - inline bool operator()(const LocalMinimum& locMin1, const LocalMinimum& locMin2) - { - return locMin2.Y < locMin1.Y; - } + inline bool operator()(const LocalMinimum& locMin1, const LocalMinimum& locMin2) + { + return locMin2.Y < locMin1.Y; + } }; //------------------------------------------------------------------------------ @@ -134,15 +145,18 @@ struct LocMinSorter inline cInt Round(double val) { - if ((val < 0)) - return static_cast(val - 0.5); - else return static_cast(val + 0.5); + if ((val < 0)) { + return static_cast(val - 0.5); + } + else { + return static_cast(val + 0.5); + } } //------------------------------------------------------------------------------ inline cInt Abs(cInt val) { - return val < 0 ? -val : val; + return val < 0 ? -val : val; } //------------------------------------------------------------------------------ @@ -151,88 +165,100 @@ inline cInt Abs(cInt val) void PolyTree::Clear() { - for (PolyNodes::size_type i = 0; i < AllNodes.size(); ++i) - delete AllNodes[i]; - AllNodes.resize(0); + for (PolyNodes::size_type i = 0; i < AllNodes.size(); ++i) { + delete AllNodes[i]; + } + AllNodes.resize(0); Childs.resize(0); } //------------------------------------------------------------------------------ PolyNode* PolyTree::GetFirst() const { - if (!Childs.empty()) - return Childs[0]; - else - return 0; + if (!Childs.empty()) { + return Childs[0]; + } + else { + return 0; + } } //------------------------------------------------------------------------------ int PolyTree::Total() const { - return (int)AllNodes.size(); + return (int)AllNodes.size(); } //------------------------------------------------------------------------------ // PolyNode methods ... //------------------------------------------------------------------------------ -PolyNode::PolyNode(): Childs(), Parent(0), Index(0), m_IsOpen(false), m_jointype(jtSquare), m_endtype(etClosedPolygon) -{ -} +PolyNode::PolyNode() + : Childs() + , Parent(0) + , Index(0) + , m_IsOpen(false) + , m_jointype(jtSquare) + , m_endtype(etClosedPolygon) +{} //------------------------------------------------------------------------------ int PolyNode::ChildCount() const { - return (int)Childs.size(); + return (int)Childs.size(); } //------------------------------------------------------------------------------ void PolyNode::AddChild(PolyNode& child) { - unsigned cnt = (unsigned)Childs.size(); - Childs.push_back(&child); - child.Parent = this; - child.Index = cnt; + unsigned cnt = (unsigned)Childs.size(); + Childs.push_back(&child); + child.Parent = this; + child.Index = cnt; } //------------------------------------------------------------------------------ PolyNode* PolyNode::GetNext() const -{ - if (!Childs.empty()) - return Childs[0]; - else - return GetNextSiblingUp(); -} +{ + if (!Childs.empty()) { + return Childs[0]; + } + else { + return GetNextSiblingUp(); + } +} //------------------------------------------------------------------------------ PolyNode* PolyNode::GetNextSiblingUp() const -{ - if (!Parent) //protects against PolyTree.GetNextSiblingUp() - return 0; - else if (Index == Parent->Childs.size() - 1) - return Parent->GetNextSiblingUp(); - else - return Parent->Childs[Index + 1]; -} +{ + if (!Parent) { // protects against PolyTree.GetNextSiblingUp() + return 0; + } + else if (Index == Parent->Childs.size() - 1) { + return Parent->GetNextSiblingUp(); + } + else { + return Parent->Childs[Index + 1]; + } +} //------------------------------------------------------------------------------ bool PolyNode::IsHole() const -{ - bool result = true; - PolyNode* node = Parent; - while (node) - { - result = !result; - node = node->Parent; - } - return result; -} +{ + bool result = true; + PolyNode* node = Parent; + while (node) { + result = !result; + node = node->Parent; + } + return result; +} //------------------------------------------------------------------------------ bool PolyNode::IsOpen() const -{ - return m_IsOpen; -} +{ + return m_IsOpen; +} //------------------------------------------------------------------------------ #ifndef use_int32 @@ -247,132 +273,171 @@ bool PolyNode::IsOpen() const class Int128 { - public: +public: ulong64 lo; long64 hi; Int128(long64 _lo = 0) { - lo = (ulong64)_lo; - if (_lo < 0) hi = -1; else hi = 0; + lo = (ulong64)_lo; + if (_lo < 0) { + hi = -1; + } + else { + hi = 0; + } } - //Int128(const Int128 &val): lo(val.lo), hi(val.hi){} + // Int128(const Int128 &val): lo(val.lo), hi(val.hi){} - Int128(const long64& _hi, const ulong64& _lo): lo(_lo), hi(_hi){} - - Int128& operator = (const long64 &val) + Int128(const long64& _hi, const ulong64& _lo) + : lo(_lo) + , hi(_hi) + {} + + Int128& operator=(const long64& val) { - lo = (ulong64)val; - if (val < 0) hi = -1; else hi = 0; - return *this; + lo = (ulong64)val; + if (val < 0) { + hi = -1; + } + else { + hi = 0; + } + return *this; } - bool operator == (const Int128 &val) const - {return (hi == val.hi && lo == val.lo);} - - bool operator != (const Int128 &val) const - { return !(*this == val);} - - bool operator > (const Int128 &val) const + bool operator==(const Int128& val) const { - if (hi != val.hi) - return hi > val.hi; - else - return lo > val.lo; + return (hi == val.hi && lo == val.lo); } - bool operator < (const Int128 &val) const + bool operator!=(const Int128& val) const { - if (hi != val.hi) - return hi < val.hi; - else - return lo < val.lo; + return !(*this == val); } - bool operator >= (const Int128 &val) const - { return !(*this < val);} - - bool operator <= (const Int128 &val) const - { return !(*this > val);} - - Int128& operator += (const Int128 &rhs) + bool operator>(const Int128& val) const { - hi += rhs.hi; - lo += rhs.lo; - if (lo < rhs.lo) hi++; - return *this; + if (hi != val.hi) { + return hi > val.hi; + } + else { + return lo > val.lo; + } } - Int128 operator + (const Int128 &rhs) const + bool operator<(const Int128& val) const { - Int128 result(*this); - result+= rhs; - return result; + if (hi != val.hi) { + return hi < val.hi; + } + else { + return lo < val.lo; + } } - Int128& operator -= (const Int128 &rhs) + bool operator>=(const Int128& val) const { - *this += -rhs; - return *this; + return !(*this < val); } - Int128 operator - (const Int128 &rhs) const + bool operator<=(const Int128& val) const { - Int128 result(*this); - result -= rhs; - return result; + return !(*this > val); } - Int128 operator-() const //unary negation + Int128& operator+=(const Int128& rhs) { - if (lo == 0) - return Int128(-hi, 0); - else - return Int128(~hi, ~lo + 1); + hi += rhs.hi; + lo += rhs.lo; + if (lo < rhs.lo) { + hi++; + } + return *this; + } + + Int128 operator+(const Int128& rhs) const + { + Int128 result(*this); + result += rhs; + return result; + } + + Int128& operator-=(const Int128& rhs) + { + *this += -rhs; + return *this; + } + + Int128 operator-(const Int128& rhs) const + { + Int128 result(*this); + result -= rhs; + return result; + } + + Int128 operator-() const // unary negation + { + if (lo == 0) { + return Int128(-hi, 0); + } + else { + return Int128(~hi, ~lo + 1); + } } operator double() const { - const double shift64 = 18446744073709551616.0; //2^64 - if (hi < 0) - { - if (lo == 0) - return (double)hi * shift64; - else return -(double)(~lo + ~hi * shift64); - } - else - return (double)(lo + hi * shift64); + const double shift64 = 18446744073709551616.0; // 2^64 + if (hi < 0) { + if (lo == 0) { + return (double)hi * shift64; + } + else { + return -(double)(~lo + ~hi * shift64); + } + } + else { + return (double)(lo + hi * shift64); + } } - }; //------------------------------------------------------------------------------ -Int128 Int128Mul (long64 lhs, long64 rhs) +Int128 Int128Mul(long64 lhs, long64 rhs) { - bool negate = (lhs < 0) != (rhs < 0); + bool negate = (lhs < 0) != (rhs < 0); - if (lhs < 0) lhs = -lhs; - ulong64 int1Hi = ulong64(lhs) >> 32; - ulong64 int1Lo = ulong64(lhs & 0xFFFFFFFF); + if (lhs < 0) { + lhs = -lhs; + } + ulong64 int1Hi = ulong64(lhs) >> 32; + ulong64 int1Lo = ulong64(lhs & 0xFFFFFFFF); - if (rhs < 0) rhs = -rhs; - ulong64 int2Hi = ulong64(rhs) >> 32; - ulong64 int2Lo = ulong64(rhs & 0xFFFFFFFF); + if (rhs < 0) { + rhs = -rhs; + } + ulong64 int2Hi = ulong64(rhs) >> 32; + ulong64 int2Lo = ulong64(rhs & 0xFFFFFFFF); - //nb: see comments in clipper.pas - ulong64 a = int1Hi * int2Hi; - ulong64 b = int1Lo * int2Lo; - ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi; + // nb: see comments in clipper.pas + ulong64 a = int1Hi * int2Hi; + ulong64 b = int1Lo * int2Lo; + ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi; - Int128 tmp; - tmp.hi = long64(a + (c >> 32)); - tmp.lo = long64(c << 32); - tmp.lo += long64(b); - if (tmp.lo < b) tmp.hi++; - if (negate) tmp = -tmp; - return tmp; + Int128 tmp; + tmp.hi = long64(a + (c >> 32)); + tmp.lo = long64(c << 32); + tmp.lo += long64(b); + if (tmp.lo < b) { + tmp.hi++; + } + if (negate) { + tmp = -tmp; + } + return tmp; }; #endif @@ -382,2726 +447,3008 @@ Int128 Int128Mul (long64 lhs, long64 rhs) void Swap(cInt& val1, cInt& val2) { - cInt tmp = val1; - val1 = val2; - val2 = tmp; + cInt tmp = val1; + val1 = val2; + val2 = tmp; } //------------------------------------------------------------------------------ -bool Orientation(const Path &poly) +bool Orientation(const Path& poly) { return Area(poly) >= 0; } //------------------------------------------------------------------------------ -double Area(const Path &poly) +double Area(const Path& poly) { - int size = (int)poly.size(); - if (size < 3) - return 0; - - double a = 0; - for (int i = 0, j = size -1; i < size; ++i) - { - a += ((double)poly[j].X + poly[i].X) * ((double)poly[j].Y - poly[i].Y); - j = i; - } - return -a * 0.5; -} -//------------------------------------------------------------------------------ - -double Area(const OutRec &outRec) -{ - OutPt *op = outRec.Pts; - if (!op) - return 0; - double a = 0; - do { - a += (double)(op->Prev->Pt.X + op->Pt.X) * (double)(op->Prev->Pt.Y - op->Pt.Y); - op = op->Next; - } while (op != outRec.Pts); - return a * 0.5; -} -//------------------------------------------------------------------------------ - -bool PointIsVertex(const IntPoint &Pt, OutPt *pp) -{ - OutPt *pp2 = pp; - do - { - if (pp2->Pt == Pt) - return true; - pp2 = pp2->Next; - } - while (pp2 != pp); - return false; -} -//------------------------------------------------------------------------------ - -int PointInPolygon (const IntPoint &pt, const Path &path) -{ - //returns 0 if false, +1 if true, -1 if pt ON polygon boundary - //See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos - //http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf - int result = 0; - size_t cnt = path.size(); - if (cnt < 3) - return 0; - IntPoint ip = path[0]; - for(size_t i = 1; i <= cnt; ++i) - { - IntPoint ipNext = (i == cnt ? path[0] : path[i]); - if (ipNext.Y == pt.Y) - { - if ((ipNext.X == pt.X) || (ip.Y == pt.Y && - ((ipNext.X > pt.X) == (ip.X < pt.X)))) return -1; + int size = (int)poly.size(); + if (size < 3) { + return 0; } - if ((ip.Y < pt.Y) != (ipNext.Y < pt.Y)) - { - if (ip.X >= pt.X) - { - if (ipNext.X > pt.X) result = 1 - result; - else - { - double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - - (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); - if (!d) - return -1; - if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result; - } - } else - { - if (ipNext.X > pt.X) - { - double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - - (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); - if (!d) - return -1; - if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result; - } - } + + double a = 0; + for (int i = 0, j = size - 1; i < size; ++i) { + a += ((double)poly[j].X + poly[i].X) * ((double)poly[j].Y - poly[i].Y); + j = i; } - ip = ipNext; - } - return result; + return -a * 0.5; } //------------------------------------------------------------------------------ -int PointInPolygon (const IntPoint &pt, OutPt *op) +double Area(const OutRec& outRec) { - //returns 0 if false, +1 if true, -1 if pt ON polygon boundary - int result = 0; - OutPt* startOp = op; - for(;;) - { - if (op->Next->Pt.Y == pt.Y) - { - if ((op->Next->Pt.X == pt.X) || (op->Pt.Y == pt.Y && - ((op->Next->Pt.X > pt.X) == (op->Pt.X < pt.X)))) return -1; + OutPt* op = outRec.Pts; + if (!op) { + return 0; } - if ((op->Pt.Y < pt.Y) != (op->Next->Pt.Y < pt.Y)) - { - if (op->Pt.X >= pt.X) - { - if (op->Next->Pt.X > pt.X) result = 1 - result; - else - { - double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - - (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); - if (!d) - return -1; - if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result; - } - } else - { - if (op->Next->Pt.X > pt.X) - { - double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - - (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); - if (!d) - return -1; - if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result; - } - } - } - op = op->Next; - if (startOp == op) break; - } - return result; + double a = 0; + do { + a += (double)(op->Prev->Pt.X + op->Pt.X) * (double)(op->Prev->Pt.Y - op->Pt.Y); + op = op->Next; + } while (op != outRec.Pts); + return a * 0.5; } //------------------------------------------------------------------------------ -bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2) +bool PointIsVertex(const IntPoint& Pt, OutPt* pp) { - OutPt* op = OutPt1; - do - { - //nb: PointInPolygon returns 0 if false, +1 if true, -1 if pt on polygon - int res = PointInPolygon(op->Pt, OutPt2); - if (res >= 0) - return res > 0; - op = op->Next; - } - while (op != OutPt1); - return true; + OutPt* pp2 = pp; + do { + if (pp2->Pt == Pt) { + return true; + } + pp2 = pp2->Next; + } while (pp2 != pp); + return false; +} +//------------------------------------------------------------------------------ + +int PointInPolygon(const IntPoint& pt, const Path& path) +{ + // returns 0 if false, +1 if true, -1 if pt ON polygon boundary + // See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos + // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf + int result = 0; + size_t cnt = path.size(); + if (cnt < 3) { + return 0; + } + IntPoint ip = path[0]; + for (size_t i = 1; i <= cnt; ++i) { + IntPoint ipNext = (i == cnt ? path[0] : path[i]); + if (ipNext.Y == pt.Y) { + if ((ipNext.X == pt.X) || (ip.Y == pt.Y && ((ipNext.X > pt.X) == (ip.X < pt.X)))) { + return -1; + } + } + if ((ip.Y < pt.Y) != (ipNext.Y < pt.Y)) { + if (ip.X >= pt.X) { + if (ipNext.X > pt.X) { + result = 1 - result; + } + else { + double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) + - (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); + if (!d) { + return -1; + } + if ((d > 0) == (ipNext.Y > ip.Y)) { + result = 1 - result; + } + } + } + else { + if (ipNext.X > pt.X) { + double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) + - (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); + if (!d) { + return -1; + } + if ((d > 0) == (ipNext.Y > ip.Y)) { + result = 1 - result; + } + } + } + } + ip = ipNext; + } + return result; +} +//------------------------------------------------------------------------------ + +int PointInPolygon(const IntPoint& pt, OutPt* op) +{ + // returns 0 if false, +1 if true, -1 if pt ON polygon boundary + int result = 0; + OutPt* startOp = op; + for (;;) { + if (op->Next->Pt.Y == pt.Y) { + if ((op->Next->Pt.X == pt.X) + || (op->Pt.Y == pt.Y && ((op->Next->Pt.X > pt.X) == (op->Pt.X < pt.X)))) { + return -1; + } + } + if ((op->Pt.Y < pt.Y) != (op->Next->Pt.Y < pt.Y)) { + if (op->Pt.X >= pt.X) { + if (op->Next->Pt.X > pt.X) { + result = 1 - result; + } + else { + double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) + - (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); + if (!d) { + return -1; + } + if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) { + result = 1 - result; + } + } + } + else { + if (op->Next->Pt.X > pt.X) { + double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) + - (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); + if (!d) { + return -1; + } + if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) { + result = 1 - result; + } + } + } + } + op = op->Next; + if (startOp == op) { + break; + } + } + return result; +} +//------------------------------------------------------------------------------ + +bool Poly2ContainsPoly1(OutPt* OutPt1, OutPt* OutPt2) +{ + OutPt* op = OutPt1; + do { + // nb: PointInPolygon returns 0 if false, +1 if true, -1 if pt on polygon + int res = PointInPolygon(op->Pt, OutPt2); + if (res >= 0) { + return res > 0; + } + op = op->Next; + } while (op != OutPt1); + return true; } //---------------------------------------------------------------------- -bool SlopesEqual(const TEdge &e1, const TEdge &e2, bool UseFullInt64Range) +bool SlopesEqual(const TEdge& e1, const TEdge& e2, bool UseFullInt64Range) { #ifndef use_int32 - if (UseFullInt64Range) - return Int128Mul(e1.Delta.Y, e2.Delta.X) == Int128Mul(e1.Delta.X, e2.Delta.Y); - else + if (UseFullInt64Range) { + return Int128Mul(e1.Delta.Y, e2.Delta.X) == Int128Mul(e1.Delta.X, e2.Delta.Y); + } + else #endif - return e1.Delta.Y * e2.Delta.X == e1.Delta.X * e2.Delta.Y; + return e1.Delta.Y * e2.Delta.X == e1.Delta.X * e2.Delta.Y; } //------------------------------------------------------------------------------ -bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, - const IntPoint pt3, bool UseFullInt64Range) +bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, const IntPoint pt3, bool UseFullInt64Range) { #ifndef use_int32 - if (UseFullInt64Range) - return Int128Mul(pt1.Y-pt2.Y, pt2.X-pt3.X) == Int128Mul(pt1.X-pt2.X, pt2.Y-pt3.Y); - else + if (UseFullInt64Range) { + return Int128Mul(pt1.Y - pt2.Y, pt2.X - pt3.X) == Int128Mul(pt1.X - pt2.X, pt2.Y - pt3.Y); + } + else #endif - return (pt1.Y-pt2.Y)*(pt2.X-pt3.X) == (pt1.X-pt2.X)*(pt2.Y-pt3.Y); + return (pt1.Y - pt2.Y) * (pt2.X - pt3.X) == (pt1.X - pt2.X) * (pt2.Y - pt3.Y); } //------------------------------------------------------------------------------ -bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, - const IntPoint pt3, const IntPoint pt4, bool UseFullInt64Range) +bool SlopesEqual(const IntPoint pt1, + const IntPoint pt2, + const IntPoint pt3, + const IntPoint pt4, + bool UseFullInt64Range) { #ifndef use_int32 - if (UseFullInt64Range) - return Int128Mul(pt1.Y-pt2.Y, pt3.X-pt4.X) == Int128Mul(pt1.X-pt2.X, pt3.Y-pt4.Y); - else + if (UseFullInt64Range) { + return Int128Mul(pt1.Y - pt2.Y, pt3.X - pt4.X) == Int128Mul(pt1.X - pt2.X, pt3.Y - pt4.Y); + } + else #endif - return (pt1.Y-pt2.Y)*(pt3.X-pt4.X) == (pt1.X-pt2.X)*(pt3.Y-pt4.Y); + return (pt1.Y - pt2.Y) * (pt3.X - pt4.X) == (pt1.X - pt2.X) * (pt3.Y - pt4.Y); } //------------------------------------------------------------------------------ -inline bool IsHorizontal(TEdge &e) +inline bool IsHorizontal(TEdge& e) { - return e.Delta.Y == 0; + return e.Delta.Y == 0; } //------------------------------------------------------------------------------ inline double GetDx(const IntPoint pt1, const IntPoint pt2) { - return (pt1.Y == pt2.Y) ? - HORIZONTAL : (double)(pt2.X - pt1.X) / (pt2.Y - pt1.Y); + return (pt1.Y == pt2.Y) ? HORIZONTAL : (double)(pt2.X - pt1.X) / (pt2.Y - pt1.Y); } //--------------------------------------------------------------------------- -inline void SetDx(TEdge &e) +inline void SetDx(TEdge& e) { - e.Delta.X = (e.Top.X - e.Bot.X); - e.Delta.Y = (e.Top.Y - e.Bot.Y); + e.Delta.X = (e.Top.X - e.Bot.X); + e.Delta.Y = (e.Top.Y - e.Bot.Y); - if (e.Delta.Y == 0) e.Dx = HORIZONTAL; - else e.Dx = (double)(e.Delta.X) / e.Delta.Y; + if (e.Delta.Y == 0) { + e.Dx = HORIZONTAL; + } + else { + e.Dx = (double)(e.Delta.X) / e.Delta.Y; + } } //--------------------------------------------------------------------------- -inline void SwapSides(TEdge &Edge1, TEdge &Edge2) +inline void SwapSides(TEdge& Edge1, TEdge& Edge2) { - EdgeSide Side = Edge1.Side; - Edge1.Side = Edge2.Side; - Edge2.Side = Side; + EdgeSide Side = Edge1.Side; + Edge1.Side = Edge2.Side; + Edge2.Side = Side; } //------------------------------------------------------------------------------ -inline void SwapPolyIndexes(TEdge &Edge1, TEdge &Edge2) +inline void SwapPolyIndexes(TEdge& Edge1, TEdge& Edge2) { - int OutIdx = Edge1.OutIdx; - Edge1.OutIdx = Edge2.OutIdx; - Edge2.OutIdx = OutIdx; + int OutIdx = Edge1.OutIdx; + Edge1.OutIdx = Edge2.OutIdx; + Edge2.OutIdx = OutIdx; } //------------------------------------------------------------------------------ -inline cInt TopX(TEdge &edge, const cInt currentY) +inline cInt TopX(TEdge& edge, const cInt currentY) { - return ( currentY == edge.Top.Y ) ? - edge.Top.X : edge.Bot.X + Round(edge.Dx *(currentY - edge.Bot.Y)); + return (currentY == edge.Top.Y) ? edge.Top.X + : edge.Bot.X + Round(edge.Dx * (currentY - edge.Bot.Y)); } //------------------------------------------------------------------------------ -void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip) +void IntersectPoint(TEdge& Edge1, TEdge& Edge2, IntPoint& ip) { -#ifdef use_xyz - ip.Z = 0; +#ifdef use_xyz + ip.Z = 0; #endif - double b1, b2; - if (Edge1.Dx == Edge2.Dx) - { - ip.Y = Edge1.Curr.Y; - ip.X = TopX(Edge1, ip.Y); - return; - } - else if (Edge1.Delta.X == 0) - { - ip.X = Edge1.Bot.X; - if (IsHorizontal(Edge2)) - ip.Y = Edge2.Bot.Y; - else - { - b2 = Edge2.Bot.Y - (Edge2.Bot.X / Edge2.Dx); - ip.Y = Round(ip.X / Edge2.Dx + b2); + double b1, b2; + if (Edge1.Dx == Edge2.Dx) { + ip.Y = Edge1.Curr.Y; + ip.X = TopX(Edge1, ip.Y); + return; } - } - else if (Edge2.Delta.X == 0) - { - ip.X = Edge2.Bot.X; - if (IsHorizontal(Edge1)) - ip.Y = Edge1.Bot.Y; - else - { - b1 = Edge1.Bot.Y - (Edge1.Bot.X / Edge1.Dx); - ip.Y = Round(ip.X / Edge1.Dx + b1); + else if (Edge1.Delta.X == 0) { + ip.X = Edge1.Bot.X; + if (IsHorizontal(Edge2)) { + ip.Y = Edge2.Bot.Y; + } + else { + b2 = Edge2.Bot.Y - (Edge2.Bot.X / Edge2.Dx); + ip.Y = Round(ip.X / Edge2.Dx + b2); + } + } + else if (Edge2.Delta.X == 0) { + ip.X = Edge2.Bot.X; + if (IsHorizontal(Edge1)) { + ip.Y = Edge1.Bot.Y; + } + else { + b1 = Edge1.Bot.Y - (Edge1.Bot.X / Edge1.Dx); + ip.Y = Round(ip.X / Edge1.Dx + b1); + } + } + else { + b1 = Edge1.Bot.X - Edge1.Bot.Y * Edge1.Dx; + b2 = Edge2.Bot.X - Edge2.Bot.Y * Edge2.Dx; + double q = (b2 - b1) / (Edge1.Dx - Edge2.Dx); + ip.Y = Round(q); + if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) { + ip.X = Round(Edge1.Dx * q + b1); + } + else { + ip.X = Round(Edge2.Dx * q + b2); + } } - } - else - { - b1 = Edge1.Bot.X - Edge1.Bot.Y * Edge1.Dx; - b2 = Edge2.Bot.X - Edge2.Bot.Y * Edge2.Dx; - double q = (b2-b1) / (Edge1.Dx - Edge2.Dx); - ip.Y = Round(q); - if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) - ip.X = Round(Edge1.Dx * q + b1); - else - ip.X = Round(Edge2.Dx * q + b2); - } - if (ip.Y < Edge1.Top.Y || ip.Y < Edge2.Top.Y) - { - if (Edge1.Top.Y > Edge2.Top.Y) - ip.Y = Edge1.Top.Y; - else - ip.Y = Edge2.Top.Y; - if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) - ip.X = TopX(Edge1, ip.Y); - else - ip.X = TopX(Edge2, ip.Y); - } - //finally, don't allow 'ip' to be BELOW curr.Y (ie bottom of scanbeam) ... - if (ip.Y > Edge1.Curr.Y) - { - ip.Y = Edge1.Curr.Y; - //use the more vertical edge to derive X ... - if (std::fabs(Edge1.Dx) > std::fabs(Edge2.Dx)) - ip.X = TopX(Edge2, ip.Y); else - ip.X = TopX(Edge1, ip.Y); - } + if (ip.Y < Edge1.Top.Y || ip.Y < Edge2.Top.Y) { + if (Edge1.Top.Y > Edge2.Top.Y) { + ip.Y = Edge1.Top.Y; + } + else { + ip.Y = Edge2.Top.Y; + } + if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) { + ip.X = TopX(Edge1, ip.Y); + } + else { + ip.X = TopX(Edge2, ip.Y); + } + } + // finally, don't allow 'ip' to be BELOW curr.Y (ie bottom of scanbeam) ... + if (ip.Y > Edge1.Curr.Y) { + ip.Y = Edge1.Curr.Y; + // use the more vertical edge to derive X ... + if (std::fabs(Edge1.Dx) > std::fabs(Edge2.Dx)) { + ip.X = TopX(Edge2, ip.Y); + } + else { + ip.X = TopX(Edge1, ip.Y); + } + } } //------------------------------------------------------------------------------ -void ReversePolyPtLinks(OutPt *pp) +void ReversePolyPtLinks(OutPt* pp) { - if (!pp) - return; - OutPt *pp1, *pp2; - pp1 = pp; - do { - pp2 = pp1->Next; - pp1->Next = pp1->Prev; - pp1->Prev = pp2; - pp1 = pp2; - } while( pp1 != pp ); + if (!pp) { + return; + } + OutPt *pp1, *pp2; + pp1 = pp; + do { + pp2 = pp1->Next; + pp1->Next = pp1->Prev; + pp1->Prev = pp2; + pp1 = pp2; + } while (pp1 != pp); } //------------------------------------------------------------------------------ void DisposeOutPts(OutPt*& pp) { - if (pp == 0) - return; + if (pp == 0) { + return; + } pp->Prev->Next = 0; - while( pp ) - { - OutPt *tmpPp = pp; - pp = pp->Next; - delete tmpPp; - } + while (pp) { + OutPt* tmpPp = pp; + pp = pp->Next; + delete tmpPp; + } } //------------------------------------------------------------------------------ inline void InitEdge(TEdge* e, TEdge* eNext, TEdge* ePrev, const IntPoint& Pt) { - e->Next = eNext; - e->Prev = ePrev; - e->Curr = Pt; - e->OutIdx = Unassigned; + e->Next = eNext; + e->Prev = ePrev; + e->Curr = Pt; + e->OutIdx = Unassigned; } //------------------------------------------------------------------------------ void InitEdge2(TEdge& e, PolyType Pt) { - if (e.Curr.Y >= e.Next->Curr.Y) - { - e.Bot = e.Curr; - e.Top = e.Next->Curr; - } else - { - e.Top = e.Curr; - e.Bot = e.Next->Curr; - } - SetDx(e); - e.PolyTyp = Pt; + if (e.Curr.Y >= e.Next->Curr.Y) { + e.Bot = e.Curr; + e.Top = e.Next->Curr; + } + else { + e.Top = e.Curr; + e.Bot = e.Next->Curr; + } + SetDx(e); + e.PolyTyp = Pt; } //------------------------------------------------------------------------------ TEdge* RemoveEdge(TEdge* e) { - //removes e from double_linked_list (but without removing from memory) - e->Prev->Next = e->Next; - e->Next->Prev = e->Prev; - TEdge* result = e->Next; - e->Prev = 0; //flag as removed (see ClipperBase.Clear) - return result; + // removes e from double_linked_list (but without removing from memory) + e->Prev->Next = e->Next; + e->Next->Prev = e->Prev; + TEdge* result = e->Next; + e->Prev = 0; // flag as removed (see ClipperBase.Clear) + return result; } //------------------------------------------------------------------------------ -inline void ReverseHorizontal(TEdge &e) +inline void ReverseHorizontal(TEdge& e) { - //swap horizontal edges' Top and Bottom x's so they follow the natural - //progression of the bounds - ie so their xbots will align with the - //adjoining lower edge. [Helpful in the ProcessHorizontal() method.] - Swap(e.Top.X, e.Bot.X); -#ifdef use_xyz - Swap(e.Top.Z, e.Bot.Z); + // swap horizontal edges' Top and Bottom x's so they follow the natural + // progression of the bounds - ie so their xbots will align with the + // adjoining lower edge. [Helpful in the ProcessHorizontal() method.] + Swap(e.Top.X, e.Bot.X); +#ifdef use_xyz + Swap(e.Top.Z, e.Bot.Z); #endif } //------------------------------------------------------------------------------ -void SwapPoints(IntPoint &pt1, IntPoint &pt2) +void SwapPoints(IntPoint& pt1, IntPoint& pt2) { - IntPoint tmp = pt1; - pt1 = pt2; - pt2 = tmp; + IntPoint tmp = pt1; + pt1 = pt2; + pt2 = tmp; } //------------------------------------------------------------------------------ -bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, - IntPoint pt2b, IntPoint &pt1, IntPoint &pt2) +bool GetOverlapSegment(IntPoint pt1a, + IntPoint pt1b, + IntPoint pt2a, + IntPoint pt2b, + IntPoint& pt1, + IntPoint& pt2) { - //precondition: segments are Collinear. - if (Abs(pt1a.X - pt1b.X) > Abs(pt1a.Y - pt1b.Y)) - { - if (pt1a.X > pt1b.X) SwapPoints(pt1a, pt1b); - if (pt2a.X > pt2b.X) SwapPoints(pt2a, pt2b); - if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a; - if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b; - return pt1.X < pt2.X; - } else - { - if (pt1a.Y < pt1b.Y) SwapPoints(pt1a, pt1b); - if (pt2a.Y < pt2b.Y) SwapPoints(pt2a, pt2b); - if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a; - if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b; - return pt1.Y > pt2.Y; - } + // precondition: segments are Collinear. + if (Abs(pt1a.X - pt1b.X) > Abs(pt1a.Y - pt1b.Y)) { + if (pt1a.X > pt1b.X) { + SwapPoints(pt1a, pt1b); + } + if (pt2a.X > pt2b.X) { + SwapPoints(pt2a, pt2b); + } + if (pt1a.X > pt2a.X) { + pt1 = pt1a; + } + else { + pt1 = pt2a; + } + if (pt1b.X < pt2b.X) { + pt2 = pt1b; + } + else { + pt2 = pt2b; + } + return pt1.X < pt2.X; + } + else { + if (pt1a.Y < pt1b.Y) { + SwapPoints(pt1a, pt1b); + } + if (pt2a.Y < pt2b.Y) { + SwapPoints(pt2a, pt2b); + } + if (pt1a.Y < pt2a.Y) { + pt1 = pt1a; + } + else { + pt1 = pt2a; + } + if (pt1b.Y > pt2b.Y) { + pt2 = pt1b; + } + else { + pt2 = pt2b; + } + return pt1.Y > pt2.Y; + } } //------------------------------------------------------------------------------ bool FirstIsBottomPt(const OutPt* btmPt1, const OutPt* btmPt2) { - OutPt *p = btmPt1->Prev; - while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) p = p->Prev; - double dx1p = std::fabs(GetDx(btmPt1->Pt, p->Pt)); - p = btmPt1->Next; - while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) p = p->Next; - double dx1n = std::fabs(GetDx(btmPt1->Pt, p->Pt)); + OutPt* p = btmPt1->Prev; + while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) { + p = p->Prev; + } + double dx1p = std::fabs(GetDx(btmPt1->Pt, p->Pt)); + p = btmPt1->Next; + while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) { + p = p->Next; + } + double dx1n = std::fabs(GetDx(btmPt1->Pt, p->Pt)); - p = btmPt2->Prev; - while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) p = p->Prev; - double dx2p = std::fabs(GetDx(btmPt2->Pt, p->Pt)); - p = btmPt2->Next; - while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) p = p->Next; - double dx2n = std::fabs(GetDx(btmPt2->Pt, p->Pt)); - return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n); + p = btmPt2->Prev; + while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) { + p = p->Prev; + } + double dx2p = std::fabs(GetDx(btmPt2->Pt, p->Pt)); + p = btmPt2->Next; + while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) { + p = p->Next; + } + double dx2n = std::fabs(GetDx(btmPt2->Pt, p->Pt)); + return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n); } //------------------------------------------------------------------------------ -OutPt* GetBottomPt(OutPt *pp) +OutPt* GetBottomPt(OutPt* pp) { - OutPt* dups = 0; - OutPt* p = pp->Next; - while (p != pp) - { - if (p->Pt.Y > pp->Pt.Y) - { - pp = p; - dups = 0; + OutPt* dups = 0; + OutPt* p = pp->Next; + while (p != pp) { + if (p->Pt.Y > pp->Pt.Y) { + pp = p; + dups = 0; + } + else if (p->Pt.Y == pp->Pt.Y && p->Pt.X <= pp->Pt.X) { + if (p->Pt.X < pp->Pt.X) { + dups = 0; + pp = p; + } + else { + if (p->Next != pp && p->Prev != pp) { + dups = p; + } + } + } + p = p->Next; } - else if (p->Pt.Y == pp->Pt.Y && p->Pt.X <= pp->Pt.X) - { - if (p->Pt.X < pp->Pt.X) - { - dups = 0; - pp = p; - } else - { - if (p->Next != pp && p->Prev != pp) dups = p; - } + if (dups) { + // there appears to be at least 2 vertices at BottomPt so ... + while (dups != p) { + if (!FirstIsBottomPt(p, dups)) { + pp = dups; + } + dups = dups->Next; + while (dups->Pt != pp->Pt) { + dups = dups->Next; + } + } } - p = p->Next; - } - if (dups) - { - //there appears to be at least 2 vertices at BottomPt so ... - while (dups != p) - { - if (!FirstIsBottomPt(p, dups)) pp = dups; - dups = dups->Next; - while (dups->Pt != pp->Pt) dups = dups->Next; - } - } - return pp; + return pp; } //------------------------------------------------------------------------------ -bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1, - const IntPoint pt2, const IntPoint pt3) +bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1, const IntPoint pt2, const IntPoint pt3) { - if ((pt1 == pt3) || (pt1 == pt2) || (pt3 == pt2)) - return false; - else if (pt1.X != pt3.X) - return (pt2.X > pt1.X) == (pt2.X < pt3.X); - else - return (pt2.Y > pt1.Y) == (pt2.Y < pt3.Y); + if ((pt1 == pt3) || (pt1 == pt2) || (pt3 == pt2)) { + return false; + } + else if (pt1.X != pt3.X) { + return (pt2.X > pt1.X) == (pt2.X < pt3.X); + } + else { + return (pt2.Y > pt1.Y) == (pt2.Y < pt3.Y); + } } //------------------------------------------------------------------------------ bool HorzSegmentsOverlap(cInt seg1a, cInt seg1b, cInt seg2a, cInt seg2b) { - if (seg1a > seg1b) Swap(seg1a, seg1b); - if (seg2a > seg2b) Swap(seg2a, seg2b); - return (seg1a < seg2b) && (seg2a < seg1b); + if (seg1a > seg1b) { + Swap(seg1a, seg1b); + } + if (seg2a > seg2b) { + Swap(seg2a, seg2b); + } + return (seg1a < seg2b) && (seg2a < seg1b); } //------------------------------------------------------------------------------ // ClipperBase class methods ... //------------------------------------------------------------------------------ -ClipperBase::ClipperBase() //constructor +ClipperBase::ClipperBase() // constructor { - m_CurrentLM = m_MinimaList.begin(); //begin() == end() here - m_UseFullRange = false; - m_PreserveCollinear = false; - m_HasOpenPaths = false; + m_CurrentLM = m_MinimaList.begin(); // begin() == end() here + m_UseFullRange = false; + m_PreserveCollinear = false; + m_HasOpenPaths = false; } //------------------------------------------------------------------------------ -ClipperBase::~ClipperBase() //destructor +ClipperBase::~ClipperBase() // destructor { - Clear(); + Clear(); } //------------------------------------------------------------------------------ void RangeTest(const IntPoint& Pt, bool& useFullRange) { - if (useFullRange) - { - if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange) - throw std::range_error("Coordinate outside allowed range"); - } - else if (Pt.X > loRange|| Pt.Y > loRange || -Pt.X > loRange || -Pt.Y > loRange) - { - useFullRange = true; - RangeTest(Pt, useFullRange); - } + if (useFullRange) { + if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange) { + throw std::range_error("Coordinate outside allowed range"); + } + } + else if (Pt.X > loRange || Pt.Y > loRange || -Pt.X > loRange || -Pt.Y > loRange) { + useFullRange = true; + RangeTest(Pt, useFullRange); + } } //------------------------------------------------------------------------------ TEdge* FindNextLocMin(TEdge* E) { - for (;;) - { - while (E->Bot != E->Prev->Bot || E->Curr == E->Top) E = E->Next; - if (!IsHorizontal(*E) && !IsHorizontal(*E->Prev)) break; - while (IsHorizontal(*E->Prev)) E = E->Prev; - TEdge* E2 = E; - while (IsHorizontal(*E)) E = E->Next; - if (E->Top.Y == E->Prev->Bot.Y) continue; //ie just an intermediate horz. - if (E2->Prev->Bot.X < E->Bot.X) E = E2; - break; - } - return E; + for (;;) { + while (E->Bot != E->Prev->Bot || E->Curr == E->Top) { + E = E->Next; + } + if (!IsHorizontal(*E) && !IsHorizontal(*E->Prev)) { + break; + } + while (IsHorizontal(*E->Prev)) { + E = E->Prev; + } + TEdge* E2 = E; + while (IsHorizontal(*E)) { + E = E->Next; + } + if (E->Top.Y == E->Prev->Bot.Y) { + continue; // ie just an intermediate horz. + } + if (E2->Prev->Bot.X < E->Bot.X) { + E = E2; + } + break; + } + return E; } //------------------------------------------------------------------------------ TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward) { - TEdge *Result = E; - TEdge *Horz = 0; + TEdge* Result = E; + TEdge* Horz = 0; - if (E->OutIdx == Skip) - { - //if edges still remain in the current bound beyond the skip edge then - //create another LocMin and call ProcessBound once more - if (NextIsForward) - { - while (E->Top.Y == E->Next->Bot.Y) E = E->Next; - //don't include top horizontals when parsing a bound a second time, - //they will be contained in the opposite bound ... - while (E != Result && IsHorizontal(*E)) E = E->Prev; - } - else - { - while (E->Top.Y == E->Prev->Bot.Y) E = E->Prev; - while (E != Result && IsHorizontal(*E)) E = E->Next; + if (E->OutIdx == Skip) { + // if edges still remain in the current bound beyond the skip edge then + // create another LocMin and call ProcessBound once more + if (NextIsForward) { + while (E->Top.Y == E->Next->Bot.Y) { + E = E->Next; + } + // don't include top horizontals when parsing a bound a second time, + // they will be contained in the opposite bound ... + while (E != Result && IsHorizontal(*E)) { + E = E->Prev; + } + } + else { + while (E->Top.Y == E->Prev->Bot.Y) { + E = E->Prev; + } + while (E != Result && IsHorizontal(*E)) { + E = E->Next; + } + } + + if (E == Result) { + if (NextIsForward) { + Result = E->Next; + } + else { + Result = E->Prev; + } + } + else { + // there are more edges in the bound beyond result starting with E + if (NextIsForward) { + E = Result->Next; + } + else { + E = Result->Prev; + } + MinimaList::value_type locMin; + locMin.Y = E->Bot.Y; + locMin.LeftBound = 0; + locMin.RightBound = E; + E->WindDelta = 0; + Result = ProcessBound(E, NextIsForward); + m_MinimaList.push_back(locMin); + } + return Result; } - if (E == Result) - { - if (NextIsForward) Result = E->Next; - else Result = E->Prev; + TEdge* EStart; + + if (IsHorizontal(*E)) { + // We need to be careful with open paths because this may not be a + // true local minima (ie E may be following a skip edge). + // Also, consecutive horz. edges may start heading left before going right. + if (NextIsForward) { + EStart = E->Prev; + } + else { + EStart = E->Next; + } + if (EStart->OutIdx != Skip) { + if (IsHorizontal(*EStart)) // ie an adjoining horizontal skip edge + { + if (EStart->Bot.X != E->Bot.X && EStart->Top.X != E->Bot.X) { + ReverseHorizontal(*E); + } + } + else if (EStart->Bot.X != E->Bot.X) { + ReverseHorizontal(*E); + } + } } - else - { - //there are more edges in the bound beyond result starting with E - if (NextIsForward) - E = Result->Next; - else - E = Result->Prev; - MinimaList::value_type locMin; - locMin.Y = E->Bot.Y; - locMin.LeftBound = 0; - locMin.RightBound = E; - E->WindDelta = 0; - Result = ProcessBound(E, NextIsForward); - m_MinimaList.push_back(locMin); + + EStart = E; + if (NextIsForward) { + while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip) { + Result = Result->Next; + } + if (IsHorizontal(*Result) && Result->Next->OutIdx != Skip) { + // nb: at the top of a bound, horizontals are added to the bound + // only when the preceding edge attaches to the horizontal's left vertex + // unless a Skip edge is encountered when that becomes the top divide + Horz = Result; + while (IsHorizontal(*Horz->Prev)) { + Horz = Horz->Prev; + } + if (Horz->Prev->Top.X == Result->Next->Top.X) { + if (!NextIsForward) { + Result = Horz->Prev; + } + } + else if (Horz->Prev->Top.X > Result->Next->Top.X) { + Result = Horz->Prev; + } + } + while (E != Result) { + E->NextInLML = E->Next; + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X) { + ReverseHorizontal(*E); + } + E = E->Next; + } + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X) { + ReverseHorizontal(*E); + } + Result = Result->Next; // move to the edge just beyond current bound } + else { + while (Result->Top.Y == Result->Prev->Bot.Y && Result->Prev->OutIdx != Skip) { + Result = Result->Prev; + } + if (IsHorizontal(*Result) && Result->Prev->OutIdx != Skip) { + Horz = Result; + while (IsHorizontal(*Horz->Next)) { + Horz = Horz->Next; + } + if (Horz->Next->Top.X == Result->Prev->Top.X) { + if (!NextIsForward) { + Result = Horz->Next; + } + } + else if (Horz->Next->Top.X > Result->Prev->Top.X) { + Result = Horz->Next; + } + } + + while (E != Result) { + E->NextInLML = E->Prev; + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) { + ReverseHorizontal(*E); + } + E = E->Prev; + } + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) { + ReverseHorizontal(*E); + } + Result = Result->Prev; // move to the edge just beyond current bound + } + return Result; - } - - TEdge *EStart; - - if (IsHorizontal(*E)) - { - //We need to be careful with open paths because this may not be a - //true local minima (ie E may be following a skip edge). - //Also, consecutive horz. edges may start heading left before going right. - if (NextIsForward) - EStart = E->Prev; - else - EStart = E->Next; - if (EStart->OutIdx != Skip) - { - if (IsHorizontal(*EStart)) //ie an adjoining horizontal skip edge - { - if (EStart->Bot.X != E->Bot.X && EStart->Top.X != E->Bot.X) - ReverseHorizontal(*E); - } - else if (EStart->Bot.X != E->Bot.X) - ReverseHorizontal(*E); - } - } - - EStart = E; - if (NextIsForward) - { - while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip) - Result = Result->Next; - if (IsHorizontal(*Result) && Result->Next->OutIdx != Skip) - { - //nb: at the top of a bound, horizontals are added to the bound - //only when the preceding edge attaches to the horizontal's left vertex - //unless a Skip edge is encountered when that becomes the top divide - Horz = Result; - while (IsHorizontal(*Horz->Prev)) Horz = Horz->Prev; - if (Horz->Prev->Top.X == Result->Next->Top.X) - { - if (!NextIsForward) Result = Horz->Prev; - } - else if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev; - } - while (E != Result) - { - E->NextInLML = E->Next; - if (IsHorizontal(*E) && E != EStart && - E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); - E = E->Next; - } - if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X) - ReverseHorizontal(*E); - Result = Result->Next; //move to the edge just beyond current bound - } else - { - while (Result->Top.Y == Result->Prev->Bot.Y && Result->Prev->OutIdx != Skip) - Result = Result->Prev; - if (IsHorizontal(*Result) && Result->Prev->OutIdx != Skip) - { - Horz = Result; - while (IsHorizontal(*Horz->Next)) Horz = Horz->Next; - if (Horz->Next->Top.X == Result->Prev->Top.X) - { - if (!NextIsForward) Result = Horz->Next; - } - else if (Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next; - } - - while (E != Result) - { - E->NextInLML = E->Prev; - if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) - ReverseHorizontal(*E); - E = E->Prev; - } - if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) - ReverseHorizontal(*E); - Result = Result->Prev; //move to the edge just beyond current bound - } - - return Result; } //------------------------------------------------------------------------------ -bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) +bool ClipperBase::AddPath(const Path& pg, PolyType PolyTyp, bool Closed) { #ifdef use_lines - if (!Closed && PolyTyp == ptClip) - throw clipperException("AddPath: Open paths must be subject."); + if (!Closed && PolyTyp == ptClip) { + throw clipperException("AddPath: Open paths must be subject."); + } #else - if (!Closed) - throw clipperException("AddPath: Open paths have been disabled."); + if (!Closed) { + throw clipperException("AddPath: Open paths have been disabled."); + } #endif - int highI = (int)pg.size() -1; - if (Closed) while (highI > 0 && (pg[highI] == pg[0])) --highI; - while (highI > 0 && (pg[highI] == pg[highI -1])) --highI; - if ((Closed && highI < 2) || (!Closed && highI < 1)) - return false; - - //create a new edge array ... - TEdge *edges = new TEdge [highI +1]; - - bool IsFlat = true; - //1. Basic (first) edge initialization ... - try - { - edges[1].Curr = pg[1]; - RangeTest(pg[0], m_UseFullRange); - RangeTest(pg[highI], m_UseFullRange); - InitEdge(&edges[0], &edges[1], &edges[highI], pg[0]); - InitEdge(&edges[highI], &edges[0], &edges[highI-1], pg[highI]); - for (int i = highI - 1; i >= 1; --i) - { - RangeTest(pg[i], m_UseFullRange); - InitEdge(&edges[i], &edges[i+1], &edges[i-1], pg[i]); + int highI = (int)pg.size() - 1; + if (Closed) { + while (highI > 0 && (pg[highI] == pg[0])) { + --highI; + } } - } - catch(...) - { - delete [] edges; - throw; //range test fails - } - TEdge *eStart = &edges[0]; - - //2. Remove duplicate vertices, and (when closed) collinear edges ... - TEdge *E = eStart, *eLoopStop = eStart; - for (;;) - { - //nb: allows matching start and end points when not Closed ... - if (E->Curr == E->Next->Curr && (Closed || E->Next != eStart)) - { - if (E == E->Next) break; - if (E == eStart) eStart = E->Next; - E = RemoveEdge(E); - eLoopStop = E; - continue; + while (highI > 0 && (pg[highI] == pg[highI - 1])) { + --highI; } - if (E->Prev == E->Next) - break; //only two vertices - else if (Closed && - SlopesEqual(E->Prev->Curr, E->Curr, E->Next->Curr, m_UseFullRange) && - (!m_PreserveCollinear || - !Pt2IsBetweenPt1AndPt3(E->Prev->Curr, E->Curr, E->Next->Curr))) - { - //Collinear edges are allowed for open paths but in closed paths - //the default is to merge adjacent collinear edges into a single edge. - //However, if the PreserveCollinear property is enabled, only overlapping - //collinear edges (ie spikes) will be removed from closed paths. - if (E == eStart) eStart = E->Next; - E = RemoveEdge(E); - E = E->Prev; - eLoopStop = E; - continue; + if ((Closed && highI < 2) || (!Closed && highI < 1)) { + return false; } - E = E->Next; - if ((E == eLoopStop) || (!Closed && E->Next == eStart)) break; - } - if ((!Closed && (E == E->Next)) || (Closed && (E->Prev == E->Next))) - { - delete [] edges; - return false; - } + // create a new edge array ... + TEdge* edges = new TEdge[highI + 1]; - if (!Closed) - { - m_HasOpenPaths = true; - eStart->Prev->OutIdx = Skip; - } - - //3. Do second stage of edge initialization ... - E = eStart; - do - { - InitEdge2(*E, PolyTyp); - E = E->Next; - if (IsFlat && E->Curr.Y != eStart->Curr.Y) IsFlat = false; - } - while (E != eStart); - - //4. Finally, add edge bounds to LocalMinima list ... - - //Totally flat paths must be handled differently when adding them - //to LocalMinima list to avoid endless loops etc ... - if (IsFlat) - { - if (Closed) - { - delete [] edges; - return false; + bool IsFlat = true; + // 1. Basic (first) edge initialization ... + try { + edges[1].Curr = pg[1]; + RangeTest(pg[0], m_UseFullRange); + RangeTest(pg[highI], m_UseFullRange); + InitEdge(&edges[0], &edges[1], &edges[highI], pg[0]); + InitEdge(&edges[highI], &edges[0], &edges[highI - 1], pg[highI]); + for (int i = highI - 1; i >= 1; --i) { + RangeTest(pg[i], m_UseFullRange); + InitEdge(&edges[i], &edges[i + 1], &edges[i - 1], pg[i]); + } } - E->Prev->OutIdx = Skip; - if (E->Prev->Bot.X < E->Prev->Top.X) ReverseHorizontal(*E->Prev); - MinimaList::value_type locMin; - locMin.Y = E->Bot.Y; - locMin.LeftBound = 0; - locMin.RightBound = E; - locMin.RightBound->Side = esRight; - locMin.RightBound->WindDelta = 0; - while (E->Next->OutIdx != Skip) - { - E->NextInLML = E->Next; - if (E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); - E = E->Next; + catch (...) { + delete[] edges; + throw; // range test fails } - m_MinimaList.push_back(locMin); + TEdge* eStart = &edges[0]; + + // 2. Remove duplicate vertices, and (when closed) collinear edges ... + TEdge *E = eStart, *eLoopStop = eStart; + for (;;) { + // nb: allows matching start and end points when not Closed ... + if (E->Curr == E->Next->Curr && (Closed || E->Next != eStart)) { + if (E == E->Next) { + break; + } + if (E == eStart) { + eStart = E->Next; + } + E = RemoveEdge(E); + eLoopStop = E; + continue; + } + if (E->Prev == E->Next) { + break; // only two vertices + } + else if (Closed && SlopesEqual(E->Prev->Curr, E->Curr, E->Next->Curr, m_UseFullRange) + && (!m_PreserveCollinear + || !Pt2IsBetweenPt1AndPt3(E->Prev->Curr, E->Curr, E->Next->Curr))) { + // Collinear edges are allowed for open paths but in closed paths + // the default is to merge adjacent collinear edges into a single edge. + // However, if the PreserveCollinear property is enabled, only overlapping + // collinear edges (ie spikes) will be removed from closed paths. + if (E == eStart) { + eStart = E->Next; + } + E = RemoveEdge(E); + E = E->Prev; + eLoopStop = E; + continue; + } + E = E->Next; + if ((E == eLoopStop) || (!Closed && E->Next == eStart)) { + break; + } + } + + if ((!Closed && (E == E->Next)) || (Closed && (E->Prev == E->Next))) { + delete[] edges; + return false; + } + + if (!Closed) { + m_HasOpenPaths = true; + eStart->Prev->OutIdx = Skip; + } + + // 3. Do second stage of edge initialization ... + E = eStart; + do { + InitEdge2(*E, PolyTyp); + E = E->Next; + if (IsFlat && E->Curr.Y != eStart->Curr.Y) { + IsFlat = false; + } + } while (E != eStart); + + // 4. Finally, add edge bounds to LocalMinima list ... + + // Totally flat paths must be handled differently when adding them + // to LocalMinima list to avoid endless loops etc ... + if (IsFlat) { + if (Closed) { + delete[] edges; + return false; + } + E->Prev->OutIdx = Skip; + if (E->Prev->Bot.X < E->Prev->Top.X) { + ReverseHorizontal(*E->Prev); + } + MinimaList::value_type locMin; + locMin.Y = E->Bot.Y; + locMin.LeftBound = 0; + locMin.RightBound = E; + locMin.RightBound->Side = esRight; + locMin.RightBound->WindDelta = 0; + while (E->Next->OutIdx != Skip) { + E->NextInLML = E->Next; + if (E->Bot.X != E->Prev->Top.X) { + ReverseHorizontal(*E); + } + E = E->Next; + } + m_MinimaList.push_back(locMin); + m_edges.push_back(edges); + return true; + } + m_edges.push_back(edges); - return true; - } + bool leftBoundIsForward; + TEdge* EMin = 0; - m_edges.push_back(edges); - bool leftBoundIsForward; - TEdge* EMin = 0; - - //workaround to avoid an endless loop in the while loop below when - //open paths have matching start and end points ... - if (E->Prev->Bot == E->Prev->Top) E = E->Next; - - for (;;) - { - E = FindNextLocMin(E); - if (E == EMin) break; - else if (!EMin) EMin = E; - - //E and E.Prev now share a local minima (left aligned if horizontal). - //Compare their slopes to find which starts which bound ... - MinimaList::value_type locMin; - locMin.Y = E->Bot.Y; - if (E->Dx < E->Prev->Dx) - { - locMin.LeftBound = E->Prev; - locMin.RightBound = E; - leftBoundIsForward = false; //Q.nextInLML = Q.prev - } else - { - locMin.LeftBound = E; - locMin.RightBound = E->Prev; - leftBoundIsForward = true; //Q.nextInLML = Q.next + // workaround to avoid an endless loop in the while loop below when + // open paths have matching start and end points ... + if (E->Prev->Bot == E->Prev->Top) { + E = E->Next; } - locMin.LeftBound->Side = esLeft; - locMin.RightBound->Side = esRight; - if (!Closed) locMin.LeftBound->WindDelta = 0; - else if (locMin.LeftBound->Next == locMin.RightBound) - locMin.LeftBound->WindDelta = -1; - else locMin.LeftBound->WindDelta = 1; - locMin.RightBound->WindDelta = -locMin.LeftBound->WindDelta; + for (;;) { + E = FindNextLocMin(E); + if (E == EMin) { + break; + } + else if (!EMin) { + EMin = E; + } - E = ProcessBound(locMin.LeftBound, leftBoundIsForward); - if (E->OutIdx == Skip) E = ProcessBound(E, leftBoundIsForward); + // E and E.Prev now share a local minima (left aligned if horizontal). + // Compare their slopes to find which starts which bound ... + MinimaList::value_type locMin; + locMin.Y = E->Bot.Y; + if (E->Dx < E->Prev->Dx) { + locMin.LeftBound = E->Prev; + locMin.RightBound = E; + leftBoundIsForward = false; // Q.nextInLML = Q.prev + } + else { + locMin.LeftBound = E; + locMin.RightBound = E->Prev; + leftBoundIsForward = true; // Q.nextInLML = Q.next + } + locMin.LeftBound->Side = esLeft; + locMin.RightBound->Side = esRight; - TEdge* E2 = ProcessBound(locMin.RightBound, !leftBoundIsForward); - if (E2->OutIdx == Skip) E2 = ProcessBound(E2, !leftBoundIsForward); + if (!Closed) { + locMin.LeftBound->WindDelta = 0; + } + else if (locMin.LeftBound->Next == locMin.RightBound) { + locMin.LeftBound->WindDelta = -1; + } + else { + locMin.LeftBound->WindDelta = 1; + } + locMin.RightBound->WindDelta = -locMin.LeftBound->WindDelta; - if (locMin.LeftBound->OutIdx == Skip) - locMin.LeftBound = 0; - else if (locMin.RightBound->OutIdx == Skip) - locMin.RightBound = 0; - m_MinimaList.push_back(locMin); - if (!leftBoundIsForward) E = E2; - } - return true; + E = ProcessBound(locMin.LeftBound, leftBoundIsForward); + if (E->OutIdx == Skip) { + E = ProcessBound(E, leftBoundIsForward); + } + + TEdge* E2 = ProcessBound(locMin.RightBound, !leftBoundIsForward); + if (E2->OutIdx == Skip) { + E2 = ProcessBound(E2, !leftBoundIsForward); + } + + if (locMin.LeftBound->OutIdx == Skip) { + locMin.LeftBound = 0; + } + else if (locMin.RightBound->OutIdx == Skip) { + locMin.RightBound = 0; + } + m_MinimaList.push_back(locMin); + if (!leftBoundIsForward) { + E = E2; + } + } + return true; } //------------------------------------------------------------------------------ -bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed) +bool ClipperBase::AddPaths(const Paths& ppg, PolyType PolyTyp, bool Closed) { - bool result = false; - for (Paths::size_type i = 0; i < ppg.size(); ++i) - if (AddPath(ppg[i], PolyTyp, Closed)) result = true; - return result; + bool result = false; + for (Paths::size_type i = 0; i < ppg.size(); ++i) { + if (AddPath(ppg[i], PolyTyp, Closed)) { + result = true; + } + } + return result; } //------------------------------------------------------------------------------ void ClipperBase::Clear() { - DisposeLocalMinimaList(); - for (EdgeList::size_type i = 0; i < m_edges.size(); ++i) - { - //for each edge array in turn, find the first used edge and - //check for and remove any hiddenPts in each edge in the array. - TEdge* edges = m_edges[i]; - delete [] edges; - } - m_edges.clear(); - m_UseFullRange = false; - m_HasOpenPaths = false; + DisposeLocalMinimaList(); + for (EdgeList::size_type i = 0; i < m_edges.size(); ++i) { + // for each edge array in turn, find the first used edge and + // check for and remove any hiddenPts in each edge in the array. + TEdge* edges = m_edges[i]; + delete[] edges; + } + m_edges.clear(); + m_UseFullRange = false; + m_HasOpenPaths = false; } //------------------------------------------------------------------------------ void ClipperBase::Reset() { - m_CurrentLM = m_MinimaList.begin(); - if (m_CurrentLM == m_MinimaList.end()) //ie nothing to process - return; - std::sort(m_MinimaList.begin(), m_MinimaList.end(), LocMinSorter()); - - //reset all edges ... - for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm) - { - TEdge* e = lm->LeftBound; - if (e) - { - e->Curr = e->Bot; - e->Side = esLeft; - e->OutIdx = Unassigned; + m_CurrentLM = m_MinimaList.begin(); + if (m_CurrentLM == m_MinimaList.end()) { // ie nothing to process + return; } + std::sort(m_MinimaList.begin(), m_MinimaList.end(), LocMinSorter()); - e = lm->RightBound; - if (e) - { - e->Curr = e->Bot; - e->Side = esRight; - e->OutIdx = Unassigned; + // reset all edges ... + for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm) { + TEdge* e = lm->LeftBound; + if (e) { + e->Curr = e->Bot; + e->Side = esLeft; + e->OutIdx = Unassigned; + } + + e = lm->RightBound; + if (e) { + e->Curr = e->Bot; + e->Side = esRight; + e->OutIdx = Unassigned; + } } - } } //------------------------------------------------------------------------------ void ClipperBase::DisposeLocalMinimaList() { - m_MinimaList.clear(); - m_CurrentLM = m_MinimaList.begin(); + m_MinimaList.clear(); + m_CurrentLM = m_MinimaList.begin(); } //------------------------------------------------------------------------------ void ClipperBase::PopLocalMinima() { - if (m_CurrentLM == m_MinimaList.end()) - return; - ++m_CurrentLM; + if (m_CurrentLM == m_MinimaList.end()) { + return; + } + ++m_CurrentLM; } //------------------------------------------------------------------------------ IntRect ClipperBase::GetBounds() { - IntRect result; - MinimaList::iterator lm = m_MinimaList.begin(); - if (lm == m_MinimaList.end()) - { - result.left = result.top = result.right = result.bottom = 0; - return result; - } - result.left = lm->LeftBound->Bot.X; - result.top = lm->LeftBound->Bot.Y; - result.right = lm->LeftBound->Bot.X; - result.bottom = lm->LeftBound->Bot.Y; - while (lm != m_MinimaList.end()) - { - result.bottom = std::max(result.bottom, lm->LeftBound->Bot.Y); - TEdge* e = lm->LeftBound; - for (;;) { - TEdge* bottomE = e; - while (e->NextInLML) - { - if (e->Bot.X < result.left) result.left = e->Bot.X; - if (e->Bot.X > result.right) result.right = e->Bot.X; - e = e->NextInLML; - } - result.left = std::min(result.left, e->Bot.X); - result.right = std::max(result.right, e->Bot.X); - result.left = std::min(result.left, e->Top.X); - result.right = std::max(result.right, e->Top.X); - result.top = std::min(result.top, e->Top.Y); - if (bottomE == lm->LeftBound) e = lm->RightBound; - else break; + IntRect result; + MinimaList::iterator lm = m_MinimaList.begin(); + if (lm == m_MinimaList.end()) { + result.left = result.top = result.right = result.bottom = 0; + return result; } - ++lm; - } - return result; + result.left = lm->LeftBound->Bot.X; + result.top = lm->LeftBound->Bot.Y; + result.right = lm->LeftBound->Bot.X; + result.bottom = lm->LeftBound->Bot.Y; + while (lm != m_MinimaList.end()) { + result.bottom = std::max(result.bottom, lm->LeftBound->Bot.Y); + TEdge* e = lm->LeftBound; + for (;;) { + TEdge* bottomE = e; + while (e->NextInLML) { + if (e->Bot.X < result.left) { + result.left = e->Bot.X; + } + if (e->Bot.X > result.right) { + result.right = e->Bot.X; + } + e = e->NextInLML; + } + result.left = std::min(result.left, e->Bot.X); + result.right = std::max(result.right, e->Bot.X); + result.left = std::min(result.left, e->Top.X); + result.right = std::max(result.right, e->Top.X); + result.top = std::min(result.top, e->Top.Y); + if (bottomE == lm->LeftBound) { + e = lm->RightBound; + } + else { + break; + } + } + ++lm; + } + return result; } //------------------------------------------------------------------------------ // TClipper methods ... //------------------------------------------------------------------------------ -Clipper::Clipper(int initOptions) : ClipperBase() //constructor +Clipper::Clipper(int initOptions) + : ClipperBase() // constructor { - m_ActiveEdges = 0; - m_SortedEdges = 0; - m_ExecuteLocked = false; - m_UseFullRange = false; - m_ReverseOutput = ((initOptions & ioReverseSolution) != 0); - m_StrictSimple = ((initOptions & ioStrictlySimple) != 0); - m_PreserveCollinear = ((initOptions & ioPreserveCollinear) != 0); - m_HasOpenPaths = false; -#ifdef use_xyz - m_ZFill = 0; + m_ActiveEdges = 0; + m_SortedEdges = 0; + m_ExecuteLocked = false; + m_UseFullRange = false; + m_ReverseOutput = ((initOptions & ioReverseSolution) != 0); + m_StrictSimple = ((initOptions & ioStrictlySimple) != 0); + m_PreserveCollinear = ((initOptions & ioPreserveCollinear) != 0); + m_HasOpenPaths = false; +#ifdef use_xyz + m_ZFill = 0; #endif - m_ClipType = ctIntersection; - m_ClipFillType = pftEvenOdd; - m_SubjFillType = pftEvenOdd; - m_UsingPolyTree = false; + m_ClipType = ctIntersection; + m_ClipFillType = pftEvenOdd; + m_SubjFillType = pftEvenOdd; + m_UsingPolyTree = false; } //------------------------------------------------------------------------------ -Clipper::~Clipper() //destructor +Clipper::~Clipper() // destructor { - Clear(); + Clear(); } //------------------------------------------------------------------------------ -#ifdef use_xyz +#ifdef use_xyz void Clipper::ZFillFunction(ZFillCallback zFillFunc) -{ - m_ZFill = zFillFunc; +{ + m_ZFill = zFillFunc; } //------------------------------------------------------------------------------ #endif void Clipper::Reset() { - ClipperBase::Reset(); - m_Scanbeam = ScanbeamList(); - m_ActiveEdges = 0; - m_SortedEdges = 0; - for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm) - InsertScanbeam(lm->Y); + ClipperBase::Reset(); + m_Scanbeam = ScanbeamList(); + m_ActiveEdges = 0; + m_SortedEdges = 0; + for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm) { + InsertScanbeam(lm->Y); + } } //------------------------------------------------------------------------------ -bool Clipper::Execute(ClipType clipType, Paths &solution, - PolyFillType subjFillType, PolyFillType clipFillType) +bool Clipper::Execute(ClipType clipType, + Paths& solution, + PolyFillType subjFillType, + PolyFillType clipFillType) { - if( m_ExecuteLocked ) - return false; - if (m_HasOpenPaths) - throw clipperException("Error: PolyTree struct is need for open path clipping."); - m_ExecuteLocked = true; - solution.resize(0); - m_SubjFillType = subjFillType; - m_ClipFillType = clipFillType; - m_ClipType = clipType; - m_UsingPolyTree = false; - bool succeeded = ExecuteInternal(); - if (succeeded) BuildResult(solution); - DisposeAllOutRecs(); - m_ExecuteLocked = false; - return succeeded; + if (m_ExecuteLocked) { + return false; + } + if (m_HasOpenPaths) { + throw clipperException("Error: PolyTree struct is need for open path clipping."); + } + m_ExecuteLocked = true; + solution.resize(0); + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + m_UsingPolyTree = false; + bool succeeded = ExecuteInternal(); + if (succeeded) { + BuildResult(solution); + } + DisposeAllOutRecs(); + m_ExecuteLocked = false; + return succeeded; } //------------------------------------------------------------------------------ -bool Clipper::Execute(ClipType clipType, PolyTree& polytree, - PolyFillType subjFillType, PolyFillType clipFillType) +bool Clipper::Execute(ClipType clipType, + PolyTree& polytree, + PolyFillType subjFillType, + PolyFillType clipFillType) { - if( m_ExecuteLocked ) - return false; - m_ExecuteLocked = true; - m_SubjFillType = subjFillType; - m_ClipFillType = clipFillType; - m_ClipType = clipType; - m_UsingPolyTree = true; - bool succeeded = ExecuteInternal(); - if (succeeded) BuildResult2(polytree); - DisposeAllOutRecs(); - m_ExecuteLocked = false; - return succeeded; + if (m_ExecuteLocked) { + return false; + } + m_ExecuteLocked = true; + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + m_UsingPolyTree = true; + bool succeeded = ExecuteInternal(); + if (succeeded) { + BuildResult2(polytree); + } + DisposeAllOutRecs(); + m_ExecuteLocked = false; + return succeeded; } //------------------------------------------------------------------------------ -void Clipper::FixHoleLinkage(OutRec &outrec) +void Clipper::FixHoleLinkage(OutRec& outrec) { - //skip OutRecs that (a) contain outermost polygons or - //(b) already have the correct owner/child linkage ... - if (!outrec.FirstLeft || - (outrec.IsHole != outrec.FirstLeft->IsHole && - outrec.FirstLeft->Pts)) return; + // skip OutRecs that (a) contain outermost polygons or + //(b) already have the correct owner/child linkage ... + if (!outrec.FirstLeft || (outrec.IsHole != outrec.FirstLeft->IsHole && outrec.FirstLeft->Pts)) { + return; + } - OutRec* orfl = outrec.FirstLeft; - while (orfl && ((orfl->IsHole == outrec.IsHole) || !orfl->Pts)) - orfl = orfl->FirstLeft; - outrec.FirstLeft = orfl; + OutRec* orfl = outrec.FirstLeft; + while (orfl && ((orfl->IsHole == outrec.IsHole) || !orfl->Pts)) { + orfl = orfl->FirstLeft; + } + outrec.FirstLeft = orfl; } //------------------------------------------------------------------------------ bool Clipper::ExecuteInternal() { - bool succeeded = true; - try { - Reset(); - if (m_CurrentLM == m_MinimaList.end()) - return true; - cInt botY = PopScanbeam(); - do { - InsertLocalMinimaIntoAEL(botY); - ClearGhostJoins(); - ProcessHorizontals(false); - if (m_Scanbeam.empty()) break; - cInt topY = PopScanbeam(); - succeeded = ProcessIntersections(topY); - if (!succeeded) break; - ProcessEdgesAtTopOfScanbeam(topY); - botY = topY; - } while (!m_Scanbeam.empty() || m_CurrentLM != m_MinimaList.end()); - } - catch(...) - { - succeeded = false; - } - - if (succeeded) - { - //fix orientations ... - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - { - OutRec *outRec = m_PolyOuts[i]; - if (!outRec->Pts || outRec->IsOpen) continue; - if ((outRec->IsHole ^ m_ReverseOutput) == (Area(*outRec) > 0)) - ReversePolyPtLinks(outRec->Pts); + bool succeeded = true; + try { + Reset(); + if (m_CurrentLM == m_MinimaList.end()) { + return true; + } + cInt botY = PopScanbeam(); + do { + InsertLocalMinimaIntoAEL(botY); + ClearGhostJoins(); + ProcessHorizontals(false); + if (m_Scanbeam.empty()) { + break; + } + cInt topY = PopScanbeam(); + succeeded = ProcessIntersections(topY); + if (!succeeded) { + break; + } + ProcessEdgesAtTopOfScanbeam(topY); + botY = topY; + } while (!m_Scanbeam.empty() || m_CurrentLM != m_MinimaList.end()); + } + catch (...) { + succeeded = false; } - if (!m_Joins.empty()) JoinCommonEdges(); + if (succeeded) { + // fix orientations ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { + OutRec* outRec = m_PolyOuts[i]; + if (!outRec->Pts || outRec->IsOpen) { + continue; + } + if ((outRec->IsHole ^ m_ReverseOutput) == (Area(*outRec) > 0)) { + ReversePolyPtLinks(outRec->Pts); + } + } - //unfortunately FixupOutPolygon() must be done after JoinCommonEdges() - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - { - OutRec *outRec = m_PolyOuts[i]; - if (outRec->Pts && !outRec->IsOpen) - FixupOutPolygon(*outRec); + if (!m_Joins.empty()) { + JoinCommonEdges(); + } + + // unfortunately FixupOutPolygon() must be done after JoinCommonEdges() + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { + OutRec* outRec = m_PolyOuts[i]; + if (outRec->Pts && !outRec->IsOpen) { + FixupOutPolygon(*outRec); + } + } + + if (m_StrictSimple) { + DoSimplePolygons(); + } } - if (m_StrictSimple) DoSimplePolygons(); - } - - ClearJoins(); - ClearGhostJoins(); - return succeeded; + ClearJoins(); + ClearGhostJoins(); + return succeeded; } //------------------------------------------------------------------------------ void Clipper::InsertScanbeam(const cInt Y) { - //if (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) return;// avoid duplicates. - m_Scanbeam.push(Y); + // if (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) return;// avoid duplicates. + m_Scanbeam.push(Y); } //------------------------------------------------------------------------------ cInt Clipper::PopScanbeam() { - const cInt Y = m_Scanbeam.top(); - m_Scanbeam.pop(); - while (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) { m_Scanbeam.pop(); } // Pop duplicates. - return Y; + const cInt Y = m_Scanbeam.top(); + m_Scanbeam.pop(); + while (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) { + m_Scanbeam.pop(); + } // Pop duplicates. + return Y; } //------------------------------------------------------------------------------ -void Clipper::DisposeAllOutRecs(){ - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - DisposeOutRec(i); - m_PolyOuts.clear(); +void Clipper::DisposeAllOutRecs() +{ + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { + DisposeOutRec(i); + } + m_PolyOuts.clear(); } //------------------------------------------------------------------------------ void Clipper::DisposeOutRec(PolyOutList::size_type index) { - OutRec *outRec = m_PolyOuts[index]; - if (outRec->Pts) DisposeOutPts(outRec->Pts); - delete outRec; - m_PolyOuts[index] = 0; + OutRec* outRec = m_PolyOuts[index]; + if (outRec->Pts) { + DisposeOutPts(outRec->Pts); + } + delete outRec; + m_PolyOuts[index] = 0; } //------------------------------------------------------------------------------ -void Clipper::SetWindingCount(TEdge &edge) +void Clipper::SetWindingCount(TEdge& edge) { - TEdge *e = edge.PrevInAEL; - //find the edge of the same polytype that immediately precedes 'edge' in AEL - while (e && ((e->PolyTyp != edge.PolyTyp) || (e->WindDelta == 0))) e = e->PrevInAEL; - if (!e) - { - edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta); - edge.WindCnt2 = 0; - e = m_ActiveEdges; //ie get ready to calc WindCnt2 - } - else if (edge.WindDelta == 0 && m_ClipType != ctUnion) - { - edge.WindCnt = 1; - edge.WindCnt2 = e->WindCnt2; - e = e->NextInAEL; //ie get ready to calc WindCnt2 - } - else if (IsEvenOddFillType(edge)) - { - //EvenOdd filling ... - if (edge.WindDelta == 0) - { - //are we inside a subj polygon ... - bool Inside = true; - TEdge *e2 = e->PrevInAEL; - while (e2) - { - if (e2->PolyTyp == e->PolyTyp && e2->WindDelta != 0) - Inside = !Inside; - e2 = e2->PrevInAEL; - } - edge.WindCnt = (Inside ? 0 : 1); + TEdge* e = edge.PrevInAEL; + // find the edge of the same polytype that immediately precedes 'edge' in AEL + while (e && ((e->PolyTyp != edge.PolyTyp) || (e->WindDelta == 0))) { + e = e->PrevInAEL; } - else - { - edge.WindCnt = edge.WindDelta; - } - edge.WindCnt2 = e->WindCnt2; - e = e->NextInAEL; //ie get ready to calc WindCnt2 - } - else - { - //nonZero, Positive or Negative filling ... - if (e->WindCnt * e->WindDelta < 0) - { - //prev edge is 'decreasing' WindCount (WC) toward zero - //so we're outside the previous polygon ... - if (Abs(e->WindCnt) > 1) - { - //outside prev poly but still inside another. - //when reversing direction of prev poly use the same WC - if (e->WindDelta * edge.WindDelta < 0) edge.WindCnt = e->WindCnt; - //otherwise continue to 'decrease' WC ... - else edge.WindCnt = e->WindCnt + edge.WindDelta; - } - else - //now outside all polys of same polytype so set own WC ... + if (!e) { edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta); - } else - { - //prev edge is 'increasing' WindCount (WC) away from zero - //so we're inside the previous polygon ... - if (edge.WindDelta == 0) - edge.WindCnt = (e->WindCnt < 0 ? e->WindCnt - 1 : e->WindCnt + 1); - //if wind direction is reversing prev then use same WC - else if (e->WindDelta * edge.WindDelta < 0) edge.WindCnt = e->WindCnt; - //otherwise add to WC ... - else edge.WindCnt = e->WindCnt + edge.WindDelta; + edge.WindCnt2 = 0; + e = m_ActiveEdges; // ie get ready to calc WindCnt2 + } + else if (edge.WindDelta == 0 && m_ClipType != ctUnion) { + edge.WindCnt = 1; + edge.WindCnt2 = e->WindCnt2; + e = e->NextInAEL; // ie get ready to calc WindCnt2 + } + else if (IsEvenOddFillType(edge)) { + // EvenOdd filling ... + if (edge.WindDelta == 0) { + // are we inside a subj polygon ... + bool Inside = true; + TEdge* e2 = e->PrevInAEL; + while (e2) { + if (e2->PolyTyp == e->PolyTyp && e2->WindDelta != 0) { + Inside = !Inside; + } + e2 = e2->PrevInAEL; + } + edge.WindCnt = (Inside ? 0 : 1); + } + else { + edge.WindCnt = edge.WindDelta; + } + edge.WindCnt2 = e->WindCnt2; + e = e->NextInAEL; // ie get ready to calc WindCnt2 + } + else { + // nonZero, Positive or Negative filling ... + if (e->WindCnt * e->WindDelta < 0) { + // prev edge is 'decreasing' WindCount (WC) toward zero + // so we're outside the previous polygon ... + if (Abs(e->WindCnt) > 1) { + // outside prev poly but still inside another. + // when reversing direction of prev poly use the same WC + if (e->WindDelta * edge.WindDelta < 0) { + edge.WindCnt = e->WindCnt; + } + // otherwise continue to 'decrease' WC ... + else { + edge.WindCnt = e->WindCnt + edge.WindDelta; + } + } + else { + // now outside all polys of same polytype so set own WC ... + edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta); + } + } + else { + // prev edge is 'increasing' WindCount (WC) away from zero + // so we're inside the previous polygon ... + if (edge.WindDelta == 0) { + edge.WindCnt = (e->WindCnt < 0 ? e->WindCnt - 1 : e->WindCnt + 1); + } + // if wind direction is reversing prev then use same WC + else if (e->WindDelta * edge.WindDelta < 0) { + edge.WindCnt = e->WindCnt; + } + // otherwise add to WC ... + else { + edge.WindCnt = e->WindCnt + edge.WindDelta; + } + } + edge.WindCnt2 = e->WindCnt2; + e = e->NextInAEL; // ie get ready to calc WindCnt2 } - edge.WindCnt2 = e->WindCnt2; - e = e->NextInAEL; //ie get ready to calc WindCnt2 - } - //update WindCnt2 ... - if (IsEvenOddAltFillType(edge)) - { - //EvenOdd filling ... - while (e != &edge) - { - if (e->WindDelta != 0) - edge.WindCnt2 = (edge.WindCnt2 == 0 ? 1 : 0); - e = e->NextInAEL; + // update WindCnt2 ... + if (IsEvenOddAltFillType(edge)) { + // EvenOdd filling ... + while (e != &edge) { + if (e->WindDelta != 0) { + edge.WindCnt2 = (edge.WindCnt2 == 0 ? 1 : 0); + } + e = e->NextInAEL; + } } - } else - { - //nonZero, Positive or Negative filling ... - while ( e != &edge ) - { - edge.WindCnt2 += e->WindDelta; - e = e->NextInAEL; + else { + // nonZero, Positive or Negative filling ... + while (e != &edge) { + edge.WindCnt2 += e->WindDelta; + e = e->NextInAEL; + } } - } } //------------------------------------------------------------------------------ bool Clipper::IsEvenOddFillType(const TEdge& edge) const { - if (edge.PolyTyp == ptSubject) - return m_SubjFillType == pftEvenOdd; else - return m_ClipFillType == pftEvenOdd; + if (edge.PolyTyp == ptSubject) { + return m_SubjFillType == pftEvenOdd; + } + else { + return m_ClipFillType == pftEvenOdd; + } } //------------------------------------------------------------------------------ bool Clipper::IsEvenOddAltFillType(const TEdge& edge) const { - if (edge.PolyTyp == ptSubject) - return m_ClipFillType == pftEvenOdd; else - return m_SubjFillType == pftEvenOdd; + if (edge.PolyTyp == ptSubject) { + return m_ClipFillType == pftEvenOdd; + } + else { + return m_SubjFillType == pftEvenOdd; + } } //------------------------------------------------------------------------------ bool Clipper::IsContributing(const TEdge& edge) const { - PolyFillType pft, pft2; - if (edge.PolyTyp == ptSubject) - { - pft = m_SubjFillType; - pft2 = m_ClipFillType; - } else - { - pft = m_ClipFillType; - pft2 = m_SubjFillType; - } + PolyFillType pft, pft2; + if (edge.PolyTyp == ptSubject) { + pft = m_SubjFillType; + pft2 = m_ClipFillType; + } + else { + pft = m_ClipFillType; + pft2 = m_SubjFillType; + } - switch(pft) - { - case pftEvenOdd: - //return false if a subj line has been flagged as inside a subj polygon - if (edge.WindDelta == 0 && edge.WindCnt != 1) - return false; - break; - case pftNonZero: - if (Abs(edge.WindCnt) != 1) - return false; - break; - case pftPositive: - if (edge.WindCnt != 1) - return false; - break; - default: //pftNegative - if (edge.WindCnt != -1) - return false; - } + switch (pft) { + case pftEvenOdd: + // return false if a subj line has been flagged as inside a subj polygon + if (edge.WindDelta == 0 && edge.WindCnt != 1) { + return false; + } + break; + case pftNonZero: + if (Abs(edge.WindCnt) != 1) { + return false; + } + break; + case pftPositive: + if (edge.WindCnt != 1) { + return false; + } + break; + default: // pftNegative + if (edge.WindCnt != -1) { + return false; + } + } - switch(m_ClipType) - { - case ctIntersection: - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 != 0); - case pftPositive: - return (edge.WindCnt2 > 0); - default: - return (edge.WindCnt2 < 0); - } - break; - case ctUnion: - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 == 0); - case pftPositive: - return (edge.WindCnt2 <= 0); - default: - return (edge.WindCnt2 >= 0); - } - break; - case ctDifference: - if (edge.PolyTyp == ptSubject) - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 == 0); - case pftPositive: - return (edge.WindCnt2 <= 0); - default: - return (edge.WindCnt2 >= 0); - } - else - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 != 0); - case pftPositive: - return (edge.WindCnt2 > 0); - default: - return (edge.WindCnt2 < 0); - } - break; - case ctXor: - if (edge.WindDelta == 0) //XOr always contributing unless open - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 == 0); - case pftPositive: - return (edge.WindCnt2 <= 0); - default: - return (edge.WindCnt2 >= 0); - } - else - return true; - break; - default: - return true; - } + switch (m_ClipType) { + case ctIntersection: + switch (pft2) { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 != 0); + case pftPositive: + return (edge.WindCnt2 > 0); + default: + return (edge.WindCnt2 < 0); + } + break; + case ctUnion: + switch (pft2) { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 == 0); + case pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + break; + case ctDifference: + if (edge.PolyTyp == ptSubject) { + switch (pft2) { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 == 0); + case pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + } + else { + switch (pft2) { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 != 0); + case pftPositive: + return (edge.WindCnt2 > 0); + default: + return (edge.WindCnt2 < 0); + } + } + break; + case ctXor: + if (edge.WindDelta == 0) { // XOr always contributing unless open + switch (pft2) { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 == 0); + case pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + } + else { + return true; + } + break; + default: + return true; + } } //------------------------------------------------------------------------------ -OutPt* Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt) +OutPt* Clipper::AddLocalMinPoly(TEdge* e1, TEdge* e2, const IntPoint& Pt) { - OutPt* result; - TEdge *e, *prevE; - if (IsHorizontal(*e2) || ( e1->Dx > e2->Dx )) - { - result = AddOutPt(e1, Pt); - e2->OutIdx = e1->OutIdx; - e1->Side = esLeft; - e2->Side = esRight; - e = e1; - if (e->PrevInAEL == e2) - prevE = e2->PrevInAEL; - else - prevE = e->PrevInAEL; - } else - { - result = AddOutPt(e2, Pt); - e1->OutIdx = e2->OutIdx; - e1->Side = esRight; - e2->Side = esLeft; - e = e2; - if (e->PrevInAEL == e1) - prevE = e1->PrevInAEL; - else - prevE = e->PrevInAEL; - } + OutPt* result; + TEdge *e, *prevE; + if (IsHorizontal(*e2) || (e1->Dx > e2->Dx)) { + result = AddOutPt(e1, Pt); + e2->OutIdx = e1->OutIdx; + e1->Side = esLeft; + e2->Side = esRight; + e = e1; + if (e->PrevInAEL == e2) { + prevE = e2->PrevInAEL; + } + else { + prevE = e->PrevInAEL; + } + } + else { + result = AddOutPt(e2, Pt); + e1->OutIdx = e2->OutIdx; + e1->Side = esRight; + e2->Side = esLeft; + e = e2; + if (e->PrevInAEL == e1) { + prevE = e1->PrevInAEL; + } + else { + prevE = e->PrevInAEL; + } + } - if (prevE && prevE->OutIdx >= 0 && - (TopX(*prevE, Pt.Y) == TopX(*e, Pt.Y)) && - SlopesEqual(*e, *prevE, m_UseFullRange) && - (e->WindDelta != 0) && (prevE->WindDelta != 0)) - { - OutPt* outPt = AddOutPt(prevE, Pt); - AddJoin(result, outPt, e->Top); - } - return result; + if (prevE && prevE->OutIdx >= 0 && (TopX(*prevE, Pt.Y) == TopX(*e, Pt.Y)) + && SlopesEqual(*e, *prevE, m_UseFullRange) && (e->WindDelta != 0) + && (prevE->WindDelta != 0)) { + OutPt* outPt = AddOutPt(prevE, Pt); + AddJoin(result, outPt, e->Top); + } + return result; } //------------------------------------------------------------------------------ -void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt) +void Clipper::AddLocalMaxPoly(TEdge* e1, TEdge* e2, const IntPoint& Pt) { - AddOutPt( e1, Pt ); - if (e2->WindDelta == 0) AddOutPt(e2, Pt); - if( e1->OutIdx == e2->OutIdx ) - { - e1->OutIdx = Unassigned; - e2->OutIdx = Unassigned; - } - else if (e1->OutIdx < e2->OutIdx) - AppendPolygon(e1, e2); - else - AppendPolygon(e2, e1); + AddOutPt(e1, Pt); + if (e2->WindDelta == 0) { + AddOutPt(e2, Pt); + } + if (e1->OutIdx == e2->OutIdx) { + e1->OutIdx = Unassigned; + e2->OutIdx = Unassigned; + } + else if (e1->OutIdx < e2->OutIdx) { + AppendPolygon(e1, e2); + } + else { + AppendPolygon(e2, e1); + } } //------------------------------------------------------------------------------ -void Clipper::AddEdgeToSEL(TEdge *edge) +void Clipper::AddEdgeToSEL(TEdge* edge) { - //SEL pointers in PEdge are reused to build a list of horizontal edges. - //However, we don't need to worry about order with horizontal edge processing. - if( !m_SortedEdges ) - { - m_SortedEdges = edge; - edge->PrevInSEL = 0; - edge->NextInSEL = 0; - } - else - { - edge->NextInSEL = m_SortedEdges; - edge->PrevInSEL = 0; - m_SortedEdges->PrevInSEL = edge; - m_SortedEdges = edge; - } + // SEL pointers in PEdge are reused to build a list of horizontal edges. + // However, we don't need to worry about order with horizontal edge processing. + if (!m_SortedEdges) { + m_SortedEdges = edge; + edge->PrevInSEL = 0; + edge->NextInSEL = 0; + } + else { + edge->NextInSEL = m_SortedEdges; + edge->PrevInSEL = 0; + m_SortedEdges->PrevInSEL = edge; + m_SortedEdges = edge; + } } //------------------------------------------------------------------------------ void Clipper::CopyAELToSEL() { - TEdge* e = m_ActiveEdges; - m_SortedEdges = e; - while ( e ) - { - e->PrevInSEL = e->PrevInAEL; - e->NextInSEL = e->NextInAEL; - e = e->NextInAEL; - } + TEdge* e = m_ActiveEdges; + m_SortedEdges = e; + while (e) { + e->PrevInSEL = e->PrevInAEL; + e->NextInSEL = e->NextInAEL; + e = e->NextInAEL; + } } //------------------------------------------------------------------------------ -void Clipper::AddJoin(OutPt *op1, OutPt *op2, const IntPoint OffPt) +void Clipper::AddJoin(OutPt* op1, OutPt* op2, const IntPoint OffPt) { - Join* j = new Join; - j->OutPt1 = op1; - j->OutPt2 = op2; - j->OffPt = OffPt; - m_Joins.push_back(j); + Join* j = new Join; + j->OutPt1 = op1; + j->OutPt2 = op2; + j->OffPt = OffPt; + m_Joins.push_back(j); } //------------------------------------------------------------------------------ void Clipper::ClearJoins() { - for (JoinList::size_type i = 0; i < m_Joins.size(); i++) - delete m_Joins[i]; - m_Joins.resize(0); + for (JoinList::size_type i = 0; i < m_Joins.size(); i++) { + delete m_Joins[i]; + } + m_Joins.resize(0); } //------------------------------------------------------------------------------ void Clipper::ClearGhostJoins() { - for (JoinList::size_type i = 0; i < m_GhostJoins.size(); i++) - delete m_GhostJoins[i]; - m_GhostJoins.resize(0); + for (JoinList::size_type i = 0; i < m_GhostJoins.size(); i++) { + delete m_GhostJoins[i]; + } + m_GhostJoins.resize(0); } //------------------------------------------------------------------------------ -void Clipper::AddGhostJoin(OutPt *op, const IntPoint OffPt) +void Clipper::AddGhostJoin(OutPt* op, const IntPoint OffPt) { - Join* j = new Join; - j->OutPt1 = op; - j->OutPt2 = 0; - j->OffPt = OffPt; - m_GhostJoins.push_back(j); + Join* j = new Join; + j->OutPt1 = op; + j->OutPt2 = 0; + j->OffPt = OffPt; + m_GhostJoins.push_back(j); } //------------------------------------------------------------------------------ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY) { - while (m_CurrentLM != m_MinimaList.end() && (m_CurrentLM->Y == botY)) - { - TEdge* lb = m_CurrentLM->LeftBound; - TEdge* rb = m_CurrentLM->RightBound; - PopLocalMinima(); - OutPt *Op1 = 0; - if (!lb) - { - //nb: don't insert LB into either AEL or SEL - InsertEdgeIntoAEL(rb, 0); - SetWindingCount(*rb); - if (IsContributing(*rb)) - Op1 = AddOutPt(rb, rb->Bot); - } - else if (!rb) - { - InsertEdgeIntoAEL(lb, 0); - SetWindingCount(*lb); - if (IsContributing(*lb)) - Op1 = AddOutPt(lb, lb->Bot); - InsertScanbeam(lb->Top.Y); - } - else - { - InsertEdgeIntoAEL(lb, 0); - InsertEdgeIntoAEL(rb, lb); - SetWindingCount( *lb ); - rb->WindCnt = lb->WindCnt; - rb->WindCnt2 = lb->WindCnt2; - if (IsContributing(*lb)) - Op1 = AddLocalMinPoly(lb, rb, lb->Bot); - InsertScanbeam(lb->Top.Y); - } - - if (rb) - { - if(IsHorizontal(*rb)) AddEdgeToSEL(rb); - else InsertScanbeam( rb->Top.Y ); - } - - if (!lb || !rb) continue; - - //if any output polygons share an edge, they'll need joining later ... - if (Op1 && IsHorizontal(*rb) && - !m_GhostJoins.empty() && (rb->WindDelta != 0)) - { - for (JoinList::size_type i = 0; i < m_GhostJoins.size(); ++i) - { - Join* jr = m_GhostJoins[i]; - //if the horizontal Rb and a 'ghost' horizontal overlap, then convert - //the 'ghost' join to a real join ready for later ... - if (HorzSegmentsOverlap(jr->OutPt1->Pt.X, jr->OffPt.X, rb->Bot.X, rb->Top.X)) - AddJoin(jr->OutPt1, Op1, jr->OffPt); - } - } - - if (lb->OutIdx >= 0 && lb->PrevInAEL && - lb->PrevInAEL->Curr.X == lb->Bot.X && - lb->PrevInAEL->OutIdx >= 0 && - SlopesEqual(*lb->PrevInAEL, *lb, m_UseFullRange) && - (lb->WindDelta != 0) && (lb->PrevInAEL->WindDelta != 0)) - { - OutPt *Op2 = AddOutPt(lb->PrevInAEL, lb->Bot); - AddJoin(Op1, Op2, lb->Top); - } - - if(lb->NextInAEL != rb) - { - - if (rb->OutIdx >= 0 && rb->PrevInAEL->OutIdx >= 0 && - SlopesEqual(*rb->PrevInAEL, *rb, m_UseFullRange) && - (rb->WindDelta != 0) && (rb->PrevInAEL->WindDelta != 0)) - { - OutPt *Op2 = AddOutPt(rb->PrevInAEL, rb->Bot); - AddJoin(Op1, Op2, rb->Top); - } - - TEdge* e = lb->NextInAEL; - if (e) - { - while( e != rb ) - { - //nb: For calculating winding counts etc, IntersectEdges() assumes - //that param1 will be to the Right of param2 ABOVE the intersection ... - IntersectEdges(rb , e , lb->Curr); //order important here - e = e->NextInAEL; + while (m_CurrentLM != m_MinimaList.end() && (m_CurrentLM->Y == botY)) { + TEdge* lb = m_CurrentLM->LeftBound; + TEdge* rb = m_CurrentLM->RightBound; + PopLocalMinima(); + OutPt* Op1 = 0; + if (!lb) { + // nb: don't insert LB into either AEL or SEL + InsertEdgeIntoAEL(rb, 0); + SetWindingCount(*rb); + if (IsContributing(*rb)) { + Op1 = AddOutPt(rb, rb->Bot); + } + } + else if (!rb) { + InsertEdgeIntoAEL(lb, 0); + SetWindingCount(*lb); + if (IsContributing(*lb)) { + Op1 = AddOutPt(lb, lb->Bot); + } + InsertScanbeam(lb->Top.Y); + } + else { + InsertEdgeIntoAEL(lb, 0); + InsertEdgeIntoAEL(rb, lb); + SetWindingCount(*lb); + rb->WindCnt = lb->WindCnt; + rb->WindCnt2 = lb->WindCnt2; + if (IsContributing(*lb)) { + Op1 = AddLocalMinPoly(lb, rb, lb->Bot); + } + InsertScanbeam(lb->Top.Y); + } + + if (rb) { + if (IsHorizontal(*rb)) { + AddEdgeToSEL(rb); + } + else { + InsertScanbeam(rb->Top.Y); + } + } + + if (!lb || !rb) { + continue; + } + + // if any output polygons share an edge, they'll need joining later ... + if (Op1 && IsHorizontal(*rb) && !m_GhostJoins.empty() && (rb->WindDelta != 0)) { + for (JoinList::size_type i = 0; i < m_GhostJoins.size(); ++i) { + Join* jr = m_GhostJoins[i]; + // if the horizontal Rb and a 'ghost' horizontal overlap, then convert + // the 'ghost' join to a real join ready for later ... + if (HorzSegmentsOverlap(jr->OutPt1->Pt.X, jr->OffPt.X, rb->Bot.X, rb->Top.X)) { + AddJoin(jr->OutPt1, Op1, jr->OffPt); + } + } + } + + if (lb->OutIdx >= 0 && lb->PrevInAEL && lb->PrevInAEL->Curr.X == lb->Bot.X + && lb->PrevInAEL->OutIdx >= 0 && SlopesEqual(*lb->PrevInAEL, *lb, m_UseFullRange) + && (lb->WindDelta != 0) && (lb->PrevInAEL->WindDelta != 0)) { + OutPt* Op2 = AddOutPt(lb->PrevInAEL, lb->Bot); + AddJoin(Op1, Op2, lb->Top); + } + + if (lb->NextInAEL != rb) { + + if (rb->OutIdx >= 0 && rb->PrevInAEL->OutIdx >= 0 + && SlopesEqual(*rb->PrevInAEL, *rb, m_UseFullRange) && (rb->WindDelta != 0) + && (rb->PrevInAEL->WindDelta != 0)) { + OutPt* Op2 = AddOutPt(rb->PrevInAEL, rb->Bot); + AddJoin(Op1, Op2, rb->Top); + } + + TEdge* e = lb->NextInAEL; + if (e) { + while (e != rb) { + // nb: For calculating winding counts etc, IntersectEdges() assumes + // that param1 will be to the Right of param2 ABOVE the intersection ... + IntersectEdges(rb, e, lb->Curr); // order important here + e = e->NextInAEL; + } + } } - } } - - } } //------------------------------------------------------------------------------ -void Clipper::DeleteFromAEL(TEdge *e) +void Clipper::DeleteFromAEL(TEdge* e) { - TEdge* AelPrev = e->PrevInAEL; - TEdge* AelNext = e->NextInAEL; - if( !AelPrev && !AelNext && (e != m_ActiveEdges) ) //already deleted - return; - if( AelPrev ) AelPrev->NextInAEL = AelNext; - else m_ActiveEdges = AelNext; - if( AelNext ) AelNext->PrevInAEL = AelPrev; - e->NextInAEL = 0; - e->PrevInAEL = 0; + TEdge* AelPrev = e->PrevInAEL; + TEdge* AelNext = e->NextInAEL; + if (!AelPrev && !AelNext && (e != m_ActiveEdges)) { // already deleted + return; + } + if (AelPrev) { + AelPrev->NextInAEL = AelNext; + } + else { + m_ActiveEdges = AelNext; + } + if (AelNext) { + AelNext->PrevInAEL = AelPrev; + } + e->NextInAEL = 0; + e->PrevInAEL = 0; } //------------------------------------------------------------------------------ -void Clipper::DeleteFromSEL(TEdge *e) +void Clipper::DeleteFromSEL(TEdge* e) { - TEdge* SelPrev = e->PrevInSEL; - TEdge* SelNext = e->NextInSEL; - if( !SelPrev && !SelNext && (e != m_SortedEdges) ) //already deleted - return; - if( SelPrev ) SelPrev->NextInSEL = SelNext; - else m_SortedEdges = SelNext; - if( SelNext ) SelNext->PrevInSEL = SelPrev; - e->NextInSEL = 0; - e->PrevInSEL = 0; + TEdge* SelPrev = e->PrevInSEL; + TEdge* SelNext = e->NextInSEL; + if (!SelPrev && !SelNext && (e != m_SortedEdges)) { // already deleted + return; + } + if (SelPrev) { + SelPrev->NextInSEL = SelNext; + } + else { + m_SortedEdges = SelNext; + } + if (SelNext) { + SelNext->PrevInSEL = SelPrev; + } + e->NextInSEL = 0; + e->PrevInSEL = 0; } //------------------------------------------------------------------------------ #ifdef use_xyz void Clipper::SetZ(IntPoint& pt, TEdge& e1, TEdge& e2) { - if (pt.Z != 0 || !m_ZFill) - return; - else if (pt == e1.Bot) pt.Z = e1.Bot.Z; - else if (pt == e1.Top) pt.Z = e1.Top.Z; - else if (pt == e2.Bot) pt.Z = e2.Bot.Z; - else if (pt == e2.Top) pt.Z = e2.Top.Z; - else (*m_ZFill)(e1.Bot, e1.Top, e2.Bot, e2.Top, pt); + if (pt.Z != 0 || !m_ZFill) { + return; + } + else if (pt == e1.Bot) { + pt.Z = e1.Bot.Z; + } + else if (pt == e1.Top) { + pt.Z = e1.Top.Z; + } + else if (pt == e2.Bot) { + pt.Z = e2.Bot.Z; + } + else if (pt == e2.Top) { + pt.Z = e2.Top.Z; + } + else { + (*m_ZFill)(e1.Bot, e1.Top, e2.Bot, e2.Top, pt); + } } //------------------------------------------------------------------------------ #endif -void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &Pt) +void Clipper::IntersectEdges(TEdge* e1, TEdge* e2, IntPoint& Pt) { - bool e1Contributing = ( e1->OutIdx >= 0 ); - bool e2Contributing = ( e2->OutIdx >= 0 ); + bool e1Contributing = (e1->OutIdx >= 0); + bool e2Contributing = (e2->OutIdx >= 0); #ifdef use_xyz - SetZ(Pt, *e1, *e2); + SetZ(Pt, *e1, *e2); #endif #ifdef use_lines - //if either edge is on an OPEN path ... - if (e1->WindDelta == 0 || e2->WindDelta == 0) - { - //ignore subject-subject open path intersections UNLESS they - //are both open paths, AND they are both 'contributing maximas' ... - if (e1->WindDelta == 0 && e2->WindDelta == 0) - return; + // if either edge is on an OPEN path ... + if (e1->WindDelta == 0 || e2->WindDelta == 0) { + // ignore subject-subject open path intersections UNLESS they + // are both open paths, AND they are both 'contributing maximas' ... + if (e1->WindDelta == 0 && e2->WindDelta == 0) { + return; + } - //if intersecting a subj line with a subj poly ... - else if (e1->PolyTyp == e2->PolyTyp && - e1->WindDelta != e2->WindDelta && m_ClipType == ctUnion) - { - if (e1->WindDelta == 0) - { - if (e2Contributing) - { - AddOutPt(e1, Pt); - if (e1Contributing) e1->OutIdx = Unassigned; + // if intersecting a subj line with a subj poly ... + else if (e1->PolyTyp == e2->PolyTyp && e1->WindDelta != e2->WindDelta + && m_ClipType == ctUnion) { + if (e1->WindDelta == 0) { + if (e2Contributing) { + AddOutPt(e1, Pt); + if (e1Contributing) { + e1->OutIdx = Unassigned; + } + } + } + else { + if (e1Contributing) { + AddOutPt(e2, Pt); + if (e2Contributing) { + e2->OutIdx = Unassigned; + } + } + } } - } - else - { - if (e1Contributing) - { - AddOutPt(e2, Pt); - if (e2Contributing) e2->OutIdx = Unassigned; + else if (e1->PolyTyp != e2->PolyTyp) { + // toggle subj open path OutIdx on/off when Abs(clip.WndCnt) == 1 ... + if ((e1->WindDelta == 0) && abs(e2->WindCnt) == 1 + && (m_ClipType != ctUnion || e2->WindCnt2 == 0)) { + AddOutPt(e1, Pt); + if (e1Contributing) { + e1->OutIdx = Unassigned; + } + } + else if ((e2->WindDelta == 0) && (abs(e1->WindCnt) == 1) + && (m_ClipType != ctUnion || e1->WindCnt2 == 0)) { + AddOutPt(e2, Pt); + if (e2Contributing) { + e2->OutIdx = Unassigned; + } + } } - } + return; } - else if (e1->PolyTyp != e2->PolyTyp) - { - //toggle subj open path OutIdx on/off when Abs(clip.WndCnt) == 1 ... - if ((e1->WindDelta == 0) && abs(e2->WindCnt) == 1 && - (m_ClipType != ctUnion || e2->WindCnt2 == 0)) - { - AddOutPt(e1, Pt); - if (e1Contributing) e1->OutIdx = Unassigned; - } - else if ((e2->WindDelta == 0) && (abs(e1->WindCnt) == 1) && - (m_ClipType != ctUnion || e1->WindCnt2 == 0)) - { - AddOutPt(e2, Pt); - if (e2Contributing) e2->OutIdx = Unassigned; - } - } - return; - } #endif - //update winding counts... - //assumes that e1 will be to the Right of e2 ABOVE the intersection - if ( e1->PolyTyp == e2->PolyTyp ) - { - if ( IsEvenOddFillType( *e1) ) - { - int oldE1WindCnt = e1->WindCnt; - e1->WindCnt = e2->WindCnt; - e2->WindCnt = oldE1WindCnt; - } else - { - if (e1->WindCnt + e2->WindDelta == 0 ) e1->WindCnt = -e1->WindCnt; - else e1->WindCnt += e2->WindDelta; - if ( e2->WindCnt - e1->WindDelta == 0 ) e2->WindCnt = -e2->WindCnt; - else e2->WindCnt -= e1->WindDelta; + // update winding counts... + // assumes that e1 will be to the Right of e2 ABOVE the intersection + if (e1->PolyTyp == e2->PolyTyp) { + if (IsEvenOddFillType(*e1)) { + int oldE1WindCnt = e1->WindCnt; + e1->WindCnt = e2->WindCnt; + e2->WindCnt = oldE1WindCnt; + } + else { + if (e1->WindCnt + e2->WindDelta == 0) { + e1->WindCnt = -e1->WindCnt; + } + else { + e1->WindCnt += e2->WindDelta; + } + if (e2->WindCnt - e1->WindDelta == 0) { + e2->WindCnt = -e2->WindCnt; + } + else { + e2->WindCnt -= e1->WindDelta; + } + } } - } else - { - if (!IsEvenOddFillType(*e2)) e1->WindCnt2 += e2->WindDelta; - else e1->WindCnt2 = ( e1->WindCnt2 == 0 ) ? 1 : 0; - if (!IsEvenOddFillType(*e1)) e2->WindCnt2 -= e1->WindDelta; - else e2->WindCnt2 = ( e2->WindCnt2 == 0 ) ? 1 : 0; - } - - PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; - if (e1->PolyTyp == ptSubject) - { - e1FillType = m_SubjFillType; - e1FillType2 = m_ClipFillType; - } else - { - e1FillType = m_ClipFillType; - e1FillType2 = m_SubjFillType; - } - if (e2->PolyTyp == ptSubject) - { - e2FillType = m_SubjFillType; - e2FillType2 = m_ClipFillType; - } else - { - e2FillType = m_ClipFillType; - e2FillType2 = m_SubjFillType; - } - - cInt e1Wc, e2Wc; - switch (e1FillType) - { - case pftPositive: e1Wc = e1->WindCnt; break; - case pftNegative: e1Wc = -e1->WindCnt; break; - default: e1Wc = Abs(e1->WindCnt); - } - switch(e2FillType) - { - case pftPositive: e2Wc = e2->WindCnt; break; - case pftNegative: e2Wc = -e2->WindCnt; break; - default: e2Wc = Abs(e2->WindCnt); - } - - if ( e1Contributing && e2Contributing ) - { - if ((e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || - (e1->PolyTyp != e2->PolyTyp && m_ClipType != ctXor) ) - { - AddLocalMaxPoly(e1, e2, Pt); - } - else - { - AddOutPt(e1, Pt); - AddOutPt(e2, Pt); - SwapSides( *e1 , *e2 ); - SwapPolyIndexes( *e1 , *e2 ); - } - } - else if ( e1Contributing ) - { - if (e2Wc == 0 || e2Wc == 1) - { - AddOutPt(e1, Pt); - SwapSides(*e1, *e2); - SwapPolyIndexes(*e1, *e2); - } - } - else if ( e2Contributing ) - { - if (e1Wc == 0 || e1Wc == 1) - { - AddOutPt(e2, Pt); - SwapSides(*e1, *e2); - SwapPolyIndexes(*e1, *e2); - } - } - else if ( (e1Wc == 0 || e1Wc == 1) && (e2Wc == 0 || e2Wc == 1)) - { - //neither edge is currently contributing ... - - cInt e1Wc2, e2Wc2; - switch (e1FillType2) - { - case pftPositive: e1Wc2 = e1->WindCnt2; break; - case pftNegative : e1Wc2 = -e1->WindCnt2; break; - default: e1Wc2 = Abs(e1->WindCnt2); - } - switch (e2FillType2) - { - case pftPositive: e2Wc2 = e2->WindCnt2; break; - case pftNegative: e2Wc2 = -e2->WindCnt2; break; - default: e2Wc2 = Abs(e2->WindCnt2); + else { + if (!IsEvenOddFillType(*e2)) { + e1->WindCnt2 += e2->WindDelta; + } + else { + e1->WindCnt2 = (e1->WindCnt2 == 0) ? 1 : 0; + } + if (!IsEvenOddFillType(*e1)) { + e2->WindCnt2 -= e1->WindDelta; + } + else { + e2->WindCnt2 = (e2->WindCnt2 == 0) ? 1 : 0; + } } - if (e1->PolyTyp != e2->PolyTyp) - { - AddLocalMinPoly(e1, e2, Pt); + PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; + if (e1->PolyTyp == ptSubject) { + e1FillType = m_SubjFillType; + e1FillType2 = m_ClipFillType; } - else if (e1Wc == 1 && e2Wc == 1) - switch( m_ClipType ) { - case ctIntersection: - if (e1Wc2 > 0 && e2Wc2 > 0) + else { + e1FillType = m_ClipFillType; + e1FillType2 = m_SubjFillType; + } + if (e2->PolyTyp == ptSubject) { + e2FillType = m_SubjFillType; + e2FillType2 = m_ClipFillType; + } + else { + e2FillType = m_ClipFillType; + e2FillType2 = m_SubjFillType; + } + + cInt e1Wc, e2Wc; + switch (e1FillType) { + case pftPositive: + e1Wc = e1->WindCnt; + break; + case pftNegative: + e1Wc = -e1->WindCnt; + break; + default: + e1Wc = Abs(e1->WindCnt); + } + switch (e2FillType) { + case pftPositive: + e2Wc = e2->WindCnt; + break; + case pftNegative: + e2Wc = -e2->WindCnt; + break; + default: + e2Wc = Abs(e2->WindCnt); + } + + if (e1Contributing && e2Contributing) { + if ((e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) + || (e1->PolyTyp != e2->PolyTyp && m_ClipType != ctXor)) { + AddLocalMaxPoly(e1, e2, Pt); + } + else { + AddOutPt(e1, Pt); + AddOutPt(e2, Pt); + SwapSides(*e1, *e2); + SwapPolyIndexes(*e1, *e2); + } + } + else if (e1Contributing) { + if (e2Wc == 0 || e2Wc == 1) { + AddOutPt(e1, Pt); + SwapSides(*e1, *e2); + SwapPolyIndexes(*e1, *e2); + } + } + else if (e2Contributing) { + if (e1Wc == 0 || e1Wc == 1) { + AddOutPt(e2, Pt); + SwapSides(*e1, *e2); + SwapPolyIndexes(*e1, *e2); + } + } + else if ((e1Wc == 0 || e1Wc == 1) && (e2Wc == 0 || e2Wc == 1)) { + // neither edge is currently contributing ... + + cInt e1Wc2, e2Wc2; + switch (e1FillType2) { + case pftPositive: + e1Wc2 = e1->WindCnt2; + break; + case pftNegative: + e1Wc2 = -e1->WindCnt2; + break; + default: + e1Wc2 = Abs(e1->WindCnt2); + } + switch (e2FillType2) { + case pftPositive: + e2Wc2 = e2->WindCnt2; + break; + case pftNegative: + e2Wc2 = -e2->WindCnt2; + break; + default: + e2Wc2 = Abs(e2->WindCnt2); + } + + if (e1->PolyTyp != e2->PolyTyp) { AddLocalMinPoly(e1, e2, Pt); - break; - case ctUnion: - if ( e1Wc2 <= 0 && e2Wc2 <= 0 ) - AddLocalMinPoly(e1, e2, Pt); - break; - case ctDifference: - if (((e1->PolyTyp == ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) || - ((e1->PolyTyp == ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0))) - AddLocalMinPoly(e1, e2, Pt); - break; - case ctXor: - AddLocalMinPoly(e1, e2, Pt); - } - else - SwapSides( *e1, *e2 ); - } + } + else if (e1Wc == 1 && e2Wc == 1) { + switch (m_ClipType) { + case ctIntersection: + if (e1Wc2 > 0 && e2Wc2 > 0) { + AddLocalMinPoly(e1, e2, Pt); + } + break; + case ctUnion: + if (e1Wc2 <= 0 && e2Wc2 <= 0) { + AddLocalMinPoly(e1, e2, Pt); + } + break; + case ctDifference: + if (((e1->PolyTyp == ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) + || ((e1->PolyTyp == ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0))) { + AddLocalMinPoly(e1, e2, Pt); + } + break; + case ctXor: + AddLocalMinPoly(e1, e2, Pt); + } + } + else { + SwapSides(*e1, *e2); + } + } } //------------------------------------------------------------------------------ -void Clipper::SetHoleState(TEdge *e, OutRec *outrec) +void Clipper::SetHoleState(TEdge* e, OutRec* outrec) { - bool IsHole = false; - TEdge *e2 = e->PrevInAEL; - while (e2) - { - if (e2->OutIdx >= 0 && e2->WindDelta != 0) - { - IsHole = !IsHole; - if (! outrec->FirstLeft) - outrec->FirstLeft = m_PolyOuts[e2->OutIdx]; + bool IsHole = false; + TEdge* e2 = e->PrevInAEL; + while (e2) { + if (e2->OutIdx >= 0 && e2->WindDelta != 0) { + IsHole = !IsHole; + if (!outrec->FirstLeft) { + outrec->FirstLeft = m_PolyOuts[e2->OutIdx]; + } + } + e2 = e2->PrevInAEL; + } + if (IsHole) { + outrec->IsHole = true; } - e2 = e2->PrevInAEL; - } - if (IsHole) outrec->IsHole = true; } //------------------------------------------------------------------------------ -OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2) +OutRec* GetLowermostRec(OutRec* outRec1, OutRec* outRec2) { - //work out which polygon fragment has the correct hole state ... - if (!outRec1->BottomPt) - outRec1->BottomPt = GetBottomPt(outRec1->Pts); - if (!outRec2->BottomPt) - outRec2->BottomPt = GetBottomPt(outRec2->Pts); - OutPt *OutPt1 = outRec1->BottomPt; - OutPt *OutPt2 = outRec2->BottomPt; - if (OutPt1->Pt.Y > OutPt2->Pt.Y) - return outRec1; - else if (OutPt1->Pt.Y < OutPt2->Pt.Y) return outRec2; - else if (OutPt1->Pt.X < OutPt2->Pt.X) return outRec1; - else if (OutPt1->Pt.X > OutPt2->Pt.X) return outRec2; - else if (OutPt1->Next == OutPt1) return outRec2; - else if (OutPt2->Next == OutPt2) return outRec1; - else if (FirstIsBottomPt(OutPt1, OutPt2)) return outRec1; - else return outRec2; + // work out which polygon fragment has the correct hole state ... + if (!outRec1->BottomPt) { + outRec1->BottomPt = GetBottomPt(outRec1->Pts); + } + if (!outRec2->BottomPt) { + outRec2->BottomPt = GetBottomPt(outRec2->Pts); + } + OutPt* OutPt1 = outRec1->BottomPt; + OutPt* OutPt2 = outRec2->BottomPt; + if (OutPt1->Pt.Y > OutPt2->Pt.Y) { + return outRec1; + } + else if (OutPt1->Pt.Y < OutPt2->Pt.Y) { + return outRec2; + } + else if (OutPt1->Pt.X < OutPt2->Pt.X) { + return outRec1; + } + else if (OutPt1->Pt.X > OutPt2->Pt.X) { + return outRec2; + } + else if (OutPt1->Next == OutPt1) { + return outRec2; + } + else if (OutPt2->Next == OutPt2) { + return outRec1; + } + else if (FirstIsBottomPt(OutPt1, OutPt2)) { + return outRec1; + } + else { + return outRec2; + } } //------------------------------------------------------------------------------ bool Param1RightOfParam2(OutRec* outRec1, OutRec* outRec2) { - do - { - outRec1 = outRec1->FirstLeft; - if (outRec1 == outRec2) - return true; - } while (outRec1); - return false; + do { + outRec1 = outRec1->FirstLeft; + if (outRec1 == outRec2) { + return true; + } + } while (outRec1); + return false; } //------------------------------------------------------------------------------ OutRec* Clipper::GetOutRec(int Idx) { - OutRec* outrec = m_PolyOuts[Idx]; - while (outrec != m_PolyOuts[outrec->Idx]) - outrec = m_PolyOuts[outrec->Idx]; - return outrec; + OutRec* outrec = m_PolyOuts[Idx]; + while (outrec != m_PolyOuts[outrec->Idx]) { + outrec = m_PolyOuts[outrec->Idx]; + } + return outrec; } //------------------------------------------------------------------------------ -void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) +void Clipper::AppendPolygon(TEdge* e1, TEdge* e2) { - //get the start and ends of both output polygons ... - OutRec *outRec1 = m_PolyOuts[e1->OutIdx]; - OutRec *outRec2 = m_PolyOuts[e2->OutIdx]; + // get the start and ends of both output polygons ... + OutRec* outRec1 = m_PolyOuts[e1->OutIdx]; + OutRec* outRec2 = m_PolyOuts[e2->OutIdx]; - OutRec *holeStateRec; - if (Param1RightOfParam2(outRec1, outRec2)) - holeStateRec = outRec2; - else if (Param1RightOfParam2(outRec2, outRec1)) - holeStateRec = outRec1; - else - holeStateRec = GetLowermostRec(outRec1, outRec2); - - //get the start and ends of both output polygons and - //join e2 poly onto e1 poly and delete pointers to e2 ... - - OutPt* p1_lft = outRec1->Pts; - OutPt* p1_rt = p1_lft->Prev; - OutPt* p2_lft = outRec2->Pts; - OutPt* p2_rt = p2_lft->Prev; - - EdgeSide Side; - //join e2 poly onto e1 poly and delete pointers to e2 ... - if( e1->Side == esLeft ) - { - if( e2->Side == esLeft ) - { - //z y x a b c - ReversePolyPtLinks(p2_lft); - p2_lft->Next = p1_lft; - p1_lft->Prev = p2_lft; - p1_rt->Next = p2_rt; - p2_rt->Prev = p1_rt; - outRec1->Pts = p2_rt; - } else - { - //x y z a b c - p2_rt->Next = p1_lft; - p1_lft->Prev = p2_rt; - p2_lft->Prev = p1_rt; - p1_rt->Next = p2_lft; - outRec1->Pts = p2_lft; + OutRec* holeStateRec; + if (Param1RightOfParam2(outRec1, outRec2)) { + holeStateRec = outRec2; } - Side = esLeft; - } else - { - if( e2->Side == esRight ) - { - //a b c z y x - ReversePolyPtLinks(p2_lft); - p1_rt->Next = p2_rt; - p2_rt->Prev = p1_rt; - p2_lft->Next = p1_lft; - p1_lft->Prev = p2_lft; - } else - { - //a b c x y z - p1_rt->Next = p2_lft; - p2_lft->Prev = p1_rt; - p1_lft->Prev = p2_rt; - p2_rt->Next = p1_lft; + else if (Param1RightOfParam2(outRec2, outRec1)) { + holeStateRec = outRec1; } - Side = esRight; - } - - outRec1->BottomPt = 0; - if (holeStateRec == outRec2) - { - if (outRec2->FirstLeft != outRec1) - outRec1->FirstLeft = outRec2->FirstLeft; - outRec1->IsHole = outRec2->IsHole; - } - outRec2->Pts = 0; - outRec2->BottomPt = 0; - outRec2->FirstLeft = outRec1; - - int OKIdx = e1->OutIdx; - int ObsoleteIdx = e2->OutIdx; - - e1->OutIdx = Unassigned; //nb: safe because we only get here via AddLocalMaxPoly - e2->OutIdx = Unassigned; - - TEdge* e = m_ActiveEdges; - while( e ) - { - if( e->OutIdx == ObsoleteIdx ) - { - e->OutIdx = OKIdx; - e->Side = Side; - break; + else { + holeStateRec = GetLowermostRec(outRec1, outRec2); } - e = e->NextInAEL; - } - outRec2->Idx = outRec1->Idx; + // get the start and ends of both output polygons and + // join e2 poly onto e1 poly and delete pointers to e2 ... + + OutPt* p1_lft = outRec1->Pts; + OutPt* p1_rt = p1_lft->Prev; + OutPt* p2_lft = outRec2->Pts; + OutPt* p2_rt = p2_lft->Prev; + + EdgeSide Side; + // join e2 poly onto e1 poly and delete pointers to e2 ... + if (e1->Side == esLeft) { + if (e2->Side == esLeft) { + // z y x a b c + ReversePolyPtLinks(p2_lft); + p2_lft->Next = p1_lft; + p1_lft->Prev = p2_lft; + p1_rt->Next = p2_rt; + p2_rt->Prev = p1_rt; + outRec1->Pts = p2_rt; + } + else { + // x y z a b c + p2_rt->Next = p1_lft; + p1_lft->Prev = p2_rt; + p2_lft->Prev = p1_rt; + p1_rt->Next = p2_lft; + outRec1->Pts = p2_lft; + } + Side = esLeft; + } + else { + if (e2->Side == esRight) { + // a b c z y x + ReversePolyPtLinks(p2_lft); + p1_rt->Next = p2_rt; + p2_rt->Prev = p1_rt; + p2_lft->Next = p1_lft; + p1_lft->Prev = p2_lft; + } + else { + // a b c x y z + p1_rt->Next = p2_lft; + p2_lft->Prev = p1_rt; + p1_lft->Prev = p2_rt; + p2_rt->Next = p1_lft; + } + Side = esRight; + } + + outRec1->BottomPt = 0; + if (holeStateRec == outRec2) { + if (outRec2->FirstLeft != outRec1) { + outRec1->FirstLeft = outRec2->FirstLeft; + } + outRec1->IsHole = outRec2->IsHole; + } + outRec2->Pts = 0; + outRec2->BottomPt = 0; + outRec2->FirstLeft = outRec1; + + int OKIdx = e1->OutIdx; + int ObsoleteIdx = e2->OutIdx; + + e1->OutIdx = Unassigned; // nb: safe because we only get here via AddLocalMaxPoly + e2->OutIdx = Unassigned; + + TEdge* e = m_ActiveEdges; + while (e) { + if (e->OutIdx == ObsoleteIdx) { + e->OutIdx = OKIdx; + e->Side = Side; + break; + } + e = e->NextInAEL; + } + + outRec2->Idx = outRec1->Idx; } //------------------------------------------------------------------------------ OutRec* Clipper::CreateOutRec() { - OutRec* result = new OutRec; - result->IsHole = false; - result->IsOpen = false; - result->FirstLeft = 0; - result->Pts = 0; - result->BottomPt = 0; - result->PolyNd = 0; - m_PolyOuts.push_back(result); - result->Idx = (int)m_PolyOuts.size()-1; - return result; + OutRec* result = new OutRec; + result->IsHole = false; + result->IsOpen = false; + result->FirstLeft = 0; + result->Pts = 0; + result->BottomPt = 0; + result->PolyNd = 0; + m_PolyOuts.push_back(result); + result->Idx = (int)m_PolyOuts.size() - 1; + return result; } //------------------------------------------------------------------------------ -OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt) +OutPt* Clipper::AddOutPt(TEdge* e, const IntPoint& pt) { - bool ToFront = (e->Side == esLeft); - if( e->OutIdx < 0 ) - { - OutRec *outRec = CreateOutRec(); - outRec->IsOpen = (e->WindDelta == 0); - OutPt* newOp = new OutPt; - outRec->Pts = newOp; - newOp->Idx = outRec->Idx; - newOp->Pt = pt; - newOp->Next = newOp; - newOp->Prev = newOp; - if (!outRec->IsOpen) - SetHoleState(e, outRec); - e->OutIdx = outRec->Idx; - return newOp; - } else - { - OutRec *outRec = m_PolyOuts[e->OutIdx]; - //OutRec.Pts is the 'Left-most' point & OutRec.Pts.Prev is the 'Right-most' - OutPt* op = outRec->Pts; + bool ToFront = (e->Side == esLeft); + if (e->OutIdx < 0) { + OutRec* outRec = CreateOutRec(); + outRec->IsOpen = (e->WindDelta == 0); + OutPt* newOp = new OutPt; + outRec->Pts = newOp; + newOp->Idx = outRec->Idx; + newOp->Pt = pt; + newOp->Next = newOp; + newOp->Prev = newOp; + if (!outRec->IsOpen) { + SetHoleState(e, outRec); + } + e->OutIdx = outRec->Idx; + return newOp; + } + else { + OutRec* outRec = m_PolyOuts[e->OutIdx]; + // OutRec.Pts is the 'Left-most' point & OutRec.Pts.Prev is the 'Right-most' + OutPt* op = outRec->Pts; - if (ToFront && (pt == op->Pt)) - return op; - else if (!ToFront && (pt == op->Prev->Pt)) return op->Prev; + if (ToFront && (pt == op->Pt)) { + return op; + } + else if (!ToFront && (pt == op->Prev->Pt)) { + return op->Prev; + } - OutPt* newOp = new OutPt; - newOp->Idx = outRec->Idx; - newOp->Pt = pt; - newOp->Next = op; - newOp->Prev = op->Prev; - newOp->Prev->Next = newOp; - op->Prev = newOp; - if (ToFront) outRec->Pts = newOp; - return newOp; - } + OutPt* newOp = new OutPt; + newOp->Idx = outRec->Idx; + newOp->Pt = pt; + newOp->Next = op; + newOp->Prev = op->Prev; + newOp->Prev->Next = newOp; + op->Prev = newOp; + if (ToFront) { + outRec->Pts = newOp; + } + return newOp; + } } //------------------------------------------------------------------------------ void Clipper::ProcessHorizontals(bool IsTopOfScanbeam) { - TEdge* horzEdge = m_SortedEdges; - while(horzEdge) - { - DeleteFromSEL(horzEdge); - ProcessHorizontal(horzEdge, IsTopOfScanbeam); - horzEdge = m_SortedEdges; - } + TEdge* horzEdge = m_SortedEdges; + while (horzEdge) { + DeleteFromSEL(horzEdge); + ProcessHorizontal(horzEdge, IsTopOfScanbeam); + horzEdge = m_SortedEdges; + } } //------------------------------------------------------------------------------ -inline bool IsMinima(TEdge *e) +inline bool IsMinima(TEdge* e) { - return e && (e->Prev->NextInLML != e) && (e->Next->NextInLML != e); + return e && (e->Prev->NextInLML != e) && (e->Next->NextInLML != e); } //------------------------------------------------------------------------------ -inline bool IsMaxima(TEdge *e, const cInt Y) +inline bool IsMaxima(TEdge* e, const cInt Y) { - return e && e->Top.Y == Y && !e->NextInLML; + return e && e->Top.Y == Y && !e->NextInLML; } //------------------------------------------------------------------------------ -inline bool IsIntermediate(TEdge *e, const cInt Y) +inline bool IsIntermediate(TEdge* e, const cInt Y) { - return e->Top.Y == Y && e->NextInLML; + return e->Top.Y == Y && e->NextInLML; } //------------------------------------------------------------------------------ -TEdge *GetMaximaPair(TEdge *e) +TEdge* GetMaximaPair(TEdge* e) { - TEdge* result = 0; - if ((e->Next->Top == e->Top) && !e->Next->NextInLML) - result = e->Next; - else if ((e->Prev->Top == e->Top) && !e->Prev->NextInLML) - result = e->Prev; + TEdge* result = 0; + if ((e->Next->Top == e->Top) && !e->Next->NextInLML) { + result = e->Next; + } + else if ((e->Prev->Top == e->Top) && !e->Prev->NextInLML) { + result = e->Prev; + } - if (result && (result->OutIdx == Skip || - //result is false if both NextInAEL & PrevInAEL are nil & not horizontal ... - (result->NextInAEL == result->PrevInAEL && !IsHorizontal(*result)))) - return 0; - return result; + if (result + && (result->OutIdx == Skip || + // result is false if both NextInAEL & PrevInAEL are nil & not horizontal ... + (result->NextInAEL == result->PrevInAEL && !IsHorizontal(*result)))) { + return 0; + } + return result; } //------------------------------------------------------------------------------ -void Clipper::SwapPositionsInAEL(TEdge *Edge1, TEdge *Edge2) +void Clipper::SwapPositionsInAEL(TEdge* Edge1, TEdge* Edge2) { - //check that one or other edge hasn't already been removed from AEL ... - if (Edge1->NextInAEL == Edge1->PrevInAEL || - Edge2->NextInAEL == Edge2->PrevInAEL) return; + // check that one or other edge hasn't already been removed from AEL ... + if (Edge1->NextInAEL == Edge1->PrevInAEL || Edge2->NextInAEL == Edge2->PrevInAEL) { + return; + } - if( Edge1->NextInAEL == Edge2 ) - { - TEdge* Next = Edge2->NextInAEL; - if( Next ) Next->PrevInAEL = Edge1; - TEdge* Prev = Edge1->PrevInAEL; - if( Prev ) Prev->NextInAEL = Edge2; - Edge2->PrevInAEL = Prev; - Edge2->NextInAEL = Edge1; - Edge1->PrevInAEL = Edge2; - Edge1->NextInAEL = Next; - } - else if( Edge2->NextInAEL == Edge1 ) - { - TEdge* Next = Edge1->NextInAEL; - if( Next ) Next->PrevInAEL = Edge2; - TEdge* Prev = Edge2->PrevInAEL; - if( Prev ) Prev->NextInAEL = Edge1; - Edge1->PrevInAEL = Prev; - Edge1->NextInAEL = Edge2; - Edge2->PrevInAEL = Edge1; - Edge2->NextInAEL = Next; - } - else - { - TEdge* Next = Edge1->NextInAEL; - TEdge* Prev = Edge1->PrevInAEL; - Edge1->NextInAEL = Edge2->NextInAEL; - if( Edge1->NextInAEL ) Edge1->NextInAEL->PrevInAEL = Edge1; - Edge1->PrevInAEL = Edge2->PrevInAEL; - if( Edge1->PrevInAEL ) Edge1->PrevInAEL->NextInAEL = Edge1; - Edge2->NextInAEL = Next; - if( Edge2->NextInAEL ) Edge2->NextInAEL->PrevInAEL = Edge2; - Edge2->PrevInAEL = Prev; - if( Edge2->PrevInAEL ) Edge2->PrevInAEL->NextInAEL = Edge2; - } + if (Edge1->NextInAEL == Edge2) { + TEdge* Next = Edge2->NextInAEL; + if (Next) { + Next->PrevInAEL = Edge1; + } + TEdge* Prev = Edge1->PrevInAEL; + if (Prev) { + Prev->NextInAEL = Edge2; + } + Edge2->PrevInAEL = Prev; + Edge2->NextInAEL = Edge1; + Edge1->PrevInAEL = Edge2; + Edge1->NextInAEL = Next; + } + else if (Edge2->NextInAEL == Edge1) { + TEdge* Next = Edge1->NextInAEL; + if (Next) { + Next->PrevInAEL = Edge2; + } + TEdge* Prev = Edge2->PrevInAEL; + if (Prev) { + Prev->NextInAEL = Edge1; + } + Edge1->PrevInAEL = Prev; + Edge1->NextInAEL = Edge2; + Edge2->PrevInAEL = Edge1; + Edge2->NextInAEL = Next; + } + else { + TEdge* Next = Edge1->NextInAEL; + TEdge* Prev = Edge1->PrevInAEL; + Edge1->NextInAEL = Edge2->NextInAEL; + if (Edge1->NextInAEL) { + Edge1->NextInAEL->PrevInAEL = Edge1; + } + Edge1->PrevInAEL = Edge2->PrevInAEL; + if (Edge1->PrevInAEL) { + Edge1->PrevInAEL->NextInAEL = Edge1; + } + Edge2->NextInAEL = Next; + if (Edge2->NextInAEL) { + Edge2->NextInAEL->PrevInAEL = Edge2; + } + Edge2->PrevInAEL = Prev; + if (Edge2->PrevInAEL) { + Edge2->PrevInAEL->NextInAEL = Edge2; + } + } - if( !Edge1->PrevInAEL ) m_ActiveEdges = Edge1; - else if( !Edge2->PrevInAEL ) m_ActiveEdges = Edge2; + if (!Edge1->PrevInAEL) { + m_ActiveEdges = Edge1; + } + else if (!Edge2->PrevInAEL) { + m_ActiveEdges = Edge2; + } } //------------------------------------------------------------------------------ -void Clipper::SwapPositionsInSEL(TEdge *Edge1, TEdge *Edge2) +void Clipper::SwapPositionsInSEL(TEdge* Edge1, TEdge* Edge2) { - if( !( Edge1->NextInSEL ) && !( Edge1->PrevInSEL ) ) - return; - if( !( Edge2->NextInSEL ) && !( Edge2->PrevInSEL ) ) - return; + if (!(Edge1->NextInSEL) && !(Edge1->PrevInSEL)) { + return; + } + if (!(Edge2->NextInSEL) && !(Edge2->PrevInSEL)) { + return; + } - if( Edge1->NextInSEL == Edge2 ) - { - TEdge* Next = Edge2->NextInSEL; - if( Next ) Next->PrevInSEL = Edge1; - TEdge* Prev = Edge1->PrevInSEL; - if( Prev ) Prev->NextInSEL = Edge2; - Edge2->PrevInSEL = Prev; - Edge2->NextInSEL = Edge1; - Edge1->PrevInSEL = Edge2; - Edge1->NextInSEL = Next; - } - else if( Edge2->NextInSEL == Edge1 ) - { - TEdge* Next = Edge1->NextInSEL; - if( Next ) Next->PrevInSEL = Edge2; - TEdge* Prev = Edge2->PrevInSEL; - if( Prev ) Prev->NextInSEL = Edge1; - Edge1->PrevInSEL = Prev; - Edge1->NextInSEL = Edge2; - Edge2->PrevInSEL = Edge1; - Edge2->NextInSEL = Next; - } - else - { - TEdge* Next = Edge1->NextInSEL; - TEdge* Prev = Edge1->PrevInSEL; - Edge1->NextInSEL = Edge2->NextInSEL; - if( Edge1->NextInSEL ) Edge1->NextInSEL->PrevInSEL = Edge1; - Edge1->PrevInSEL = Edge2->PrevInSEL; - if( Edge1->PrevInSEL ) Edge1->PrevInSEL->NextInSEL = Edge1; - Edge2->NextInSEL = Next; - if( Edge2->NextInSEL ) Edge2->NextInSEL->PrevInSEL = Edge2; - Edge2->PrevInSEL = Prev; - if( Edge2->PrevInSEL ) Edge2->PrevInSEL->NextInSEL = Edge2; - } + if (Edge1->NextInSEL == Edge2) { + TEdge* Next = Edge2->NextInSEL; + if (Next) { + Next->PrevInSEL = Edge1; + } + TEdge* Prev = Edge1->PrevInSEL; + if (Prev) { + Prev->NextInSEL = Edge2; + } + Edge2->PrevInSEL = Prev; + Edge2->NextInSEL = Edge1; + Edge1->PrevInSEL = Edge2; + Edge1->NextInSEL = Next; + } + else if (Edge2->NextInSEL == Edge1) { + TEdge* Next = Edge1->NextInSEL; + if (Next) { + Next->PrevInSEL = Edge2; + } + TEdge* Prev = Edge2->PrevInSEL; + if (Prev) { + Prev->NextInSEL = Edge1; + } + Edge1->PrevInSEL = Prev; + Edge1->NextInSEL = Edge2; + Edge2->PrevInSEL = Edge1; + Edge2->NextInSEL = Next; + } + else { + TEdge* Next = Edge1->NextInSEL; + TEdge* Prev = Edge1->PrevInSEL; + Edge1->NextInSEL = Edge2->NextInSEL; + if (Edge1->NextInSEL) { + Edge1->NextInSEL->PrevInSEL = Edge1; + } + Edge1->PrevInSEL = Edge2->PrevInSEL; + if (Edge1->PrevInSEL) { + Edge1->PrevInSEL->NextInSEL = Edge1; + } + Edge2->NextInSEL = Next; + if (Edge2->NextInSEL) { + Edge2->NextInSEL->PrevInSEL = Edge2; + } + Edge2->PrevInSEL = Prev; + if (Edge2->PrevInSEL) { + Edge2->PrevInSEL->NextInSEL = Edge2; + } + } - if( !Edge1->PrevInSEL ) m_SortedEdges = Edge1; - else if( !Edge2->PrevInSEL ) m_SortedEdges = Edge2; + if (!Edge1->PrevInSEL) { + m_SortedEdges = Edge1; + } + else if (!Edge2->PrevInSEL) { + m_SortedEdges = Edge2; + } } //------------------------------------------------------------------------------ -TEdge* GetNextInAEL(TEdge *e, Direction dir) +TEdge* GetNextInAEL(TEdge* e, Direction dir) { - return dir == dLeftToRight ? e->NextInAEL : e->PrevInAEL; + return dir == dLeftToRight ? e->NextInAEL : e->PrevInAEL; } //------------------------------------------------------------------------------ void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt& Right) { - if (HorzEdge.Bot.X < HorzEdge.Top.X) - { - Left = HorzEdge.Bot.X; - Right = HorzEdge.Top.X; - Dir = dLeftToRight; - } else - { - Left = HorzEdge.Top.X; - Right = HorzEdge.Bot.X; - Dir = dRightToLeft; - } + if (HorzEdge.Bot.X < HorzEdge.Top.X) { + Left = HorzEdge.Bot.X; + Right = HorzEdge.Top.X; + Dir = dLeftToRight; + } + else { + Left = HorzEdge.Top.X; + Right = HorzEdge.Bot.X; + Dir = dRightToLeft; + } } //------------------------------------------------------------------------ /******************************************************************************* -* Notes: Horizontal edges (HEs) at scanline intersections (ie at the Top or * -* Bottom of a scanbeam) are processed as if layered. The order in which HEs * -* are processed doesn't matter. HEs intersect with other HE Bot.Xs only [#] * -* (or they could intersect with Top.Xs only, ie EITHER Bot.Xs OR Top.Xs), * -* and with other non-horizontal edges [*]. Once these intersections are * -* processed, intermediate HEs then 'promote' the Edge above (NextInLML) into * -* the AEL. These 'promoted' edges may in turn intersect [%] with other HEs. * -*******************************************************************************/ + * Notes: Horizontal edges (HEs) at scanline intersections (ie at the Top or * + * Bottom of a scanbeam) are processed as if layered. The order in which HEs * + * are processed doesn't matter. HEs intersect with other HE Bot.Xs only [#] * + * (or they could intersect with Top.Xs only, ie EITHER Bot.Xs OR Top.Xs), * + * and with other non-horizontal edges [*]. Once these intersections are * + * processed, intermediate HEs then 'promote' the Edge above (NextInLML) into * + * the AEL. These 'promoted' edges may in turn intersect [%] with other HEs. * + *******************************************************************************/ -void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam) +void Clipper::ProcessHorizontal(TEdge* horzEdge, bool isTopOfScanbeam) { - Direction dir; - cInt horzLeft, horzRight; + Direction dir; + cInt horzLeft, horzRight; - GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); + GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); - TEdge* eLastHorz = horzEdge, *eMaxPair = 0; - while (eLastHorz->NextInLML && IsHorizontal(*eLastHorz->NextInLML)) - eLastHorz = eLastHorz->NextInLML; - if (!eLastHorz->NextInLML) - eMaxPair = GetMaximaPair(eLastHorz); - - for (;;) - { - bool IsLastHorz = (horzEdge == eLastHorz); - TEdge* e = GetNextInAEL(horzEdge, dir); - while(e) - { - //Break if we've got to the end of an intermediate horizontal edge ... - //nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal. - if (e->Curr.X == horzEdge->Top.X && horzEdge->NextInLML && - e->Dx < horzEdge->NextInLML->Dx) break; - - TEdge* eNext = GetNextInAEL(e, dir); //saves eNext for later - - if ((dir == dLeftToRight && e->Curr.X <= horzRight) || - (dir == dRightToLeft && e->Curr.X >= horzLeft)) - { - //so far we're still in range of the horizontal Edge but make sure - //we're at the last of consec. horizontals when matching with eMaxPair - if(e == eMaxPair && IsLastHorz) - { - - if (horzEdge->OutIdx >= 0) - { - OutPt* op1 = AddOutPt(horzEdge, horzEdge->Top); - TEdge* eNextHorz = m_SortedEdges; - while (eNextHorz) - { - if (eNextHorz->OutIdx >= 0 && - HorzSegmentsOverlap(horzEdge->Bot.X, - horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X)) - { - OutPt* op2 = AddOutPt(eNextHorz, eNextHorz->Bot); - AddJoin(op2, op1, eNextHorz->Top); - } - eNextHorz = eNextHorz->NextInSEL; - } - AddGhostJoin(op1, horzEdge->Bot); - AddLocalMaxPoly(horzEdge, eMaxPair, horzEdge->Top); - } - DeleteFromAEL(horzEdge); - DeleteFromAEL(eMaxPair); - return; - } - else if(dir == dLeftToRight) - { - IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); - IntersectEdges(horzEdge, e, Pt); - } - else - { - IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); - IntersectEdges( e, horzEdge, Pt); - } - SwapPositionsInAEL( horzEdge, e ); - } - else if( (dir == dLeftToRight && e->Curr.X >= horzRight) || - (dir == dRightToLeft && e->Curr.X <= horzLeft) ) break; - e = eNext; - } //end while - - if (horzEdge->NextInLML && IsHorizontal(*horzEdge->NextInLML)) - { - UpdateEdgeIntoAEL(horzEdge); - if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Bot); - GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); - } else - break; - } //end for (;;) - - if(horzEdge->NextInLML) - { - if(horzEdge->OutIdx >= 0) - { - OutPt* op1 = AddOutPt( horzEdge, horzEdge->Top); - if (isTopOfScanbeam) AddGhostJoin(op1, horzEdge->Bot); - UpdateEdgeIntoAEL(horzEdge); - if (horzEdge->WindDelta == 0) - return; - //nb: HorzEdge is no longer horizontal here - TEdge* ePrev = horzEdge->PrevInAEL; - TEdge* eNext = horzEdge->NextInAEL; - if (ePrev && ePrev->Curr.X == horzEdge->Bot.X && - ePrev->Curr.Y == horzEdge->Bot.Y && ePrev->WindDelta != 0 && - (ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y && - SlopesEqual(*horzEdge, *ePrev, m_UseFullRange))) - { - OutPt* op2 = AddOutPt(ePrev, horzEdge->Bot); - AddJoin(op1, op2, horzEdge->Top); - } - else if (eNext && eNext->Curr.X == horzEdge->Bot.X && - eNext->Curr.Y == horzEdge->Bot.Y && eNext->WindDelta != 0 && - eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y && - SlopesEqual(*horzEdge, *eNext, m_UseFullRange)) - { - OutPt* op2 = AddOutPt(eNext, horzEdge->Bot); - AddJoin(op1, op2, horzEdge->Top); - } + TEdge *eLastHorz = horzEdge, *eMaxPair = 0; + while (eLastHorz->NextInLML && IsHorizontal(*eLastHorz->NextInLML)) { + eLastHorz = eLastHorz->NextInLML; + } + if (!eLastHorz->NextInLML) { + eMaxPair = GetMaximaPair(eLastHorz); + } + + for (;;) { + bool IsLastHorz = (horzEdge == eLastHorz); + TEdge* e = GetNextInAEL(horzEdge, dir); + while (e) { + // Break if we've got to the end of an intermediate horizontal edge ... + // nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal. + if (e->Curr.X == horzEdge->Top.X && horzEdge->NextInLML + && e->Dx < horzEdge->NextInLML->Dx) { + break; + } + + TEdge* eNext = GetNextInAEL(e, dir); // saves eNext for later + + if ((dir == dLeftToRight && e->Curr.X <= horzRight) + || (dir == dRightToLeft && e->Curr.X >= horzLeft)) { + // so far we're still in range of the horizontal Edge but make sure + // we're at the last of consec. horizontals when matching with eMaxPair + if (e == eMaxPair && IsLastHorz) { + + if (horzEdge->OutIdx >= 0) { + OutPt* op1 = AddOutPt(horzEdge, horzEdge->Top); + TEdge* eNextHorz = m_SortedEdges; + while (eNextHorz) { + if (eNextHorz->OutIdx >= 0 + && HorzSegmentsOverlap(horzEdge->Bot.X, + horzEdge->Top.X, + eNextHorz->Bot.X, + eNextHorz->Top.X)) { + OutPt* op2 = AddOutPt(eNextHorz, eNextHorz->Bot); + AddJoin(op2, op1, eNextHorz->Top); + } + eNextHorz = eNextHorz->NextInSEL; + } + AddGhostJoin(op1, horzEdge->Bot); + AddLocalMaxPoly(horzEdge, eMaxPair, horzEdge->Top); + } + DeleteFromAEL(horzEdge); + DeleteFromAEL(eMaxPair); + return; + } + else if (dir == dLeftToRight) { + IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); + IntersectEdges(horzEdge, e, Pt); + } + else { + IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); + IntersectEdges(e, horzEdge, Pt); + } + SwapPositionsInAEL(horzEdge, e); + } + else if ((dir == dLeftToRight && e->Curr.X >= horzRight) + || (dir == dRightToLeft && e->Curr.X <= horzLeft)) { + break; + } + e = eNext; + } // end while + + if (horzEdge->NextInLML && IsHorizontal(*horzEdge->NextInLML)) { + UpdateEdgeIntoAEL(horzEdge); + if (horzEdge->OutIdx >= 0) { + AddOutPt(horzEdge, horzEdge->Bot); + } + GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); + } + else { + break; + } + } // end for (;;) + + if (horzEdge->NextInLML) { + if (horzEdge->OutIdx >= 0) { + OutPt* op1 = AddOutPt(horzEdge, horzEdge->Top); + if (isTopOfScanbeam) { + AddGhostJoin(op1, horzEdge->Bot); + } + UpdateEdgeIntoAEL(horzEdge); + if (horzEdge->WindDelta == 0) { + return; + } + // nb: HorzEdge is no longer horizontal here + TEdge* ePrev = horzEdge->PrevInAEL; + TEdge* eNext = horzEdge->NextInAEL; + if (ePrev && ePrev->Curr.X == horzEdge->Bot.X && ePrev->Curr.Y == horzEdge->Bot.Y + && ePrev->WindDelta != 0 + && (ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y + && SlopesEqual(*horzEdge, *ePrev, m_UseFullRange))) { + OutPt* op2 = AddOutPt(ePrev, horzEdge->Bot); + AddJoin(op1, op2, horzEdge->Top); + } + else if (eNext && eNext->Curr.X == horzEdge->Bot.X && eNext->Curr.Y == horzEdge->Bot.Y + && eNext->WindDelta != 0 && eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y + && SlopesEqual(*horzEdge, *eNext, m_UseFullRange)) { + OutPt* op2 = AddOutPt(eNext, horzEdge->Bot); + AddJoin(op1, op2, horzEdge->Top); + } + } + else { + UpdateEdgeIntoAEL(horzEdge); + } + } + else { + if (horzEdge->OutIdx >= 0) { + AddOutPt(horzEdge, horzEdge->Top); + } + DeleteFromAEL(horzEdge); } - else - UpdateEdgeIntoAEL(horzEdge); - } - else - { - if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Top); - DeleteFromAEL(horzEdge); - } } //------------------------------------------------------------------------------ -void Clipper::UpdateEdgeIntoAEL(TEdge *&e) +void Clipper::UpdateEdgeIntoAEL(TEdge*& e) { - if( !e->NextInLML ) throw - clipperException("UpdateEdgeIntoAEL: invalid call"); + if (!e->NextInLML) { + throw clipperException("UpdateEdgeIntoAEL: invalid call"); + } - e->NextInLML->OutIdx = e->OutIdx; - TEdge* AelPrev = e->PrevInAEL; - TEdge* AelNext = e->NextInAEL; - if (AelPrev) AelPrev->NextInAEL = e->NextInLML; - else m_ActiveEdges = e->NextInLML; - if (AelNext) AelNext->PrevInAEL = e->NextInLML; - e->NextInLML->Side = e->Side; - e->NextInLML->WindDelta = e->WindDelta; - e->NextInLML->WindCnt = e->WindCnt; - e->NextInLML->WindCnt2 = e->WindCnt2; - e = e->NextInLML; - e->Curr = e->Bot; - e->PrevInAEL = AelPrev; - e->NextInAEL = AelNext; - if (!IsHorizontal(*e)) InsertScanbeam(e->Top.Y); + e->NextInLML->OutIdx = e->OutIdx; + TEdge* AelPrev = e->PrevInAEL; + TEdge* AelNext = e->NextInAEL; + if (AelPrev) { + AelPrev->NextInAEL = e->NextInLML; + } + else { + m_ActiveEdges = e->NextInLML; + } + if (AelNext) { + AelNext->PrevInAEL = e->NextInLML; + } + e->NextInLML->Side = e->Side; + e->NextInLML->WindDelta = e->WindDelta; + e->NextInLML->WindCnt = e->WindCnt; + e->NextInLML->WindCnt2 = e->WindCnt2; + e = e->NextInLML; + e->Curr = e->Bot; + e->PrevInAEL = AelPrev; + e->NextInAEL = AelNext; + if (!IsHorizontal(*e)) { + InsertScanbeam(e->Top.Y); + } } //------------------------------------------------------------------------------ bool Clipper::ProcessIntersections(const cInt topY) { - if( !m_ActiveEdges ) - return true; - try { - BuildIntersectList(topY); - size_t IlSize = m_IntersectList.size(); - if (IlSize == 0) + if (!m_ActiveEdges) { return true; - if (IlSize == 1 || FixupIntersectionOrder()) ProcessIntersectList(); - else return false; - } - catch(...) - { + } + try { + BuildIntersectList(topY); + size_t IlSize = m_IntersectList.size(); + if (IlSize == 0) { + return true; + } + if (IlSize == 1 || FixupIntersectionOrder()) { + ProcessIntersectList(); + } + else { + return false; + } + } + catch (...) { + m_SortedEdges = 0; + DisposeIntersectNodes(); + throw clipperException("ProcessIntersections error"); + } m_SortedEdges = 0; - DisposeIntersectNodes(); - throw clipperException("ProcessIntersections error"); - } - m_SortedEdges = 0; - return true; + return true; } //------------------------------------------------------------------------------ void Clipper::DisposeIntersectNodes() { - for (size_t i = 0; i < m_IntersectList.size(); ++i ) - delete m_IntersectList[i]; - m_IntersectList.clear(); + for (size_t i = 0; i < m_IntersectList.size(); ++i) { + delete m_IntersectList[i]; + } + m_IntersectList.clear(); } //------------------------------------------------------------------------------ void Clipper::BuildIntersectList(const cInt topY) { - if ( !m_ActiveEdges ) - return; - - //prepare for sorting ... - TEdge* e = m_ActiveEdges; - m_SortedEdges = e; - while( e ) - { - e->PrevInSEL = e->PrevInAEL; - e->NextInSEL = e->NextInAEL; - e->Curr.X = TopX( *e, topY ); - e = e->NextInAEL; - } - - //bubblesort ... - bool isModified; - do - { - isModified = false; - e = m_SortedEdges; - while( e->NextInSEL ) - { - TEdge *eNext = e->NextInSEL; - IntPoint Pt; - if(e->Curr.X > eNext->Curr.X) - { - IntersectPoint(*e, *eNext, Pt); - IntersectNode * newNode = new IntersectNode; - newNode->Edge1 = e; - newNode->Edge2 = eNext; - newNode->Pt = Pt; - m_IntersectList.push_back(newNode); - - SwapPositionsInSEL(e, eNext); - isModified = true; - } - else - e = eNext; + if (!m_ActiveEdges) { + return; } - if( e->PrevInSEL ) e->PrevInSEL->NextInSEL = 0; - else break; - } - while ( isModified ); - m_SortedEdges = 0; //important + + // prepare for sorting ... + TEdge* e = m_ActiveEdges; + m_SortedEdges = e; + while (e) { + e->PrevInSEL = e->PrevInAEL; + e->NextInSEL = e->NextInAEL; + e->Curr.X = TopX(*e, topY); + e = e->NextInAEL; + } + + // bubblesort ... + bool isModified; + do { + isModified = false; + e = m_SortedEdges; + while (e->NextInSEL) { + TEdge* eNext = e->NextInSEL; + IntPoint Pt; + if (e->Curr.X > eNext->Curr.X) { + IntersectPoint(*e, *eNext, Pt); + IntersectNode* newNode = new IntersectNode; + newNode->Edge1 = e; + newNode->Edge2 = eNext; + newNode->Pt = Pt; + m_IntersectList.push_back(newNode); + + SwapPositionsInSEL(e, eNext); + isModified = true; + } + else { + e = eNext; + } + } + if (e->PrevInSEL) { + e->PrevInSEL->NextInSEL = 0; + } + else { + break; + } + } while (isModified); + m_SortedEdges = 0; // important } //------------------------------------------------------------------------------ void Clipper::ProcessIntersectList() { - for (size_t i = 0; i < m_IntersectList.size(); ++i) - { - IntersectNode* iNode = m_IntersectList[i]; - { - IntersectEdges( iNode->Edge1, iNode->Edge2, iNode->Pt); - SwapPositionsInAEL( iNode->Edge1 , iNode->Edge2 ); + for (size_t i = 0; i < m_IntersectList.size(); ++i) { + IntersectNode* iNode = m_IntersectList[i]; + { + IntersectEdges(iNode->Edge1, iNode->Edge2, iNode->Pt); + SwapPositionsInAEL(iNode->Edge1, iNode->Edge2); + } + delete iNode; } - delete iNode; - } - m_IntersectList.clear(); + m_IntersectList.clear(); } //------------------------------------------------------------------------------ bool IntersectListSort(IntersectNode* node1, IntersectNode* node2) { - return node2->Pt.Y < node1->Pt.Y; + return node2->Pt.Y < node1->Pt.Y; } //------------------------------------------------------------------------------ -inline bool EdgesAdjacent(const IntersectNode &inode) +inline bool EdgesAdjacent(const IntersectNode& inode) { - return (inode.Edge1->NextInSEL == inode.Edge2) || - (inode.Edge1->PrevInSEL == inode.Edge2); + return (inode.Edge1->NextInSEL == inode.Edge2) || (inode.Edge1->PrevInSEL == inode.Edge2); } //------------------------------------------------------------------------------ bool Clipper::FixupIntersectionOrder() { - //pre-condition: intersections are sorted Bottom-most first. - //Now it's crucial that intersections are made only between adjacent edges, - //so to ensure this the order of intersections may need adjusting ... - CopyAELToSEL(); - std::sort(m_IntersectList.begin(), m_IntersectList.end(), IntersectListSort); - size_t cnt = m_IntersectList.size(); - for (size_t i = 0; i < cnt; ++i) - { - if (!EdgesAdjacent(*m_IntersectList[i])) - { - size_t j = i + 1; - while (j < cnt && !EdgesAdjacent(*m_IntersectList[j])) j++; - if (j == cnt) - return false; - std::swap(m_IntersectList[i], m_IntersectList[j]); + // pre-condition: intersections are sorted Bottom-most first. + // Now it's crucial that intersections are made only between adjacent edges, + // so to ensure this the order of intersections may need adjusting ... + CopyAELToSEL(); + std::sort(m_IntersectList.begin(), m_IntersectList.end(), IntersectListSort); + size_t cnt = m_IntersectList.size(); + for (size_t i = 0; i < cnt; ++i) { + if (!EdgesAdjacent(*m_IntersectList[i])) { + size_t j = i + 1; + while (j < cnt && !EdgesAdjacent(*m_IntersectList[j])) { + j++; + } + if (j == cnt) { + return false; + } + std::swap(m_IntersectList[i], m_IntersectList[j]); + } + SwapPositionsInSEL(m_IntersectList[i]->Edge1, m_IntersectList[i]->Edge2); } - SwapPositionsInSEL(m_IntersectList[i]->Edge1, m_IntersectList[i]->Edge2); - } - return true; + return true; } //------------------------------------------------------------------------------ -void Clipper::DoMaxima(TEdge *e) +void Clipper::DoMaxima(TEdge* e) { - TEdge* eMaxPair = GetMaximaPair(e); - if (!eMaxPair) - { - if (e->OutIdx >= 0) - AddOutPt(e, e->Top); - DeleteFromAEL(e); - return; - } + TEdge* eMaxPair = GetMaximaPair(e); + if (!eMaxPair) { + if (e->OutIdx >= 0) { + AddOutPt(e, e->Top); + } + DeleteFromAEL(e); + return; + } - TEdge* eNext = e->NextInAEL; - while(eNext && eNext != eMaxPair) - { - IntersectEdges(e, eNext, e->Top); - SwapPositionsInAEL(e, eNext); - eNext = e->NextInAEL; - } + TEdge* eNext = e->NextInAEL; + while (eNext && eNext != eMaxPair) { + IntersectEdges(e, eNext, e->Top); + SwapPositionsInAEL(e, eNext); + eNext = e->NextInAEL; + } - if(e->OutIdx == Unassigned && eMaxPair->OutIdx == Unassigned) - { - DeleteFromAEL(e); - DeleteFromAEL(eMaxPair); - } - else if( e->OutIdx >= 0 && eMaxPair->OutIdx >= 0 ) - { - if (e->OutIdx >= 0) AddLocalMaxPoly(e, eMaxPair, e->Top); - DeleteFromAEL(e); - DeleteFromAEL(eMaxPair); - } + if (e->OutIdx == Unassigned && eMaxPair->OutIdx == Unassigned) { + DeleteFromAEL(e); + DeleteFromAEL(eMaxPair); + } + else if (e->OutIdx >= 0 && eMaxPair->OutIdx >= 0) { + if (e->OutIdx >= 0) { + AddLocalMaxPoly(e, eMaxPair, e->Top); + } + DeleteFromAEL(e); + DeleteFromAEL(eMaxPair); + } #ifdef use_lines - else if (e->WindDelta == 0) - { - if (e->OutIdx >= 0) - { - AddOutPt(e, e->Top); - e->OutIdx = Unassigned; - } - DeleteFromAEL(e); + else if (e->WindDelta == 0) { + if (e->OutIdx >= 0) { + AddOutPt(e, e->Top); + e->OutIdx = Unassigned; + } + DeleteFromAEL(e); - if (eMaxPair->OutIdx >= 0) - { - AddOutPt(eMaxPair, e->Top); - eMaxPair->OutIdx = Unassigned; + if (eMaxPair->OutIdx >= 0) { + AddOutPt(eMaxPair, e->Top); + eMaxPair->OutIdx = Unassigned; + } + DeleteFromAEL(eMaxPair); } - DeleteFromAEL(eMaxPair); - } #endif - else throw clipperException("DoMaxima error"); + else { + throw clipperException("DoMaxima error"); + } } //------------------------------------------------------------------------------ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY) { - TEdge* e = m_ActiveEdges; - while( e ) - { - //1. process maxima, treating them as if they're 'bent' horizontal edges, - // but exclude maxima with horizontal edges. nb: e can't be a horizontal. - bool IsMaximaEdge = IsMaxima(e, topY); + TEdge* e = m_ActiveEdges; + while (e) { + // 1. process maxima, treating them as if they're 'bent' horizontal edges, + // but exclude maxima with horizontal edges. nb: e can't be a horizontal. + bool IsMaximaEdge = IsMaxima(e, topY); - if(IsMaximaEdge) - { - TEdge* eMaxPair = GetMaximaPair(e); - IsMaximaEdge = (!eMaxPair || !IsHorizontal(*eMaxPair)); - } - - if(IsMaximaEdge) - { - TEdge* ePrev = e->PrevInAEL; - DoMaxima(e); - if( !ePrev ) e = m_ActiveEdges; - else e = ePrev->NextInAEL; - } - else - { - //2. promote horizontal edges, otherwise update Curr.X and Curr.Y ... - if (IsIntermediate(e, topY) && IsHorizontal(*e->NextInLML)) - { - UpdateEdgeIntoAEL(e); - if (e->OutIdx >= 0) - AddOutPt(e, e->Bot); - AddEdgeToSEL(e); - } - else - { - e->Curr.X = TopX( *e, topY ); - e->Curr.Y = topY; - } - - if (m_StrictSimple) - { - TEdge* ePrev = e->PrevInAEL; - if ((e->OutIdx >= 0) && (e->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) && - (ePrev->Curr.X == e->Curr.X) && (ePrev->WindDelta != 0)) - { - IntPoint pt = e->Curr; -#ifdef use_xyz - SetZ(pt, *ePrev, *e); -#endif - OutPt* op = AddOutPt(ePrev, pt); - OutPt* op2 = AddOutPt(e, pt); - AddJoin(op, op2, pt); //StrictlySimple (type-3) join + if (IsMaximaEdge) { + TEdge* eMaxPair = GetMaximaPair(e); + IsMaximaEdge = (!eMaxPair || !IsHorizontal(*eMaxPair)); } - } - e = e->NextInAEL; + if (IsMaximaEdge) { + TEdge* ePrev = e->PrevInAEL; + DoMaxima(e); + if (!ePrev) { + e = m_ActiveEdges; + } + else { + e = ePrev->NextInAEL; + } + } + else { + // 2. promote horizontal edges, otherwise update Curr.X and Curr.Y ... + if (IsIntermediate(e, topY) && IsHorizontal(*e->NextInLML)) { + UpdateEdgeIntoAEL(e); + if (e->OutIdx >= 0) { + AddOutPt(e, e->Bot); + } + AddEdgeToSEL(e); + } + else { + e->Curr.X = TopX(*e, topY); + e->Curr.Y = topY; + } + + if (m_StrictSimple) { + TEdge* ePrev = e->PrevInAEL; + if ((e->OutIdx >= 0) && (e->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) + && (ePrev->Curr.X == e->Curr.X) && (ePrev->WindDelta != 0)) { + IntPoint pt = e->Curr; +#ifdef use_xyz + SetZ(pt, *ePrev, *e); +#endif + OutPt* op = AddOutPt(ePrev, pt); + OutPt* op2 = AddOutPt(e, pt); + AddJoin(op, op2, pt); // StrictlySimple (type-3) join + } + } + + e = e->NextInAEL; + } } - } - //3. Process horizontals at the Top of the scanbeam ... - ProcessHorizontals(true); + // 3. Process horizontals at the Top of the scanbeam ... + ProcessHorizontals(true); - //4. Promote intermediate vertices ... - e = m_ActiveEdges; - while(e) - { - if(IsIntermediate(e, topY)) - { - OutPt* op = 0; - if( e->OutIdx >= 0 ) - op = AddOutPt(e, e->Top); - UpdateEdgeIntoAEL(e); + // 4. Promote intermediate vertices ... + e = m_ActiveEdges; + while (e) { + if (IsIntermediate(e, topY)) { + OutPt* op = 0; + if (e->OutIdx >= 0) { + op = AddOutPt(e, e->Top); + } + UpdateEdgeIntoAEL(e); - //if output polygons share an edge, they'll need joining later ... - TEdge* ePrev = e->PrevInAEL; - TEdge* eNext = e->NextInAEL; - if (ePrev && ePrev->Curr.X == e->Bot.X && - ePrev->Curr.Y == e->Bot.Y && op && - ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y && - SlopesEqual(*e, *ePrev, m_UseFullRange) && - (e->WindDelta != 0) && (ePrev->WindDelta != 0)) - { - OutPt* op2 = AddOutPt(ePrev, e->Bot); - AddJoin(op, op2, e->Top); - } - else if (eNext && eNext->Curr.X == e->Bot.X && - eNext->Curr.Y == e->Bot.Y && op && - eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y && - SlopesEqual(*e, *eNext, m_UseFullRange) && - (e->WindDelta != 0) && (eNext->WindDelta != 0)) - { - OutPt* op2 = AddOutPt(eNext, e->Bot); - AddJoin(op, op2, e->Top); - } + // if output polygons share an edge, they'll need joining later ... + TEdge* ePrev = e->PrevInAEL; + TEdge* eNext = e->NextInAEL; + if (ePrev && ePrev->Curr.X == e->Bot.X && ePrev->Curr.Y == e->Bot.Y && op + && ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y + && SlopesEqual(*e, *ePrev, m_UseFullRange) && (e->WindDelta != 0) + && (ePrev->WindDelta != 0)) { + OutPt* op2 = AddOutPt(ePrev, e->Bot); + AddJoin(op, op2, e->Top); + } + else if (eNext && eNext->Curr.X == e->Bot.X && eNext->Curr.Y == e->Bot.Y && op + && eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y + && SlopesEqual(*e, *eNext, m_UseFullRange) && (e->WindDelta != 0) + && (eNext->WindDelta != 0)) { + OutPt* op2 = AddOutPt(eNext, e->Bot); + AddJoin(op, op2, e->Top); + } + } + e = e->NextInAEL; } - e = e->NextInAEL; - } } //------------------------------------------------------------------------------ -void Clipper::FixupOutPolygon(OutRec &outrec) +void Clipper::FixupOutPolygon(OutRec& outrec) { - //FixupOutPolygon() - removes duplicate points and simplifies consecutive - //parallel edges by removing the middle vertex. - OutPt *lastOK = 0; - outrec.BottomPt = 0; - OutPt *pp = outrec.Pts; + // FixupOutPolygon() - removes duplicate points and simplifies consecutive + // parallel edges by removing the middle vertex. + OutPt* lastOK = 0; + outrec.BottomPt = 0; + OutPt* pp = outrec.Pts; - for (;;) - { - if (pp->Prev == pp || pp->Prev == pp->Next ) - { - DisposeOutPts(pp); - outrec.Pts = 0; - return; - } + for (;;) { + if (pp->Prev == pp || pp->Prev == pp->Next) { + DisposeOutPts(pp); + outrec.Pts = 0; + return; + } - //test for duplicate points and collinear edges ... - if ((pp->Pt == pp->Next->Pt) || (pp->Pt == pp->Prev->Pt) || - (SlopesEqual(pp->Prev->Pt, pp->Pt, pp->Next->Pt, m_UseFullRange) && - (!m_PreserveCollinear || - !Pt2IsBetweenPt1AndPt3(pp->Prev->Pt, pp->Pt, pp->Next->Pt)))) - { - lastOK = 0; - OutPt *tmp = pp; - pp->Prev->Next = pp->Next; - pp->Next->Prev = pp->Prev; - pp = pp->Prev; - delete tmp; + // test for duplicate points and collinear edges ... + if ((pp->Pt == pp->Next->Pt) || (pp->Pt == pp->Prev->Pt) + || (SlopesEqual(pp->Prev->Pt, pp->Pt, pp->Next->Pt, m_UseFullRange) + && (!m_PreserveCollinear + || !Pt2IsBetweenPt1AndPt3(pp->Prev->Pt, pp->Pt, pp->Next->Pt)))) { + lastOK = 0; + OutPt* tmp = pp; + pp->Prev->Next = pp->Next; + pp->Next->Prev = pp->Prev; + pp = pp->Prev; + delete tmp; + } + else if (pp == lastOK) { + break; + } + else { + if (!lastOK) { + lastOK = pp; + } + pp = pp->Next; + } } - else if (pp == lastOK) break; - else - { - if (!lastOK) lastOK = pp; - pp = pp->Next; - } - } - outrec.Pts = pp; + outrec.Pts = pp; } //------------------------------------------------------------------------------ -int PointCount(OutPt *Pts) +int PointCount(OutPt* Pts) { - if (!Pts) + if (!Pts) { return 0; + } int result = 0; OutPt* p = Pts; - do - { + do { result++; p = p->Next; - } - while (p != Pts); + } while (p != Pts); return result; } //------------------------------------------------------------------------------ -void Clipper::BuildResult(Paths &polys) +void Clipper::BuildResult(Paths& polys) { - polys.reserve(m_PolyOuts.size()); - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - { - if (!m_PolyOuts[i]->Pts) continue; - Path pg; - OutPt* p = m_PolyOuts[i]->Pts->Prev; - int cnt = PointCount(p); - if (cnt < 2) continue; - pg.reserve(cnt); - for (int i = 0; i < cnt; ++i) - { - pg.push_back(p->Pt); - p = p->Prev; + polys.reserve(m_PolyOuts.size()); + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { + if (!m_PolyOuts[i]->Pts) { + continue; + } + Path pg; + OutPt* p = m_PolyOuts[i]->Pts->Prev; + int cnt = PointCount(p); + if (cnt < 2) { + continue; + } + pg.reserve(cnt); + for (int i = 0; i < cnt; ++i) { + pg.push_back(p->Pt); + p = p->Prev; + } + polys.push_back(pg); } - polys.push_back(pg); - } } //------------------------------------------------------------------------------ @@ -3109,555 +3456,609 @@ void Clipper::BuildResult2(PolyTree& polytree) { polytree.Clear(); polytree.AllNodes.reserve(m_PolyOuts.size()); - //add each output polygon/contour to polytree ... - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); i++) - { + // add each output polygon/contour to polytree ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); i++) { OutRec* outRec = m_PolyOuts[i]; int cnt = PointCount(outRec->Pts); - if ((outRec->IsOpen && cnt < 2) || (!outRec->IsOpen && cnt < 3)) continue; + if ((outRec->IsOpen && cnt < 2) || (!outRec->IsOpen && cnt < 3)) { + continue; + } FixHoleLinkage(*outRec); PolyNode* pn = new PolyNode(); - //nb: polytree takes ownership of all the PolyNodes + // nb: polytree takes ownership of all the PolyNodes polytree.AllNodes.push_back(pn); outRec->PolyNd = pn; pn->Parent = 0; pn->Index = 0; pn->Contour.reserve(cnt); - OutPt *op = outRec->Pts->Prev; - for (int j = 0; j < cnt; j++) - { + OutPt* op = outRec->Pts->Prev; + for (int j = 0; j < cnt; j++) { pn->Contour.push_back(op->Pt); op = op->Prev; } } - //fixup PolyNode links etc ... + // fixup PolyNode links etc ... polytree.Childs.reserve(m_PolyOuts.size()); - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); i++) - { + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); i++) { OutRec* outRec = m_PolyOuts[i]; - if (!outRec->PolyNd) continue; - if (outRec->IsOpen) - { - outRec->PolyNd->m_IsOpen = true; - polytree.AddChild(*outRec->PolyNd); + if (!outRec->PolyNd) { + continue; + } + if (outRec->IsOpen) { + outRec->PolyNd->m_IsOpen = true; + polytree.AddChild(*outRec->PolyNd); + } + else if (outRec->FirstLeft && outRec->FirstLeft->PolyNd) { + outRec->FirstLeft->PolyNd->AddChild(*outRec->PolyNd); + } + else { + polytree.AddChild(*outRec->PolyNd); } - else if (outRec->FirstLeft && outRec->FirstLeft->PolyNd) - outRec->FirstLeft->PolyNd->AddChild(*outRec->PolyNd); - else - polytree.AddChild(*outRec->PolyNd); } } //------------------------------------------------------------------------------ -void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2) +void SwapIntersectNodes(IntersectNode& int1, IntersectNode& int2) { - //just swap the contents (because fIntersectNodes is a single-linked-list) - IntersectNode inode = int1; //gets a copy of Int1 - int1.Edge1 = int2.Edge1; - int1.Edge2 = int2.Edge2; - int1.Pt = int2.Pt; - int2.Edge1 = inode.Edge1; - int2.Edge2 = inode.Edge2; - int2.Pt = inode.Pt; + // just swap the contents (because fIntersectNodes is a single-linked-list) + IntersectNode inode = int1; // gets a copy of Int1 + int1.Edge1 = int2.Edge1; + int1.Edge2 = int2.Edge2; + int1.Pt = int2.Pt; + int2.Edge1 = inode.Edge1; + int2.Edge2 = inode.Edge2; + int2.Pt = inode.Pt; } //------------------------------------------------------------------------------ -inline bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) +inline bool E2InsertsBeforeE1(TEdge& e1, TEdge& e2) { - if (e2.Curr.X == e1.Curr.X) - { - if (e2.Top.Y > e1.Top.Y) - return e2.Top.X < TopX(e1, e2.Top.Y); - else return e1.Top.X > TopX(e2, e1.Top.Y); - } - else return e2.Curr.X < e1.Curr.X; + if (e2.Curr.X == e1.Curr.X) { + if (e2.Top.Y > e1.Top.Y) { + return e2.Top.X < TopX(e1, e2.Top.Y); + } + else { + return e1.Top.X > TopX(e2, e1.Top.Y); + } + } + else { + return e2.Curr.X < e1.Curr.X; + } } //------------------------------------------------------------------------------ -bool GetOverlap(const cInt a1, const cInt a2, const cInt b1, const cInt b2, - cInt& Left, cInt& Right) +bool GetOverlap(const cInt a1, const cInt a2, const cInt b1, const cInt b2, cInt& Left, cInt& Right) { - if (a1 < a2) - { - if (b1 < b2) {Left = std::max(a1,b1); Right = std::min(a2,b2);} - else {Left = std::max(a1,b2); Right = std::min(a2,b1);} - } - else - { - if (b1 < b2) {Left = std::max(a2,b1); Right = std::min(a1,b2);} - else {Left = std::max(a2,b2); Right = std::min(a1,b1);} - } - return Left < Right; + if (a1 < a2) { + if (b1 < b2) { + Left = std::max(a1, b1); + Right = std::min(a2, b2); + } + else { + Left = std::max(a1, b2); + Right = std::min(a2, b1); + } + } + else { + if (b1 < b2) { + Left = std::max(a2, b1); + Right = std::min(a1, b2); + } + else { + Left = std::max(a2, b2); + Right = std::min(a1, b1); + } + } + return Left < Right; } //------------------------------------------------------------------------------ inline void UpdateOutPtIdxs(OutRec& outrec) -{ - OutPt* op = outrec.Pts; - do - { - op->Idx = outrec.Idx; - op = op->Prev; - } - while(op != outrec.Pts); +{ + OutPt* op = outrec.Pts; + do { + op->Idx = outrec.Idx; + op = op->Prev; + } while (op != outrec.Pts); } //------------------------------------------------------------------------------ -void Clipper::InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge) +void Clipper::InsertEdgeIntoAEL(TEdge* edge, TEdge* startEdge) { - if(!m_ActiveEdges) - { - edge->PrevInAEL = 0; - edge->NextInAEL = 0; - m_ActiveEdges = edge; - } - else if(!startEdge && E2InsertsBeforeE1(*m_ActiveEdges, *edge)) - { - edge->PrevInAEL = 0; - edge->NextInAEL = m_ActiveEdges; - m_ActiveEdges->PrevInAEL = edge; - m_ActiveEdges = edge; - } - else - { - if(!startEdge) startEdge = m_ActiveEdges; - while(startEdge->NextInAEL && - !E2InsertsBeforeE1(*startEdge->NextInAEL , *edge)) - startEdge = startEdge->NextInAEL; - edge->NextInAEL = startEdge->NextInAEL; - if(startEdge->NextInAEL) startEdge->NextInAEL->PrevInAEL = edge; - edge->PrevInAEL = startEdge; - startEdge->NextInAEL = edge; - } + if (!m_ActiveEdges) { + edge->PrevInAEL = 0; + edge->NextInAEL = 0; + m_ActiveEdges = edge; + } + else if (!startEdge && E2InsertsBeforeE1(*m_ActiveEdges, *edge)) { + edge->PrevInAEL = 0; + edge->NextInAEL = m_ActiveEdges; + m_ActiveEdges->PrevInAEL = edge; + m_ActiveEdges = edge; + } + else { + if (!startEdge) { + startEdge = m_ActiveEdges; + } + while (startEdge->NextInAEL && !E2InsertsBeforeE1(*startEdge->NextInAEL, *edge)) { + startEdge = startEdge->NextInAEL; + } + edge->NextInAEL = startEdge->NextInAEL; + if (startEdge->NextInAEL) { + startEdge->NextInAEL->PrevInAEL = edge; + } + edge->PrevInAEL = startEdge; + startEdge->NextInAEL = edge; + } } //---------------------------------------------------------------------- OutPt* DupOutPt(OutPt* outPt, bool InsertAfter) { - OutPt* result = new OutPt; - result->Pt = outPt->Pt; - result->Idx = outPt->Idx; - if (InsertAfter) - { - result->Next = outPt->Next; - result->Prev = outPt; - outPt->Next->Prev = result; - outPt->Next = result; - } - else - { - result->Prev = outPt->Prev; - result->Next = outPt; - outPt->Prev->Next = result; - outPt->Prev = result; - } - return result; + OutPt* result = new OutPt; + result->Pt = outPt->Pt; + result->Idx = outPt->Idx; + if (InsertAfter) { + result->Next = outPt->Next; + result->Prev = outPt; + outPt->Next->Prev = result; + outPt->Next = result; + } + else { + result->Prev = outPt->Prev; + result->Next = outPt; + outPt->Prev->Next = result; + outPt->Prev = result; + } + return result; } //------------------------------------------------------------------------------ -bool JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b, - const IntPoint Pt, bool DiscardLeft) +bool JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b, const IntPoint Pt, bool DiscardLeft) { - Direction Dir1 = (op1->Pt.X > op1b->Pt.X ? dRightToLeft : dLeftToRight); - Direction Dir2 = (op2->Pt.X > op2b->Pt.X ? dRightToLeft : dLeftToRight); - if (Dir1 == Dir2) - return false; - - //When DiscardLeft, we want Op1b to be on the Left of Op1, otherwise we - //want Op1b to be on the Right. (And likewise with Op2 and Op2b.) - //So, to facilitate this while inserting Op1b and Op2b ... - //when DiscardLeft, make sure we're AT or RIGHT of Pt before adding Op1b, - //otherwise make sure we're AT or LEFT of Pt. (Likewise with Op2b.) - if (Dir1 == dLeftToRight) - { - while (op1->Next->Pt.X <= Pt.X && - op1->Next->Pt.X >= op1->Pt.X && op1->Next->Pt.Y == Pt.Y) - op1 = op1->Next; - if (DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next; - op1b = DupOutPt(op1, !DiscardLeft); - if (op1b->Pt != Pt) - { - op1 = op1b; - op1->Pt = Pt; - op1b = DupOutPt(op1, !DiscardLeft); + Direction Dir1 = (op1->Pt.X > op1b->Pt.X ? dRightToLeft : dLeftToRight); + Direction Dir2 = (op2->Pt.X > op2b->Pt.X ? dRightToLeft : dLeftToRight); + if (Dir1 == Dir2) { + return false; } - } - else - { - while (op1->Next->Pt.X >= Pt.X && - op1->Next->Pt.X <= op1->Pt.X && op1->Next->Pt.Y == Pt.Y) - op1 = op1->Next; - if (!DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next; - op1b = DupOutPt(op1, DiscardLeft); - if (op1b->Pt != Pt) - { - op1 = op1b; - op1->Pt = Pt; - op1b = DupOutPt(op1, DiscardLeft); + + // When DiscardLeft, we want Op1b to be on the Left of Op1, otherwise we + // want Op1b to be on the Right. (And likewise with Op2 and Op2b.) + // So, to facilitate this while inserting Op1b and Op2b ... + // when DiscardLeft, make sure we're AT or RIGHT of Pt before adding Op1b, + // otherwise make sure we're AT or LEFT of Pt. (Likewise with Op2b.) + if (Dir1 == dLeftToRight) { + while (op1->Next->Pt.X <= Pt.X && op1->Next->Pt.X >= op1->Pt.X && op1->Next->Pt.Y == Pt.Y) { + op1 = op1->Next; + } + if (DiscardLeft && (op1->Pt.X != Pt.X)) { + op1 = op1->Next; + } + op1b = DupOutPt(op1, !DiscardLeft); + if (op1b->Pt != Pt) { + op1 = op1b; + op1->Pt = Pt; + op1b = DupOutPt(op1, !DiscardLeft); + } + } + else { + while (op1->Next->Pt.X >= Pt.X && op1->Next->Pt.X <= op1->Pt.X && op1->Next->Pt.Y == Pt.Y) { + op1 = op1->Next; + } + if (!DiscardLeft && (op1->Pt.X != Pt.X)) { + op1 = op1->Next; + } + op1b = DupOutPt(op1, DiscardLeft); + if (op1b->Pt != Pt) { + op1 = op1b; + op1->Pt = Pt; + op1b = DupOutPt(op1, DiscardLeft); + } } - } - if (Dir2 == dLeftToRight) - { - while (op2->Next->Pt.X <= Pt.X && - op2->Next->Pt.X >= op2->Pt.X && op2->Next->Pt.Y == Pt.Y) - op2 = op2->Next; - if (DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next; - op2b = DupOutPt(op2, !DiscardLeft); - if (op2b->Pt != Pt) - { - op2 = op2b; - op2->Pt = Pt; - op2b = DupOutPt(op2, !DiscardLeft); + if (Dir2 == dLeftToRight) { + while (op2->Next->Pt.X <= Pt.X && op2->Next->Pt.X >= op2->Pt.X && op2->Next->Pt.Y == Pt.Y) { + op2 = op2->Next; + } + if (DiscardLeft && (op2->Pt.X != Pt.X)) { + op2 = op2->Next; + } + op2b = DupOutPt(op2, !DiscardLeft); + if (op2b->Pt != Pt) { + op2 = op2b; + op2->Pt = Pt; + op2b = DupOutPt(op2, !DiscardLeft); + }; + } + else { + while (op2->Next->Pt.X >= Pt.X && op2->Next->Pt.X <= op2->Pt.X && op2->Next->Pt.Y == Pt.Y) { + op2 = op2->Next; + } + if (!DiscardLeft && (op2->Pt.X != Pt.X)) { + op2 = op2->Next; + } + op2b = DupOutPt(op2, DiscardLeft); + if (op2b->Pt != Pt) { + op2 = op2b; + op2->Pt = Pt; + op2b = DupOutPt(op2, DiscardLeft); + }; }; - } else - { - while (op2->Next->Pt.X >= Pt.X && - op2->Next->Pt.X <= op2->Pt.X && op2->Next->Pt.Y == Pt.Y) - op2 = op2->Next; - if (!DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next; - op2b = DupOutPt(op2, DiscardLeft); - if (op2b->Pt != Pt) - { - op2 = op2b; - op2->Pt = Pt; - op2b = DupOutPt(op2, DiscardLeft); - }; - }; - if ((Dir1 == dLeftToRight) == DiscardLeft) - { - op1->Prev = op2; - op2->Next = op1; - op1b->Next = op2b; - op2b->Prev = op1b; - } - else - { - op1->Next = op2; - op2->Prev = op1; - op1b->Prev = op2b; - op2b->Next = op1b; - } - return true; + if ((Dir1 == dLeftToRight) == DiscardLeft) { + op1->Prev = op2; + op2->Next = op1; + op1b->Next = op2b; + op2b->Prev = op1b; + } + else { + op1->Next = op2; + op2->Prev = op1; + op1b->Prev = op2b; + op2b->Next = op1b; + } + return true; } //------------------------------------------------------------------------------ -bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2) +bool Clipper::JoinPoints(Join* j, OutRec* outRec1, OutRec* outRec2) { - OutPt *op1 = j->OutPt1, *op1b; - OutPt *op2 = j->OutPt2, *op2b; + OutPt *op1 = j->OutPt1, *op1b; + OutPt *op2 = j->OutPt2, *op2b; - //There are 3 kinds of joins for output polygons ... - //1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are a vertices anywhere - //along (horizontal) collinear edges (& Join.OffPt is on the same horizontal). - //2. Non-horizontal joins where Join.OutPt1 & Join.OutPt2 are at the same - //location at the Bottom of the overlapping segment (& Join.OffPt is above). - //3. StrictSimple joins where edges touch but are not collinear and where - //Join.OutPt1, Join.OutPt2 & Join.OffPt all share the same point. - bool isHorizontal = (j->OutPt1->Pt.Y == j->OffPt.Y); + // There are 3 kinds of joins for output polygons ... + // 1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are a vertices anywhere + // along (horizontal) collinear edges (& Join.OffPt is on the same horizontal). + // 2. Non-horizontal joins where Join.OutPt1 & Join.OutPt2 are at the same + // location at the Bottom of the overlapping segment (& Join.OffPt is above). + // 3. StrictSimple joins where edges touch but are not collinear and where + // Join.OutPt1, Join.OutPt2 & Join.OffPt all share the same point. + bool isHorizontal = (j->OutPt1->Pt.Y == j->OffPt.Y); - if (isHorizontal && (j->OffPt == j->OutPt1->Pt) && - (j->OffPt == j->OutPt2->Pt)) - { - //Strictly Simple join ... - if (outRec1 != outRec2) - return false; - op1b = j->OutPt1->Next; - while (op1b != op1 && (op1b->Pt == j->OffPt)) - op1b = op1b->Next; - bool reverse1 = (op1b->Pt.Y > j->OffPt.Y); - op2b = j->OutPt2->Next; - while (op2b != op2 && (op2b->Pt == j->OffPt)) - op2b = op2b->Next; - bool reverse2 = (op2b->Pt.Y > j->OffPt.Y); - if (reverse1 == reverse2) - return false; - if (reverse1) - { - op1b = DupOutPt(op1, false); - op2b = DupOutPt(op2, true); - op1->Prev = op2; - op2->Next = op1; - op1b->Next = op2b; - op2b->Prev = op1b; - j->OutPt1 = op1; - j->OutPt2 = op1b; - return true; - } else - { - op1b = DupOutPt(op1, true); - op2b = DupOutPt(op2, false); - op1->Next = op2; - op2->Prev = op1; - op1b->Prev = op2b; - op2b->Next = op1b; - j->OutPt1 = op1; - j->OutPt2 = op1b; - return true; + if (isHorizontal && (j->OffPt == j->OutPt1->Pt) && (j->OffPt == j->OutPt2->Pt)) { + // Strictly Simple join ... + if (outRec1 != outRec2) { + return false; + } + op1b = j->OutPt1->Next; + while (op1b != op1 && (op1b->Pt == j->OffPt)) { + op1b = op1b->Next; + } + bool reverse1 = (op1b->Pt.Y > j->OffPt.Y); + op2b = j->OutPt2->Next; + while (op2b != op2 && (op2b->Pt == j->OffPt)) { + op2b = op2b->Next; + } + bool reverse2 = (op2b->Pt.Y > j->OffPt.Y); + if (reverse1 == reverse2) { + return false; + } + if (reverse1) { + op1b = DupOutPt(op1, false); + op2b = DupOutPt(op2, true); + op1->Prev = op2; + op2->Next = op1; + op1b->Next = op2b; + op2b->Prev = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } + else { + op1b = DupOutPt(op1, true); + op2b = DupOutPt(op2, false); + op1->Next = op2; + op2->Prev = op1; + op1b->Prev = op2b; + op2b->Next = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } } - } - else if (isHorizontal) - { - //treat horizontal joins differently to non-horizontal joins since with - //them we're not yet sure where the overlapping is. OutPt1.Pt & OutPt2.Pt - //may be anywhere along the horizontal edge. - op1b = op1; - while (op1->Prev->Pt.Y == op1->Pt.Y && op1->Prev != op1b && op1->Prev != op2) - op1 = op1->Prev; - while (op1b->Next->Pt.Y == op1b->Pt.Y && op1b->Next != op1 && op1b->Next != op2) - op1b = op1b->Next; - if (op1b->Next == op1 || op1b->Next == op2) //a flat 'polygon' - return false; + else if (isHorizontal) { + // treat horizontal joins differently to non-horizontal joins since with + // them we're not yet sure where the overlapping is. OutPt1.Pt & OutPt2.Pt + // may be anywhere along the horizontal edge. + op1b = op1; + while (op1->Prev->Pt.Y == op1->Pt.Y && op1->Prev != op1b && op1->Prev != op2) { + op1 = op1->Prev; + } + while (op1b->Next->Pt.Y == op1b->Pt.Y && op1b->Next != op1 && op1b->Next != op2) { + op1b = op1b->Next; + } + if (op1b->Next == op1 || op1b->Next == op2) { // a flat 'polygon' + return false; + } - op2b = op2; - while (op2->Prev->Pt.Y == op2->Pt.Y && op2->Prev != op2b && op2->Prev != op1b) - op2 = op2->Prev; - while (op2b->Next->Pt.Y == op2b->Pt.Y && op2b->Next != op2 && op2b->Next != op1) - op2b = op2b->Next; - if (op2b->Next == op2 || op2b->Next == op1) //a flat 'polygon' - return false; + op2b = op2; + while (op2->Prev->Pt.Y == op2->Pt.Y && op2->Prev != op2b && op2->Prev != op1b) { + op2 = op2->Prev; + } + while (op2b->Next->Pt.Y == op2b->Pt.Y && op2b->Next != op2 && op2b->Next != op1) { + op2b = op2b->Next; + } + if (op2b->Next == op2 || op2b->Next == op1) { // a flat 'polygon' + return false; + } - cInt Left, Right; - //Op1 --> Op1b & Op2 --> Op2b are the extremites of the horizontal edges - if (!GetOverlap(op1->Pt.X, op1b->Pt.X, op2->Pt.X, op2b->Pt.X, Left, Right)) - return false; + cInt Left, Right; + // Op1 --> Op1b & Op2 --> Op2b are the extremites of the horizontal edges + if (!GetOverlap(op1->Pt.X, op1b->Pt.X, op2->Pt.X, op2b->Pt.X, Left, Right)) { + return false; + } - //DiscardLeftSide: when overlapping edges are joined, a spike will created - //which needs to be cleaned up. However, we don't want Op1 or Op2 caught up - //on the discard Side as either may still be needed for other joins ... - IntPoint Pt; - bool DiscardLeftSide; - if (op1->Pt.X >= Left && op1->Pt.X <= Right) - { - Pt = op1->Pt; DiscardLeftSide = (op1->Pt.X > op1b->Pt.X); - } - else if (op2->Pt.X >= Left&& op2->Pt.X <= Right) - { - Pt = op2->Pt; DiscardLeftSide = (op2->Pt.X > op2b->Pt.X); - } - else if (op1b->Pt.X >= Left && op1b->Pt.X <= Right) - { - Pt = op1b->Pt; DiscardLeftSide = op1b->Pt.X > op1->Pt.X; - } - else - { - Pt = op2b->Pt; DiscardLeftSide = (op2b->Pt.X > op2->Pt.X); + // DiscardLeftSide: when overlapping edges are joined, a spike will created + // which needs to be cleaned up. However, we don't want Op1 or Op2 caught up + // on the discard Side as either may still be needed for other joins ... + IntPoint Pt; + bool DiscardLeftSide; + if (op1->Pt.X >= Left && op1->Pt.X <= Right) { + Pt = op1->Pt; + DiscardLeftSide = (op1->Pt.X > op1b->Pt.X); + } + else if (op2->Pt.X >= Left && op2->Pt.X <= Right) { + Pt = op2->Pt; + DiscardLeftSide = (op2->Pt.X > op2b->Pt.X); + } + else if (op1b->Pt.X >= Left && op1b->Pt.X <= Right) { + Pt = op1b->Pt; + DiscardLeftSide = op1b->Pt.X > op1->Pt.X; + } + else { + Pt = op2b->Pt; + DiscardLeftSide = (op2b->Pt.X > op2->Pt.X); + } + j->OutPt1 = op1; + j->OutPt2 = op2; + return JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide); } - j->OutPt1 = op1; j->OutPt2 = op2; - return JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide); - } else - { - //nb: For non-horizontal joins ... - // 1. Jr.OutPt1.Pt.Y == Jr.OutPt2.Pt.Y - // 2. Jr.OutPt1.Pt > Jr.OffPt.Y + else { + // nb: For non-horizontal joins ... + // 1. Jr.OutPt1.Pt.Y == Jr.OutPt2.Pt.Y + // 2. Jr.OutPt1.Pt > Jr.OffPt.Y - //make sure the polygons are correctly oriented ... - op1b = op1->Next; - while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Next; - bool Reverse1 = ((op1b->Pt.Y > op1->Pt.Y) || - !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)); - if (Reverse1) - { - op1b = op1->Prev; - while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Prev; - if ((op1b->Pt.Y > op1->Pt.Y) || - !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)) return false; - }; - op2b = op2->Next; - while ((op2b->Pt == op2->Pt) && (op2b != op2))op2b = op2b->Next; - bool Reverse2 = ((op2b->Pt.Y > op2->Pt.Y) || - !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)); - if (Reverse2) - { - op2b = op2->Prev; - while ((op2b->Pt == op2->Pt) && (op2b != op2)) op2b = op2b->Prev; - if ((op2b->Pt.Y > op2->Pt.Y) || - !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)) return false; + // make sure the polygons are correctly oriented ... + op1b = op1->Next; + while ((op1b->Pt == op1->Pt) && (op1b != op1)) { + op1b = op1b->Next; + } + bool Reverse1 = + ((op1b->Pt.Y > op1->Pt.Y) || !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)); + if (Reverse1) { + op1b = op1->Prev; + while ((op1b->Pt == op1->Pt) && (op1b != op1)) { + op1b = op1b->Prev; + } + if ((op1b->Pt.Y > op1->Pt.Y) + || !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)) { + return false; + } + }; + op2b = op2->Next; + while ((op2b->Pt == op2->Pt) && (op2b != op2)) { + op2b = op2b->Next; + } + bool Reverse2 = + ((op2b->Pt.Y > op2->Pt.Y) || !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)); + if (Reverse2) { + op2b = op2->Prev; + while ((op2b->Pt == op2->Pt) && (op2b != op2)) { + op2b = op2b->Prev; + } + if ((op2b->Pt.Y > op2->Pt.Y) + || !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)) { + return false; + } + } + + if ((op1b == op1) || (op2b == op2) || (op1b == op2b) + || ((outRec1 == outRec2) && (Reverse1 == Reverse2))) { + return false; + } + + if (Reverse1) { + op1b = DupOutPt(op1, false); + op2b = DupOutPt(op2, true); + op1->Prev = op2; + op2->Next = op1; + op1b->Next = op2b; + op2b->Prev = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } + else { + op1b = DupOutPt(op1, true); + op2b = DupOutPt(op2, false); + op1->Next = op2; + op2->Prev = op1; + op1b->Prev = op2b; + op2b->Next = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } } - - if ((op1b == op1) || (op2b == op2) || (op1b == op2b) || - ((outRec1 == outRec2) && (Reverse1 == Reverse2))) return false; - - if (Reverse1) - { - op1b = DupOutPt(op1, false); - op2b = DupOutPt(op2, true); - op1->Prev = op2; - op2->Next = op1; - op1b->Next = op2b; - op2b->Prev = op1b; - j->OutPt1 = op1; - j->OutPt2 = op1b; - return true; - } else - { - op1b = DupOutPt(op1, true); - op2b = DupOutPt(op2, false); - op1->Next = op2; - op2->Prev = op1; - op1b->Prev = op2b; - op2b->Next = op1b; - j->OutPt1 = op1; - j->OutPt2 = op1b; - return true; - } - } } //---------------------------------------------------------------------- static OutRec* ParseFirstLeft(OutRec* FirstLeft) { - while (FirstLeft && !FirstLeft->Pts) - FirstLeft = FirstLeft->FirstLeft; - return FirstLeft; + while (FirstLeft && !FirstLeft->Pts) { + FirstLeft = FirstLeft->FirstLeft; + } + return FirstLeft; } //------------------------------------------------------------------------------ void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec) -{ - //tests if NewOutRec contains the polygon before reassigning FirstLeft - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - { - OutRec* outRec = m_PolyOuts[i]; - if (!outRec->Pts || !outRec->FirstLeft) continue; - OutRec* firstLeft = ParseFirstLeft(outRec->FirstLeft); - if (firstLeft == OldOutRec) - { - if (Poly2ContainsPoly1(outRec->Pts, NewOutRec->Pts)) - outRec->FirstLeft = NewOutRec; +{ + // tests if NewOutRec contains the polygon before reassigning FirstLeft + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { + OutRec* outRec = m_PolyOuts[i]; + if (!outRec->Pts || !outRec->FirstLeft) { + continue; + } + OutRec* firstLeft = ParseFirstLeft(outRec->FirstLeft); + if (firstLeft == OldOutRec) { + if (Poly2ContainsPoly1(outRec->Pts, NewOutRec->Pts)) { + outRec->FirstLeft = NewOutRec; + } + } } - } } //---------------------------------------------------------------------- void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec) -{ - //reassigns FirstLeft WITHOUT testing if NewOutRec contains the polygon - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - { - OutRec* outRec = m_PolyOuts[i]; - if (outRec->FirstLeft == OldOutRec) outRec->FirstLeft = NewOutRec; - } +{ + // reassigns FirstLeft WITHOUT testing if NewOutRec contains the polygon + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { + OutRec* outRec = m_PolyOuts[i]; + if (outRec->FirstLeft == OldOutRec) { + outRec->FirstLeft = NewOutRec; + } + } } //---------------------------------------------------------------------- void Clipper::JoinCommonEdges() { - for (JoinList::size_type i = 0; i < m_Joins.size(); i++) - { - Join* join = m_Joins[i]; + for (JoinList::size_type i = 0; i < m_Joins.size(); i++) { + Join* join = m_Joins[i]; - OutRec *outRec1 = GetOutRec(join->OutPt1->Idx); - OutRec *outRec2 = GetOutRec(join->OutPt2->Idx); + OutRec* outRec1 = GetOutRec(join->OutPt1->Idx); + OutRec* outRec2 = GetOutRec(join->OutPt2->Idx); - if (!outRec1->Pts || !outRec2->Pts) continue; - - //get the polygon fragment with the correct hole state (FirstLeft) - //before calling JoinPoints() ... - OutRec *holeStateRec; - if (outRec1 == outRec2) holeStateRec = outRec1; - else if (Param1RightOfParam2(outRec1, outRec2)) holeStateRec = outRec2; - else if (Param1RightOfParam2(outRec2, outRec1)) holeStateRec = outRec1; - else holeStateRec = GetLowermostRec(outRec1, outRec2); - - if (!JoinPoints(join, outRec1, outRec2)) continue; - - if (outRec1 == outRec2) - { - //instead of joining two polygons, we've just created a new one by - //splitting one polygon into two. - outRec1->Pts = join->OutPt1; - outRec1->BottomPt = 0; - outRec2 = CreateOutRec(); - outRec2->Pts = join->OutPt2; - - //update all OutRec2.Pts Idx's ... - UpdateOutPtIdxs(*outRec2); - - //We now need to check every OutRec.FirstLeft pointer. If it points - //to OutRec1 it may need to point to OutRec2 instead ... - if (m_UsingPolyTree) - for (PolyOutList::size_type j = 0; j < m_PolyOuts.size() - 1; j++) - { - OutRec* oRec = m_PolyOuts[j]; - if (!oRec->Pts || ParseFirstLeft(oRec->FirstLeft) != outRec1 || - oRec->IsHole == outRec1->IsHole) continue; - if (Poly2ContainsPoly1(oRec->Pts, join->OutPt2)) - oRec->FirstLeft = outRec2; + if (!outRec1->Pts || !outRec2->Pts) { + continue; } - if (Poly2ContainsPoly1(outRec2->Pts, outRec1->Pts)) - { - //outRec2 is contained by outRec1 ... - outRec2->IsHole = !outRec1->IsHole; - outRec2->FirstLeft = outRec1; + // get the polygon fragment with the correct hole state (FirstLeft) + // before calling JoinPoints() ... + OutRec* holeStateRec; + if (outRec1 == outRec2) { + holeStateRec = outRec1; + } + else if (Param1RightOfParam2(outRec1, outRec2)) { + holeStateRec = outRec2; + } + else if (Param1RightOfParam2(outRec2, outRec1)) { + holeStateRec = outRec1; + } + else { + holeStateRec = GetLowermostRec(outRec1, outRec2); + } - //fixup FirstLeft pointers that may need reassigning to OutRec1 - if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1); + if (!JoinPoints(join, outRec1, outRec2)) { + continue; + } - if ((outRec2->IsHole ^ m_ReverseOutput) == (Area(*outRec2) > 0)) - ReversePolyPtLinks(outRec2->Pts); - - } else if (Poly2ContainsPoly1(outRec1->Pts, outRec2->Pts)) - { - //outRec1 is contained by outRec2 ... - outRec2->IsHole = outRec1->IsHole; - outRec1->IsHole = !outRec2->IsHole; - outRec2->FirstLeft = outRec1->FirstLeft; - outRec1->FirstLeft = outRec2; + if (outRec1 == outRec2) { + // instead of joining two polygons, we've just created a new one by + // splitting one polygon into two. + outRec1->Pts = join->OutPt1; + outRec1->BottomPt = 0; + outRec2 = CreateOutRec(); + outRec2->Pts = join->OutPt2; - //fixup FirstLeft pointers that may need reassigning to OutRec1 - if (m_UsingPolyTree) FixupFirstLefts2(outRec1, outRec2); + // update all OutRec2.Pts Idx's ... + UpdateOutPtIdxs(*outRec2); - if ((outRec1->IsHole ^ m_ReverseOutput) == (Area(*outRec1) > 0)) - ReversePolyPtLinks(outRec1->Pts); - } - else - { - //the 2 polygons are completely separate ... - outRec2->IsHole = outRec1->IsHole; - outRec2->FirstLeft = outRec1->FirstLeft; + // We now need to check every OutRec.FirstLeft pointer. If it points + // to OutRec1 it may need to point to OutRec2 instead ... + if (m_UsingPolyTree) { + for (PolyOutList::size_type j = 0; j < m_PolyOuts.size() - 1; j++) { + OutRec* oRec = m_PolyOuts[j]; + if (!oRec->Pts || ParseFirstLeft(oRec->FirstLeft) != outRec1 + || oRec->IsHole == outRec1->IsHole) { + continue; + } + if (Poly2ContainsPoly1(oRec->Pts, join->OutPt2)) { + oRec->FirstLeft = outRec2; + } + } + } - //fixup FirstLeft pointers that may need reassigning to OutRec2 - if (m_UsingPolyTree) FixupFirstLefts1(outRec1, outRec2); - } - - } else - { - //joined 2 polygons together ... + if (Poly2ContainsPoly1(outRec2->Pts, outRec1->Pts)) { + // outRec2 is contained by outRec1 ... + outRec2->IsHole = !outRec1->IsHole; + outRec2->FirstLeft = outRec1; - outRec2->Pts = 0; - outRec2->BottomPt = 0; - outRec2->Idx = outRec1->Idx; + // fixup FirstLeft pointers that may need reassigning to OutRec1 + if (m_UsingPolyTree) { + FixupFirstLefts2(outRec2, outRec1); + } - outRec1->IsHole = holeStateRec->IsHole; - if (holeStateRec == outRec2) - outRec1->FirstLeft = outRec2->FirstLeft; - outRec2->FirstLeft = outRec1; + if ((outRec2->IsHole ^ m_ReverseOutput) == (Area(*outRec2) > 0)) { + ReversePolyPtLinks(outRec2->Pts); + } + } + else if (Poly2ContainsPoly1(outRec1->Pts, outRec2->Pts)) { + // outRec1 is contained by outRec2 ... + outRec2->IsHole = outRec1->IsHole; + outRec1->IsHole = !outRec2->IsHole; + outRec2->FirstLeft = outRec1->FirstLeft; + outRec1->FirstLeft = outRec2; - //fixup FirstLeft pointers that may need reassigning to OutRec1 - if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1); + // fixup FirstLeft pointers that may need reassigning to OutRec1 + if (m_UsingPolyTree) { + FixupFirstLefts2(outRec1, outRec2); + } + + if ((outRec1->IsHole ^ m_ReverseOutput) == (Area(*outRec1) > 0)) { + ReversePolyPtLinks(outRec1->Pts); + } + } + else { + // the 2 polygons are completely separate ... + outRec2->IsHole = outRec1->IsHole; + outRec2->FirstLeft = outRec1->FirstLeft; + + // fixup FirstLeft pointers that may need reassigning to OutRec2 + if (m_UsingPolyTree) { + FixupFirstLefts1(outRec1, outRec2); + } + } + } + else { + // joined 2 polygons together ... + + outRec2->Pts = 0; + outRec2->BottomPt = 0; + outRec2->Idx = outRec1->Idx; + + outRec1->IsHole = holeStateRec->IsHole; + if (holeStateRec == outRec2) { + outRec1->FirstLeft = outRec2->FirstLeft; + } + outRec2->FirstLeft = outRec1; + + // fixup FirstLeft pointers that may need reassigning to OutRec1 + if (m_UsingPolyTree) { + FixupFirstLefts2(outRec2, outRec1); + } + } } - } } //------------------------------------------------------------------------------ // ClipperOffset support functions ... //------------------------------------------------------------------------------ -DoublePoint GetUnitNormal(const IntPoint &pt1, const IntPoint &pt2) +DoublePoint GetUnitNormal(const IntPoint& pt1, const IntPoint& pt2) { - if(pt2.X == pt1.X && pt2.Y == pt1.Y) - return DoublePoint(0, 0); + if (pt2.X == pt1.X && pt2.Y == pt1.Y) { + return DoublePoint(0, 0); + } - double Dx = (double)(pt2.X - pt1.X); - double dy = (double)(pt2.Y - pt1.Y); - double f = 1 *1.0/ std::sqrt( Dx*Dx + dy*dy ); - Dx *= f; - dy *= f; - return DoublePoint(dy, -Dx); + double Dx = (double)(pt2.X - pt1.X); + double dy = (double)(pt2.Y - pt1.Y); + double f = 1 * 1.0 / std::sqrt(Dx * Dx + dy * dy); + Dx *= f; + dy *= f; + return DoublePoint(dy, -Dx); } //------------------------------------------------------------------------------ @@ -3666,440 +4067,468 @@ DoublePoint GetUnitNormal(const IntPoint &pt1, const IntPoint &pt2) ClipperOffset::ClipperOffset(double miterLimit, double arcTolerance) { - this->MiterLimit = miterLimit; - this->ArcTolerance = arcTolerance; - m_lowest.X = -1; - m_delta = 0; - m_sinA = 0; - m_sin = 0; - m_cos = 0; - m_miterLim = 0; - m_StepsPerRad = 0; + this->MiterLimit = miterLimit; + this->ArcTolerance = arcTolerance; + m_lowest.X = -1; + m_delta = 0; + m_sinA = 0; + m_sin = 0; + m_cos = 0; + m_miterLim = 0; + m_StepsPerRad = 0; } //------------------------------------------------------------------------------ ClipperOffset::~ClipperOffset() { - Clear(); + Clear(); } //------------------------------------------------------------------------------ void ClipperOffset::Clear() { - for (int i = 0; i < m_polyNodes.ChildCount(); ++i) - delete m_polyNodes.Childs[i]; - m_polyNodes.Childs.clear(); - m_lowest.X = -1; + for (int i = 0; i < m_polyNodes.ChildCount(); ++i) { + delete m_polyNodes.Childs[i]; + } + m_polyNodes.Childs.clear(); + m_lowest.X = -1; } //------------------------------------------------------------------------------ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType) { - int highI = (int)path.size() - 1; - if (highI < 0) - return; - PolyNode* newNode = new PolyNode(); - newNode->m_jointype = joinType; - newNode->m_endtype = endType; - - //strip duplicate points from path and also get index to the lowest point ... - if (endType == etClosedLine || endType == etClosedPolygon) - while (highI > 0 && path[0] == path[highI]) highI--; - newNode->Contour.reserve(highI + 1); - newNode->Contour.push_back(path[0]); - int j = 0, k = 0; - for (int i = 1; i <= highI; i++) - if (newNode->Contour[j] != path[i]) - { - j++; - newNode->Contour.push_back(path[i]); - if (path[i].Y > newNode->Contour[k].Y || - (path[i].Y == newNode->Contour[k].Y && - path[i].X < newNode->Contour[k].X)) k = j; + int highI = (int)path.size() - 1; + if (highI < 0) { + return; } - if (endType == etClosedPolygon && j < 2) - { - delete newNode; - return; - } - m_polyNodes.AddChild(*newNode); + PolyNode* newNode = new PolyNode(); + newNode->m_jointype = joinType; + newNode->m_endtype = endType; - //if this path's lowest pt is lower than all the others then update m_lowest - if (endType != etClosedPolygon) - return; - if (m_lowest.X < 0) - m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); - else - { - IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X]->Contour[(int)m_lowest.Y]; - if (newNode->Contour[k].Y > ip.Y || - (newNode->Contour[k].Y == ip.Y && - newNode->Contour[k].X < ip.X)) - m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); - } + // strip duplicate points from path and also get index to the lowest point ... + if (endType == etClosedLine || endType == etClosedPolygon) { + while (highI > 0 && path[0] == path[highI]) { + highI--; + } + } + newNode->Contour.reserve(highI + 1); + newNode->Contour.push_back(path[0]); + int j = 0, k = 0; + for (int i = 1; i <= highI; i++) { + if (newNode->Contour[j] != path[i]) { + j++; + newNode->Contour.push_back(path[i]); + if (path[i].Y > newNode->Contour[k].Y + || (path[i].Y == newNode->Contour[k].Y && path[i].X < newNode->Contour[k].X)) { + k = j; + } + } + } + if (endType == etClosedPolygon && j < 2) { + delete newNode; + return; + } + m_polyNodes.AddChild(*newNode); + + // if this path's lowest pt is lower than all the others then update m_lowest + if (endType != etClosedPolygon) { + return; + } + if (m_lowest.X < 0) { + m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); + } + else { + IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X]->Contour[(int)m_lowest.Y]; + if (newNode->Contour[k].Y > ip.Y + || (newNode->Contour[k].Y == ip.Y && newNode->Contour[k].X < ip.X)) { + m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); + } + } } //------------------------------------------------------------------------------ void ClipperOffset::AddPaths(const Paths& paths, JoinType joinType, EndType endType) { - for (Paths::size_type i = 0; i < paths.size(); ++i) - AddPath(paths[i], joinType, endType); + for (Paths::size_type i = 0; i < paths.size(); ++i) { + AddPath(paths[i], joinType, endType); + } } //------------------------------------------------------------------------------ void ClipperOffset::FixOrientations() { - //fixup orientations of all closed paths if the orientation of the - //closed path with the lowermost vertex is wrong ... - if (m_lowest.X >= 0 && - !Orientation(m_polyNodes.Childs[(int)m_lowest.X]->Contour)) - { - for (int i = 0; i < m_polyNodes.ChildCount(); ++i) - { - PolyNode& node = *m_polyNodes.Childs[i]; - if (node.m_endtype == etClosedPolygon || - (node.m_endtype == etClosedLine && Orientation(node.Contour))) - ReversePath(node.Contour); + // fixup orientations of all closed paths if the orientation of the + // closed path with the lowermost vertex is wrong ... + if (m_lowest.X >= 0 && !Orientation(m_polyNodes.Childs[(int)m_lowest.X]->Contour)) { + for (int i = 0; i < m_polyNodes.ChildCount(); ++i) { + PolyNode& node = *m_polyNodes.Childs[i]; + if (node.m_endtype == etClosedPolygon + || (node.m_endtype == etClosedLine && Orientation(node.Contour))) { + ReversePath(node.Contour); + } + } } - } else - { - for (int i = 0; i < m_polyNodes.ChildCount(); ++i) - { - PolyNode& node = *m_polyNodes.Childs[i]; - if (node.m_endtype == etClosedLine && !Orientation(node.Contour)) - ReversePath(node.Contour); + else { + for (int i = 0; i < m_polyNodes.ChildCount(); ++i) { + PolyNode& node = *m_polyNodes.Childs[i]; + if (node.m_endtype == etClosedLine && !Orientation(node.Contour)) { + ReversePath(node.Contour); + } + } } - } } //------------------------------------------------------------------------------ void ClipperOffset::Execute(Paths& solution, double delta) { - solution.clear(); - FixOrientations(); - DoOffset(delta); - - //now clean up 'corners' ... - Clipper clpr; - clpr.AddPaths(m_destPolys, ptSubject, true); - if (delta > 0) - { - clpr.Execute(ctUnion, solution, pftPositive, pftPositive); - } - else - { - IntRect r = clpr.GetBounds(); - Path outer(4); - outer[0] = IntPoint(r.left - 10, r.bottom + 10); - outer[1] = IntPoint(r.right + 10, r.bottom + 10); - outer[2] = IntPoint(r.right + 10, r.top - 10); - outer[3] = IntPoint(r.left - 10, r.top - 10); + solution.clear(); + FixOrientations(); + DoOffset(delta); - clpr.AddPath(outer, ptSubject, true); - clpr.ReverseSolution(true); - clpr.Execute(ctUnion, solution, pftNegative, pftNegative); - if (!solution.empty()) solution.erase(solution.begin()); - } + // now clean up 'corners' ... + Clipper clpr; + clpr.AddPaths(m_destPolys, ptSubject, true); + if (delta > 0) { + clpr.Execute(ctUnion, solution, pftPositive, pftPositive); + } + else { + IntRect r = clpr.GetBounds(); + Path outer(4); + outer[0] = IntPoint(r.left - 10, r.bottom + 10); + outer[1] = IntPoint(r.right + 10, r.bottom + 10); + outer[2] = IntPoint(r.right + 10, r.top - 10); + outer[3] = IntPoint(r.left - 10, r.top - 10); + + clpr.AddPath(outer, ptSubject, true); + clpr.ReverseSolution(true); + clpr.Execute(ctUnion, solution, pftNegative, pftNegative); + if (!solution.empty()) { + solution.erase(solution.begin()); + } + } } //------------------------------------------------------------------------------ void ClipperOffset::Execute(PolyTree& solution, double delta) { - solution.Clear(); - FixOrientations(); - DoOffset(delta); + solution.Clear(); + FixOrientations(); + DoOffset(delta); - //now clean up 'corners' ... - Clipper clpr; - clpr.AddPaths(m_destPolys, ptSubject, true); - if (delta > 0) - { - clpr.Execute(ctUnion, solution, pftPositive, pftPositive); - } - else - { - IntRect r = clpr.GetBounds(); - Path outer(4); - outer[0] = IntPoint(r.left - 10, r.bottom + 10); - outer[1] = IntPoint(r.right + 10, r.bottom + 10); - outer[2] = IntPoint(r.right + 10, r.top - 10); - outer[3] = IntPoint(r.left - 10, r.top - 10); - - clpr.AddPath(outer, ptSubject, true); - clpr.ReverseSolution(true); - clpr.Execute(ctUnion, solution, pftNegative, pftNegative); - //remove the outer PolyNode rectangle ... - if (solution.ChildCount() == 1 && solution.Childs[0]->ChildCount() > 0) - { - PolyNode* outerNode = solution.Childs[0]; - solution.Childs.reserve(outerNode->ChildCount()); - solution.Childs[0] = outerNode->Childs[0]; - for (int i = 1; i < outerNode->ChildCount(); ++i) - solution.AddChild(*outerNode->Childs[i]); + // now clean up 'corners' ... + Clipper clpr; + clpr.AddPaths(m_destPolys, ptSubject, true); + if (delta > 0) { + clpr.Execute(ctUnion, solution, pftPositive, pftPositive); + } + else { + IntRect r = clpr.GetBounds(); + Path outer(4); + outer[0] = IntPoint(r.left - 10, r.bottom + 10); + outer[1] = IntPoint(r.right + 10, r.bottom + 10); + outer[2] = IntPoint(r.right + 10, r.top - 10); + outer[3] = IntPoint(r.left - 10, r.top - 10); + + clpr.AddPath(outer, ptSubject, true); + clpr.ReverseSolution(true); + clpr.Execute(ctUnion, solution, pftNegative, pftNegative); + // remove the outer PolyNode rectangle ... + if (solution.ChildCount() == 1 && solution.Childs[0]->ChildCount() > 0) { + PolyNode* outerNode = solution.Childs[0]; + solution.Childs.reserve(outerNode->ChildCount()); + solution.Childs[0] = outerNode->Childs[0]; + for (int i = 1; i < outerNode->ChildCount(); ++i) { + solution.AddChild(*outerNode->Childs[i]); + } + } + else { + solution.Clear(); + } } - else - solution.Clear(); - } } //------------------------------------------------------------------------------ void ClipperOffset::DoOffset(double delta) { - m_destPolys.clear(); - m_delta = delta; + m_destPolys.clear(); + m_delta = delta; - //if Zero offset, just copy any CLOSED polygons to m_p and return ... - if (NEAR_ZERO(delta)) - { - m_destPolys.reserve(m_polyNodes.ChildCount()); - for (int i = 0; i < m_polyNodes.ChildCount(); i++) - { - PolyNode& node = *m_polyNodes.Childs[i]; - if (node.m_endtype == etClosedPolygon) - m_destPolys.push_back(node.Contour); - } - return; - } - - //see offset_triginometry3.svg in the documentation folder ... - if (MiterLimit > 2) m_miterLim = 2/(MiterLimit * MiterLimit); - else m_miterLim = 0.5; - - double y; - if (ArcTolerance <= 0.0) y = def_arc_tolerance; - else if (ArcTolerance > std::fabs(delta) * def_arc_tolerance) - y = std::fabs(delta) * def_arc_tolerance; - else y = ArcTolerance; - //see offset_triginometry2.svg in the documentation folder ... - double steps = pi / std::acos(1 - y / std::fabs(delta)); - if (steps > std::fabs(delta) * pi) - steps = std::fabs(delta) * pi; //ie excessive precision check - m_sin = std::sin(two_pi / steps); - m_cos = std::cos(two_pi / steps); - m_StepsPerRad = steps / two_pi; - if (delta < 0.0) m_sin = -m_sin; - - m_destPolys.reserve(m_polyNodes.ChildCount() * 2); - for (int i = 0; i < m_polyNodes.ChildCount(); i++) - { - PolyNode& node = *m_polyNodes.Childs[i]; - m_srcPoly = node.Contour; - - int len = (int)m_srcPoly.size(); - if (len == 0 || (delta <= 0 && (len < 3 || node.m_endtype != etClosedPolygon))) - continue; - - m_destPoly.clear(); - if (len == 1) - { - if (node.m_jointype == jtRound) - { - double X = 1.0, Y = 0.0; - for (cInt j = 1; j <= steps; j++) - { - m_destPoly.push_back(IntPoint( - Round(m_srcPoly[0].X + X * delta), - Round(m_srcPoly[0].Y + Y * delta))); - double X2 = X; - X = X * m_cos - m_sin * Y; - Y = X2 * m_sin + Y * m_cos; + // if Zero offset, just copy any CLOSED polygons to m_p and return ... + if (NEAR_ZERO(delta)) { + m_destPolys.reserve(m_polyNodes.ChildCount()); + for (int i = 0; i < m_polyNodes.ChildCount(); i++) { + PolyNode& node = *m_polyNodes.Childs[i]; + if (node.m_endtype == etClosedPolygon) { + m_destPolys.push_back(node.Contour); + } } - } - else - { - double X = -1.0, Y = -1.0; - for (int j = 0; j < 4; ++j) - { - m_destPoly.push_back(IntPoint( - Round(m_srcPoly[0].X + X * delta), - Round(m_srcPoly[0].Y + Y * delta))); - if (X < 0) X = 1; - else if (Y < 0) Y = 1; - else X = -1; + return; + } + + // see offset_triginometry3.svg in the documentation folder ... + if (MiterLimit > 2) { + m_miterLim = 2 / (MiterLimit * MiterLimit); + } + else { + m_miterLim = 0.5; + } + + double y; + if (ArcTolerance <= 0.0) { + y = def_arc_tolerance; + } + else if (ArcTolerance > std::fabs(delta) * def_arc_tolerance) { + y = std::fabs(delta) * def_arc_tolerance; + } + else { + y = ArcTolerance; + } + // see offset_triginometry2.svg in the documentation folder ... + double steps = pi / std::acos(1 - y / std::fabs(delta)); + if (steps > std::fabs(delta) * pi) { + steps = std::fabs(delta) * pi; // ie excessive precision check + } + m_sin = std::sin(two_pi / steps); + m_cos = std::cos(two_pi / steps); + m_StepsPerRad = steps / two_pi; + if (delta < 0.0) { + m_sin = -m_sin; + } + + m_destPolys.reserve(m_polyNodes.ChildCount() * 2); + for (int i = 0; i < m_polyNodes.ChildCount(); i++) { + PolyNode& node = *m_polyNodes.Childs[i]; + m_srcPoly = node.Contour; + + int len = (int)m_srcPoly.size(); + if (len == 0 || (delta <= 0 && (len < 3 || node.m_endtype != etClosedPolygon))) { + continue; + } + + m_destPoly.clear(); + if (len == 1) { + if (node.m_jointype == jtRound) { + double X = 1.0, Y = 0.0; + for (cInt j = 1; j <= steps; j++) { + m_destPoly.push_back(IntPoint(Round(m_srcPoly[0].X + X * delta), + Round(m_srcPoly[0].Y + Y * delta))); + double X2 = X; + X = X * m_cos - m_sin * Y; + Y = X2 * m_sin + Y * m_cos; + } + } + else { + double X = -1.0, Y = -1.0; + for (int j = 0; j < 4; ++j) { + m_destPoly.push_back(IntPoint(Round(m_srcPoly[0].X + X * delta), + Round(m_srcPoly[0].Y + Y * delta))); + if (X < 0) { + X = 1; + } + else if (Y < 0) { + Y = 1; + } + else { + X = -1; + } + } + } + m_destPolys.push_back(m_destPoly); + continue; + } + // build m_normals ... + m_normals.clear(); + m_normals.reserve(len); + for (int j = 0; j < len - 1; ++j) { + m_normals.push_back(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1])); + } + if (node.m_endtype == etClosedLine || node.m_endtype == etClosedPolygon) { + m_normals.push_back(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0])); + } + else { + m_normals.emplace_back(m_normals[len - 2]); + } + + if (node.m_endtype == etClosedPolygon) { + int k = len - 1; + for (int j = 0; j < len; ++j) { + OffsetPoint(j, k, node.m_jointype); + } + m_destPolys.push_back(m_destPoly); + } + else if (node.m_endtype == etClosedLine) { + int k = len - 1; + for (int j = 0; j < len; ++j) { + OffsetPoint(j, k, node.m_jointype); + } + m_destPolys.push_back(m_destPoly); + m_destPoly.clear(); + // re-build m_normals ... + DoublePoint n = m_normals[len - 1]; + for (int j = len - 1; j > 0; j--) { + m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); + } + m_normals[0] = DoublePoint(-n.X, -n.Y); + k = 0; + for (int j = len - 1; j >= 0; j--) { + OffsetPoint(j, k, node.m_jointype); + } + m_destPolys.push_back(m_destPoly); + } + else { + int k = 0; + for (int j = 1; j < len - 1; ++j) { + OffsetPoint(j, k, node.m_jointype); + } + + IntPoint pt1; + if (node.m_endtype == etOpenButt) { + int j = len - 1; + pt1 = IntPoint((cInt)Round(m_srcPoly[j].X + m_normals[j].X * delta), + (cInt)Round(m_srcPoly[j].Y + m_normals[j].Y * delta)); + m_destPoly.push_back(pt1); + pt1 = IntPoint((cInt)Round(m_srcPoly[j].X - m_normals[j].X * delta), + (cInt)Round(m_srcPoly[j].Y - m_normals[j].Y * delta)); + m_destPoly.push_back(pt1); + } + else { + int j = len - 1; + k = len - 2; + m_sinA = 0; + m_normals[j] = DoublePoint(-m_normals[j].X, -m_normals[j].Y); + if (node.m_endtype == etOpenSquare) { + DoSquare(j, k); + } + else { + DoRound(j, k); + } + } + + // re-build m_normals ... + for (int j = len - 1; j > 0; j--) { + m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); + } + m_normals[0] = DoublePoint(-m_normals[1].X, -m_normals[1].Y); + + k = len - 1; + for (int j = k - 1; j > 0; --j) { + OffsetPoint(j, k, node.m_jointype); + } + + if (node.m_endtype == etOpenButt) { + pt1 = IntPoint((cInt)Round(m_srcPoly[0].X - m_normals[0].X * delta), + (cInt)Round(m_srcPoly[0].Y - m_normals[0].Y * delta)); + m_destPoly.push_back(pt1); + pt1 = IntPoint((cInt)Round(m_srcPoly[0].X + m_normals[0].X * delta), + (cInt)Round(m_srcPoly[0].Y + m_normals[0].Y * delta)); + m_destPoly.push_back(pt1); + } + else { + k = 1; + m_sinA = 0; + if (node.m_endtype == etOpenSquare) { + DoSquare(0, 1); + } + else { + DoRound(0, 1); + } + } + m_destPolys.push_back(m_destPoly); } - } - m_destPolys.push_back(m_destPoly); - continue; } - //build m_normals ... - m_normals.clear(); - m_normals.reserve(len); - for (int j = 0; j < len - 1; ++j) - m_normals.push_back(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1])); - if (node.m_endtype == etClosedLine || node.m_endtype == etClosedPolygon) - m_normals.push_back(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0])); - else - m_normals.emplace_back(m_normals[len - 2]); - - if (node.m_endtype == etClosedPolygon) - { - int k = len - 1; - for (int j = 0; j < len; ++j) - OffsetPoint(j, k, node.m_jointype); - m_destPolys.push_back(m_destPoly); - } - else if (node.m_endtype == etClosedLine) - { - int k = len - 1; - for (int j = 0; j < len; ++j) - OffsetPoint(j, k, node.m_jointype); - m_destPolys.push_back(m_destPoly); - m_destPoly.clear(); - //re-build m_normals ... - DoublePoint n = m_normals[len -1]; - for (int j = len - 1; j > 0; j--) - m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); - m_normals[0] = DoublePoint(-n.X, -n.Y); - k = 0; - for (int j = len - 1; j >= 0; j--) - OffsetPoint(j, k, node.m_jointype); - m_destPolys.push_back(m_destPoly); - } - else - { - int k = 0; - for (int j = 1; j < len - 1; ++j) - OffsetPoint(j, k, node.m_jointype); - - IntPoint pt1; - if (node.m_endtype == etOpenButt) - { - int j = len - 1; - pt1 = IntPoint((cInt)Round(m_srcPoly[j].X + m_normals[j].X * - delta), (cInt)Round(m_srcPoly[j].Y + m_normals[j].Y * delta)); - m_destPoly.push_back(pt1); - pt1 = IntPoint((cInt)Round(m_srcPoly[j].X - m_normals[j].X * - delta), (cInt)Round(m_srcPoly[j].Y - m_normals[j].Y * delta)); - m_destPoly.push_back(pt1); - } - else - { - int j = len - 1; - k = len - 2; - m_sinA = 0; - m_normals[j] = DoublePoint(-m_normals[j].X, -m_normals[j].Y); - if (node.m_endtype == etOpenSquare) - DoSquare(j, k); - else - DoRound(j, k); - } - - //re-build m_normals ... - for (int j = len - 1; j > 0; j--) - m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); - m_normals[0] = DoublePoint(-m_normals[1].X, -m_normals[1].Y); - - k = len - 1; - for (int j = k - 1; j > 0; --j) OffsetPoint(j, k, node.m_jointype); - - if (node.m_endtype == etOpenButt) - { - pt1 = IntPoint((cInt)Round(m_srcPoly[0].X - m_normals[0].X * delta), - (cInt)Round(m_srcPoly[0].Y - m_normals[0].Y * delta)); - m_destPoly.push_back(pt1); - pt1 = IntPoint((cInt)Round(m_srcPoly[0].X + m_normals[0].X * delta), - (cInt)Round(m_srcPoly[0].Y + m_normals[0].Y * delta)); - m_destPoly.push_back(pt1); - } - else - { - k = 1; - m_sinA = 0; - if (node.m_endtype == etOpenSquare) - DoSquare(0, 1); - else - DoRound(0, 1); - } - m_destPolys.push_back(m_destPoly); - } - } } //------------------------------------------------------------------------------ void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype) { - //cross product ... - m_sinA = (m_normals[k].X * m_normals[j].Y - m_normals[j].X * m_normals[k].Y); - if (std::fabs(m_sinA * m_delta) < 1.0) - { - //dot product ... - double cosA = (m_normals[k].X * m_normals[j].X + m_normals[j].Y * m_normals[k].Y ); - if (cosA > 0) // angle => 0 degrees - { - m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), - Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); - return; - } - //else angle => 180 degrees - } - else if (m_sinA > 1.0) m_sinA = 1.0; - else if (m_sinA < -1.0) m_sinA = -1.0; - - if (m_sinA * m_delta < 0) - { - m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), - Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); - m_destPoly.push_back(m_srcPoly[j]); - m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * m_delta), - Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); - } - else - switch (jointype) - { - case jtMiter: + // cross product ... + m_sinA = (m_normals[k].X * m_normals[j].Y - m_normals[j].X * m_normals[k].Y); + if (std::fabs(m_sinA * m_delta) < 1.0) { + // dot product ... + double cosA = (m_normals[k].X * m_normals[j].X + m_normals[j].Y * m_normals[k].Y); + if (cosA > 0) // angle => 0 degrees { - double r = 1 + (m_normals[j].X * m_normals[k].X + - m_normals[j].Y * m_normals[k].Y); - if (r >= m_miterLim) DoMiter(j, k, r); else DoSquare(j, k); - break; + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); + return; } - case jtSquare: DoSquare(j, k); break; - case jtRound: DoRound(j, k); break; + // else angle => 180 degrees } - k = j; + else if (m_sinA > 1.0) { + m_sinA = 1.0; + } + else if (m_sinA < -1.0) { + m_sinA = -1.0; + } + + if (m_sinA * m_delta < 0) { + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); + m_destPoly.push_back(m_srcPoly[j]); + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); + } + else { + switch (jointype) { + case jtMiter: { + double r = 1 + (m_normals[j].X * m_normals[k].X + m_normals[j].Y * m_normals[k].Y); + if (r >= m_miterLim) { + DoMiter(j, k, r); + } + else { + DoSquare(j, k); + } + break; + } + case jtSquare: + DoSquare(j, k); + break; + case jtRound: + DoRound(j, k); + break; + } + } + k = j; } //------------------------------------------------------------------------------ void ClipperOffset::DoSquare(int j, int k) { - double dx = std::tan(std::atan2(m_sinA, - m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y) / 4); - m_destPoly.push_back(IntPoint( - Round(m_srcPoly[j].X + m_delta * (m_normals[k].X - m_normals[k].Y * dx)), - Round(m_srcPoly[j].Y + m_delta * (m_normals[k].Y + m_normals[k].X * dx)))); - m_destPoly.push_back(IntPoint( - Round(m_srcPoly[j].X + m_delta * (m_normals[j].X + m_normals[j].Y * dx)), - Round(m_srcPoly[j].Y + m_delta * (m_normals[j].Y - m_normals[j].X * dx)))); + double dx = std::tan( + std::atan2(m_sinA, m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y) / 4); + m_destPoly.push_back( + IntPoint(Round(m_srcPoly[j].X + m_delta * (m_normals[k].X - m_normals[k].Y * dx)), + Round(m_srcPoly[j].Y + m_delta * (m_normals[k].Y + m_normals[k].X * dx)))); + m_destPoly.push_back( + IntPoint(Round(m_srcPoly[j].X + m_delta * (m_normals[j].X + m_normals[j].Y * dx)), + Round(m_srcPoly[j].Y + m_delta * (m_normals[j].Y - m_normals[j].X * dx)))); } //------------------------------------------------------------------------------ void ClipperOffset::DoMiter(int j, int k, double r) { - double q = m_delta / r; - m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + (m_normals[k].X + m_normals[j].X) * q), - Round(m_srcPoly[j].Y + (m_normals[k].Y + m_normals[j].Y) * q))); + double q = m_delta / r; + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + (m_normals[k].X + m_normals[j].X) * q), + Round(m_srcPoly[j].Y + (m_normals[k].Y + m_normals[j].Y) * q))); } //------------------------------------------------------------------------------ void ClipperOffset::DoRound(int j, int k) { - double a = std::atan2(m_sinA, - m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y); - int steps = (int)Round(m_StepsPerRad * std::fabs(a)); + double a = + std::atan2(m_sinA, m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y); + int steps = (int)Round(m_StepsPerRad * std::fabs(a)); - double X = m_normals[k].X, Y = m_normals[k].Y, X2; - for (int i = 0; i < steps; ++i) - { - m_destPoly.push_back(IntPoint( - Round(m_srcPoly[j].X + X * m_delta), - Round(m_srcPoly[j].Y + Y * m_delta))); - X2 = X; - X = X * m_cos - m_sin * Y; - Y = X2 * m_sin + Y * m_cos; - } - m_destPoly.push_back(IntPoint( - Round(m_srcPoly[j].X + m_normals[j].X * m_delta), - Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); + double X = m_normals[k].X, Y = m_normals[k].Y, X2; + for (int i = 0; i < steps; ++i) { + m_destPoly.push_back( + IntPoint(Round(m_srcPoly[j].X + X * m_delta), Round(m_srcPoly[j].Y + Y * m_delta))); + X2 = X; + X = X * m_cos - m_sin * Y; + Y = X2 * m_sin + Y * m_cos; + } + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); } //------------------------------------------------------------------------------ @@ -4108,152 +4537,158 @@ void ClipperOffset::DoRound(int j, int k) void Clipper::DoSimplePolygons() { - PolyOutList::size_type i = 0; - while (i < m_PolyOuts.size()) - { - OutRec* outrec = m_PolyOuts[i++]; - OutPt* op = outrec->Pts; - if (!op || outrec->IsOpen) continue; - do //for each Pt in Polygon until duplicate found do ... - { - OutPt* op2 = op->Next; - while (op2 != outrec->Pts) - { - if ((op->Pt == op2->Pt) && op2->Next != op && op2->Prev != op) - { - //split the polygon into two ... - OutPt* op3 = op->Prev; - OutPt* op4 = op2->Prev; - op->Prev = op4; - op4->Next = op; - op2->Prev = op3; - op3->Next = op2; - - outrec->Pts = op; - OutRec* outrec2 = CreateOutRec(); - outrec2->Pts = op2; - UpdateOutPtIdxs(*outrec2); - if (Poly2ContainsPoly1(outrec2->Pts, outrec->Pts)) - { - //OutRec2 is contained by OutRec1 ... - outrec2->IsHole = !outrec->IsHole; - outrec2->FirstLeft = outrec; - if (m_UsingPolyTree) FixupFirstLefts2(outrec2, outrec); - } - else - if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts)) - { - //OutRec1 is contained by OutRec2 ... - outrec2->IsHole = outrec->IsHole; - outrec->IsHole = !outrec2->IsHole; - outrec2->FirstLeft = outrec->FirstLeft; - outrec->FirstLeft = outrec2; - if (m_UsingPolyTree) FixupFirstLefts2(outrec, outrec2); - } - else - { - //the 2 polygons are separate ... - outrec2->IsHole = outrec->IsHole; - outrec2->FirstLeft = outrec->FirstLeft; - if (m_UsingPolyTree) FixupFirstLefts1(outrec, outrec2); - } - op2 = op; //ie get ready for the Next iteration + PolyOutList::size_type i = 0; + while (i < m_PolyOuts.size()) { + OutRec* outrec = m_PolyOuts[i++]; + OutPt* op = outrec->Pts; + if (!op || outrec->IsOpen) { + continue; } - op2 = op2->Next; - } - op = op->Next; + do // for each Pt in Polygon until duplicate found do ... + { + OutPt* op2 = op->Next; + while (op2 != outrec->Pts) { + if ((op->Pt == op2->Pt) && op2->Next != op && op2->Prev != op) { + // split the polygon into two ... + OutPt* op3 = op->Prev; + OutPt* op4 = op2->Prev; + op->Prev = op4; + op4->Next = op; + op2->Prev = op3; + op3->Next = op2; + + outrec->Pts = op; + OutRec* outrec2 = CreateOutRec(); + outrec2->Pts = op2; + UpdateOutPtIdxs(*outrec2); + if (Poly2ContainsPoly1(outrec2->Pts, outrec->Pts)) { + // OutRec2 is contained by OutRec1 ... + outrec2->IsHole = !outrec->IsHole; + outrec2->FirstLeft = outrec; + if (m_UsingPolyTree) { + FixupFirstLefts2(outrec2, outrec); + } + } + else if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts)) { + // OutRec1 is contained by OutRec2 ... + outrec2->IsHole = outrec->IsHole; + outrec->IsHole = !outrec2->IsHole; + outrec2->FirstLeft = outrec->FirstLeft; + outrec->FirstLeft = outrec2; + if (m_UsingPolyTree) { + FixupFirstLefts2(outrec, outrec2); + } + } + else { + // the 2 polygons are separate ... + outrec2->IsHole = outrec->IsHole; + outrec2->FirstLeft = outrec->FirstLeft; + if (m_UsingPolyTree) { + FixupFirstLefts1(outrec, outrec2); + } + } + op2 = op; // ie get ready for the Next iteration + } + op2 = op2->Next; + } + op = op->Next; + } while (op != outrec->Pts); } - while (op != outrec->Pts); - } } //------------------------------------------------------------------------------ void ReversePath(Path& p) { - std::reverse(p.begin(), p.end()); + std::reverse(p.begin(), p.end()); } //------------------------------------------------------------------------------ void ReversePaths(Paths& p) { - for (Paths::size_type i = 0; i < p.size(); ++i) - ReversePath(p[i]); + for (Paths::size_type i = 0; i < p.size(); ++i) { + ReversePath(p[i]); + } } //------------------------------------------------------------------------------ -void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType) +void SimplifyPolygon(const Path& in_poly, Paths& out_polys, PolyFillType fillType) { - Clipper c; - c.StrictlySimple(true); - c.AddPath(in_poly, ptSubject, true); - c.Execute(ctUnion, out_polys, fillType, fillType); + Clipper c; + c.StrictlySimple(true); + c.AddPath(in_poly, ptSubject, true); + c.Execute(ctUnion, out_polys, fillType, fillType); } //------------------------------------------------------------------------------ -void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType) +void SimplifyPolygons(const Paths& in_polys, Paths& out_polys, PolyFillType fillType) { - Clipper c; - c.StrictlySimple(true); - c.AddPaths(in_polys, ptSubject, true); - c.Execute(ctUnion, out_polys, fillType, fillType); + Clipper c; + c.StrictlySimple(true); + c.AddPaths(in_polys, ptSubject, true); + c.Execute(ctUnion, out_polys, fillType, fillType); } //------------------------------------------------------------------------------ -void SimplifyPolygons(Paths &polys, PolyFillType fillType) +void SimplifyPolygons(Paths& polys, PolyFillType fillType) { - SimplifyPolygons(polys, polys, fillType); + SimplifyPolygons(polys, polys, fillType); } //------------------------------------------------------------------------------ inline double DistanceSqrd(const IntPoint& pt1, const IntPoint& pt2) { - double Dx = ((double)pt1.X - pt2.X); - double dy = ((double)pt1.Y - pt2.Y); - return (Dx*Dx + dy*dy); + double Dx = ((double)pt1.X - pt2.X); + double dy = ((double)pt1.Y - pt2.Y); + return (Dx * Dx + dy * dy); } //------------------------------------------------------------------------------ -double DistanceFromLineSqrd( - const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2) +double DistanceFromLineSqrd(const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2) { - //The equation of a line in general form (Ax + By + C = 0) - //given 2 points (x¹,y¹) & (x²,y²) is ... - //(y¹ - y²)x + (x² - x¹)y + (y² - y¹)x¹ - (x² - x¹)y¹ = 0 - //A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹ - //perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²) - //see http://en.wikipedia.org/wiki/Perpendicular_distance - double A = double(ln1.Y - ln2.Y); - double B = double(ln2.X - ln1.X); - double C = A * ln1.X + B * ln1.Y; - C = A * pt.X + B * pt.Y - C; - return (C * C) / (A * A + B * B); + // The equation of a line in general form (Ax + By + C = 0) + // given 2 points (x¹,y¹) & (x²,y²) is ... + //(y¹ - y²)x + (x² - x¹)y + (y² - y¹)x¹ - (x² - x¹)y¹ = 0 + // A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹ + // perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²) + // see http://en.wikipedia.org/wiki/Perpendicular_distance + double A = double(ln1.Y - ln2.Y); + double B = double(ln2.X - ln1.X); + double C = A * ln1.X + B * ln1.Y; + C = A * pt.X + B * pt.Y - C; + return (C * C) / (A * A + B * B); } //--------------------------------------------------------------------------- -bool SlopesNearCollinear(const IntPoint& pt1, - const IntPoint& pt2, const IntPoint& pt3, double distSqrd) +bool SlopesNearCollinear(const IntPoint& pt1, + const IntPoint& pt2, + const IntPoint& pt3, + double distSqrd) { - //this function is more accurate when the point that's geometrically - //between the other 2 points is the one that's tested for distance. - //ie makes it more likely to pick up 'spikes' ... - if (Abs(pt1.X - pt2.X) > Abs(pt1.Y - pt2.Y)) - { - if ((pt1.X > pt2.X) == (pt1.X < pt3.X)) - return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; - else if ((pt2.X > pt1.X) == (pt2.X < pt3.X)) - return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; - else - return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; - } - else - { - if ((pt1.Y > pt2.Y) == (pt1.Y < pt3.Y)) - return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; - else if ((pt2.Y > pt1.Y) == (pt2.Y < pt3.Y)) - return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; - else - return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; - } + // this function is more accurate when the point that's geometrically + // between the other 2 points is the one that's tested for distance. + // ie makes it more likely to pick up 'spikes' ... + if (Abs(pt1.X - pt2.X) > Abs(pt1.Y - pt2.Y)) { + if ((pt1.X > pt2.X) == (pt1.X < pt3.X)) { + return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; + } + else if ((pt2.X > pt1.X) == (pt2.X < pt3.X)) { + return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; + } + else { + return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; + } + } + else { + if ((pt1.Y > pt2.Y) == (pt1.Y < pt3.Y)) { + return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; + } + else if ((pt2.Y > pt1.Y) == (pt2.Y < pt3.Y)) { + return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; + } + else { + return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; + } + } } //------------------------------------------------------------------------------ @@ -4267,251 +4702,264 @@ bool PointsAreClose(IntPoint pt1, IntPoint pt2, double distSqrd) OutPt* ExcludeOp(OutPt* op) { - OutPt* result = op->Prev; - result->Next = op->Next; - op->Next->Prev = result; - result->Idx = 0; - return result; + OutPt* result = op->Prev; + result->Next = op->Next; + op->Next->Prev = result; + result->Idx = 0; + return result; } //------------------------------------------------------------------------------ void CleanPolygon(const Path& in_poly, Path& out_poly, double distance) { - //distance = proximity in units/pixels below which vertices - //will be stripped. Default ~= sqrt(2). - - size_t size = in_poly.size(); - - if (size == 0) - { - out_poly.clear(); - return; - } + // distance = proximity in units/pixels below which vertices + // will be stripped. Default ~= sqrt(2). - OutPt* outPts = new OutPt[size]; - for (size_t i = 0; i < size; ++i) - { - outPts[i].Pt = in_poly[i]; - outPts[i].Next = &outPts[(i + 1) % size]; - outPts[i].Next->Prev = &outPts[i]; - outPts[i].Idx = 0; - } + size_t size = in_poly.size(); - double distSqrd = distance * distance; - OutPt* op = &outPts[0]; - while (op->Idx == 0 && op->Next != op->Prev) - { - if (PointsAreClose(op->Pt, op->Prev->Pt, distSqrd)) - { - op = ExcludeOp(op); - size--; - } - else if (PointsAreClose(op->Prev->Pt, op->Next->Pt, distSqrd)) - { - ExcludeOp(op->Next); - op = ExcludeOp(op); - size -= 2; + if (size == 0) { + out_poly.clear(); + return; } - else if (SlopesNearCollinear(op->Prev->Pt, op->Pt, op->Next->Pt, distSqrd)) - { - op = ExcludeOp(op); - size--; - } - else - { - op->Idx = 1; - op = op->Next; - } - } - if (size < 3) size = 0; - out_poly.resize(size); - for (size_t i = 0; i < size; ++i) - { - out_poly[i] = op->Pt; - op = op->Next; - } - delete [] outPts; + OutPt* outPts = new OutPt[size]; + for (size_t i = 0; i < size; ++i) { + outPts[i].Pt = in_poly[i]; + outPts[i].Next = &outPts[(i + 1) % size]; + outPts[i].Next->Prev = &outPts[i]; + outPts[i].Idx = 0; + } + + double distSqrd = distance * distance; + OutPt* op = &outPts[0]; + while (op->Idx == 0 && op->Next != op->Prev) { + if (PointsAreClose(op->Pt, op->Prev->Pt, distSqrd)) { + op = ExcludeOp(op); + size--; + } + else if (PointsAreClose(op->Prev->Pt, op->Next->Pt, distSqrd)) { + ExcludeOp(op->Next); + op = ExcludeOp(op); + size -= 2; + } + else if (SlopesNearCollinear(op->Prev->Pt, op->Pt, op->Next->Pt, distSqrd)) { + op = ExcludeOp(op); + size--; + } + else { + op->Idx = 1; + op = op->Next; + } + } + + if (size < 3) { + size = 0; + } + out_poly.resize(size); + for (size_t i = 0; i < size; ++i) { + out_poly[i] = op->Pt; + op = op->Next; + } + delete[] outPts; } //------------------------------------------------------------------------------ void CleanPolygon(Path& poly, double distance) { - CleanPolygon(poly, poly, distance); + CleanPolygon(poly, poly, distance); } //------------------------------------------------------------------------------ void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance) { - for (Paths::size_type i = 0; i < in_polys.size(); ++i) - CleanPolygon(in_polys[i], out_polys[i], distance); + for (Paths::size_type i = 0; i < in_polys.size(); ++i) { + CleanPolygon(in_polys[i], out_polys[i], distance); + } } //------------------------------------------------------------------------------ void CleanPolygons(Paths& polys, double distance) { - CleanPolygons(polys, polys, distance); + CleanPolygons(polys, polys, distance); } //------------------------------------------------------------------------------ -void Minkowski(const Path& poly, const Path& path, - Paths& solution, bool isSum, bool isClosed) +void Minkowski(const Path& poly, const Path& path, Paths& solution, bool isSum, bool isClosed) { - int delta = (isClosed ? 1 : 0); - size_t polyCnt = poly.size(); - size_t pathCnt = path.size(); - Paths pp; - pp.reserve(pathCnt); - if (isSum) - for (size_t i = 0; i < pathCnt; ++i) - { - Path p; - p.reserve(polyCnt); - for (size_t j = 0; j < poly.size(); ++j) - p.push_back(IntPoint(path[i].X + poly[j].X, path[i].Y + poly[j].Y)); - pp.push_back(p); + int delta = (isClosed ? 1 : 0); + size_t polyCnt = poly.size(); + size_t pathCnt = path.size(); + Paths pp; + pp.reserve(pathCnt); + if (isSum) { + for (size_t i = 0; i < pathCnt; ++i) { + Path p; + p.reserve(polyCnt); + for (size_t j = 0; j < poly.size(); ++j) { + p.push_back(IntPoint(path[i].X + poly[j].X, path[i].Y + poly[j].Y)); + } + pp.push_back(p); + } } - else - for (size_t i = 0; i < pathCnt; ++i) - { - Path p; - p.reserve(polyCnt); - for (size_t j = 0; j < poly.size(); ++j) - p.push_back(IntPoint(path[i].X - poly[j].X, path[i].Y - poly[j].Y)); - pp.push_back(p); + else { + for (size_t i = 0; i < pathCnt; ++i) { + Path p; + p.reserve(polyCnt); + for (size_t j = 0; j < poly.size(); ++j) { + p.push_back(IntPoint(path[i].X - poly[j].X, path[i].Y - poly[j].Y)); + } + pp.push_back(p); + } } - solution.clear(); - solution.reserve((pathCnt + delta) * (polyCnt + 1)); - for (size_t i = 0; i < pathCnt - 1 + delta; ++i) - for (size_t j = 0; j < polyCnt; ++j) - { - Path quad; - quad.reserve(4); - quad.push_back(pp[i % pathCnt][j % polyCnt]); - quad.push_back(pp[(i + 1) % pathCnt][j % polyCnt]); - quad.push_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]); - quad.push_back(pp[i % pathCnt][(j + 1) % polyCnt]); - if (!Orientation(quad)) ReversePath(quad); - solution.push_back(quad); + solution.clear(); + solution.reserve((pathCnt + delta) * (polyCnt + 1)); + for (size_t i = 0; i < pathCnt - 1 + delta; ++i) { + for (size_t j = 0; j < polyCnt; ++j) { + Path quad; + quad.reserve(4); + quad.push_back(pp[i % pathCnt][j % polyCnt]); + quad.push_back(pp[(i + 1) % pathCnt][j % polyCnt]); + quad.push_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]); + quad.push_back(pp[i % pathCnt][(j + 1) % polyCnt]); + if (!Orientation(quad)) { + ReversePath(quad); + } + solution.push_back(quad); + } } } //------------------------------------------------------------------------------ void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed) { - Minkowski(pattern, path, solution, true, pathIsClosed); - Clipper c; - c.AddPaths(solution, ptSubject, true); - c.Execute(ctUnion, solution, pftNonZero, pftNonZero); + Minkowski(pattern, path, solution, true, pathIsClosed); + Clipper c; + c.AddPaths(solution, ptSubject, true); + c.Execute(ctUnion, solution, pftNonZero, pftNonZero); } //------------------------------------------------------------------------------ -void TranslatePath(const Path& input, Path& output, IntPoint delta) +void TranslatePath(const Path& input, Path& output, IntPoint delta) { - //precondition: input != output - output.resize(input.size()); - for (size_t i = 0; i < input.size(); ++i) - output[i] = IntPoint(input[i].X + delta.X, input[i].Y + delta.Y); + // precondition: input != output + output.resize(input.size()); + for (size_t i = 0; i < input.size(); ++i) { + output[i] = IntPoint(input[i].X + delta.X, input[i].Y + delta.Y); + } } //------------------------------------------------------------------------------ void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed) { - Clipper c; - for (size_t i = 0; i < paths.size(); ++i) - { - Paths tmp; - Minkowski(pattern, paths[i], tmp, true, pathIsClosed); - c.AddPaths(tmp, ptSubject, true); - if (pathIsClosed) - { - Path tmp2; - TranslatePath(paths[i], tmp2, pattern[0]); - c.AddPath(tmp2, ptClip, true); + Clipper c; + for (size_t i = 0; i < paths.size(); ++i) { + Paths tmp; + Minkowski(pattern, paths[i], tmp, true, pathIsClosed); + c.AddPaths(tmp, ptSubject, true); + if (pathIsClosed) { + Path tmp2; + TranslatePath(paths[i], tmp2, pattern[0]); + c.AddPath(tmp2, ptClip, true); + } } - } c.Execute(ctUnion, solution, pftNonZero, pftNonZero); } //------------------------------------------------------------------------------ void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution) { - Minkowski(poly1, poly2, solution, false, true); - Clipper c; - c.AddPaths(solution, ptSubject, true); - c.Execute(ctUnion, solution, pftNonZero, pftNonZero); + Minkowski(poly1, poly2, solution, false, true); + Clipper c; + c.AddPaths(solution, ptSubject, true); + c.Execute(ctUnion, solution, pftNonZero, pftNonZero); } //------------------------------------------------------------------------------ -enum NodeType {ntAny, ntOpen, ntClosed}; +enum NodeType +{ + ntAny, + ntOpen, + ntClosed +}; void AddPolyNodeToPaths(const PolyNode& polynode, NodeType nodetype, Paths& paths) { - bool match = true; - if (nodetype == ntClosed) match = !polynode.IsOpen(); - else if (nodetype == ntOpen) return; + bool match = true; + if (nodetype == ntClosed) { + match = !polynode.IsOpen(); + } + else if (nodetype == ntOpen) { + return; + } - if (!polynode.Contour.empty() && match) - paths.push_back(polynode.Contour); - for (int i = 0; i < polynode.ChildCount(); ++i) - AddPolyNodeToPaths(*polynode.Childs[i], nodetype, paths); + if (!polynode.Contour.empty() && match) { + paths.push_back(polynode.Contour); + } + for (int i = 0; i < polynode.ChildCount(); ++i) { + AddPolyNodeToPaths(*polynode.Childs[i], nodetype, paths); + } } //------------------------------------------------------------------------------ void PolyTreeToPaths(const PolyTree& polytree, Paths& paths) { - paths.resize(0); - paths.reserve(polytree.Total()); - AddPolyNodeToPaths(polytree, ntAny, paths); + paths.resize(0); + paths.reserve(polytree.Total()); + AddPolyNodeToPaths(polytree, ntAny, paths); } //------------------------------------------------------------------------------ void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths) { - paths.resize(0); - paths.reserve(polytree.Total()); - AddPolyNodeToPaths(polytree, ntClosed, paths); + paths.resize(0); + paths.reserve(polytree.Total()); + AddPolyNodeToPaths(polytree, ntClosed, paths); } //------------------------------------------------------------------------------ void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths) { - paths.resize(0); - paths.reserve(polytree.Total()); - //Open paths are top level only, so ... - for (int i = 0; i < polytree.ChildCount(); ++i) - if (polytree.Childs[i]->IsOpen()) - paths.push_back(polytree.Childs[i]->Contour); + paths.resize(0); + paths.reserve(polytree.Total()); + // Open paths are top level only, so ... + for (int i = 0; i < polytree.ChildCount(); ++i) { + if (polytree.Childs[i]->IsOpen()) { + paths.push_back(polytree.Childs[i]->Contour); + } + } } //------------------------------------------------------------------------------ -std::ostream& operator <<(std::ostream &s, const IntPoint &p) +std::ostream& operator<<(std::ostream& s, const IntPoint& p) { - s << "(" << p.X << "," << p.Y << ")"; - return s; + s << "(" << p.X << "," << p.Y << ")"; + return s; } //------------------------------------------------------------------------------ -std::ostream& operator <<(std::ostream &s, const Path &p) +std::ostream& operator<<(std::ostream& s, const Path& p) { - if (p.empty()) - return s; - Path::size_type last = p.size() -1; - for (Path::size_type i = 0; i < last; i++) - s << "(" << p[i].X << "," << p[i].Y << "), "; - s << "(" << p[last].X << "," << p[last].Y << ")\n"; - return s; + if (p.empty()) { + return s; + } + Path::size_type last = p.size() - 1; + for (Path::size_type i = 0; i < last; i++) { + s << "(" << p[i].X << "," << p[i].Y << "), "; + } + s << "(" << p[last].X << "," << p[last].Y << ")\n"; + return s; } //------------------------------------------------------------------------------ -std::ostream& operator <<(std::ostream &s, const Paths &p) +std::ostream& operator<<(std::ostream& s, const Paths& p) { - for (Paths::size_type i = 0; i < p.size(); i++) - s << p[i]; - s << "\n"; - return s; + for (Paths::size_type i = 0; i < p.size(); i++) { + s << p[i]; + } + s << "\n"; + return s; } //------------------------------------------------------------------------------ -} //ClipperLib namespace +} // namespace ClipperLib diff --git a/src/Mod/CAM/libarea/clipper.hpp b/src/Mod/CAM/libarea/clipper.hpp index 3052f1d8ae..544d8fe24d 100644 --- a/src/Mod/CAM/libarea/clipper.hpp +++ b/src/Mod/CAM/libarea/clipper.hpp @@ -1,53 +1,53 @@ /******************************************************************************* -* * -* Author : Angus Johnson * -* Version : 6.2.0 * -* Date : 2 October 2014 * -* Website : http://www.angusj.com * -* Copyright : Angus Johnson 2010-2014 * -* * -* License: * -* Use, modification & distribution is subject to Boost Software License Ver 1. * -* http://www.boost.org/LICENSE_1_0.txt * -* * -* Attributions: * -* The code in this library is an extension of Bala Vatti's clipping algorithm: * -* "A generic solution to polygon clipping" * -* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * -* http://portal.acm.org/citation.cfm?id=129906 * -* * -* Computer graphics and geometric modeling: implementation and algorithms * -* By Max K. Agoston * -* Springer; 1 edition (January 4, 2005) * -* http://books.google.com/books?q=vatti+clipping+agoston * -* * -* See also: * -* "Polygon Offsetting by Computing Winding Numbers" * -* Paper no. DETC2005-85513 pp. 565-575 * -* ASME 2005 International Design Engineering Technical Conferences * -* and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24-28, 2005 , Long Beach, California, USA * -* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * -* * -*******************************************************************************/ + * * + * Author : Angus Johnson * + * Version : 6.2.0 * + * Date : 2 October 2014 * + * Website : http://www.angusj.com * + * Copyright : Angus Johnson 2010-2014 * + * * + * License: * + * Use, modification & distribution is subject to Boost Software License Ver 1. * + * http://www.boost.org/LICENSE_1_0.txt * + * * + * Attributions: * + * The code in this library is an extension of Bala Vatti's clipping algorithm: * + * "A generic solution to polygon clipping" * + * Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * + * http://portal.acm.org/citation.cfm?id=129906 * + * * + * Computer graphics and geometric modeling: implementation and algorithms * + * By Max K. Agoston * + * Springer; 1 edition (January 4, 2005) * + * http://books.google.com/books?q=vatti+clipping+agoston * + * * + * See also: * + * "Polygon Offsetting by Computing Winding Numbers" * + * Paper no. DETC2005-85513 pp. 565-575 * + * ASME 2005 International Design Engineering Technical Conferences * + * and Computers and Information in Engineering Conference (IDETC/CIE2005) * + * September 24-28, 2005 , Long Beach, California, USA * + * http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * + * * + *******************************************************************************/ #ifndef clipper_hpp #define clipper_hpp #define CLIPPER_VERSION "6.2.0" -//use_int32: When enabled 32bit ints are used instead of 64bit ints. This -//improve performance but coordinate values are limited to the range +/- 46340 -//#define use_int32 +// use_int32: When enabled 32bit ints are used instead of 64bit ints. This +// improve performance but coordinate values are limited to the range +/- 46340 +// #define use_int32 -//use_xyz: adds a Z member to IntPoint. Adds a minor cost to performance. -//#define use_xyz +// use_xyz: adds a Z member to IntPoint. Adds a minor cost to performance. +// #define use_xyz -//use_lines: Enables line clipping. Adds a very minor cost to performance. +// use_lines: Enables line clipping. Adds a very minor cost to performance. #define use_lines - -//use_deprecated: Enables temporary support for the obsolete functions -//#define use_deprecated + +// use_deprecated: Enables temporary support for the obsolete functions +// #define use_deprecated #include #include @@ -58,85 +58,143 @@ #include #include -namespace ClipperLib { +namespace ClipperLib +{ -enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; -enum PolyType { ptSubject, ptClip }; -//By far the most widely used winding rules for polygon filling are -//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) -//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) -//see http://glprogramming.com/red/chapter11.html -enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; +enum ClipType +{ + ctIntersection, + ctUnion, + ctDifference, + ctXor +}; +enum PolyType +{ + ptSubject, + ptClip +}; +// By far the most widely used winding rules for polygon filling are +// EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) +// Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) +// see http://glprogramming.com/red/chapter11.html +enum PolyFillType +{ + pftEvenOdd, + pftNonZero, + pftPositive, + pftNegative +}; #ifdef use_int32 - typedef int cInt; - static cInt const loRange = 0x7FFF; - static cInt const hiRange = 0x7FFF; +typedef int cInt; +static cInt const loRange = 0x7FFF; +static cInt const hiRange = 0x7FFF; #else - typedef signed long long cInt; - static cInt const loRange = 0x3FFFFFFF; - static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL; - typedef signed long long long64; //used by Int128 class - typedef unsigned long long ulong64; +typedef signed long long cInt; +static cInt const loRange = 0x3FFFFFFF; +static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL; +typedef signed long long long64; // used by Int128 class +typedef unsigned long long ulong64; #endif -struct IntPoint { - cInt X; - cInt Y; +struct IntPoint +{ + cInt X; + cInt Y; #ifdef use_xyz - cInt Z; - IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {}; + cInt Z; + IntPoint(cInt x = 0, cInt y = 0, cInt z = 0) + : X(x) + , Y(y) + , Z(z) {}; #else - IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {}; + IntPoint(cInt x = 0, cInt y = 0) + : X(x) + , Y(y) {}; #endif - friend inline bool operator== (const IntPoint& a, const IntPoint& b) - { - return a.X == b.X && a.Y == b.Y; - } - friend inline bool operator!= (const IntPoint& a, const IntPoint& b) - { - return a.X != b.X || a.Y != b.Y; - } + friend inline bool operator==(const IntPoint& a, const IntPoint& b) + { + return a.X == b.X && a.Y == b.Y; + } + friend inline bool operator!=(const IntPoint& a, const IntPoint& b) + { + return a.X != b.X || a.Y != b.Y; + } }; //------------------------------------------------------------------------------ -typedef std::vector< IntPoint > Path; -typedef std::vector< Path > Paths; +typedef std::vector Path; +typedef std::vector Paths; -inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;} -inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;} +inline Path& operator<<(Path& poly, const IntPoint& p) +{ + poly.push_back(p); + return poly; +} +inline Paths& operator<<(Paths& polys, const Path& p) +{ + polys.push_back(p); + return polys; +} -std::ostream& operator <<(std::ostream &s, const IntPoint &p); -std::ostream& operator <<(std::ostream &s, const Path &p); -std::ostream& operator <<(std::ostream &s, const Paths &p); +std::ostream& operator<<(std::ostream& s, const IntPoint& p); +std::ostream& operator<<(std::ostream& s, const Path& p); +std::ostream& operator<<(std::ostream& s, const Paths& p); struct DoublePoint { - double X; - double Y; - DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {} - DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {} + double X; + double Y; + DoublePoint(double x = 0, double y = 0) + : X(x) + , Y(y) + {} + DoublePoint(IntPoint ip) + : X((double)ip.X) + , Y((double)ip.Y) + {} }; //------------------------------------------------------------------------------ #ifdef use_xyz -typedef void (*ZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt); +typedef void (*ZFillCallback)(IntPoint& e1bot, + IntPoint& e1top, + IntPoint& e2bot, + IntPoint& e2top, + IntPoint& pt); #endif -enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4}; -enum JoinType {jtSquare, jtRound, jtMiter}; -enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound}; +enum InitOptions +{ + ioReverseSolution = 1, + ioStrictlySimple = 2, + ioPreserveCollinear = 4 +}; +enum JoinType +{ + jtSquare, + jtRound, + jtMiter +}; +enum EndType +{ + etClosedPolygon, + etClosedLine, + etOpenButt, + etOpenSquare, + etOpenRound +}; class PolyNode; -typedef std::vector< PolyNode* > PolyNodes; +typedef std::vector PolyNodes; -class PolyNode -{ +class PolyNode +{ public: PolyNode(); - virtual ~PolyNode(){}; + virtual ~PolyNode() {}; Path Contour; PolyNodes Childs; PolyNode* Parent; @@ -144,36 +202,41 @@ public: bool IsHole() const; bool IsOpen() const; int ChildCount() const; + private: - unsigned Index; //node index in Parent.Childs + unsigned Index; // node index in Parent.Childs bool m_IsOpen; JoinType m_jointype; EndType m_endtype; PolyNode* GetNextSiblingUp() const; void AddChild(PolyNode& child); - friend class Clipper; //to access Index - friend class ClipperOffset; + friend class Clipper; // to access Index + friend class ClipperOffset; }; class PolyTree: public PolyNode -{ +{ public: - ~PolyTree(){Clear();}; + ~PolyTree() + { + Clear(); + }; PolyNode* GetFirst() const; void Clear(); int Total() const; + private: PolyNodes AllNodes; - friend class Clipper; //to access AllNodes + friend class Clipper; // to access AllNodes }; -bool Orientation(const Path &poly); -double Area(const Path &poly); -int PointInPolygon(const IntPoint &pt, const Path &path); +bool Orientation(const Path& poly); +double Area(const Path& poly); +int PointInPolygon(const IntPoint& pt, const Path& path); -void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd); -void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd); -void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd); +void SimplifyPolygon(const Path& in_poly, Paths& out_polys, PolyFillType fillType = pftEvenOdd); +void SimplifyPolygons(const Paths& in_polys, Paths& out_polys, PolyFillType fillType = pftEvenOdd); +void SimplifyPolygons(Paths& polys, PolyFillType fillType = pftEvenOdd); void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415); void CleanPolygon(Path& poly, double distance = 1.415); @@ -191,12 +254,22 @@ void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths); void ReversePath(Path& p); void ReversePaths(Paths& p); -struct IntRect { cInt left; cInt top; cInt right; cInt bottom; }; +struct IntRect +{ + cInt left; + cInt top; + cInt right; + cInt bottom; +}; -//enums that are used internally ... -enum EdgeSide { esLeft = 1, esRight = 2}; +// enums that are used internally ... +enum EdgeSide +{ + esLeft = 1, + esRight = 2 +}; -//forward declarations (for stuff used internally) ... +// forward declarations (for stuff used internally) ... struct TEdge; struct IntersectNode; struct LocalMinimum; @@ -205,191 +278,217 @@ struct OutPt; struct OutRec; struct Join; -typedef std::vector < OutRec* > PolyOutList; -typedef std::vector < TEdge* > EdgeList; -typedef std::vector < Join* > JoinList; -typedef std::vector < IntersectNode* > IntersectList; +typedef std::vector PolyOutList; +typedef std::vector EdgeList; +typedef std::vector JoinList; +typedef std::vector IntersectList; //------------------------------------------------------------------------------ -//ClipperBase is the ancestor to the Clipper class. It should not be -//instantiated directly. This class simply abstracts the conversion of sets of -//polygon coordinates into edge objects that are stored in a LocalMinima list. +// ClipperBase is the ancestor to the Clipper class. It should not be +// instantiated directly. This class simply abstracts the conversion of sets of +// polygon coordinates into edge objects that are stored in a LocalMinima list. class ClipperBase { public: - ClipperBase(); - virtual ~ClipperBase(); - bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed); - bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed); - virtual void Clear(); - IntRect GetBounds(); - bool PreserveCollinear() {return m_PreserveCollinear;}; - void PreserveCollinear(bool value) {m_PreserveCollinear = value;}; + ClipperBase(); + virtual ~ClipperBase(); + bool AddPath(const Path& pg, PolyType PolyTyp, bool Closed); + bool AddPaths(const Paths& ppg, PolyType PolyTyp, bool Closed); + virtual void Clear(); + IntRect GetBounds(); + bool PreserveCollinear() + { + return m_PreserveCollinear; + }; + void PreserveCollinear(bool value) + { + m_PreserveCollinear = value; + }; + protected: - void DisposeLocalMinimaList(); - TEdge* AddBoundsToLML(TEdge *e, bool IsClosed); - void PopLocalMinima(); - virtual void Reset(); - TEdge* ProcessBound(TEdge* E, bool IsClockwise); - void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed); - TEdge* DescendToMin(TEdge *&E); - void AscendToMax(TEdge *&E, bool Appending, bool IsClosed); + void DisposeLocalMinimaList(); + TEdge* AddBoundsToLML(TEdge* e, bool IsClosed); + void PopLocalMinima(); + virtual void Reset(); + TEdge* ProcessBound(TEdge* E, bool IsClockwise); + void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed); + TEdge* DescendToMin(TEdge*& E); + void AscendToMax(TEdge*& E, bool Appending, bool IsClosed); - typedef std::vector MinimaList; - MinimaList::iterator m_CurrentLM; - MinimaList m_MinimaList; + typedef std::vector MinimaList; + MinimaList::iterator m_CurrentLM; + MinimaList m_MinimaList; - bool m_UseFullRange; - EdgeList m_edges; - bool m_PreserveCollinear; - bool m_HasOpenPaths; + bool m_UseFullRange; + EdgeList m_edges; + bool m_PreserveCollinear; + bool m_HasOpenPaths; }; //------------------------------------------------------------------------------ -class Clipper : public virtual ClipperBase +class Clipper: public virtual ClipperBase { public: - Clipper(int initOptions = 0); - ~Clipper(); - bool Execute(ClipType clipType, - Paths &solution, - PolyFillType subjFillType = pftEvenOdd, - PolyFillType clipFillType = pftEvenOdd); - bool Execute(ClipType clipType, - PolyTree &polytree, - PolyFillType subjFillType = pftEvenOdd, - PolyFillType clipFillType = pftEvenOdd); - bool ReverseSolution() {return m_ReverseOutput;}; - void ReverseSolution(bool value) {m_ReverseOutput = value;}; - bool StrictlySimple() {return m_StrictSimple;}; - void StrictlySimple(bool value) {m_StrictSimple = value;}; - //set the callback function for z value filling on intersections (otherwise Z is 0) + Clipper(int initOptions = 0); + ~Clipper(); + bool Execute(ClipType clipType, + Paths& solution, + PolyFillType subjFillType = pftEvenOdd, + PolyFillType clipFillType = pftEvenOdd); + bool Execute(ClipType clipType, + PolyTree& polytree, + PolyFillType subjFillType = pftEvenOdd, + PolyFillType clipFillType = pftEvenOdd); + bool ReverseSolution() + { + return m_ReverseOutput; + }; + void ReverseSolution(bool value) + { + m_ReverseOutput = value; + }; + bool StrictlySimple() + { + return m_StrictSimple; + }; + void StrictlySimple(bool value) + { + m_StrictSimple = value; + }; + // set the callback function for z value filling on intersections (otherwise Z is 0) #ifdef use_xyz - void ZFillFunction(ZFillCallback zFillFunc); + void ZFillFunction(ZFillCallback zFillFunc); #endif protected: - void Reset(); - virtual bool ExecuteInternal(); + void Reset(); + virtual bool ExecuteInternal(); + private: - PolyOutList m_PolyOuts; - JoinList m_Joins; - JoinList m_GhostJoins; - IntersectList m_IntersectList; - ClipType m_ClipType; - typedef std::priority_queue ScanbeamList; - ScanbeamList m_Scanbeam; - TEdge *m_ActiveEdges; - TEdge *m_SortedEdges; - bool m_ExecuteLocked; - PolyFillType m_ClipFillType; - PolyFillType m_SubjFillType; - bool m_ReverseOutput; - bool m_UsingPolyTree; - bool m_StrictSimple; + PolyOutList m_PolyOuts; + JoinList m_Joins; + JoinList m_GhostJoins; + IntersectList m_IntersectList; + ClipType m_ClipType; + typedef std::priority_queue ScanbeamList; + ScanbeamList m_Scanbeam; + TEdge* m_ActiveEdges; + TEdge* m_SortedEdges; + bool m_ExecuteLocked; + PolyFillType m_ClipFillType; + PolyFillType m_SubjFillType; + bool m_ReverseOutput; + bool m_UsingPolyTree; + bool m_StrictSimple; #ifdef use_xyz - ZFillCallback m_ZFill; //custom callback + ZFillCallback m_ZFill; // custom callback #endif - void SetWindingCount(TEdge& edge); - bool IsEvenOddFillType(const TEdge& edge) const; - bool IsEvenOddAltFillType(const TEdge& edge) const; - void InsertScanbeam(const cInt Y); - cInt PopScanbeam(); - void InsertLocalMinimaIntoAEL(const cInt botY); - void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge); - void AddEdgeToSEL(TEdge *edge); - void CopyAELToSEL(); - void DeleteFromSEL(TEdge *e); - void DeleteFromAEL(TEdge *e); - void UpdateEdgeIntoAEL(TEdge *&e); - void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); - bool IsContributing(const TEdge& edge) const; - bool IsTopHorz(const cInt XPos); - void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); - void DoMaxima(TEdge *e); - void ProcessHorizontals(bool IsTopOfScanbeam); - void ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam); - void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); - OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); - OutRec* GetOutRec(int idx); - void AppendPolygon(TEdge *e1, TEdge *e2); - void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt); - OutRec* CreateOutRec(); - OutPt* AddOutPt(TEdge *e, const IntPoint &pt); - void DisposeAllOutRecs(); - void DisposeOutRec(PolyOutList::size_type index); - bool ProcessIntersections(const cInt topY); - void BuildIntersectList(const cInt topY); - void ProcessIntersectList(); - void ProcessEdgesAtTopOfScanbeam(const cInt topY); - void BuildResult(Paths& polys); - void BuildResult2(PolyTree& polytree); - void SetHoleState(TEdge *e, OutRec *outrec); - void DisposeIntersectNodes(); - bool FixupIntersectionOrder(); - void FixupOutPolygon(OutRec &outrec); - bool IsHole(TEdge *e); - bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl); - void FixHoleLinkage(OutRec &outrec); - void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt); - void ClearJoins(); - void ClearGhostJoins(); - void AddGhostJoin(OutPt *op, const IntPoint offPt); - bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2); - void JoinCommonEdges(); - void DoSimplePolygons(); - void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec); - void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec); + void SetWindingCount(TEdge& edge); + bool IsEvenOddFillType(const TEdge& edge) const; + bool IsEvenOddAltFillType(const TEdge& edge) const; + void InsertScanbeam(const cInt Y); + cInt PopScanbeam(); + void InsertLocalMinimaIntoAEL(const cInt botY); + void InsertEdgeIntoAEL(TEdge* edge, TEdge* startEdge); + void AddEdgeToSEL(TEdge* edge); + void CopyAELToSEL(); + void DeleteFromSEL(TEdge* e); + void DeleteFromAEL(TEdge* e); + void UpdateEdgeIntoAEL(TEdge*& e); + void SwapPositionsInSEL(TEdge* edge1, TEdge* edge2); + bool IsContributing(const TEdge& edge) const; + bool IsTopHorz(const cInt XPos); + void SwapPositionsInAEL(TEdge* edge1, TEdge* edge2); + void DoMaxima(TEdge* e); + void ProcessHorizontals(bool IsTopOfScanbeam); + void ProcessHorizontal(TEdge* horzEdge, bool isTopOfScanbeam); + void AddLocalMaxPoly(TEdge* e1, TEdge* e2, const IntPoint& pt); + OutPt* AddLocalMinPoly(TEdge* e1, TEdge* e2, const IntPoint& pt); + OutRec* GetOutRec(int idx); + void AppendPolygon(TEdge* e1, TEdge* e2); + void IntersectEdges(TEdge* e1, TEdge* e2, IntPoint& pt); + OutRec* CreateOutRec(); + OutPt* AddOutPt(TEdge* e, const IntPoint& pt); + void DisposeAllOutRecs(); + void DisposeOutRec(PolyOutList::size_type index); + bool ProcessIntersections(const cInt topY); + void BuildIntersectList(const cInt topY); + void ProcessIntersectList(); + void ProcessEdgesAtTopOfScanbeam(const cInt topY); + void BuildResult(Paths& polys); + void BuildResult2(PolyTree& polytree); + void SetHoleState(TEdge* e, OutRec* outrec); + void DisposeIntersectNodes(); + bool FixupIntersectionOrder(); + void FixupOutPolygon(OutRec& outrec); + bool IsHole(TEdge* e); + bool FindOwnerFromSplitRecs(OutRec& outRec, OutRec*& currOrfl); + void FixHoleLinkage(OutRec& outrec); + void AddJoin(OutPt* op1, OutPt* op2, const IntPoint offPt); + void ClearJoins(); + void ClearGhostJoins(); + void AddGhostJoin(OutPt* op, const IntPoint offPt); + bool JoinPoints(Join* j, OutRec* outRec1, OutRec* outRec2); + void JoinCommonEdges(); + void DoSimplePolygons(); + void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec); + void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec); #ifdef use_xyz - void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2); + void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2); #endif }; //------------------------------------------------------------------------------ -class ClipperOffset +class ClipperOffset { public: - ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25); - ~ClipperOffset(); - void AddPath(const Path& path, JoinType joinType, EndType endType); - void AddPaths(const Paths& paths, JoinType joinType, EndType endType); - void Execute(Paths& solution, double delta); - void Execute(PolyTree& solution, double delta); - void Clear(); - double MiterLimit; - double ArcTolerance; -private: - Paths m_destPolys; - Path m_srcPoly; - Path m_destPoly; - std::vector m_normals; - double m_delta, m_sinA, m_sin, m_cos; - double m_miterLim, m_StepsPerRad; - IntPoint m_lowest; - PolyNode m_polyNodes; + ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25); + ~ClipperOffset(); + void AddPath(const Path& path, JoinType joinType, EndType endType); + void AddPaths(const Paths& paths, JoinType joinType, EndType endType); + void Execute(Paths& solution, double delta); + void Execute(PolyTree& solution, double delta); + void Clear(); + double MiterLimit; + double ArcTolerance; - void FixOrientations(); - void DoOffset(double delta); - void OffsetPoint(int j, int& k, JoinType jointype); - void DoSquare(int j, int k); - void DoMiter(int j, int k, double r); - void DoRound(int j, int k); +private: + Paths m_destPolys; + Path m_srcPoly; + Path m_destPoly; + std::vector m_normals; + double m_delta, m_sinA, m_sin, m_cos; + double m_miterLim, m_StepsPerRad; + IntPoint m_lowest; + PolyNode m_polyNodes; + + void FixOrientations(); + void DoOffset(double delta); + void OffsetPoint(int j, int& k, JoinType jointype); + void DoSquare(int j, int k); + void DoMiter(int j, int k, double r); + void DoRound(int j, int k); }; //------------------------------------------------------------------------------ -class clipperException : public std::exception +class clipperException: public std::exception { - public: - clipperException(const char* description): m_descr(description) {} - virtual ~clipperException() throw() {} - virtual const char* what() const throw() {return m_descr.c_str();} - private: +public: + clipperException(const char* description) + : m_descr(description) + {} + virtual ~clipperException() throw() + {} + virtual const char* what() const throw() + { + return m_descr.c_str(); + } + +private: std::string m_descr; }; //------------------------------------------------------------------------------ -} //ClipperLib namespace - -#endif //clipper_hpp - +} // namespace ClipperLib +#endif // clipper_hpp diff --git a/src/Mod/CAM/libarea/kurve/Construction.cpp b/src/Mod/CAM/libarea/kurve/Construction.cpp index 455239ac63..bb56399a67 100644 --- a/src/Mod/CAM/libarea/kurve/Construction.cpp +++ b/src/Mod/CAM/libarea/kurve/Construction.cpp @@ -9,866 +9,1037 @@ #include "geometry.h" using namespace geoff_geometry; -namespace geoff_geometry { - int UNITS = MM; - double TOLERANCE = 1.0e-06; - double TOLERANCE_SQ = TOLERANCE * TOLERANCE; - double TIGHT_TOLERANCE = 1.0e-09; - double UNIT_VECTOR_TOLERANCE = 1.0e-10; - double RESOLUTION = 1.0e-06; - - // dummy functions - const wchar_t* getMessage(const wchar_t* original){return original;} - void FAILURE(const wchar_t* str){throw(str);} - void FAILURE(const std::wstring& str){throw(str);} - - void set_Tolerances(int mode) { - UNIT_VECTOR_TOLERANCE = 1.0e-10; - switch (UNITS = mode) - { - case MM: - geoff_geometry::TOLERANCE = 1.0e-03; // Peps - RESOLUTION = 1.0e-03; - TIGHT_TOLERANCE = 1.0e-06; - break; - case INCHES: - TOLERANCE = 1.0e-04; // Peps - RESOLUTION = 1.0e-04; - TIGHT_TOLERANCE = 1.0e-7; - break; - case METRES: - TOLERANCE = 1.0e-06; // p4c...SW - RESOLUTION = 1.0e-06; - TIGHT_TOLERANCE = 1.0e-09; - break; - default: - FAILURE(L"INVALID UNITS"); - } - TOLERANCE_SQ = TOLERANCE * TOLERANCE; - } - - double mm(double value) { - switch(UNITS) { - default: - return value; - case METRES: - return value * .001; - case INCHES: - return value / 25.4; - } - } - - // ostream operators = non-member overload - // ********************************************************************************************************* - wostream& operator << (wostream& op, Point& p){ - // for debug - print point to file - if(!p.ok) - op << L" ok=\"false\""; - else - op << L" x=\"" << p.x << L"\" y=\"" << p.y << L"\""; - return op; - } - - wostream& operator <<(wostream& op, CLine& cl){ - // for debug - print cline to file - if(!cl.ok) - op << L"(CLine UNSET)"; - else - op << L"sp=" << cl.p << L" v=" << cl.v; - return op; - } - - wostream& operator <<(wostream& op, Plane& pl){ - // for debug - print plane to file stream - if(!pl.ok) - op << L"(Plane UNSET)"; - else - op << L"d=" << pl.d << L" normal=" << pl.normal; - return op; - } - - ostream& operator << (ostream& op, Point3d& p){ - // for debug - print point to file -// if(!p.ok) -// op << "ok=\"false\""; -// else - op << "x=\"" << p.x << "\" y=\"" << p.y << "\" z=" << p.z << "\""; - return op; - - } - - wostream& operator <<(wostream& op, Vector2d& v){ - // for debug - print vector to file - op << L"(" << v.getx() << L", " << v.gety() << L")"; - return op; - } - - wostream& operator <<(wostream& op, Vector3d& v){ - // for debug - print vector to file - op << L"(" << v.getx() << L", " << v.gety() << L"," << v.getz() << L")"; - return op; - } - - wostream& operator <<(wostream& op, Circle& c){ - // for debug - print circle to file - if(!c.ok) - op << L"ok=\"false\""; - else - op << L" x=\"" << c.pc.x << L"\" y=\"" << c.pc.y << L"\" radius=\"" << c.radius << L"\""; - return op; - } - - wostream& operator <<(wostream& op, Span& sp){ - // for debug - print span to file stream - op << L"p0 = " << sp.p0 << L" p1=" << sp.p1; - if(sp.dir) { - op << L" pc=" << sp.pc << L" dir=" << ((sp.dir == CW)?L"CW" : L"ACW") << L" radius=" << sp.radius; - } - return op; - } - - - - // *************************************************************************************************************************************** - // point classes - // *************************************************************************************************************************************** - Point::Point( const Point3d& p ) { // copy constructor Point p1(p2); - x = p.x; - y = p.y; -// ok = p.ok; - ok = true; - } - - Point::Point(const Vector2d& v) - { - x = v.getx(); y = v.gety(); ok = true; - } - - Point3d::Point3d(const Vector3d& v) { - x = v.getx(); y = v.gety(); z = v.getz();// ok = true; - } - - bool Point3d::operator==(const Point3d &p)const{ - // p1 == p2 (uses TOLERANCE) - if(FNE(this->x, p.x, TOLERANCE) || FNE(this->y, p.y, TOLERANCE) || FNE(this->z, p.z, TOLERANCE)) - return false; - return true; - } - - Point Point::Transform(const Matrix& m) { - // transform Point - Point ret; - m.Transform2d(&x, &ret.x); - ret.ok = true; - return ret; - } - Point3d Point3d::Transform(const Matrix& m) { - // transform Point - Point3d ret; - m.Transform(&x, &ret.x); -// ret.ok = true; - return ret; - } - - Point Point::operator+(const Vector2d &v)const{ - return Point(x + v.getx(), y + v.gety()); - } - - Point3d Point3d::operator+(const Vector3d &v)const{ - return Point3d(x + v.getx(), y + v.gety(), z + v.getz()); - } - - bool Point::operator==(const Point &p) const{ - // p1 == p2 (uses TOLERANCE) - if(FNE(this->x, p.x, TOLERANCE) || FNE(this->y, p.y, TOLERANCE)) - return false; - return true; - } - - - - double Point::Dist(const Point& p)const{ // distance between 2 points - return Vector2d(*this, p).magnitude(); - } - - double Point::DistSq(const Point& p)const{ // distance squared between 2 points - return Vector2d(*this, p).magnitudesqd(); - } - - double Point3d::Dist(const Point3d& p)const { // distance between 2 points - return Vector3d(*this, p).magnitude(); - } - - double Point3d::DistSq(const Point3d& p)const { // distance squared - return (this->x - p.x) * (this->x - p.x) + (this->y - p.y) * (this->y - p.y) + (this->z - p.z) * (this->z - p.z); - } - - Point Point::Mid(const Point& p1, double factor)const{ - // Mid - return geoff_geometry::Mid(*this, p1, factor); - } - - Point3d Point3d::Mid(const Point3d& p, double factor)const{ - // Mid - return Vector3d(*this, p) * factor + *this; - } - - Point Mid(const Point& p0, const Point& p1, double factor){ - // mid or partway between 2 points - return Vector2d(p0, p1) * factor + p0; - } - Point Rel(const Point& p, double x0, double y0) { - // Relative point - return (p.ok)?Point(p.x + x0, p.y + y0) : INVALID_POINT; - } - - Point Polar(const Point& p, double angle, double r) { - // polar from this point - angle *= DegreesToRadians; - return (p.ok)?Point(p.x + r * cos(angle), p.y + r * sin(angle)) : INVALID_POINT; - } - - // *************************************************************************************************************************************** - // clines - // *************************************************************************************************************************************** - // const CLine horiz(Point(0, 0), 1, 0); // define global horizontal line - - double CLine::c() { - // returns c for ax + by + c = 0 format (peps format where needed) - return (v.getx() * p.y - v.gety() * p.x); - } - void CLine::Normalise() { - // normalise the cline vector - ok = v.normalise() >= TOLERANCE; - } - - CLine::CLine(const Span& sp){ - p = sp.p0; - v = sp.vs; - ok = sp.returnSpanProperties && !sp.NullSpan; - } - - CLine Normal(const CLine& s) { - // returns normal to this line - return CLine(s.p, ~s.v, false); - } - const CLine CLine::operator ~(void){ - return CLine(this->p, ~v, false); - } - CLine Normal(const CLine& s, const Point& p) { - // returns normal to this line thro' p - return CLine(p, ~s.v, false); - } - - CLine CLine::Transform(Matrix& m) { - - Point p0 = this->p; - Point p1(p0.x + v.getx(), p0.y + v.gety()); - return CLine(p0.Transform(m), p1.Transform(m)); - } - - - double CLine::Dist(const Point& p0)const { - // distance between cline & point >0 cw about point <0 acw about point - return this->v ^ Vector2d(p0, this->p); - } - - double Point::Dist(const CLine& cl)const { - // distance between cline & point >0 cw about point <0 acw about point - return cl.v ^ Vector2d(*this, cl.p); - } - - Point CLine::Intof(const CLine& s) { - // Intof 2 Clines - return geoff_geometry::Intof(*this, s); - } - - Point CLine::Intof(int NF, const Circle& c) { - // Intof Cline & Circleconst - return geoff_geometry::Intof(NF, *this, c); - } - Point CLine::Intof(int NF, const Circle& c, Point& otherInters) { - // Intof Cline & Circle & other intersection - return geoff_geometry::Intof(NF, *this, c, otherInters); - } - - Point Intof(const CLine& s0, const CLine& s1) { - // inters of 2 clines (parameterise lines x = x0 + t * dx) - double cp = s1.v ^ s0.v; - if(fabs (cp) > 1.0e-6) { - double t = (s1.v ^ Vector2d(s0.p, s1.p)) / cp; - return s0.v * t + s0.p; - } - return INVALID_POINT; - } - Point XonCLine(CLine& s, double xval) { - // return point given X on a line - return Intof(s, CLine(Point(xval,0),0,1,false)); - } - Point YonCLine(CLine& s, double yval) { - // return point given Y on a line - return Intof(s, CLine(Point(0,yval),1,0,false)); - } - Point Along(const CLine& s, double d) { - // distance along line - return Point(s.p.x + d * s.v.getx(), s.p.y + d * s.v.gety(), s.ok); - } - - Point Along(const CLine& s, double d, Point& p) { - // distance along line from point - return Point(p.x + d * s.v.getx(), p.y + d * s.v.gety(), p.ok); - } - Point Around(const Circle& c, double d, const Point& p) { - // distance around circle from point - CLine radial(c.pc, p); - if(radial.ok) { - if(fabs(c.radius) > TOLERANCE ) { - double a = sin(- d / c.radius); - double b = cos(- d / c.radius); - return Point(c.pc.x - c.radius * (radial.v.gety() * a - radial.v.getx() * b), c.pc.y + c.radius * (radial.v.gety() * b + radial.v.getx() * a)); - } - } - return INVALID_POINT; - } - CLine AtAngle(double angle, const Point& p0, const CLine& s) { - // cline at angle [to a cline] thro' a point - angle *= DegreesToRadians; - Vector2d v(cos(angle), sin(angle)); - return CLine(p0, v.getx() * s.v.getx() - v.gety() * s.v.gety(), v.gety() * s.v.getx() + v.getx() * s.v.gety()); - } - CLine Parallel(int side, const CLine& s0, double distance) { - // parallel to line by distance - Vector2d v = ~s0.v; - return CLine(v * ((double)side * distance) + s0.p, s0.v.getx(), s0.v.gety()); - } - - CLine Parallel(const CLine& s0, Point& p) { - // parallel to line through point - return CLine(p, s0.v.getx(), s0.v.gety()); - } - - CLine CLine::Bisector(const CLine& s) { - // bisector of 2 clines - return CLine (this->Intof(s), this->v.getx() + s.v.getx(), this->v.gety() + s.v.gety()); - } - - - - - // *************************************************************************************************************************************** - // circle methods - // *************************************************************************************************************************************** - - Circle::Circle(const Point& p, double rad){ - // Circle - pc = p; - radius = rad; - ok = pc.ok; - } - - Circle::Circle( const Point& p, const Point& pc0){ - if((ok = (p.ok && pc0.ok))) { - pc = pc0; - radius = p.Dist(pc0); - } - else { - radius = 0; - } - } - - Circle::Circle( const Span& sp){ - pc = sp.pc; - radius = sp.radius; - ok = sp.returnSpanProperties; - } - - bool Circle::operator==(const Circle &c)const{ - // c1 == c2 (uses TOLERANCE) - return FEQ(this->radius, c.radius, TOLERANCE) && (this->pc == c.pc); - } - - Circle Circle::Transform(Matrix& m) { // transform - Point p0 = this->pc; - double scale; - if(!m.GetScale(scale)) - FAILURE(getMessage(L"Differential Scale not allowed for this method")); - return Circle(p0.Transform(m), radius * scale); - } - - Point Circle::Intof(int LR, const Circle& c1) { - // intof 2 circles - return geoff_geometry::Intof(LR, *this, c1); - } - Point Circle::Intof(int LR, const Circle& c1, Point& otherInters) { - // intof 2 circles, (returns the other intersection) - return geoff_geometry::Intof(LR, *this, c1, otherInters); - } - int Circle::Intof(const Circle& c1, Point& leftInters, Point& rightInters) { - // intof 2 circles, (returns the other intersection) - return geoff_geometry::Intof(*this, c1, leftInters, rightInters); - } - - CLine Circle::Tanto(int AT, double angle, const CLine& s0) const{ - // cline tanto circle at angle to optional cline - return geoff_geometry::Tanto(AT, *this, angle, s0); - } - - CLine Tanto(int AT, const Circle& c, const Point& p) { - // CLine tangent to a circle through a point - Vector2d v(p, c.pc); - double d = v.magnitude(); - CLine s(p, ~v, false); // initialise cline - - if ( d < TOLERANCE || d < fabs(c.radius) - TOLERANCE) // point inside circle ? - return INVALID_CLINE; - else { - if(d > fabs(c.radius) + TOLERANCE) { // point outside circle - v.Rotate(sqrt((d - c.radius) * (d + c.radius)), - AT * c.radius); - s.v = v; - } - } - s.Normalise(); - return s; - } - - CLine Tanto(int AT0, const Circle& c0, int AT1, const Circle& c) { - // cline tanto 2 circles - CLine s; - Circle c1 = c; - c1.radius -= (double) (AT0 * AT1) * c0.radius; - s = Tanto(AT1, c1, c0.pc); - s.p.x += (double) AT0 * c0.radius * s.v.gety(); - s.p.y -= (double) AT0 * c0.radius * s.v.getx(); - return s; - } - - CLine Tanto(int AT, const Circle& c, double angle, const CLine& s0) { - // cline at an angle [to a cline] tanto a circle - CLine s = AtAngle(angle, c.pc, s0); - s.p.x += (double) AT * c.radius * s.v.gety(); - s.p.y -= (double) AT * c.radius * s.v.getx(); - // s.p += ~s.v * (AT * c.radius); - s.ok = true; - return s; - } - Point AtAngle(const Circle& c, double angle) { - // Point at an angle on circle - angle *= DegreesToRadians; - return Point(c.pc.x + c.radius * cos(angle), c.pc.y + c.radius * sin(angle)); - } - - Point On(const CLine& s, const Point& p) { - // returns point that is nearest to s from p - double t = s.v * Vector2d(s.p, p); - return s.v * t + s.p; - } - - Point On(const Circle& c, const Point& p) { - // returns point that is nearest to c from p - double r = p.Dist(c.pc); - if(r < TOLERANCE) FAILURE(getMessage(L",Point on Circle centre - On(Circle& c, Point& p)")); - return(Mid(p, c.pc, (r - c.radius) / r)); - } - - - Point Intof( int NF, const CLine& s, const Circle& c) { - // inters of cline & circle eg. p1 = Intof(NEARINT, s1, c1); - Point otherInters; - return Intof(NF, s, c, otherInters); - } - - Point Intof( int NF, const CLine& s, const Circle& c, Point& otherInters) { - // inters of cline & circle eg. p1 = Intof(NEARINT, s1, c1); - // otherInters returns the other intersection +namespace geoff_geometry +{ +int UNITS = MM; +double TOLERANCE = 1.0e-06; +double TOLERANCE_SQ = TOLERANCE * TOLERANCE; +double TIGHT_TOLERANCE = 1.0e-09; +double UNIT_VECTOR_TOLERANCE = 1.0e-10; +double RESOLUTION = 1.0e-06; + +// dummy functions +const wchar_t* getMessage(const wchar_t* original) +{ + return original; +} +void FAILURE(const wchar_t* str) +{ + throw(str); +} +void FAILURE(const std::wstring& str) +{ + throw(str); +} + +void set_Tolerances(int mode) +{ + UNIT_VECTOR_TOLERANCE = 1.0e-10; + switch (UNITS = mode) { + case MM: + geoff_geometry::TOLERANCE = 1.0e-03; // Peps + RESOLUTION = 1.0e-03; + TIGHT_TOLERANCE = 1.0e-06; + break; + case INCHES: + TOLERANCE = 1.0e-04; // Peps + RESOLUTION = 1.0e-04; + TIGHT_TOLERANCE = 1.0e-7; + break; + case METRES: + TOLERANCE = 1.0e-06; // p4c...SW + RESOLUTION = 1.0e-06; + TIGHT_TOLERANCE = 1.0e-09; + break; + default: + FAILURE(L"INVALID UNITS"); + } + TOLERANCE_SQ = TOLERANCE * TOLERANCE; +} + +double mm(double value) +{ + switch (UNITS) { + default: + return value; + case METRES: + return value * .001; + case INCHES: + return value / 25.4; + } +} + +// ostream operators = non-member overload +// ********************************************************************************************************* +wostream& operator<<(wostream& op, Point& p) +{ + // for debug - print point to file + if (!p.ok) { + op << L" ok=\"false\""; + } + else { + op << L" x=\"" << p.x << L"\" y=\"" << p.y << L"\""; + } + return op; +} + +wostream& operator<<(wostream& op, CLine& cl) +{ + // for debug - print cline to file + if (!cl.ok) { + op << L"(CLine UNSET)"; + } + else { + op << L"sp=" << cl.p << L" v=" << cl.v; + } + return op; +} + +wostream& operator<<(wostream& op, Plane& pl) +{ + // for debug - print plane to file stream + if (!pl.ok) { + op << L"(Plane UNSET)"; + } + else { + op << L"d=" << pl.d << L" normal=" << pl.normal; + } + return op; +} + +ostream& operator<<(ostream& op, Point3d& p) +{ + // for debug - print point to file + // if(!p.ok) + // op << "ok=\"false\""; + // else + op << "x=\"" << p.x << "\" y=\"" << p.y << "\" z=" << p.z << "\""; + return op; +} + +wostream& operator<<(wostream& op, Vector2d& v) +{ + // for debug - print vector to file + op << L"(" << v.getx() << L", " << v.gety() << L")"; + return op; +} + +wostream& operator<<(wostream& op, Vector3d& v) +{ + // for debug - print vector to file + op << L"(" << v.getx() << L", " << v.gety() << L"," << v.getz() << L")"; + return op; +} + +wostream& operator<<(wostream& op, Circle& c) +{ + // for debug - print circle to file + if (!c.ok) { + op << L"ok=\"false\""; + } + else { + op << L" x=\"" << c.pc.x << L"\" y=\"" << c.pc.y << L"\" radius=\"" << c.radius << L"\""; + } + return op; +} + +wostream& operator<<(wostream& op, Span& sp) +{ + // for debug - print span to file stream + op << L"p0 = " << sp.p0 << L" p1=" << sp.p1; + if (sp.dir) { + op << L" pc=" << sp.pc << L" dir=" << ((sp.dir == CW) ? L"CW" : L"ACW") << L" radius=" + << sp.radius; + } + return op; +} + + +// *************************************************************************************************************************************** +// point classes +// *************************************************************************************************************************************** +Point::Point(const Point3d& p) +{ // copy constructor Point p1(p2); + x = p.x; + y = p.y; + // ok = p.ok; + ok = true; +} + +Point::Point(const Vector2d& v) +{ + x = v.getx(); + y = v.gety(); + ok = true; +} + +Point3d::Point3d(const Vector3d& v) +{ + x = v.getx(); + y = v.gety(); + z = v.getz(); // ok = true; +} + +bool Point3d::operator==(const Point3d& p) const +{ + // p1 == p2 (uses TOLERANCE) + if (FNE(this->x, p.x, TOLERANCE) || FNE(this->y, p.y, TOLERANCE) + || FNE(this->z, p.z, TOLERANCE)) { + return false; + } + return true; +} + +Point Point::Transform(const Matrix& m) +{ + // transform Point + Point ret; + m.Transform2d(&x, &ret.x); + ret.ok = true; + return ret; +} +Point3d Point3d::Transform(const Matrix& m) +{ + // transform Point + Point3d ret; + m.Transform(&x, &ret.x); + // ret.ok = true; + return ret; +} + +Point Point::operator+(const Vector2d& v) const +{ + return Point(x + v.getx(), y + v.gety()); +} + +Point3d Point3d::operator+(const Vector3d& v) const +{ + return Point3d(x + v.getx(), y + v.gety(), z + v.getz()); +} + +bool Point::operator==(const Point& p) const +{ + // p1 == p2 (uses TOLERANCE) + if (FNE(this->x, p.x, TOLERANCE) || FNE(this->y, p.y, TOLERANCE)) { + return false; + } + return true; +} + + +double Point::Dist(const Point& p) const +{ // distance between 2 points + return Vector2d(*this, p).magnitude(); +} + +double Point::DistSq(const Point& p) const +{ // distance squared between 2 points + return Vector2d(*this, p).magnitudesqd(); +} + +double Point3d::Dist(const Point3d& p) const +{ // distance between 2 points + return Vector3d(*this, p).magnitude(); +} + +double Point3d::DistSq(const Point3d& p) const +{ // distance squared + return (this->x - p.x) * (this->x - p.x) + (this->y - p.y) * (this->y - p.y) + + (this->z - p.z) * (this->z - p.z); +} + +Point Point::Mid(const Point& p1, double factor) const +{ + // Mid + return geoff_geometry::Mid(*this, p1, factor); +} + +Point3d Point3d::Mid(const Point3d& p, double factor) const +{ + // Mid + return Vector3d(*this, p) * factor + *this; +} + +Point Mid(const Point& p0, const Point& p1, double factor) +{ + // mid or partway between 2 points + return Vector2d(p0, p1) * factor + p0; +} +Point Rel(const Point& p, double x0, double y0) +{ + // Relative point + return (p.ok) ? Point(p.x + x0, p.y + y0) : INVALID_POINT; +} + +Point Polar(const Point& p, double angle, double r) +{ + // polar from this point + angle *= DegreesToRadians; + return (p.ok) ? Point(p.x + r * cos(angle), p.y + r * sin(angle)) : INVALID_POINT; +} + +// *************************************************************************************************************************************** +// clines +// *************************************************************************************************************************************** +// const CLine horiz(Point(0, 0), 1, 0); // define global horizontal line + +double CLine::c() +{ + // returns c for ax + by + c = 0 format (peps format where needed) + return (v.getx() * p.y - v.gety() * p.x); +} +void CLine::Normalise() +{ + // normalise the cline vector + ok = v.normalise() >= TOLERANCE; +} + +CLine::CLine(const Span& sp) +{ + p = sp.p0; + v = sp.vs; + ok = sp.returnSpanProperties && !sp.NullSpan; +} + +CLine Normal(const CLine& s) +{ + // returns normal to this line + return CLine(s.p, ~s.v, false); +} +const CLine CLine::operator~(void) +{ + return CLine(this->p, ~v, false); +} +CLine Normal(const CLine& s, const Point& p) +{ + // returns normal to this line thro' p + return CLine(p, ~s.v, false); +} + +CLine CLine::Transform(Matrix& m) +{ + + Point p0 = this->p; + Point p1(p0.x + v.getx(), p0.y + v.gety()); + return CLine(p0.Transform(m), p1.Transform(m)); +} + + +double CLine::Dist(const Point& p0) const +{ + // distance between cline & point >0 cw about point <0 acw about point + return this->v ^ Vector2d(p0, this->p); +} + +double Point::Dist(const CLine& cl) const +{ + // distance between cline & point >0 cw about point <0 acw about point + return cl.v ^ Vector2d(*this, cl.p); +} + +Point CLine::Intof(const CLine& s) +{ + // Intof 2 Clines + return geoff_geometry::Intof(*this, s); +} + +Point CLine::Intof(int NF, const Circle& c) +{ + // Intof Cline & Circleconst + return geoff_geometry::Intof(NF, *this, c); +} +Point CLine::Intof(int NF, const Circle& c, Point& otherInters) +{ + // Intof Cline & Circle & other intersection + return geoff_geometry::Intof(NF, *this, c, otherInters); +} + +Point Intof(const CLine& s0, const CLine& s1) +{ + // inters of 2 clines (parameterise lines x = x0 + t * dx) + double cp = s1.v ^ s0.v; + if (fabs(cp) > 1.0e-6) { + double t = (s1.v ^ Vector2d(s0.p, s1.p)) / cp; + return s0.v * t + s0.p; + } + return INVALID_POINT; +} +Point XonCLine(CLine& s, double xval) +{ + // return point given X on a line + return Intof(s, CLine(Point(xval, 0), 0, 1, false)); +} +Point YonCLine(CLine& s, double yval) +{ + // return point given Y on a line + return Intof(s, CLine(Point(0, yval), 1, 0, false)); +} +Point Along(const CLine& s, double d) +{ + // distance along line + return Point(s.p.x + d * s.v.getx(), s.p.y + d * s.v.gety(), s.ok); +} + +Point Along(const CLine& s, double d, Point& p) +{ + // distance along line from point + return Point(p.x + d * s.v.getx(), p.y + d * s.v.gety(), p.ok); +} +Point Around(const Circle& c, double d, const Point& p) +{ + // distance around circle from point + CLine radial(c.pc, p); + if (radial.ok) { + if (fabs(c.radius) > TOLERANCE) { + double a = sin(-d / c.radius); + double b = cos(-d / c.radius); + return Point(c.pc.x - c.radius * (radial.v.gety() * a - radial.v.getx() * b), + c.pc.y + c.radius * (radial.v.gety() * b + radial.v.getx() * a)); + } + } + return INVALID_POINT; +} +CLine AtAngle(double angle, const Point& p0, const CLine& s) +{ + // cline at angle [to a cline] thro' a point + angle *= DegreesToRadians; + Vector2d v(cos(angle), sin(angle)); + return CLine(p0, + v.getx() * s.v.getx() - v.gety() * s.v.gety(), + v.gety() * s.v.getx() + v.getx() * s.v.gety()); +} +CLine Parallel(int side, const CLine& s0, double distance) +{ + // parallel to line by distance + Vector2d v = ~s0.v; + return CLine(v * ((double)side * distance) + s0.p, s0.v.getx(), s0.v.gety()); +} + +CLine Parallel(const CLine& s0, Point& p) +{ + // parallel to line through point + return CLine(p, s0.v.getx(), s0.v.gety()); +} + +CLine CLine::Bisector(const CLine& s) +{ + // bisector of 2 clines + return CLine(this->Intof(s), this->v.getx() + s.v.getx(), this->v.gety() + s.v.gety()); +} + + +// *************************************************************************************************************************************** +// circle methods +// *************************************************************************************************************************************** + +Circle::Circle(const Point& p, double rad) +{ + // Circle + pc = p; + radius = rad; + ok = pc.ok; +} + +Circle::Circle(const Point& p, const Point& pc0) +{ + if ((ok = (p.ok && pc0.ok))) { + pc = pc0; + radius = p.Dist(pc0); + } + else { + radius = 0; + } +} + +Circle::Circle(const Span& sp) +{ + pc = sp.pc; + radius = sp.radius; + ok = sp.returnSpanProperties; +} + +bool Circle::operator==(const Circle& c) const +{ + // c1 == c2 (uses TOLERANCE) + return FEQ(this->radius, c.radius, TOLERANCE) && (this->pc == c.pc); +} + +Circle Circle::Transform(Matrix& m) +{ // transform + Point p0 = this->pc; + double scale; + if (!m.GetScale(scale)) { + FAILURE(getMessage(L"Differential Scale not allowed for this method")); + } + return Circle(p0.Transform(m), radius * scale); +} + +Point Circle::Intof(int LR, const Circle& c1) +{ + // intof 2 circles + return geoff_geometry::Intof(LR, *this, c1); +} +Point Circle::Intof(int LR, const Circle& c1, Point& otherInters) +{ + // intof 2 circles, (returns the other intersection) + return geoff_geometry::Intof(LR, *this, c1, otherInters); +} +int Circle::Intof(const Circle& c1, Point& leftInters, Point& rightInters) +{ + // intof 2 circles, (returns the other intersection) + return geoff_geometry::Intof(*this, c1, leftInters, rightInters); +} + +CLine Circle::Tanto(int AT, double angle, const CLine& s0) const +{ + // cline tanto circle at angle to optional cline + return geoff_geometry::Tanto(AT, *this, angle, s0); +} + +CLine Tanto(int AT, const Circle& c, const Point& p) +{ + // CLine tangent to a circle through a point + Vector2d v(p, c.pc); + double d = v.magnitude(); + CLine s(p, ~v, false); // initialise cline + + if (d < TOLERANCE || d < fabs(c.radius) - TOLERANCE) { // point inside circle ? + return INVALID_CLINE; + } + else { + if (d > fabs(c.radius) + TOLERANCE) { // point outside circle + v.Rotate(sqrt((d - c.radius) * (d + c.radius)), -AT * c.radius); + s.v = v; + } + } + s.Normalise(); + return s; +} + +CLine Tanto(int AT0, const Circle& c0, int AT1, const Circle& c) +{ + // cline tanto 2 circles + CLine s; + Circle c1 = c; + c1.radius -= (double)(AT0 * AT1) * c0.radius; + s = Tanto(AT1, c1, c0.pc); + s.p.x += (double)AT0 * c0.radius * s.v.gety(); + s.p.y -= (double)AT0 * c0.radius * s.v.getx(); + return s; +} + +CLine Tanto(int AT, const Circle& c, double angle, const CLine& s0) +{ + // cline at an angle [to a cline] tanto a circle + CLine s = AtAngle(angle, c.pc, s0); + s.p.x += (double)AT * c.radius * s.v.gety(); + s.p.y -= (double)AT * c.radius * s.v.getx(); + // s.p += ~s.v * (AT * c.radius); + s.ok = true; + return s; +} +Point AtAngle(const Circle& c, double angle) +{ + // Point at an angle on circle + angle *= DegreesToRadians; + return Point(c.pc.x + c.radius * cos(angle), c.pc.y + c.radius * sin(angle)); +} + +Point On(const CLine& s, const Point& p) +{ + // returns point that is nearest to s from p + double t = s.v * Vector2d(s.p, p); + return s.v * t + s.p; +} + +Point On(const Circle& c, const Point& p) +{ + // returns point that is nearest to c from p + double r = p.Dist(c.pc); + if (r < TOLERANCE) { + FAILURE(getMessage(L",Point on Circle centre - On(Circle& c, Point& p)")); + } + return (Mid(p, c.pc, (r - c.radius) / r)); +} + + +Point Intof(int NF, const CLine& s, const Circle& c) +{ + // inters of cline & circle eg. p1 = Intof(NEARINT, s1, c1); + Point otherInters; + return Intof(NF, s, c, otherInters); +} + +Point Intof(int NF, const CLine& s, const Circle& c, Point& otherInters) +{ + // inters of cline & circle eg. p1 = Intof(NEARINT, s1, c1); + // otherInters returns the other intersection #if 1 - // solving x = x0 + dx * t x = y0 + dy * t - // x = xc + R * cos(a) y = yc + R * sin(a) for t - // gives :- t� (dx� + dy�) + 2t(dx*dx0 + dy*dy0) + (x0-xc)� + (y0-yc)� - R� = 0 - int nRoots; - double t, tFar, tNear, tOther; - Vector2d v0(c.pc, s.p); - if((nRoots = quadratic(1, 2 * (v0 * s.v), v0.magnitudesqd() - c.radius * c.radius, tFar, tNear)) != 0) { - if(nRoots == 2 && NF == NEARINT) { - t = tNear; - tOther = tFar; - } else { - t = tFar; - tOther = (nRoots == 2)?tNear : tFar; - } - otherInters = s.v * tOther + s.p; - return s.v * t + s.p; - } - return INVALID_POINT; - } + // solving x = x0 + dx * t x = y0 + dy * t + // x = xc + R * cos(a) y = yc + R * sin(a) for t + // gives :- t� (dx� + dy�) + 2t(dx*dx0 + dy*dy0) + (x0-xc)� + (y0-yc)� - R� = 0 + int nRoots; + double t, tFar, tNear, tOther; + Vector2d v0(c.pc, s.p); + if ((nRoots = + quadratic(1, 2 * (v0 * s.v), v0.magnitudesqd() - c.radius * c.radius, tFar, tNear)) + != 0) { + if (nRoots == 2 && NF == NEARINT) { + t = tNear; + tOther = tFar; + } + else { + t = tFar; + tOther = (nRoots == 2) ? tNear : tFar; + } + otherInters = s.v * tOther + s.p; + return s.v * t + s.p; + } + return INVALID_POINT; +} #else - // geometric solution - this is similar to the peps method, and it may offer better tolerancing than above?? - Point intof; - CLine normal = Normal(s, c.pc); - intof = s.Intof(normal); - double d = intof.Dist(c.pc); + // geometric solution - this is similar to the peps method, and it may offer better tolerancing + // than above?? + Point intof; + CLine normal = Normal(s, c.pc); + intof = s.Intof(normal); + double d = intof.Dist(c.pc); - if(fabs(d - c.radius) < TOLERANCE) // tangent (near enough for non-large radius I suppose?) - return intof; + if (fabs(d - c.radius) < TOLERANCE) { // tangent (near enough for non-large radius I suppose?) + return intof; + } - if(d > c.radius + TOLERANCE) // no intersection - return INVALID_POINT; + if (d > c.radius + TOLERANCE) { // no intersection + return INVALID_POINT; + } - double q = (c.radius - d) * (c.radius + d); - if(q < 0) // line inside tolerance - return intof; + double q = (c.radius - d) * (c.radius + d); + if (q < 0) { // line inside tolerance + return intof; + } - return Along(s, -(double)NF * sqrt(q), intof); // 2 intersections (return near/far case) - } + return Along(s, -(double)NF * sqrt(q), intof); // 2 intersections (return near/far case) +} #endif - Point Intof( int intMode, const Circle& c0, const Circle& c1) { - // inters of 2 circles eg. p1 = Intof(LEFTINT, c1, c2) - Point otherInters; - return Intof(intMode, c0, c1, otherInters); - } - - Point Intof( int intMode, const Circle& c0, const Circle& c1, Point& otherInters) { - // inters of 2 circles eg. p1 = Intof(LEFTINT, c1, c2);u - Point pLeft, pRight; - switch(Intof(c0, c1, pLeft, pRight)) { - default: - return INVALID_POINT; - case 1: - otherInters = pLeft; - return pLeft; - case 2: - if(intMode == LEFTINT) { - otherInters = pRight; - return pLeft; - }else { - otherInters = pLeft; - return pRight; - } - } - } - - int Intof(const Circle& c0, const Circle& c1, Point& pLeft, Point& pRight) { - // inters of 2 circles - // returns the number of intersctions - Vector2d v(c0.pc, c1.pc); - double d = v.normalise(); - if(d < TOLERANCE) // co-incident circles - return 0; - - double sum = fabs(c0.radius) + fabs(c1.radius); - double diff = fabs(fabs(c0.radius) - fabs(c1.radius)); - if(d > sum + TOLERANCE || d < diff - TOLERANCE) - return 0; - - // dist from centre of this circle to mid intersection - double d0 = 0.5 * (d + (c0.radius + c1.radius) * (c0.radius - c1.radius) / d); - if(d0 - c0.radius > TOLERANCE) // circles don't intersect - return 0; - - double h = (c0.radius - d0) * (c0.radius + d0); // half distance between intersects squared - if(h < 0) d0 = c0.radius; // tangent - pLeft = v * d0 + c0.pc; // mid-point of intersects - if(h < TOLERANCE_SQ) // tangent - return 1; - h = sqrt(h); - - v = ~v; // calculate 2 intersects - pRight = v * h + pLeft; - v = -v; - pLeft = v * h + pLeft; - return 2; - } - - Circle Tanto(int NF, CLine& s0, Point& p, double rad) { - // circle tanto a CLine thro' a point - double d = s0.Dist(p); - if(fabs(d) > rad + TOLERANCE) // point too far from line - return INVALID_CIRCLE; - CLine s0offset = Parallel(RIGHTINT, s0, rad); - - return Circle(Intof(NF, s0offset, Circle(p, rad)), rad); - } - - Circle Tanto(int AT1, CLine& s1, int AT2, CLine& s2, double rad) { - // circle tanto 2 clines with radius - CLine Offs1 = Parallel(AT1, s1, rad); - CLine Offs2 = Parallel(AT2, s2, rad); - Point pc = Intof(Offs1, Offs2); - return (pc.ok)? Circle(pc, rad) : INVALID_CIRCLE; - } - Circle Tanto(int AT1, CLine s1, int AT2, CLine s2, int AT3, CLine s3) { - // circle tanto 3 CLines - double s1c = s1.c(), s2c = s2.c(), s3c = s3.c(); - double d = s1.v.gety() * (AT2 * s3.v.getx() - AT3 * s2.v.getx()) - + s2.v.gety() * (AT3 * s1.v.getx() - AT1 * s3.v.getx()) - + s3.v.gety() * (AT1 * s2.v.getx() - AT2 * s1.v.getx()); - if(fabs(d) < UNIT_VECTOR_TOLERANCE) - return INVALID_CIRCLE; - double radius = (s1.v.gety() * (s2.v.getx() * s3c - s3.v.getx() * s2c) - + s2.v.gety() * (s3.v.getx() * s1c - s1.v.getx() * s3c) - + s3.v.gety() * (s1.v.getx() * s2c - s2.v.getx() * s1c)) / d ; - if(radius < TOLERANCE) - return INVALID_CIRCLE; - - CLine Offs1 = Parallel(AT1, s1, radius); - CLine Offs2 = Parallel(AT2, s2, radius); - - Point p = Intof(Offs1, Offs2); - if(!p.ok) { - CLine Offs3 = Parallel(AT3, s3, radius); // s1 & s2 parallel - p = Intof(Offs1, Offs3); - if(!p.ok) // 3 parallel lines - return INVALID_CIRCLE; - } - return Circle(p, radius); - } - Circle Thro(int LR, const Point& p0, const Point& p1, double rad) { - // circle thro' 2 points, given radius and side - CLine thro(p0, p1); - if(thro.ok) { - double d = 0.5 * p0.Dist(p1); - Point pm = Mid(p0, p1); - - if(d > rad + TOLERANCE) - return INVALID_CIRCLE; - else if(d > rad - TOLERANCE) { - // within tolerance of centre of 2 points - return Circle(pm, d); - } - else { - // 2 solutions - return Circle(Along(Normal(thro, pm), (double)LR * sqrt((rad + d) * (rad - d)), pm), rad); - } - } - return INVALID_CIRCLE; - } - - Circle Thro(const Point& p0, const Point& p1) { - // circle thro 2 points (diametric) - return Circle(p0.Mid(p1), .5*p0.Dist(p1)); - } - Circle Thro(const Point& p0, const Point& p1, const Point& p2) { - // circle thro 3 points - CLine s0(p0, p1); - if(!s0.ok) // p0 & p1 coincident - return Thro(p1,p2); - - CLine s1(p0, p2); - if(!s1.ok) // p0 & p2 coincident - return Thro(p0, p1); - - CLine s2(p2, p1); - if(!s2.ok) // p1 & p2 coincident - return Thro(p0, p2); - - Point p = Intof(Normal(s0, Mid(p0, p1)), Normal(s1, Mid(p0, p2))); - return (p.ok)? Circle(p, p0.Dist(p)) : INVALID_CIRCLE; - } - Circle Tanto(int NF, int AT0, const CLine& s0, int AT1, const Circle &c1, double rad) { - // circle tanto cline & circle with radius - CLine Offs0 = Parallel(AT0, s0, rad); - Circle c2 = c1; - c2.radius += AT1 * rad; - Point pc = Intof(NF, Offs0, c2); - return (pc.ok)? Circle(pc, rad) : INVALID_CIRCLE; - } - - Circle Tanto( int LR, int AT0, const Circle& c0, const Point& p, double rad) { - // circle tanto circle & thro' a point - Circle c2 = c0; - c2.radius += AT0 * rad; - Circle c1(p, rad); - Point pc = Intof(LR, c2, c1); - return (pc.ok)? Circle(pc, rad) : INVALID_CIRCLE; - } - Circle Tanto(int LR, int AT0, const Circle& c0, int AT1, const Circle& c1, double rad) { - // circle tanto 2 circles - Circle c2 = c0; - Circle c3 = c1; - c2.radius += AT0 * rad; - c3.radius += AT1 * rad; - Point pc = Intof(LR, c2, c3); - return (pc.ok)? Circle(pc, rad) : INVALID_CIRCLE; - } - - Circle Parallel(int side, const Circle& c0, double distance) { - // parallel to circle by distance - return Circle(c0.pc, c0.radius + (double) side * distance); - } - - // distance - double atn360(double dy, double dx) { - // angle 0 to 2pi - double ang = atan2(dy, dx); - return ((ang < 0)? 2 * PI + ang : ang); - } - - double Dist(const Point& p0, const Circle& c, const Point& p1) { - // clockwise distance around c from p0 to p1 - double a0 = atn360(p0.y - c.pc.y, p0.x - c.pc.x); - double a1 = atn360(p1.y - c.pc.y ,p1.x - c.pc.x); - if ( a1 > a0 ) a1 -= 2 * PI ; - return (a0 - a1) * c.radius; - } - double Dist(const CLine& s, const Circle& c) { - // distance between line and circle - return fabs(s.Dist(c.pc)) - c.radius; - } - double Dist(const Circle& c0, const Circle& c1) { - // distance between 2 circles - return c0.pc.Dist(c1.pc) - c0.radius - c1.radius; - } - double Dist(const Circle& c, const Point& p) { - // distance between circle and point - return p.Dist(On(c, p)); - } - - double IncludedAngle(const Vector2d& v0, const Vector2d& v1, int dir) { - // returns the absolute included angle between 2 vectors in the direction of dir ( 1=acw -1=cw) - double inc_ang = v0 * v1; - if(inc_ang > 1. - UNIT_VECTOR_TOLERANCE) - return 0; - if(inc_ang < -1. + UNIT_VECTOR_TOLERANCE) - inc_ang = PI; - else { // dot product, v1 . v2 = cos ang - if(inc_ang > 1.0) inc_ang = 1.0; - inc_ang = acos(inc_ang); // 0 to pi radians - - if(dir * (v0 ^ v1) < 0) inc_ang = 2 * PI - inc_ang ; // cp - } - return dir * inc_ang; - } - - double IncludedAngle(const Vector3d& v0, const Vector3d& v1, const Vector3d& normal, int dir) { - // returns the absolute included angle between 2 vectors in the direction of dir ( 1=acw -1=cw) about normal - double inc_ang = v0 * v1; - - if(inc_ang >= -NEARLY_ONE) { // dot product, v1 . v2 = cos ang - inc_ang = acos(inc_ang); // 0 to pi radians - - if(dir * (normal * (v0 ^ v1)) < 0) inc_ang = 2 * PI - inc_ang ; // cp - } - else - inc_ang = PI; // semi-cicle - - return dir * inc_ang; - } - - int corner(const Vector2d& v0, const Vector2d& v1, double cpTol) { - // returns corner - // 0 (TANGENT) = tangent - // 1 (LEFT) = left turn - // -1 (RIGHT) = right turn - double cp = v0 ^ v1; - if(fabs(cp) < cpTol) - return TANGENT; - - return (cp > 0)?GEOFF_LEFT : GEOFF_RIGHT; - } - - int quadratic(double a, double b, double c, double& x0, double& x1) { - // solves quadratic equation ax² + bx + c = 0 - // returns number of real roots -// double epsilon = 1.0e-6; - double epsilon = (geoff_geometry::UNITS == METRES)?1.0e-09 : 1.0e-06; - double epsilonsq = epsilon * epsilon; - if(fabs(a) < epsilon) { - if(fabs(b) < epsilon) // invalid - return 0; - x0 = - c / b; - return 1; - } - b /= a; - c /= a; - double s = b * b - 4 * c; - if(s < -epsilon) // imaginary roots - return 0; - x0 = - 0.5 * b; - if(s > epsilonsq) { - s = 0.5 * sqrt(s); - x1 = x0 - s; - x0 += s; - return 2; - } - return 1; - } - - Plane::Plane(const Point3d& p0, const Point3d& p1, const Point3d& p2) { - // constructor plane from 3 points - normal = Vector3d(p0, p1) ^ Vector3d(p0, p2); - normal.normalise(); - ok = (normal != NULL_VECTOR); - d = -(normal * Vector3d(p0)); - } - - Plane::Plane(const Point3d& p0, const Vector3d& v, bool normalise) { - // constructor plane from point & vector - normal = v; - if (normalise) - normal.normalise(); - ok = (normal != NULL_VECTOR); - d = -(normal * Vector3d(p0)); - } - - Plane::Plane(double dist, const Vector3d& n) { - normal = n; - double mag = normal.normalise(); - ok = (normal != NULL_VECTOR); - if(ok) d = dist / mag; - else d = 0; - } - - double Plane::Dist(const Point3d& p)const{ - // returns signed distance to plane from point p - return (normal * Vector3d(p)) + d; +Point Intof(int intMode, const Circle& c0, const Circle& c1) +{ + // inters of 2 circles eg. p1 = Intof(LEFTINT, c1, c2) + Point otherInters; + return Intof(intMode, c0, c1, otherInters); } - Point3d Plane::Near(const Point3d& p)const { - // returns near point to p on the plane - return - normal * Dist(p) + p; - } - - bool Plane::Intof(const Line& l, Point3d& intof, double& t) const{ - // intersection between plane and line - // input this plane, line - // output intof - // method returns true for valid intersection - double den = l.v * this->normal; - if(fabs(den) < UNIT_VECTOR_TOLERANCE) // line is parallel to the plane, return false, even if the line lies on the plane - return false; - - t = -(normal * Vector3d(l.p0) + d) / den; - intof = l.v * t + l.p0; - return true; - } - - bool Plane::Intof(const Plane& pl, Line& intof)const { - // intersection of 2 planes - Vector3d d = this->normal ^ pl.normal; - d.normalise(); - intof.ok = false; - if(d == NULL_VECTOR) // parallel planes - return false; - - intof.v = d; - intof.length = 1; - - double dot = this->normal * pl.normal; - - double den = dot * dot - 1.; - double a = (this->d - pl.d * dot) / den; - double b = (pl.d - this->d * dot) / den; - intof.p0 = a * this->normal + b * pl.normal; - intof.ok = true; - return true; - } - - bool Plane::Intof(const Plane& pl0, const Plane& pl1, Point3d& intof) const{ - // intersection of 3 planes - Line tmp; - if(Intof(pl0, tmp)) { - double t; - return pl1.Intof(tmp, intof, t); - } - return false; - } +Point Intof(int intMode, const Circle& c0, const Circle& c1, Point& otherInters) +{ + // inters of 2 circles eg. p1 = Intof(LEFTINT, c1, c2);u + Point pLeft, pRight; + switch (Intof(c0, c1, pLeft, pRight)) { + default: + return INVALID_POINT; + case 1: + otherInters = pLeft; + return pLeft; + case 2: + if (intMode == LEFTINT) { + otherInters = pRight; + return pLeft; + } + else { + otherInters = pLeft; + return pRight; + } + } } + +int Intof(const Circle& c0, const Circle& c1, Point& pLeft, Point& pRight) +{ + // inters of 2 circles + // returns the number of intersctions + Vector2d v(c0.pc, c1.pc); + double d = v.normalise(); + if (d < TOLERANCE) { // co-incident circles + return 0; + } + + double sum = fabs(c0.radius) + fabs(c1.radius); + double diff = fabs(fabs(c0.radius) - fabs(c1.radius)); + if (d > sum + TOLERANCE || d < diff - TOLERANCE) { + return 0; + } + + // dist from centre of this circle to mid intersection + double d0 = 0.5 * (d + (c0.radius + c1.radius) * (c0.radius - c1.radius) / d); + if (d0 - c0.radius > TOLERANCE) { // circles don't intersect + return 0; + } + + double h = (c0.radius - d0) * (c0.radius + d0); // half distance between intersects squared + if (h < 0) { + d0 = c0.radius; // tangent + } + pLeft = v * d0 + c0.pc; // mid-point of intersects + if (h < TOLERANCE_SQ) { // tangent + return 1; + } + h = sqrt(h); + + v = ~v; // calculate 2 intersects + pRight = v * h + pLeft; + v = -v; + pLeft = v * h + pLeft; + return 2; +} + +Circle Tanto(int NF, CLine& s0, Point& p, double rad) +{ + // circle tanto a CLine thro' a point + double d = s0.Dist(p); + if (fabs(d) > rad + TOLERANCE) { // point too far from line + return INVALID_CIRCLE; + } + CLine s0offset = Parallel(RIGHTINT, s0, rad); + + return Circle(Intof(NF, s0offset, Circle(p, rad)), rad); +} + +Circle Tanto(int AT1, CLine& s1, int AT2, CLine& s2, double rad) +{ + // circle tanto 2 clines with radius + CLine Offs1 = Parallel(AT1, s1, rad); + CLine Offs2 = Parallel(AT2, s2, rad); + Point pc = Intof(Offs1, Offs2); + return (pc.ok) ? Circle(pc, rad) : INVALID_CIRCLE; +} +Circle Tanto(int AT1, CLine s1, int AT2, CLine s2, int AT3, CLine s3) +{ + // circle tanto 3 CLines + double s1c = s1.c(), s2c = s2.c(), s3c = s3.c(); + double d = s1.v.gety() * (AT2 * s3.v.getx() - AT3 * s2.v.getx()) + + s2.v.gety() * (AT3 * s1.v.getx() - AT1 * s3.v.getx()) + + s3.v.gety() * (AT1 * s2.v.getx() - AT2 * s1.v.getx()); + if (fabs(d) < UNIT_VECTOR_TOLERANCE) { + return INVALID_CIRCLE; + } + double radius = (s1.v.gety() * (s2.v.getx() * s3c - s3.v.getx() * s2c) + + s2.v.gety() * (s3.v.getx() * s1c - s1.v.getx() * s3c) + + s3.v.gety() * (s1.v.getx() * s2c - s2.v.getx() * s1c)) + / d; + if (radius < TOLERANCE) { + return INVALID_CIRCLE; + } + + CLine Offs1 = Parallel(AT1, s1, radius); + CLine Offs2 = Parallel(AT2, s2, radius); + + Point p = Intof(Offs1, Offs2); + if (!p.ok) { + CLine Offs3 = Parallel(AT3, s3, radius); // s1 & s2 parallel + p = Intof(Offs1, Offs3); + if (!p.ok) { // 3 parallel lines + return INVALID_CIRCLE; + } + } + return Circle(p, radius); +} +Circle Thro(int LR, const Point& p0, const Point& p1, double rad) +{ + // circle thro' 2 points, given radius and side + CLine thro(p0, p1); + if (thro.ok) { + double d = 0.5 * p0.Dist(p1); + Point pm = Mid(p0, p1); + + if (d > rad + TOLERANCE) { + return INVALID_CIRCLE; + } + else if (d > rad - TOLERANCE) { + // within tolerance of centre of 2 points + return Circle(pm, d); + } + else { + // 2 solutions + return Circle(Along(Normal(thro, pm), (double)LR * sqrt((rad + d) * (rad - d)), pm), + rad); + } + } + return INVALID_CIRCLE; +} + +Circle Thro(const Point& p0, const Point& p1) +{ + // circle thro 2 points (diametric) + return Circle(p0.Mid(p1), .5 * p0.Dist(p1)); +} +Circle Thro(const Point& p0, const Point& p1, const Point& p2) +{ + // circle thro 3 points + CLine s0(p0, p1); + if (!s0.ok) { // p0 & p1 coincident + return Thro(p1, p2); + } + + CLine s1(p0, p2); + if (!s1.ok) { // p0 & p2 coincident + return Thro(p0, p1); + } + + CLine s2(p2, p1); + if (!s2.ok) { // p1 & p2 coincident + return Thro(p0, p2); + } + + Point p = Intof(Normal(s0, Mid(p0, p1)), Normal(s1, Mid(p0, p2))); + return (p.ok) ? Circle(p, p0.Dist(p)) : INVALID_CIRCLE; +} +Circle Tanto(int NF, int AT0, const CLine& s0, int AT1, const Circle& c1, double rad) +{ + // circle tanto cline & circle with radius + CLine Offs0 = Parallel(AT0, s0, rad); + Circle c2 = c1; + c2.radius += AT1 * rad; + Point pc = Intof(NF, Offs0, c2); + return (pc.ok) ? Circle(pc, rad) : INVALID_CIRCLE; +} + +Circle Tanto(int LR, int AT0, const Circle& c0, const Point& p, double rad) +{ + // circle tanto circle & thro' a point + Circle c2 = c0; + c2.radius += AT0 * rad; + Circle c1(p, rad); + Point pc = Intof(LR, c2, c1); + return (pc.ok) ? Circle(pc, rad) : INVALID_CIRCLE; +} +Circle Tanto(int LR, int AT0, const Circle& c0, int AT1, const Circle& c1, double rad) +{ + // circle tanto 2 circles + Circle c2 = c0; + Circle c3 = c1; + c2.radius += AT0 * rad; + c3.radius += AT1 * rad; + Point pc = Intof(LR, c2, c3); + return (pc.ok) ? Circle(pc, rad) : INVALID_CIRCLE; +} + +Circle Parallel(int side, const Circle& c0, double distance) +{ + // parallel to circle by distance + return Circle(c0.pc, c0.radius + (double)side * distance); +} + +// distance +double atn360(double dy, double dx) +{ + // angle 0 to 2pi + double ang = atan2(dy, dx); + return ((ang < 0) ? 2 * PI + ang : ang); +} + +double Dist(const Point& p0, const Circle& c, const Point& p1) +{ + // clockwise distance around c from p0 to p1 + double a0 = atn360(p0.y - c.pc.y, p0.x - c.pc.x); + double a1 = atn360(p1.y - c.pc.y, p1.x - c.pc.x); + if (a1 > a0) { + a1 -= 2 * PI; + } + return (a0 - a1) * c.radius; +} +double Dist(const CLine& s, const Circle& c) +{ + // distance between line and circle + return fabs(s.Dist(c.pc)) - c.radius; +} +double Dist(const Circle& c0, const Circle& c1) +{ + // distance between 2 circles + return c0.pc.Dist(c1.pc) - c0.radius - c1.radius; +} +double Dist(const Circle& c, const Point& p) +{ + // distance between circle and point + return p.Dist(On(c, p)); +} + +double IncludedAngle(const Vector2d& v0, const Vector2d& v1, int dir) +{ + // returns the absolute included angle between 2 vectors in the direction of dir ( 1=acw -1=cw) + double inc_ang = v0 * v1; + if (inc_ang > 1. - UNIT_VECTOR_TOLERANCE) { + return 0; + } + if (inc_ang < -1. + UNIT_VECTOR_TOLERANCE) { + inc_ang = PI; + } + else { // dot product, v1 . v2 = cos ang + if (inc_ang > 1.0) { + inc_ang = 1.0; + } + inc_ang = acos(inc_ang); // 0 to pi radians + + if (dir * (v0 ^ v1) < 0) { + inc_ang = 2 * PI - inc_ang; // cp + } + } + return dir * inc_ang; +} + +double IncludedAngle(const Vector3d& v0, const Vector3d& v1, const Vector3d& normal, int dir) +{ + // returns the absolute included angle between 2 vectors in the direction of dir ( 1=acw -1=cw) + // about normal + double inc_ang = v0 * v1; + + if (inc_ang >= -NEARLY_ONE) { // dot product, v1 . v2 = cos ang + inc_ang = acos(inc_ang); // 0 to pi radians + + if (dir * (normal * (v0 ^ v1)) < 0) { + inc_ang = 2 * PI - inc_ang; // cp + } + } + else { + inc_ang = PI; // semi-cicle + } + + return dir * inc_ang; +} + +int corner(const Vector2d& v0, const Vector2d& v1, double cpTol) +{ + // returns corner + // 0 (TANGENT) = tangent + // 1 (LEFT) = left turn + // -1 (RIGHT) = right turn + double cp = v0 ^ v1; + if (fabs(cp) < cpTol) { + return TANGENT; + } + + return (cp > 0) ? GEOFF_LEFT : GEOFF_RIGHT; +} + +int quadratic(double a, double b, double c, double& x0, double& x1) +{ + // solves quadratic equation ax² + bx + c = 0 + // returns number of real roots + // double epsilon = 1.0e-6; + double epsilon = (geoff_geometry::UNITS == METRES) ? 1.0e-09 : 1.0e-06; + double epsilonsq = epsilon * epsilon; + if (fabs(a) < epsilon) { + if (fabs(b) < epsilon) { // invalid + return 0; + } + x0 = -c / b; + return 1; + } + b /= a; + c /= a; + double s = b * b - 4 * c; + if (s < -epsilon) { // imaginary roots + return 0; + } + x0 = -0.5 * b; + if (s > epsilonsq) { + s = 0.5 * sqrt(s); + x1 = x0 - s; + x0 += s; + return 2; + } + return 1; +} + +Plane::Plane(const Point3d& p0, const Point3d& p1, const Point3d& p2) +{ + // constructor plane from 3 points + normal = Vector3d(p0, p1) ^ Vector3d(p0, p2); + normal.normalise(); + ok = (normal != NULL_VECTOR); + d = -(normal * Vector3d(p0)); +} + +Plane::Plane(const Point3d& p0, const Vector3d& v, bool normalise) +{ + // constructor plane from point & vector + normal = v; + if (normalise) { + normal.normalise(); + } + ok = (normal != NULL_VECTOR); + d = -(normal * Vector3d(p0)); +} + +Plane::Plane(double dist, const Vector3d& n) +{ + normal = n; + double mag = normal.normalise(); + ok = (normal != NULL_VECTOR); + if (ok) { + d = dist / mag; + } + else { + d = 0; + } +} + +double Plane::Dist(const Point3d& p) const +{ + // returns signed distance to plane from point p + return (normal * Vector3d(p)) + d; +} + +Point3d Plane::Near(const Point3d& p) const +{ + // returns near point to p on the plane + return -normal * Dist(p) + p; +} + +bool Plane::Intof(const Line& l, Point3d& intof, double& t) const +{ + // intersection between plane and line + // input this plane, line + // output intof + // method returns true for valid intersection + double den = l.v * this->normal; + if (fabs(den) < UNIT_VECTOR_TOLERANCE) { // line is parallel to the plane, return false, even + // if the line lies on the plane + return false; + } + + t = -(normal * Vector3d(l.p0) + d) / den; + intof = l.v * t + l.p0; + return true; +} + +bool Plane::Intof(const Plane& pl, Line& intof) const +{ + // intersection of 2 planes + Vector3d d = this->normal ^ pl.normal; + d.normalise(); + intof.ok = false; + if (d == NULL_VECTOR) { // parallel planes + return false; + } + + intof.v = d; + intof.length = 1; + + double dot = this->normal * pl.normal; + + double den = dot * dot - 1.; + double a = (this->d - pl.d * dot) / den; + double b = (pl.d - this->d * dot) / den; + intof.p0 = a * this->normal + b * pl.normal; + intof.ok = true; + return true; +} + +bool Plane::Intof(const Plane& pl0, const Plane& pl1, Point3d& intof) const +{ + // intersection of 3 planes + Line tmp; + if (Intof(pl0, tmp)) { + double t; + return pl1.Intof(tmp, intof, t); + } + return false; +} +} // namespace geoff_geometry diff --git a/src/Mod/CAM/libarea/kurve/Finite.cpp b/src/Mod/CAM/libarea/kurve/Finite.cpp index 48549e59b0..b90fe93bbf 100644 --- a/src/Mod/CAM/libarea/kurve/Finite.cpp +++ b/src/Mod/CAM/libarea/kurve/Finite.cpp @@ -10,157 +10,169 @@ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef WIN32 -#define __min(a,b) ((ab)?a:b) +#define __min(a, b) ((a < b) ? a : b) +#define __max(a, b) ((a > b) ? a : b) #endif -namespace geoff_geometry { - int Intof(const Span& sp0, const Span& sp1, Point& p0, Point& p1, double t[4]) - { - // returns the number of intersects (lying within spans sp0, sp1) - if(sp0.box.outside(sp1.box)) - return 0; - if(!sp0.dir) { - if(!sp1.dir) { - // line line - return LineLineIntof(sp0, sp1, p0, t); - } - else { - // line arc - return LineArcIntof(sp0, sp1, p0, p1, t); - } - } - else { - if(!sp1.dir) { - // arc line - return LineArcIntof(sp1, sp0, p0, p1, t); - } - else { - // arc arc - return ArcArcIntof(sp0, sp1, p0, p1); - } - } - } +namespace geoff_geometry +{ +int Intof(const Span& sp0, const Span& sp1, Point& p0, Point& p1, double t[4]) +{ + // returns the number of intersects (lying within spans sp0, sp1) + if (sp0.box.outside(sp1.box)) { + return 0; + } + if (!sp0.dir) { + if (!sp1.dir) { + // line line + return LineLineIntof(sp0, sp1, p0, t); + } + else { + // line arc + return LineArcIntof(sp0, sp1, p0, p1, t); + } + } + else { + if (!sp1.dir) { + // arc line + return LineArcIntof(sp1, sp0, p0, p1, t); + } + else { + // arc arc + return ArcArcIntof(sp0, sp1, p0, p1); + } + } +} - int LineLineIntof(const Span& sp0 , const Span& sp1, Point& p, double t[2]) { - // intersection between 2 Line2d - // returns 0 for no intersection in range of either span - // returns 1 for intersction in range of both spans - // t[0] is parameter on sp0, - // t[1] is parameter on sp1 - Vector2d v0(sp0.p0, sp0.p1); - Vector2d v1(sp1.p0, sp1.p1); - Vector2d v2(sp0.p0, sp1.p0); +int LineLineIntof(const Span& sp0, const Span& sp1, Point& p, double t[2]) +{ + // intersection between 2 Line2d + // returns 0 for no intersection in range of either span + // returns 1 for intersction in range of both spans + // t[0] is parameter on sp0, + // t[1] is parameter on sp1 + Vector2d v0(sp0.p0, sp0.p1); + Vector2d v1(sp1.p0, sp1.p1); + Vector2d v2(sp0.p0, sp1.p0); - double cp = v1 ^ v0; + double cp = v1 ^ v0; - if(fabs(cp) < UNIT_VECTOR_TOLERANCE ) { - p = INVALID_POINT; - return 0; // parallel or degenerate lines - } + if (fabs(cp) < UNIT_VECTOR_TOLERANCE) { + p = INVALID_POINT; + return 0; // parallel or degenerate lines + } - t[0] = (v1 ^ v2) / cp; - p = v0 * t[0] + sp0.p0; - p.ok = true; - double toler = geoff_geometry::TOLERANCE / sp0.length; // calc a parametric tolerance + t[0] = (v1 ^ v2) / cp; + p = v0 * t[0] + sp0.p0; + p.ok = true; + double toler = geoff_geometry::TOLERANCE / sp0.length; // calc a parametric tolerance - t[1] = (v0 ^ v2) / cp; - if(t[0] < -toler || t[0] > 1 + toler) // intersection on first? - return 0; - toler = geoff_geometry::TOLERANCE / sp1.length; // calc a parametric tolerance - if(t[1] < -toler || t[1] > 1 + toler) // intersection on second? - return 0; - return 1; - } + t[1] = (v0 ^ v2) / cp; + if (t[0] < -toler || t[0] > 1 + toler) { // intersection on first? + return 0; + } + toler = geoff_geometry::TOLERANCE / sp1.length; // calc a parametric tolerance + if (t[1] < -toler || t[1] > 1 + toler) { // intersection on second? + return 0; + } + return 1; +} - int LineArcIntof(const Span& line, const Span& arc, Point& p0, Point& p1, double t[4]) { - // inters of line arc - // solving x = x0 + dx * t x = y0 + dy * t - // x = xc + R * cos(a) y = yc + R * sin(a) for t - // gives :- t² (dx² + dy²) + 2t(dx*dx0 + dy*dy0) + (x0-xc)² + (y0-yc)² - R² = 0 - int nRoots; - Vector2d v0(arc.pc, line.p0); - Vector2d v1(line.p0, line.p1); - double s = v1.magnitudesqd(); +int LineArcIntof(const Span& line, const Span& arc, Point& p0, Point& p1, double t[4]) +{ + // inters of line arc + // solving x = x0 + dx * t x = y0 + dy * t + // x = xc + R * cos(a) y = yc + R * sin(a) for t + // gives :- t² (dx² + dy²) + 2t(dx*dx0 + dy*dy0) + (x0-xc)² + (y0-yc)² - R² = 0 + int nRoots; + Vector2d v0(arc.pc, line.p0); + Vector2d v1(line.p0, line.p1); + double s = v1.magnitudesqd(); - p0.ok = p1.ok = false; - if((nRoots = quadratic(s, 2 * (v0 * v1), v0.magnitudesqd() - arc.radius * arc.radius, t[0], t[1])) != 0) { - double toler = geoff_geometry::TOLERANCE / sqrt(s); // calc a parametric tolerance - if(t[0] > -toler && t[0] < 1 + toler) { - p0 = v1 * t[0] + line.p0; - p0.ok = arc.OnSpan(p0, &t[2]); - } - if(nRoots == 2) { - if(t[1] > -toler && t[1] < 1 + toler) { - p1 = v1 * t[1] + line.p0; - p1.ok = arc.OnSpan(p1, &t[3]); - } - } - if(!p0.ok && p1.ok) { - p0 = p1; - p1.ok = false; - } - nRoots = (int)p0.ok + (int)p1.ok; - } - return nRoots; - } + p0.ok = p1.ok = false; + if ((nRoots = + quadratic(s, 2 * (v0 * v1), v0.magnitudesqd() - arc.radius * arc.radius, t[0], t[1])) + != 0) { + double toler = geoff_geometry::TOLERANCE / sqrt(s); // calc a parametric tolerance + if (t[0] > -toler && t[0] < 1 + toler) { + p0 = v1 * t[0] + line.p0; + p0.ok = arc.OnSpan(p0, &t[2]); + } + if (nRoots == 2) { + if (t[1] > -toler && t[1] < 1 + toler) { + p1 = v1 * t[1] + line.p0; + p1.ok = arc.OnSpan(p1, &t[3]); + } + } + if (!p0.ok && p1.ok) { + p0 = p1; + p1.ok = false; + } + nRoots = (int)p0.ok + (int)p1.ok; + } + return nRoots; +} - int ArcArcIntof(const Span& arc0, const Span& arc1, Point& pLeft, Point& pRight) { - // Intof 2 arcs - int numInts = Intof(Circle(arc0.pc, arc0.radius), Circle(arc1.pc, arc1.radius), pLeft, pRight); +int ArcArcIntof(const Span& arc0, const Span& arc1, Point& pLeft, Point& pRight) +{ + // Intof 2 arcs + int numInts = Intof(Circle(arc0.pc, arc0.radius), Circle(arc1.pc, arc1.radius), pLeft, pRight); - if(numInts == 0) { - pLeft = arc0.p1; - pLeft.ok = false; - return 0; - } - int nLeft = arc0.OnSpan(pLeft) && arc1.OnSpan(pLeft); - int nRight = (numInts == 2)?arc0.OnSpan(pRight) && arc1.OnSpan(pRight) : 0; - if(nLeft == 0 && nRight) pLeft = pRight; - return nLeft + nRight; - } + if (numInts == 0) { + pLeft = arc0.p1; + pLeft.ok = false; + return 0; + } + int nLeft = arc0.OnSpan(pLeft) && arc1.OnSpan(pLeft); + int nRight = (numInts == 2) ? arc0.OnSpan(pRight) && arc1.OnSpan(pRight) : 0; + if (nLeft == 0 && nRight) { + pLeft = pRight; + } + return nLeft + nRight; +} - bool Span::OnSpan(const Point& p)const { - double t; - return OnSpan(p, &t); - } +bool Span::OnSpan(const Point& p) const +{ + double t; + return OnSpan(p, &t); +} - bool Span::OnSpan(const Point& p, double* t)const { - // FAST OnSpan test - assumes that p lies ON the unbounded span +bool Span::OnSpan(const Point& p, double* t) const +{ + // FAST OnSpan test - assumes that p lies ON the unbounded span #if _DEBUG - if(!this->returnSpanProperties) { - FAILURE(L"OnSpan - properties no set, incorrect calling code"); - } + if (!this->returnSpanProperties) { + FAILURE(L"OnSpan - properties no set, incorrect calling code"); + } #endif - bool ret; + bool ret; - if(dir == LINEAR) { + if (dir == LINEAR) { #if _DEBUG - // check p is on line - CLine cl(*this); - double d = fabs(cl.Dist(p)); - if( d > geoff_geometry::TOLERANCE) { - FAILURE(L"OnSpan - point not on linear span, incorrect calling code"); - } + // check p is on line + CLine cl(*this); + double d = fabs(cl.Dist(p)); + if (d > geoff_geometry::TOLERANCE) { + FAILURE(L"OnSpan - point not on linear span, incorrect calling code"); + } #endif - Vector2d v0(p0, p); - *t = vs * v0; - *t = *t / length; - ret = (*t >= 0 && *t <= 1.0 ); - - } - else { - // true if p lies on arc span sp (p must be on circle of span) + Vector2d v0(p0, p); + *t = vs * v0; + *t = *t / length; + ret = (*t >= 0 && *t <= 1.0); + } + else { + // true if p lies on arc span sp (p must be on circle of span) #if _DEBUG - // check that p lies on the arc - double d = p.Dist(pc); - if(FNE(d, radius, geoff_geometry::TOLERANCE)) { - FAILURE(L"OnSpan - point not on circular span, incorrect calling code"); - } + // check that p lies on the arc + double d = p.Dist(pc); + if (FNE(d, radius, geoff_geometry::TOLERANCE)) { + FAILURE(L"OnSpan - point not on circular span, incorrect calling code"); + } #endif -#if 0 // alt method (faster, but doesn't provide t) +#if 0 // alt method (faster, but doesn't provide t) Vector2d v0(p0, p); Vector2d v1(p0, p1); @@ -169,435 +181,522 @@ namespace geoff_geometry { ret = ((cp = (dir * (v0 ^ v1))) > 0); *t = 0.0;// incorrect !!! #else - Vector2d v = ~Vector2d(pc, p); - v.normalise(); - if(dir == CW) v = -v; + Vector2d v = ~Vector2d(pc, p); + v.normalise(); + if (dir == CW) { + v = -v; + } - double ang = IncludedAngle(vs, v, dir); - *t = ang / angle; - ret = (*t >= 0 && *t <= 1.0); + double ang = IncludedAngle(vs, v, dir); + *t = ang / angle; + ret = (*t >= 0 && *t <= 1.0); #endif - } + } - return ret; - } - - Line::Line(const Point3d& p, const Vector3d& v0, bool boxed){ - // constructor from point & vector - p0 = p; - v = v0; - length = v.magnitude(); - if(boxed) minmax(); - ok = (length > geoff_geometry::TOLERANCE); - } - - Line::Line(const Point3d& p, const Point3d& p1){ - // constructor from 2 points - p0 = p; - v = Vector3d(p, p1); - length = v.magnitude(); - minmax(); - ok = (length > geoff_geometry::TOLERANCE); - } - - Line::Line(const Span& sp){ - // constructor from linear span - p0 = sp.p0; - v = sp.vs * sp.length; - length = sp.length; - // box = sp.box; - box.min = Point3d(sp.box.min); - box.max = Point3d(sp.box.max); - ok = !sp.NullSpan; - } - - void Line::minmax() { - MinMax(this->p0, box.min, box.max); - MinMax(this->v + this->p0, box.min, box.max); - } - - bool Line::atZ(double z, Point3d& p)const { - // returns p at z on line - if(FEQZ(this->v.getz())) - return false; - double t = (z - this->p0.z) / this->v.getz(); - p = Point3d(this->p0.x + t * this->v.getx(), this->p0.y + t * this->v.gety(), z); - return true; - } - - - bool Line::Shortest(const Line& l2, Line& lshort, double& t1, double& t2)const { - /* - Calculate the line segment PaPb that is the shortest route between - two lines P1P2 and P3P4. Calculate also the values of mua and mub where - Pa = P1 + t1 (P2 - P1) - Pb = P3 + t2 (P4 - P3) - Return FALSE if no solution exists. P Bourke method. - Input this 1st line - Input l2 2nd line - Output lshort shortest line between lines (if !lshort.ok, the line intersect at a point lshort.p0) - Output t1 parameter at intersection on 1st Line - Output t2 parameter at intersection on 2nd Line - - */ - Vector3d v13(l2.p0, this->p0); - if(!this->ok || !l2.ok) - return false; - - double d1343 = v13 * l2.v; // dot products - double d4321 = l2.v * this->v; - double d1321 = v13 * this->v; - double d4343 = l2.v * l2.v; - double d2121 = this->v * this->v; - - double denom = d2121 * d4343 - d4321 * d4321; - if(fabs(denom) < 1.0e-09) - return false; - double numer = d1343 * d4321 - d1321 * d4343; - - t1 = numer / denom; - t2 = (d1343 + d4321 * t1) / d4343; - - lshort = Line(t1* this->v + this->p0, t2 * l2.v + l2.p0); - t1 *= this->length; - t2 *= l2.length; // parameter in line length for tolerance checking - return true; - } - - int Intof(const Line& l0, const Line& l1, Point3d& intof) - { - /* intersection of 2 vectors - returns 0 for intercept but not within either vector - returns 1 for intercept on both vectors - - note that this routine always returns 0 for parallel vectors - method: - x = x0 + dx0 * t0 for l0 - ... - ... - x = x1 + dx1 * t1 for l1 - ... - ... - - x0 + dx0 * t0 = x1 + dx1 * t1 - dx0 * t0 - dx1 * t1 + x0 - x1 = 0 - - setup 3 x 3 determinent for - a0 t0 + b0 t1 + c0 = 0 - a1 t0 + b1 t1 + c1 = 0 - a2 t0 + b2 t1 + c2 = 0 - - from above a = l0.v - b = -l1.v - c = Vector3d(l1, l0) - */ - // Vector3d a = l0.v; - if(l0.box.outside(l1.box)) - return 0; - Vector3d b = -l1.v; - Vector3d c = Vector3d(l1.p0, l0.p0); - Vector3d det = l0.v ^ b; - Vector3d t = b ^ c; - - // choose largest determinant & corresponding parameter for accuracy - double t0 = t.getx(); - double d = det.getx(); - - if(fabs(det.getz()) > fabs(det.gety())) { - if(fabs(det.getz()) > fabs(det.getx())) { - t0 = t.getz(); - d = det.getz(); - } - } - else { - if(fabs(det.gety()) > fabs(det.getx())) { - t0 = t.gety(); - d = det.gety(); - } - } - - if(fabs(d) < 1.0e-06) - return 0; - - t0 /= d; - intof = l0.v * t0 + l0.p0; - - Point3d other; - double t1; - if(Dist(l1, intof, other, t1) > geoff_geometry::TOLERANCE) - return 0; - - t0 *= l0.length; - if( t0 < -geoff_geometry::TOLERANCE || t0 > l0.length + geoff_geometry::TOLERANCE || t1 < -geoff_geometry::TOLERANCE || t1 > l1.length + geoff_geometry::TOLERANCE ) - return 0; - return 1; - } - - - double Dist(const Line& l, const Point3d& p, Point3d& pnear, double& t){ - // returns the distance of a point from a line and the near point on the extended line and the parameter of the near point (0-length) in range - pnear = Near(l, p, t ); - return p.Dist(pnear); - } - - Point3d Near(const Line& l, const Point3d& p, double& t){ - // returns the near point from a line on the extended line and the parameter of the near point (0-length) in range - t = (Vector3d(l.p0, p) * l.v) / l.length; // t parametrised 0 - line length - return l.v * (t / l.length) + l.p0; - } - - Point3d Line::Near(const Point3d& p, double& t)const{ - // returns the near point from a line on the extended line and the parameter of the near point (0-length) in range - t = (Vector3d(this->p0, p) * this->v) / this->length; // t parametrised 0 - line length - return this->v * (t / this->length) + this->p0; - } - - double DistSq(const Point3d *p, const Vector3d *vl, const Point3d *pf) { - /// returns the distance squared of pf from the line given by p,vl - /// vl must be normalised - Vector3d v(*p, *pf); - Vector3d vcp = *vl ^ v; - double d = vcp.magnitudeSq(); // l * sina - return d; - } - - double Dist(const Point3d *p, const Vector3d *vl, const Point3d *pf) { - /// returns the distance of pf from the line given by p,vl - /// vl must be normalised - Vector3d v(*p, *pf); - Vector3d vcp = *vl ^ v; - double d = vcp.magnitude(); // l * sina - return d; - } - - double Dist(const Span& sp, const Point& p , Point& pnear ) { - // returns distance of p from span, pnear is the nearpoint on the span (or endpoint) - if(!sp.dir) { - double d, t; - Point3d unused_pnear; - d = Dist(Line(sp), Point3d(p), unused_pnear, t); - if(t < -geoff_geometry::TOLERANCE) { - pnear = sp.p0; // nearpoint - d = pnear.Dist(p); - } - else if(t > sp.length + geoff_geometry::TOLERANCE) { - pnear = sp.p1; - d = pnear.Dist(p); - } - return d; - } - else { - // put pnear on the circle - double radiusp; - Vector2d v(sp.pc, p); - if((radiusp = v.magnitude()) < geoff_geometry::TOLERANCE) { - // point specified on circle centre - use first point as near point - pnear = sp.p0; // nearpoint - return sp.radius; - } - else { - pnear = v * (sp.radius / radiusp) + sp.pc; - - // check if projected point is on the arc - if(sp.OnSpan(pnear)) - return fabs(radiusp - sp.radius); - - // point not on arc so calc nearest end-point - double ndist = p.Dist(sp.p0); - double dist = p.Dist(sp.p1); - if(ndist >= dist) { - // sp.p1 is near point - pnear = sp.p1; - return dist; - } - - // sp.p0 is near point - pnear = sp.p0; // nearpoint - return ndist ; - } - } - } - - bool OnSpan(const Span& sp, const Point& p) { - Point nullPoint; - return OnSpan(sp, p, false, nullPoint, nullPoint); - } - - bool OnSpan(const Span& sp, const Point& p, bool nearPoints, Point& pNear, Point& pOnSpan) { - // function returns true if pNear == pOnSpan - // returns pNear & pOnSpan if nearPoints true - // pNear (nearest on unbound span) - // pOnSpan (nearest on finite span) - if(sp.dir) { - // arc - if(fabs(p.Dist(sp.pc) - sp.radius) > geoff_geometry::TOLERANCE) { - if(!nearPoints) - return false; - } - - pNear = On(Circle(sp.pc, sp.radius), p); - - if(sp.OnSpan(pNear)) { - if(nearPoints) pOnSpan = pNear; - return true; // near point is on arc - already calculated - } - - // point not on arc return the nearest end-point - if(nearPoints) pOnSpan = (p.Dist(sp.p0) >= p.Dist(sp.p1)) ?sp.p1 : sp.p0; - return false; - } - else { - // straight - if(fabs(CLine(sp.p0, sp.vs).Dist(p)) > geoff_geometry::TOLERANCE) { - if(!nearPoints) - return false; - } - Vector2d v(sp.p0, p); - double t = v * sp.vs; - if(nearPoints) pNear = sp.vs * t + sp.p0; - bool onSpan = (t > - geoff_geometry::TOLERANCE && t < sp.length + geoff_geometry::TOLERANCE); - if(! onSpan) { - if(nearPoints) pOnSpan = (p.Dist(sp.p0) >= p.Dist(sp.p1))?sp.p1 : sp.p0; - } - else { - if(nearPoints) pOnSpan = pNear; - } - return onSpan; - } - } - - // Triangle3d Constructors - Triangle3d::Triangle3d(const Point3d& p1, const Point3d& p2, const Point3d& p3) { - vert1 = p1; - vert2 = p2; - vert3 = p3; - v0 = Vector3d(vert1, vert2); - v1 = Vector3d(vert1, vert3); - ok = true; - - // set box - box.min.x = __min(__min(vert1.x, vert2.x), vert3.x); - box.min.y = __min(__min(vert1.y, vert2.y), vert3.y); - box.min.z = __min(__min(vert1.z, vert2.z), vert3.z); - - box.max.x = __max(__max(vert1.x, vert2.x), vert3.x); - box.max.y = __max(__max(vert1.y, vert2.y), vert3.y); - box.max.z = __max(__max(vert1.z, vert2.z), vert3.z); - } - - // Triangle3d methods - bool Triangle3d::Intof(const Line& l, Point3d& intof)const { - // returns intersection triangle to line in intof - // function returns true for intersection, false for no intersection - // method based on Möller & Trumbore(1997) (Barycentric coordinates) - // based on incorrect Pseudo code from "Geometric Tools for Computer Graphics" p.487 - if(box.outside(l.box)) - return false; - - Vector3d line(l.v); - line.normalise(); - - Vector3d p = line ^ v1; // cross product - double tmp = p * v0; // dot product - - if(FEQZ(tmp)) - return false; - - tmp = 1 / tmp; - Vector3d s(vert1, l.p0); - - double u = tmp * (s * p); // barycentric coordinate - if(u < 0 || u > 1) // not inside triangle - return false; - - Vector3d q = s ^ v0; - double v = tmp * (line * q); // barycentric coordinate - if(v < 0 || v > 1) // not inside triangle - return false; - - if( u + v > 1) // not inside triangle - return false; - - double t = tmp * (v1 * q); - intof = line * t + l.p0; - return true; - } - - - // box class - bool Box::outside(const Box& b)const { - // returns true if this box is outside b - if(!b.ok || !this->ok) // no box set - return false; - if(this->max.x < b.min.x) - return true; - if(this->max.y < b.min.y) - return true; - if(this->min.x > b.max.x) - return true; - if(this->min.y > b.max.y) - return true; - return false; - } - - void Box::combine(const Box& b) { - if(b.max.x > this->max.x) this->max.x = b.max.x; - if(b.max.y > this->max.y) this->max.y = b.max.y; - if(b.min.x < this->min.x) this->min.x = b.min.x; - if(b.min.y < this->min.y) this->min.y = b.min.y; - } - - void Box3d::combine(const Box3d& b) { - if(b.max.x > this->max.x) this->max.x = b.max.x; - if(b.max.y > this->max.y) this->max.y = b.max.y; - if(b.max.z > this->max.z) this->max.z = b.max.z; - if(b.min.x < this->min.x) this->min.x = b.min.x; - if(b.min.y < this->min.y) this->min.y = b.min.y; - if(b.min.z < this->min.z) this->min.z = b.min.z; - } - - bool Box3d::outside(const Box3d& b) const{ - // returns true if this box is outside b - if(!b.ok || !this->ok) // no box set - return false; - if(this->max.x < b.min.x) - return true; - if(this->max.y < b.min.y) - return true; - if(this->max.z < b.min.z) - return true; - if(this->min.x > b.max.x) - return true; - if(this->min.y > b.max.y) - return true; - if(this->min.z > b.max.z) - return true; - return false; - } - - Line IsPtsLine(const double* a, int n, double tolerance, double* deviation) { - // returns a Line if all points are within tolerance - // deviation is returned as the sum of all deviations of interior points to line(sp,ep) - int np = n / 3; // number of points - *deviation = 0; // cumulative deviation - if(np < 2) // Invalid line - return Line(); - - Point3d sp(&a[0]); - Point3d ep(&a[n-3]); - Line line(sp, ep); // line start - end - - if(line.ok) { - for(int j = 1; j < np - 1; j++) { - Point3d mp(&a[j * 3]); - double t, d=0; - if((d = mp.Dist(line.Near(mp, t))) > tolerance) { - line.ok = false; - return line; - } - *deviation = *deviation + d; - } - } - return line; - } + return ret; } + +Line::Line(const Point3d& p, const Vector3d& v0, bool boxed) +{ + // constructor from point & vector + p0 = p; + v = v0; + length = v.magnitude(); + if (boxed) { + minmax(); + } + ok = (length > geoff_geometry::TOLERANCE); +} + +Line::Line(const Point3d& p, const Point3d& p1) +{ + // constructor from 2 points + p0 = p; + v = Vector3d(p, p1); + length = v.magnitude(); + minmax(); + ok = (length > geoff_geometry::TOLERANCE); +} + +Line::Line(const Span& sp) +{ + // constructor from linear span + p0 = sp.p0; + v = sp.vs * sp.length; + length = sp.length; + // box = sp.box; + box.min = Point3d(sp.box.min); + box.max = Point3d(sp.box.max); + ok = !sp.NullSpan; +} + +void Line::minmax() +{ + MinMax(this->p0, box.min, box.max); + MinMax(this->v + this->p0, box.min, box.max); +} + +bool Line::atZ(double z, Point3d& p) const +{ + // returns p at z on line + if (FEQZ(this->v.getz())) { + return false; + } + double t = (z - this->p0.z) / this->v.getz(); + p = Point3d(this->p0.x + t * this->v.getx(), this->p0.y + t * this->v.gety(), z); + return true; +} + + +bool Line::Shortest(const Line& l2, Line& lshort, double& t1, double& t2) const +{ + /* + Calculate the line segment PaPb that is the shortest route between + two lines P1P2 and P3P4. Calculate also the values of mua and mub where + Pa = P1 + t1 (P2 - P1) + Pb = P3 + t2 (P4 - P3) + Return FALSE if no solution exists. P Bourke method. + Input this 1st line + Input l2 2nd line + Output lshort shortest line between lines (if !lshort.ok, the line intersect at a point + lshort.p0) Output t1 parameter at intersection on 1st Line Output t2 parameter at intersection + on 2nd Line + + */ + Vector3d v13(l2.p0, this->p0); + if (!this->ok || !l2.ok) { + return false; + } + + double d1343 = v13 * l2.v; // dot products + double d4321 = l2.v * this->v; + double d1321 = v13 * this->v; + double d4343 = l2.v * l2.v; + double d2121 = this->v * this->v; + + double denom = d2121 * d4343 - d4321 * d4321; + if (fabs(denom) < 1.0e-09) { + return false; + } + double numer = d1343 * d4321 - d1321 * d4343; + + t1 = numer / denom; + t2 = (d1343 + d4321 * t1) / d4343; + + lshort = Line(t1 * this->v + this->p0, t2 * l2.v + l2.p0); + t1 *= this->length; + t2 *= l2.length; // parameter in line length for tolerance checking + return true; +} + +int Intof(const Line& l0, const Line& l1, Point3d& intof) +{ + /* intersection of 2 vectors + returns 0 for intercept but not within either vector + returns 1 for intercept on both vectors + + note that this routine always returns 0 for parallel vectors + method: + x = x0 + dx0 * t0 for l0 + ... + ... + x = x1 + dx1 * t1 for l1 + ... + ... + + x0 + dx0 * t0 = x1 + dx1 * t1 + dx0 * t0 - dx1 * t1 + x0 - x1 = 0 + + setup 3 x 3 determinent for + a0 t0 + b0 t1 + c0 = 0 + a1 t0 + b1 t1 + c1 = 0 + a2 t0 + b2 t1 + c2 = 0 + + from above a = l0.v + b = -l1.v + c = Vector3d(l1, l0) + */ + // Vector3d a = l0.v; + if (l0.box.outside(l1.box)) { + return 0; + } + Vector3d b = -l1.v; + Vector3d c = Vector3d(l1.p0, l0.p0); + Vector3d det = l0.v ^ b; + Vector3d t = b ^ c; + + // choose largest determinant & corresponding parameter for accuracy + double t0 = t.getx(); + double d = det.getx(); + + if (fabs(det.getz()) > fabs(det.gety())) { + if (fabs(det.getz()) > fabs(det.getx())) { + t0 = t.getz(); + d = det.getz(); + } + } + else { + if (fabs(det.gety()) > fabs(det.getx())) { + t0 = t.gety(); + d = det.gety(); + } + } + + if (fabs(d) < 1.0e-06) { + return 0; + } + + t0 /= d; + intof = l0.v * t0 + l0.p0; + + Point3d other; + double t1; + if (Dist(l1, intof, other, t1) > geoff_geometry::TOLERANCE) { + return 0; + } + + t0 *= l0.length; + if (t0 < -geoff_geometry::TOLERANCE || t0 > l0.length + geoff_geometry::TOLERANCE + || t1 < -geoff_geometry::TOLERANCE || t1 > l1.length + geoff_geometry::TOLERANCE) { + return 0; + } + return 1; +} + + +double Dist(const Line& l, const Point3d& p, Point3d& pnear, double& t) +{ + // returns the distance of a point from a line and the near point on the extended line and the + // parameter of the near point (0-length) in range + pnear = Near(l, p, t); + return p.Dist(pnear); +} + +Point3d Near(const Line& l, const Point3d& p, double& t) +{ + // returns the near point from a line on the extended line and the parameter of the near point + // (0-length) in range + t = (Vector3d(l.p0, p) * l.v) / l.length; // t parametrised 0 - line length + return l.v * (t / l.length) + l.p0; +} + +Point3d Line::Near(const Point3d& p, double& t) const +{ + // returns the near point from a line on the extended line and the parameter of the near point + // (0-length) in range + t = (Vector3d(this->p0, p) * this->v) / this->length; // t parametrised 0 - line length + return this->v * (t / this->length) + this->p0; +} + +double DistSq(const Point3d* p, const Vector3d* vl, const Point3d* pf) +{ + /// returns the distance squared of pf from the line given by p,vl + /// vl must be normalised + Vector3d v(*p, *pf); + Vector3d vcp = *vl ^ v; + double d = vcp.magnitudeSq(); // l * sina + return d; +} + +double Dist(const Point3d* p, const Vector3d* vl, const Point3d* pf) +{ + /// returns the distance of pf from the line given by p,vl + /// vl must be normalised + Vector3d v(*p, *pf); + Vector3d vcp = *vl ^ v; + double d = vcp.magnitude(); // l * sina + return d; +} + +double Dist(const Span& sp, const Point& p, Point& pnear) +{ + // returns distance of p from span, pnear is the nearpoint on the span (or endpoint) + if (!sp.dir) { + double d, t; + Point3d unused_pnear; + d = Dist(Line(sp), Point3d(p), unused_pnear, t); + if (t < -geoff_geometry::TOLERANCE) { + pnear = sp.p0; // nearpoint + d = pnear.Dist(p); + } + else if (t > sp.length + geoff_geometry::TOLERANCE) { + pnear = sp.p1; + d = pnear.Dist(p); + } + return d; + } + else { + // put pnear on the circle + double radiusp; + Vector2d v(sp.pc, p); + if ((radiusp = v.magnitude()) < geoff_geometry::TOLERANCE) { + // point specified on circle centre - use first point as near point + pnear = sp.p0; // nearpoint + return sp.radius; + } + else { + pnear = v * (sp.radius / radiusp) + sp.pc; + + // check if projected point is on the arc + if (sp.OnSpan(pnear)) { + return fabs(radiusp - sp.radius); + } + + // point not on arc so calc nearest end-point + double ndist = p.Dist(sp.p0); + double dist = p.Dist(sp.p1); + if (ndist >= dist) { + // sp.p1 is near point + pnear = sp.p1; + return dist; + } + + // sp.p0 is near point + pnear = sp.p0; // nearpoint + return ndist; + } + } +} + +bool OnSpan(const Span& sp, const Point& p) +{ + Point nullPoint; + return OnSpan(sp, p, false, nullPoint, nullPoint); +} + +bool OnSpan(const Span& sp, const Point& p, bool nearPoints, Point& pNear, Point& pOnSpan) +{ + // function returns true if pNear == pOnSpan + // returns pNear & pOnSpan if nearPoints true + // pNear (nearest on unbound span) + // pOnSpan (nearest on finite span) + if (sp.dir) { + // arc + if (fabs(p.Dist(sp.pc) - sp.radius) > geoff_geometry::TOLERANCE) { + if (!nearPoints) { + return false; + } + } + + pNear = On(Circle(sp.pc, sp.radius), p); + + if (sp.OnSpan(pNear)) { + if (nearPoints) { + pOnSpan = pNear; + } + return true; // near point is on arc - already calculated + } + + // point not on arc return the nearest end-point + if (nearPoints) { + pOnSpan = (p.Dist(sp.p0) >= p.Dist(sp.p1)) ? sp.p1 : sp.p0; + } + return false; + } + else { + // straight + if (fabs(CLine(sp.p0, sp.vs).Dist(p)) > geoff_geometry::TOLERANCE) { + if (!nearPoints) { + return false; + } + } + Vector2d v(sp.p0, p); + double t = v * sp.vs; + if (nearPoints) { + pNear = sp.vs * t + sp.p0; + } + bool onSpan = (t > -geoff_geometry::TOLERANCE && t < sp.length + geoff_geometry::TOLERANCE); + if (!onSpan) { + if (nearPoints) { + pOnSpan = (p.Dist(sp.p0) >= p.Dist(sp.p1)) ? sp.p1 : sp.p0; + } + } + else { + if (nearPoints) { + pOnSpan = pNear; + } + } + return onSpan; + } +} + +// Triangle3d Constructors +Triangle3d::Triangle3d(const Point3d& p1, const Point3d& p2, const Point3d& p3) +{ + vert1 = p1; + vert2 = p2; + vert3 = p3; + v0 = Vector3d(vert1, vert2); + v1 = Vector3d(vert1, vert3); + ok = true; + + // set box + box.min.x = __min(__min(vert1.x, vert2.x), vert3.x); + box.min.y = __min(__min(vert1.y, vert2.y), vert3.y); + box.min.z = __min(__min(vert1.z, vert2.z), vert3.z); + + box.max.x = __max(__max(vert1.x, vert2.x), vert3.x); + box.max.y = __max(__max(vert1.y, vert2.y), vert3.y); + box.max.z = __max(__max(vert1.z, vert2.z), vert3.z); +} + +// Triangle3d methods +bool Triangle3d::Intof(const Line& l, Point3d& intof) const +{ + // returns intersection triangle to line in intof + // function returns true for intersection, false for no intersection + // method based on Möller & Trumbore(1997) (Barycentric coordinates) + // based on incorrect Pseudo code from "Geometric Tools for Computer Graphics" p.487 + if (box.outside(l.box)) { + return false; + } + + Vector3d line(l.v); + line.normalise(); + + Vector3d p = line ^ v1; // cross product + double tmp = p * v0; // dot product + + if (FEQZ(tmp)) { + return false; + } + + tmp = 1 / tmp; + Vector3d s(vert1, l.p0); + + double u = tmp * (s * p); // barycentric coordinate + if (u < 0 || u > 1) { // not inside triangle + return false; + } + + Vector3d q = s ^ v0; + double v = tmp * (line * q); // barycentric coordinate + if (v < 0 || v > 1) { // not inside triangle + return false; + } + + if (u + v > 1) { // not inside triangle + return false; + } + + double t = tmp * (v1 * q); + intof = line * t + l.p0; + return true; +} + + +// box class +bool Box::outside(const Box& b) const +{ + // returns true if this box is outside b + if (!b.ok || !this->ok) { // no box set + return false; + } + if (this->max.x < b.min.x) { + return true; + } + if (this->max.y < b.min.y) { + return true; + } + if (this->min.x > b.max.x) { + return true; + } + if (this->min.y > b.max.y) { + return true; + } + return false; +} + +void Box::combine(const Box& b) +{ + if (b.max.x > this->max.x) { + this->max.x = b.max.x; + } + if (b.max.y > this->max.y) { + this->max.y = b.max.y; + } + if (b.min.x < this->min.x) { + this->min.x = b.min.x; + } + if (b.min.y < this->min.y) { + this->min.y = b.min.y; + } +} + +void Box3d::combine(const Box3d& b) +{ + if (b.max.x > this->max.x) { + this->max.x = b.max.x; + } + if (b.max.y > this->max.y) { + this->max.y = b.max.y; + } + if (b.max.z > this->max.z) { + this->max.z = b.max.z; + } + if (b.min.x < this->min.x) { + this->min.x = b.min.x; + } + if (b.min.y < this->min.y) { + this->min.y = b.min.y; + } + if (b.min.z < this->min.z) { + this->min.z = b.min.z; + } +} + +bool Box3d::outside(const Box3d& b) const +{ + // returns true if this box is outside b + if (!b.ok || !this->ok) { // no box set + return false; + } + if (this->max.x < b.min.x) { + return true; + } + if (this->max.y < b.min.y) { + return true; + } + if (this->max.z < b.min.z) { + return true; + } + if (this->min.x > b.max.x) { + return true; + } + if (this->min.y > b.max.y) { + return true; + } + if (this->min.z > b.max.z) { + return true; + } + return false; +} + +Line IsPtsLine(const double* a, int n, double tolerance, double* deviation) +{ + // returns a Line if all points are within tolerance + // deviation is returned as the sum of all deviations of interior points to line(sp,ep) + int np = n / 3; // number of points + *deviation = 0; // cumulative deviation + if (np < 2) { // Invalid line + return Line(); + } + + Point3d sp(&a[0]); + Point3d ep(&a[n - 3]); + Line line(sp, ep); // line start - end + + if (line.ok) { + for (int j = 1; j < np - 1; j++) { + Point3d mp(&a[j * 3]); + double t, d = 0; + if ((d = mp.Dist(line.Near(mp, t))) > tolerance) { + line.ok = false; + return line; + } + *deviation = *deviation + d; + } + } + return line; +} +} // namespace geoff_geometry diff --git a/src/Mod/CAM/libarea/kurve/Matrix.cpp b/src/Mod/CAM/libarea/kurve/Matrix.cpp index 9409a238cc..39f53e535e 100644 --- a/src/Mod/CAM/libarea/kurve/Matrix.cpp +++ b/src/Mod/CAM/libarea/kurve/Matrix.cpp @@ -11,38 +11,45 @@ using namespace geoff_geometry; #ifdef PEPSDLL - #include "vdm.h" - #include "pepsdll.h" - #include "realds.h" +#include "vdm.h" +#include "pepsdll.h" +#include "realds.h" #endif //////////////////////////////////////////////////////////////////////////////////////////////// // matrix //////////////////////////////////////////////////////////////////////////////////////////////// -namespace geoff_geometry { +namespace geoff_geometry +{ - Matrix::Matrix(){ - Unit(); - } - Matrix::Matrix(double m[16]) { - memcpy(e, m, sizeof(e)); - this->IsUnit(); - this->IsMirrored(); - } +Matrix::Matrix() +{ + Unit(); +} +Matrix::Matrix(double m[16]) +{ + memcpy(e, m, sizeof(e)); + this->IsUnit(); + this->IsMirrored(); +} - //Matrix::Matrix( const Matrix& m) - //{ - //*this = m; - //} +// Matrix::Matrix( const Matrix& m) +//{ +//*this = m; +//} - bool Matrix::operator==(const Matrix &m)const{ - // m1 == m2 - if(this->m_unit != m.m_unit || this->m_mirrored != m.m_mirrored) - return false; - for(int i = 0; i < 16; i++) - if(!FEQ(this->e[i], m.e[i], TIGHT_TOLERANCE)) - return false; - return true; - } +bool Matrix::operator==(const Matrix& m) const +{ + // m1 == m2 + if (this->m_unit != m.m_unit || this->m_mirrored != m.m_mirrored) { + return false; + } + for (int i = 0; i < 16; i++) { + if (!FEQ(this->e[i], m.e[i], TIGHT_TOLERANCE)) { + return false; + } + } + return true; +} #if 0 const Matrix& Matrix::operator=( Matrix &m) { @@ -52,579 +59,616 @@ namespace geoff_geometry { return *this; } #endif - void Matrix::Unit() - { - // homogeneous matrix - set as unit matrix - memset(e, 0, sizeof(e)); - e[0] = e[5] = e[10] = e[15] = 1; - m_unit = true; - m_mirrored = false; - } +void Matrix::Unit() +{ + // homogeneous matrix - set as unit matrix + memset(e, 0, sizeof(e)); + e[0] = e[5] = e[10] = e[15] = 1; + m_unit = true; + m_mirrored = false; +} - void Matrix::Get(double* p) const - { - // copy the matrix - memcpy(p, e, sizeof(e)); - } - void Matrix::Put(double* p) - { - // assign the matrix - memcpy(e, p, sizeof(e)); - m_unit = false; // don't know - m_mirrored = -1; // don't know +void Matrix::Get(double* p) const +{ + // copy the matrix + memcpy(p, e, sizeof(e)); +} +void Matrix::Put(double* p) +{ + // assign the matrix + memcpy(e, p, sizeof(e)); + m_unit = false; // don't know + m_mirrored = -1; // don't know +} +void Matrix::Translate(double x, double y, double z) +{ + // translation + e[3] += x; + e[7] += y; + e[11] += z; + m_unit = false; +} - } - void Matrix::Translate(double x, double y, double z) - { - // translation - e[3] += x; - e[7] += y; - e[11] += z; - m_unit = false; - } +void Matrix::Rotate(double angle, Vector3d* rotAxis) +{ + /// Rotation about rotAxis with angle + Rotate(sin(angle), cos(angle), rotAxis); +} - void Matrix::Rotate(double angle, Vector3d *rotAxis) { - /// Rotation about rotAxis with angle - Rotate(sin(angle), cos(angle), rotAxis); - } +void Matrix::Rotate(double sinang, double cosang, Vector3d* rotAxis) +{ + /// Rotation about rotAxis with cp & dp + Matrix rotate; + double oneminusc = 1.0 - cosang; - void Matrix::Rotate(double sinang, double cosang, Vector3d *rotAxis) { - /// Rotation about rotAxis with cp & dp - Matrix rotate; - double oneminusc = 1.0 - cosang; + rotate.e[0] = rotAxis->getx() * rotAxis->getx() * oneminusc + cosang; + rotate.e[1] = rotAxis->getx() * rotAxis->gety() * oneminusc - rotAxis->getz() * sinang; + rotate.e[2] = rotAxis->getx() * rotAxis->getz() * oneminusc + rotAxis->gety() * sinang; - rotate.e[0] = rotAxis->getx() * rotAxis->getx() * oneminusc + cosang; - rotate.e[1] = rotAxis->getx() * rotAxis->gety() * oneminusc - rotAxis->getz() * sinang; - rotate.e[2] = rotAxis->getx() * rotAxis->getz() * oneminusc + rotAxis->gety() * sinang; + rotate.e[4] = rotAxis->getx() * rotAxis->gety() * oneminusc + rotAxis->getz() * sinang; + rotate.e[5] = rotAxis->gety() * rotAxis->gety() * oneminusc + cosang; + rotate.e[6] = rotAxis->gety() * rotAxis->getz() * oneminusc - rotAxis->getx() * sinang; - rotate.e[4] = rotAxis->getx() * rotAxis->gety() * oneminusc + rotAxis->getz() * sinang; - rotate.e[5] = rotAxis->gety() * rotAxis->gety() * oneminusc + cosang; - rotate.e[6] = rotAxis->gety() * rotAxis->getz() * oneminusc - rotAxis->getx() * sinang; - - rotate.e[8] = rotAxis->getx() * rotAxis->getz() * oneminusc - rotAxis->gety() * sinang; - rotate.e[9] = rotAxis->gety() * rotAxis->getz() * oneminusc + rotAxis->getx() * sinang; - rotate.e[10] = rotAxis->getz() * rotAxis->getz() * oneminusc + cosang; - Multiply(rotate); // concatenate rotation with this matrix - m_unit = false; - m_mirrored = -1; // don't know - } + rotate.e[8] = rotAxis->getx() * rotAxis->getz() * oneminusc - rotAxis->gety() * sinang; + rotate.e[9] = rotAxis->gety() * rotAxis->getz() * oneminusc + rotAxis->getx() * sinang; + rotate.e[10] = rotAxis->getz() * rotAxis->getz() * oneminusc + cosang; + Multiply(rotate); // concatenate rotation with this matrix + m_unit = false; + m_mirrored = -1; // don't know +} - void Matrix::Rotate(double angle, int Axis) - { // Rotation (Axis 1 = x , 2 = y , 3 = z - Rotate(sin(angle), cos(angle), Axis); - } +void Matrix::Rotate(double angle, int Axis) +{ // Rotation (Axis 1 = x , 2 = y , 3 = z + Rotate(sin(angle), cos(angle), Axis); +} - void Matrix::Rotate(double sinang, double cosang, int Axis) - { // Rotation (Axis 1 = x , 2 = y , 3 = z - Matrix rotate; - rotate.Unit(); +void Matrix::Rotate(double sinang, double cosang, int Axis) +{ // Rotation (Axis 1 = x , 2 = y , 3 = z + Matrix rotate; + rotate.Unit(); - switch(Axis) - { - case 1: - // about x axis - rotate.e[5] = rotate.e[10] = cosang; - rotate.e[6] = -sinang; - rotate.e[9] = sinang; - break; - case 2: - // about y axis - rotate.e[0] = rotate.e[10] = cosang; - rotate.e[2] = sinang; - rotate.e[8] = -sinang; - break; - case 3: - // about z axis - rotate.e[0] = rotate.e[5] = cosang; - rotate.e[1] = -sinang; - rotate.e[4] = sinang; - break; - } - Multiply(rotate); // concatenate rotation with this matrix - m_unit = false; - m_mirrored = -1; // don't know - } + switch (Axis) { + case 1: + // about x axis + rotate.e[5] = rotate.e[10] = cosang; + rotate.e[6] = -sinang; + rotate.e[9] = sinang; + break; + case 2: + // about y axis + rotate.e[0] = rotate.e[10] = cosang; + rotate.e[2] = sinang; + rotate.e[8] = -sinang; + break; + case 3: + // about z axis + rotate.e[0] = rotate.e[5] = cosang; + rotate.e[1] = -sinang; + rotate.e[4] = sinang; + break; + } + Multiply(rotate); // concatenate rotation with this matrix + m_unit = false; + m_mirrored = -1; // don't know +} - void Matrix::Scale(double scale) - { - // add a scale - Scale(scale, scale, scale); - } +void Matrix::Scale(double scale) +{ + // add a scale + Scale(scale, scale, scale); +} - void Matrix::Scale(double scalex, double scaley, double scalez) - { - // add a scale - Matrix temp; - temp.Unit(); +void Matrix::Scale(double scalex, double scaley, double scalez) +{ + // add a scale + Matrix temp; + temp.Unit(); - temp.e[0] = scalex; - temp.e[5] = scaley; - temp.e[10] = scalez; - Multiply(temp); - m_unit = false; - m_mirrored = -1; // don't know - } - void Matrix::Multiply(Matrix& m) - { - // multiply this by give matrix - concatenate - int i, k, l; - Matrix ret; + temp.e[0] = scalex; + temp.e[5] = scaley; + temp.e[10] = scalez; + Multiply(temp); + m_unit = false; + m_mirrored = -1; // don't know +} +void Matrix::Multiply(Matrix& m) +{ + // multiply this by give matrix - concatenate + int i, k, l; + Matrix ret; - for (i = 0; i < 16; i++) - { - l = i - (k = (i % 4)); - ret.e[i] = m.e[l] * e[k] + m.e[l+1] * e[k+4] + m.e[l+2] * e[k+8] + m.e[l+3] * e[k+12]; - } + for (i = 0; i < 16; i++) { + l = i - (k = (i % 4)); + ret.e[i] = + m.e[l] * e[k] + m.e[l + 1] * e[k + 4] + m.e[l + 2] * e[k + 8] + m.e[l + 3] * e[k + 12]; + } - *this = ret; - this->IsUnit(); - } + *this = ret; + this->IsUnit(); +} - void Matrix::Transform(double p0[3], double p1[3]) const - { - // transform p0 thro' this matrix - if(m_unit) - memcpy(p1, p0, 3 * sizeof(double)); - else { - p1[0] = p0[0] * e[0] + p0[1] * e[1] + p0[2] * e[2] + e[3]; - p1[1] = p0[0] * e[4] + p0[1] * e[5] + p0[2] * e[6] + e[7]; - p1[2] = p0[0] * e[8] + p0[1] * e[9] + p0[2] * e[10] + e[11]; - } - } - void Matrix::Transform2d(double p0[2], double p1[2]) const - { - // transform p0 thro' this matrix (2d only) - if(m_unit) - memcpy(p1, p0, 2 * sizeof(double)); - else { - p1[0] = p0[0] * e[0] + p0[1] * e[1] + e[3]; - p1[1] = p0[0] * e[4] + p0[1] * e[5] + e[7]; - } - } +void Matrix::Transform(double p0[3], double p1[3]) const +{ + // transform p0 thro' this matrix + if (m_unit) { + memcpy(p1, p0, 3 * sizeof(double)); + } + else { + p1[0] = p0[0] * e[0] + p0[1] * e[1] + p0[2] * e[2] + e[3]; + p1[1] = p0[0] * e[4] + p0[1] * e[5] + p0[2] * e[6] + e[7]; + p1[2] = p0[0] * e[8] + p0[1] * e[9] + p0[2] * e[10] + e[11]; + } +} +void Matrix::Transform2d(double p0[2], double p1[2]) const +{ + // transform p0 thro' this matrix (2d only) + if (m_unit) { + memcpy(p1, p0, 2 * sizeof(double)); + } + else { + p1[0] = p0[0] * e[0] + p0[1] * e[1] + e[3]; + p1[1] = p0[0] * e[4] + p0[1] * e[5] + e[7]; + } +} - void Matrix::Transform(double p0[3]) const - { - double p1[3]; - if(!m_unit) { - Transform(p0, p1); - memcpy(p0, p1, 3 * sizeof(double)); - } - } +void Matrix::Transform(double p0[3]) const +{ + double p1[3]; + if (!m_unit) { + Transform(p0, p1); + memcpy(p0, p1, 3 * sizeof(double)); + } +} - int Matrix::IsMirrored() - { - // returns true if matrix has a mirror - if(m_unit) - m_mirrored = false; - else if(m_mirrored == -1) { +int Matrix::IsMirrored() +{ + // returns true if matrix has a mirror + if (m_unit) { + m_mirrored = false; + } + else if (m_mirrored == -1) { - m_mirrored = ((e[0] * (e[5] * e[10] - e[6] * e[9]) - - e[1] * (e[4] * e[10] - e[6] * e[8]) - + e[2] * (e[4] * e[9] - e[5] * e[8])) < 0); - } - return m_mirrored; - } - int Matrix::IsUnit() { - // returns true if unit matrix - for(int i = 0; i < 16; i++) { - if(i == 0 || i == 5 || i == 10 || i == 15) { - if(e[i] != 1) - return m_unit = false; - } - else { - if(e[i] != 0) - return m_unit = false; - } - } - m_mirrored = false; - return m_unit = true; - } + m_mirrored = ((e[0] * (e[5] * e[10] - e[6] * e[9]) - e[1] * (e[4] * e[10] - e[6] * e[8]) + + e[2] * (e[4] * e[9] - e[5] * e[8])) + < 0); + } + return m_mirrored; +} +int Matrix::IsUnit() +{ + // returns true if unit matrix + for (int i = 0; i < 16; i++) { + if (i == 0 || i == 5 || i == 10 || i == 15) { + if (e[i] != 1) { + return m_unit = false; + } + } + else { + if (e[i] != 0) { + return m_unit = false; + } + } + } + m_mirrored = false; + return m_unit = true; +} - void Matrix::GetTranslate(double& x, double& y, double& z) const - { - // return translation - x = e[3]; - y = e[7]; - z = e[11]; - } - void Matrix::GetScale(double& sx, double& sy, double& sz) const - { - // return the scale - if(m_unit) { - sx = sy = sz = 1; - } - else { - sx = sqrt(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]); - sy = sqrt(e[4] * e[4] + e[5] * e[5] + e[6] * e[6]); - sz = sqrt(e[8] * e[8] + e[9] * e[9] + e[10] * e[10]); - } - } - bool Matrix::GetScale(double& sx) const - { - // return a uniform scale (false if differential) - double sy, sz; - if(m_unit) { - sx = 1; - return true; - } - GetScale(sx, sy, sz); - return (fabs(fabs(sx) - fabs(sy)) < 0.000001)?true : false; - } - void Matrix::GetRotation(double& ax, double& ay, double& az) const - { - // return the rotations - if(m_unit) { - ax = ay = az = 0; - return; - } - double a; /* cos(bx) */ - double b; /* sin(bx) */ - double c; /* cos(by) */ - double d; /* sin(by) */ - double ee; /* cos(bz) */ - double f; /* sin(bz) */ - double sx, sy, sz; - GetScale(sx, sy, sz); - if(this->m_mirrored == -1) FAILURE(L"Don't know mirror - use IsMirrored method on object"); - if(this->m_mirrored) sx = -sx; +void Matrix::GetTranslate(double& x, double& y, double& z) const +{ + // return translation + x = e[3]; + y = e[7]; + z = e[11]; +} +void Matrix::GetScale(double& sx, double& sy, double& sz) const +{ + // return the scale + if (m_unit) { + sx = sy = sz = 1; + } + else { + sx = sqrt(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]); + sy = sqrt(e[4] * e[4] + e[5] * e[5] + e[6] * e[6]); + sz = sqrt(e[8] * e[8] + e[9] * e[9] + e[10] * e[10]); + } +} +bool Matrix::GetScale(double& sx) const +{ + // return a uniform scale (false if differential) + double sy, sz; + if (m_unit) { + sx = 1; + return true; + } + GetScale(sx, sy, sz); + return (fabs(fabs(sx) - fabs(sy)) < 0.000001) ? true : false; +} +void Matrix::GetRotation(double& ax, double& ay, double& az) const +{ + // return the rotations + if (m_unit) { + ax = ay = az = 0; + return; + } + double a; /* cos(bx) */ + double b; /* sin(bx) */ + double c; /* cos(by) */ + double d; /* sin(by) */ + double ee; /* cos(bz) */ + double f; /* sin(bz) */ + double sx, sy, sz; + GetScale(sx, sy, sz); + if (this->m_mirrored == -1) { + FAILURE(L"Don't know mirror - use IsMirrored method on object"); + } + if (this->m_mirrored) { + sx = -sx; + } - // solve for d and decide case and solve for a, b, c, e and f - d = - e[8] / sz; - if((c = (1 - d) * (1 + d)) > 0.001) - { - // case 1 - c = sqrt( c ); - a = e[10] / sz / c; - b = e[9] / sz / c; - ee = e[0] / sx / c; - f = e[4] / sy / c; - } - else - { - // case 2 - double coef; - double p, q; + // solve for d and decide case and solve for a, b, c, e and f + d = -e[8] / sz; + if ((c = (1 - d) * (1 + d)) > 0.001) { + // case 1 + c = sqrt(c); + a = e[10] / sz / c; + b = e[9] / sz / c; + ee = e[0] / sx / c; + f = e[4] / sy / c; + } + else { + // case 2 + double coef; + double p, q; - d = ( d < 0 ) ? -1 : 1 ; - c = 0 ; - p = d * e[5] / sy - e[2] / sx; - q = d * e[6] / sy + e[1] / sx; - if((coef = sqrt( p * p + q * q )) > 0.001) { - a = q / coef; - b = p / coef; - ee = b; - f = -d * b; - } - else - { - /* dependent pairs */ - a = e[5] / sy; - b = -e[6] / sy; - ee = 1 ; - f = 0 ; - } - } + d = (d < 0) ? -1 : 1; + c = 0; + p = d * e[5] / sy - e[2] / sx; + q = d * e[6] / sy + e[1] / sx; + if ((coef = sqrt(p * p + q * q)) > 0.001) { + a = q / coef; + b = p / coef; + ee = b; + f = -d * b; + } + else { + /* dependent pairs */ + a = e[5] / sy; + b = -e[6] / sy; + ee = 1; + f = 0; + } + } - // solve and return ax, ay and az - ax = atan2( b, a ); - ay = atan2( d, c ); - az = atan2( f, ee ); - } + // solve and return ax, ay and az + ax = atan2(b, a); + ay = atan2(d, c); + az = atan2(f, ee); +} - Matrix Matrix::Inverse() - { - // matrix inversion routine +Matrix Matrix::Inverse() +{ + // matrix inversion routine - // a is input matrix destroyed & replaced by inverse - // method used is gauss-jordan (ref ibm applications) + // a is input matrix destroyed & replaced by inverse + // method used is gauss-jordan (ref ibm applications) - double hold , biga ; - int i , j , k , nk , kk , ij , iz ; - int ki , ji , jp , jk , kj , jq , jr , ik; + double hold, biga; + int i, j, k, nk, kk, ij, iz; + int ki, ji, jp, jk, kj, jq, jr, ik; - int n = 4; // 4 x 4 matrix only - Matrix a = *this; - int l[4], m[4]; + int n = 4; // 4 x 4 matrix only + Matrix a = *this; + int l[4], m[4]; - if(a.m_unit) // unit matrix - return a; + if (a.m_unit) { // unit matrix + return a; + } - // search for largest element - nk = - n ; - for ( k = 0 ; k < n ; k++ ) { - nk += n ; - l [ k ] = m [ k ] = k ; - kk = nk + k ; - biga = a.e[ kk ] ; + // search for largest element + nk = -n; + for (k = 0; k < n; k++) { + nk += n; + l[k] = m[k] = k; + kk = nk + k; + biga = a.e[kk]; - for ( j = k ; j < n ; j++ ) { - iz = n * j ; - for ( i = k ; i < n ; i++ ) { - ij = iz + i ; - if ( fabs ( biga ) < fabs ( a.e[ ij ] ) ) { - biga = a.e[ ij ] ; - l[ k ] = i ; - m[ k ] = j ; - } - } - } + for (j = k; j < n; j++) { + iz = n * j; + for (i = k; i < n; i++) { + ij = iz + i; + if (fabs(biga) < fabs(a.e[ij])) { + biga = a.e[ij]; + l[k] = i; + m[k] = j; + } + } + } - // interchange rows - j = l[ k ] ; - if ( j > k ) { - ki = k - n ; + // interchange rows + j = l[k]; + if (j > k) { + ki = k - n; - for ( i = 0 ; i < n ; i++ ) { - ki += n ; - hold = - a.e[ ki ] ; - ji = ki - k + j ; - a.e[ ki ] = a.e[ ji ] ; - a.e[ ji ] = hold ; - } - } + for (i = 0; i < n; i++) { + ki += n; + hold = -a.e[ki]; + ji = ki - k + j; + a.e[ki] = a.e[ji]; + a.e[ji] = hold; + } + } - // interchange columns - i = m[ k ] ; - if ( i > k ) { - jp = n * i ; - for ( j = 0 ; j < n ; j++ ) { - jk = nk + j ; - ji = jp + j ; - hold = - a.e[ jk ] ; - a.e[ jk ] = a.e[ ji ] ; - a.e[ ji ] = hold ; - } - } + // interchange columns + i = m[k]; + if (i > k) { + jp = n * i; + for (j = 0; j < n; j++) { + jk = nk + j; + ji = jp + j; + hold = -a.e[jk]; + a.e[jk] = a.e[ji]; + a.e[ji] = hold; + } + } - // divide columns by minus pivot (value of pivot element is contained in biga) - if ( fabs ( biga ) < 1.0e-10 )FAILURE(getMessage(L"Singular Matrix - Inversion failure")); // singular matrix + // divide columns by minus pivot (value of pivot element is contained in biga) + if (fabs(biga) < 1.0e-10) { + FAILURE(getMessage(L"Singular Matrix - Inversion failure")); // singular matrix + } - for ( i = 0 ; i < n ; i++ ) { - if ( i != k ) { - ik = nk + i ; - a.e[ ik ] = - a.e[ ik ] /biga ; - } - } + for (i = 0; i < n; i++) { + if (i != k) { + ik = nk + i; + a.e[ik] = -a.e[ik] / biga; + } + } - // reduce matrix - for ( i = 0 ; i < n ; i++ ) { - ik = nk + i ; - hold = a.e[ ik ] ; - ij = i - n ; + // reduce matrix + for (i = 0; i < n; i++) { + ik = nk + i; + hold = a.e[ik]; + ij = i - n; - for ( j = 0 ; j < n ; j++ ) { - ij = ij + n ; - if ( i != k && j != k ) { - kj = ij - i + k ; - a.e[ ij ] = hold * a.e[ kj ] + a.e[ ij ] ; - } - } - } + for (j = 0; j < n; j++) { + ij = ij + n; + if (i != k && j != k) { + kj = ij - i + k; + a.e[ij] = hold * a.e[kj] + a.e[ij]; + } + } + } - // divide row by pivot - kj = k - n ; - for ( j = 0 ; j < n ; j++ ) { - kj = kj + n ; - if ( j != k ) a.e[ kj] = a.e[ kj ] /biga ; - } + // divide row by pivot + kj = k - n; + for (j = 0; j < n; j++) { + kj = kj + n; + if (j != k) { + a.e[kj] = a.e[kj] / biga; + } + } - // replace pivot by reciprocal - a.e[ kk ] = 1 / biga ; - } + // replace pivot by reciprocal + a.e[kk] = 1 / biga; + } - // final row and column interchange - k = n - 1 ; + // final row and column interchange + k = n - 1; - while ( k > 0 ) { - i = l[ --k ] ; - if ( i > k ) { - jq = n * k ; - jr = n * i ; + while (k > 0) { + i = l[--k]; + if (i > k) { + jq = n * k; + jr = n * i; - for ( j = 0 ; j < n ; j++ ) { - jk = jq + j ; - hold = a.e[jk] ; - ji = jr + j ; - a.e[jk] = - a.e[ji] ; - a.e[ji] = hold ; - } - } + for (j = 0; j < n; j++) { + jk = jq + j; + hold = a.e[jk]; + ji = jr + j; + a.e[jk] = -a.e[ji]; + a.e[ji] = hold; + } + } - j = m[ k ] ; - if ( j > k ) { - ki = k - n ; + j = m[k]; + if (j > k) { + ki = k - n; - for ( i = 1 ; i <= n ; i ++ ) { - ki = ki + n ; - hold = a.e[ ki ] ; - ji = ki - k + j ; - a.e[ ki ] = - a.e[ ji ] ; - a.e[ ji ] = hold ; - } - } - } + for (i = 1; i <= n; i++) { + ki = ki + n; + hold = a.e[ki]; + ji = ki - k + j; + a.e[ki] = -a.e[ji]; + a.e[ji] = hold; + } + } + } - return a; - } + return a; +} #ifdef PEPSDLL - void Matrix::ToPeps(int id) - { - int set = PepsVdmMake(id, VDM_MATRIX_TYPE , VDM_LOCAL); - if(set < 0) FAILURE(L"Failed to create Matrix VDM"); - struct kgm_header pepsm; +void Matrix::ToPeps(int id) +{ + int set = PepsVdmMake(id, VDM_MATRIX_TYPE, VDM_LOCAL); + if (set < 0) { + FAILURE(L"Failed to create Matrix VDM"); + } + struct kgm_header pepsm; - Get(pepsm.matrix); - pepsm.off_rad = 0; - pepsm.off_dir = pepsm.origin_id = 0; + Get(pepsm.matrix); + pepsm.off_rad = 0; + pepsm.off_dir = pepsm.origin_id = 0; - PepsVdmWriteTmx(set , &pepsm ); + PepsVdmWriteTmx(set, &pepsm); - PepsVdmClose(set); + PepsVdmClose(set); +} - } +void Matrix::FromPeps(int id) +{ + // if(id) { + int set = PepsVdmOpen(id, VDM_MATRIX_TYPE, VDM_READ_ONLY | VDM_LOCAL); + if (set < 0) { + FAILURE(L"Failed to open Matrix VDM"); + } - void Matrix::FromPeps(int id) - { - // if(id) { - int set = PepsVdmOpen(id, VDM_MATRIX_TYPE , VDM_READ_ONLY | VDM_LOCAL); - if(set < 0) FAILURE(L"Failed to open Matrix VDM"); - - struct kgm_header pepsm; - PepsVdmReadTmx(set , &pepsm); - memcpy(e, pepsm.matrix, sizeof(pepsm.matrix)); - m_unit = true; - for(int i = 0; i < 16; i++) { - // copy over matrix and check for unit matrix - if(i == 0 || i == 5 || i == 10 || i == 15) { - if((e[i] = pepsm.matrix[i]) != 1) m_unit = false; - } - else { - if((e[i] = pepsm.matrix[i]) != 0) m_unit = false; - } - } - PepsVdmClose(set); - m_mirrored = IsMirrored(); - // } - } + struct kgm_header pepsm; + PepsVdmReadTmx(set, &pepsm); + memcpy(e, pepsm.matrix, sizeof(pepsm.matrix)); + m_unit = true; + for (int i = 0; i < 16; i++) { + // copy over matrix and check for unit matrix + if (i == 0 || i == 5 || i == 10 || i == 15) { + if ((e[i] = pepsm.matrix[i]) != 1) { + m_unit = false; + } + } + else { + if ((e[i] = pepsm.matrix[i]) != 0) { + m_unit = false; + } + } + } + PepsVdmClose(set); + m_mirrored = IsMirrored(); + // } +} #endif - Matrix UnitMatrix; // a global unit matrix +Matrix UnitMatrix; // a global unit matrix - // vector - Vector2d::Vector2d(const Vector3d &v){ - if(FEQZ(v.getz())) FAILURE(L"Converting Vector3d to Vector2d illegal"); - dx = v.getx(); - dy = v.gety(); - } +// vector +Vector2d::Vector2d(const Vector3d& v) +{ + if (FEQZ(v.getz())) { + FAILURE(L"Converting Vector3d to Vector2d illegal"); + } + dx = v.getx(); + dy = v.gety(); +} - bool Vector2d::operator==(const Vector2d &v)const { - return FEQ(dx, v.getx(), 1.0e-06) && FEQ(dy, v.gety(), 1.0e-06); - } +bool Vector2d::operator==(const Vector2d& v) const +{ + return FEQ(dx, v.getx(), 1.0e-06) && FEQ(dy, v.gety(), 1.0e-06); +} - void Vector2d::Transform(const Matrix& m) { - // transform vector - if(!m.m_unit) { - double dxt = dx * m.e[0] + dy * m.e[1]; - double dyt = dx * m.e[4] + dy * m.e[5]; - dx = dxt; - dy = dyt; - } - this->normalise(); - } +void Vector2d::Transform(const Matrix& m) +{ + // transform vector + if (!m.m_unit) { + double dxt = dx * m.e[0] + dy * m.e[1]; + double dyt = dx * m.e[4] + dy * m.e[5]; + dx = dxt; + dy = dyt; + } + this->normalise(); +} - void Vector3d::Transform(const Matrix& m) { - // transform vector - if(!m.m_unit) { - double dxt = dx * m.e[0] + dy * m.e[1] + dz * m.e[2]; - double dyt = dx * m.e[4] + dy * m.e[5] + dz * m.e[6]; - double dzt = dx * m.e[8] + dy * m.e[9] + dz * m.e[10]; - dx = dxt; - dy = dyt; - dz = dzt; - } - this->normalise(); - } +void Vector3d::Transform(const Matrix& m) +{ + // transform vector + if (!m.m_unit) { + double dxt = dx * m.e[0] + dy * m.e[1] + dz * m.e[2]; + double dyt = dx * m.e[4] + dy * m.e[5] + dz * m.e[6]; + double dzt = dx * m.e[8] + dy * m.e[9] + dz * m.e[10]; + dx = dxt; + dy = dyt; + dz = dzt; + } + this->normalise(); +} - void Vector3d::arbitrary_axes(Vector3d& x, Vector3d& y){ - // arbitrary axis algorithm - acad method of generating an arbitrary but - // consistent set of axes from a single normal ( z ) - // arbitrary x & y axes +void Vector3d::arbitrary_axes(Vector3d& x, Vector3d& y) +{ + // arbitrary axis algorithm - acad method of generating an arbitrary but + // consistent set of axes from a single normal ( z ) + // arbitrary x & y axes - if ( ( fabs ( this->getx() ) < 1.0/64.0 ) && (fabs(this->gety()) < 1.0/64.0)) - x = Y_VECTOR ^ *this; - else - x = Z_VECTOR ^ *this; + if ((fabs(this->getx()) < 1.0 / 64.0) && (fabs(this->gety()) < 1.0 / 64.0)) { + x = Y_VECTOR ^ *this; + } + else { + x = Z_VECTOR ^ *this; + } - y = *this ^ x; - } + y = *this ^ x; +} - int Vector3d::setCartesianAxes(Vector3d& b, Vector3d& c) { +int Vector3d::setCartesianAxes(Vector3d& b, Vector3d& c) +{ #define a *this - // computes a RH triad of Axes (Cartesian) starting from a (normalised) - // if a & b are perpendicular then c = a ^ b - // if a & c are perpendicular then b = c ^ a - // if neither are perpendicular to a, then return arbitrary axes from a + // computes a RH triad of Axes (Cartesian) starting from a (normalised) + // if a & b are perpendicular then c = a ^ b + // if a & c are perpendicular then b = c ^ a + // if neither are perpendicular to a, then return arbitrary axes from a - // calling sequence for RH cartesian - // x y z - // y z x - // z x y - if(a == NULL_VECTOR) FAILURE(L"SetAxes given a NULL Vector"); - double epsilon = 1.0e-09; - bool bNull = (b == NULL_VECTOR); - bool cNull = (c == NULL_VECTOR); - bool abPerp = !bNull; - if(abPerp) abPerp = (fabs(a * b) < epsilon); + // calling sequence for RH cartesian + // x y z + // y z x + // z x y + if (a == NULL_VECTOR) { + FAILURE(L"SetAxes given a NULL Vector"); + } + double epsilon = 1.0e-09; + bool bNull = (b == NULL_VECTOR); + bool cNull = (c == NULL_VECTOR); + bool abPerp = !bNull; + if (abPerp) { + abPerp = (fabs(a * b) < epsilon); + } - bool acPerp = !cNull; - if(acPerp) acPerp = (fabs(a * c) < epsilon); + bool acPerp = !cNull; + if (acPerp) { + acPerp = (fabs(a * c) < epsilon); + } - if(abPerp) { - c = a ^ b; - return 1; - } + if (abPerp) { + c = a ^ b; + return 1; + } - if(acPerp) { - b = c ^ a; - return 1; - } + if (acPerp) { + b = c ^ a; + return 1; + } - arbitrary_axes(b, c); - b.normalise(); - c.normalise(); - return 2; + arbitrary_axes(b, c); + b.normalise(); + c.normalise(); + return 2; } - void Plane::Mirrored(Matrix* tmMirrored) { - // calculates a mirror transformation that mirrors 2d about plane +void Plane::Mirrored(Matrix* tmMirrored) +{ + // calculates a mirror transformation that mirrors 2d about plane - //Point3d p1 = this->Near(Point3d(0.,0.,0.)); - if(!tmMirrored->m_unit) - tmMirrored->Unit(); + // Point3d p1 = this->Near(Point3d(0.,0.,0.)); + if (!tmMirrored->m_unit) { + tmMirrored->Unit(); + } - double nx = this->normal.getx(); - double ny = this->normal.gety(); - double nz = this->normal.getz(); + double nx = this->normal.getx(); + double ny = this->normal.gety(); + double nz = this->normal.getz(); - // the translation - tmMirrored->e[ 3] = -2. * nx * this->d; - tmMirrored->e[ 7] = -2. * ny * this->d; - tmMirrored->e[11] = -2. * nz * this->d; + // the translation + tmMirrored->e[3] = -2. * nx * this->d; + tmMirrored->e[7] = -2. * ny * this->d; + tmMirrored->e[11] = -2. * nz * this->d; - // the rest - tmMirrored->e[ 0] = 1. - 2. * nx * nx; - tmMirrored->e[ 5] = 1. - 2. * ny * ny; - tmMirrored->e[10] = 1. - 2. * nz * nz; - tmMirrored->e[ 1] = tmMirrored->e[ 4] = -2. * nx * ny; - tmMirrored->e[ 2] = tmMirrored->e[ 8] = -2. * nz * nx; - tmMirrored->e[ 6] = tmMirrored->e[ 9] = -2. * ny * nz; + // the rest + tmMirrored->e[0] = 1. - 2. * nx * nx; + tmMirrored->e[5] = 1. - 2. * ny * ny; + tmMirrored->e[10] = 1. - 2. * nz * nz; + tmMirrored->e[1] = tmMirrored->e[4] = -2. * nx * ny; + tmMirrored->e[2] = tmMirrored->e[8] = -2. * nz * nx; + tmMirrored->e[6] = tmMirrored->e[9] = -2. * ny * nz; - tmMirrored->m_unit = false; - tmMirrored->m_mirrored = true; - } + tmMirrored->m_unit = false; + tmMirrored->m_mirrored = true; } +} // namespace geoff_geometry diff --git a/src/Mod/CAM/libarea/kurve/README b/src/Mod/CAM/libarea/kurve/README index 2e90f26eaf..00eeb03f2b 100644 --- a/src/Mod/CAM/libarea/kurve/README +++ b/src/Mod/CAM/libarea/kurve/README @@ -4,9 +4,9 @@ This project provides library and associated python-modules to compute profile a Written by Dan Heeks -libarea originally used kbool http://boolean.klaasholwerda.nl/bool.html written by Klaas Holwerda for calculating intersections. Since kbool uses a GPL license and HeeksCNC has a New BSD license, Dan rewrote some of the code to use the more liberally licensed (Boost license, which is compatible with LGPLv2) clipper library,written by Angus Johnson, to replace kbool. Clipper can be found here: http://sourceforge.net/p/polyclipping/code/HEAD/tree/trunk/. The clipper library is include with libarea for convenience. +libarea originally used kbool http://boolean.klaasholwerda.nl/bool.html written by Klaas Holwerda for calculating intersections. Since kbool uses a GPL license and HeeksCNC has a New BSD license, Dan rewrote some of the code to use the more liberally licensed (Boost license, which is compatible with LGPLv2) clipper library,written by Angus Johnson, to replace kbool. Clipper can be found here: http://sourceforge.net/p/polyclipping/code/HEAD/tree/trunk/. The clipper library is include with libarea for convenience. -libarea is used by HeeksCNC and FreeCAD's Path workbench. +libarea is used by HeeksCNC and FreeCAD's Path workbench. As more evidence of the legitimate New BSD licensing of libarea, I am including an email exchange between Dan Heeks, Geoff Hawkesford, and myself. In this exchange of emails, Geoff cleared up his use of the New BSD license for the code in the 'kurve' directory. See below: @@ -14,7 +14,7 @@ Subject: question about kurve license Dan Falck 1/19/12 -to Dan Heeks: +to Dan Heeks: Hi Dan, Do you know if g.j.hawkesford wanted his kurve code released under the @@ -31,7 +31,7 @@ Dan Dan Heeks 1/20/12 -to me +to me I can't find his email. But I am sure that he has no idea that there is a difference between BSD and "New BSD". I will ask him when I see him next Wednesday also. @@ -39,7 +39,7 @@ him next Wednesday also. Dan Heeks 1/30/12 -to Geoff, me +to Geoff, me Geoff, My friend, Dan Falck, from Portland Oregon, is asking about your geometry code that I released in my HeeksCNC project. @@ -52,11 +52,11 @@ http://en.wikipedia.org/wiki/BSD_licenses Geoff Hawkesford 1/31/12 -to Dan, me +to Dan, me That’s ok for me. Geoff - - + + From: Dan Heeks Sent: Monday, January 30, 2012 9:34 PM To: Geoff Hawkesford @@ -67,13 +67,12 @@ Subject: Re: question about kurve license Dan Heeks 1/31/12 -to Geoff, me +to Geoff, me Thanks. Dan Falck 1/31/12 -to Geoff, Dan +to Geoff, Dan Thank you so much. - diff --git a/src/Mod/CAM/libarea/kurve/geometry.h b/src/Mod/CAM/libarea/kurve/geometry.h index 81b2e0fd78..88cbbf5b1a 100644 --- a/src/Mod/CAM/libarea/kurve/geometry.h +++ b/src/Mod/CAM/libarea/kurve/geometry.h @@ -11,9 +11,9 @@ ///////////////////////////////////////////////////////////////////////////////////////// #pragma once #ifdef _MSC_VER -#pragma warning( disable : 4996 ) +#pragma warning(disable : 4996) #ifndef WINVER - #define WINVER 0x501 +#define WINVER 0x501 #endif #endif @@ -28,1079 +28,1674 @@ using namespace std; -namespace geoff_geometry { +namespace geoff_geometry +{ - // offset methods - enum OFFSET_METHODS { - NO_ELIMINATION = 0, - BASIC_OFFSET, - ROLLINGBALL_OFFSET // unfinished - }; +// offset methods +enum OFFSET_METHODS +{ + NO_ELIMINATION = 0, + BASIC_OFFSET, + ROLLINGBALL_OFFSET // unfinished +}; - enum SPAN_IDS { - UNMARKED = 0xe0000000, - ROLL_AROUND, - INTERSECTION, - FULL_CIRCLE_KURVE - }; +enum SPAN_IDS +{ + UNMARKED = 0xe0000000, + ROLL_AROUND, + INTERSECTION, + FULL_CIRCLE_KURVE +}; - class Vector2d; - class Vector3d; - class Point; - class Point3d; - class CLine; - class Circle; - class Span; - class Kurve; - class Line; +class Vector2d; +class Vector3d; +class Point; +class Point3d; +class CLine; +class Circle; +class Span; +class Kurve; +class Line; - enum UNITS_TYPE{ - MM = 0, - METRES, - INCHES - }; +enum UNITS_TYPE +{ + MM = 0, + METRES, + INCHES +}; - extern int UNITS; // may be enum UNITS_TYPE (MM METRES or INCHES) - extern double TOLERANCE; // CAD Geometry resolution (inexact, eg. from import) - extern double TOLERANCE_SQ; // tolerance squared for faster coding. - extern double TIGHT_TOLERANCE; - extern double UNIT_VECTOR_TOLERANCE; - extern double SMALL_ANGLE; // small angle tangency test eg isConvex - extern double SIN_SMALL_ANGLE; - extern double COS_SMALL_ANGLE; - extern double RESOLUTION; // CNC resolution +extern int UNITS; // may be enum UNITS_TYPE (MM METRES or INCHES) +extern double TOLERANCE; // CAD Geometry resolution (inexact, eg. from import) +extern double TOLERANCE_SQ; // tolerance squared for faster coding. +extern double TIGHT_TOLERANCE; +extern double UNIT_VECTOR_TOLERANCE; +extern double SMALL_ANGLE; // small angle tangency test eg isConvex +extern double SIN_SMALL_ANGLE; +extern double COS_SMALL_ANGLE; +extern double RESOLUTION; // CNC resolution - void set_Tolerances(int mode); - double mm(double value); // convert to current units from mm +void set_Tolerances(int mode); +double mm(double value); // convert to current units from mm -inline bool FEQ(double a, double b, double tolerance = TOLERANCE) {return fabs(a - b) <= tolerance;} -inline bool FNE(double a, double b, double tolerance = TOLERANCE) {return fabs(a - b) > tolerance;} +inline bool FEQ(double a, double b, double tolerance = TOLERANCE) +{ + return fabs(a - b) <= tolerance; +} +inline bool FNE(double a, double b, double tolerance = TOLERANCE) +{ + return fabs(a - b) > tolerance; +} -inline bool FEQZ(double a, double tolerance = TIGHT_TOLERANCE) {return fabs(a) <= tolerance;} -inline bool FNEZ(double a, double tolerance = TIGHT_TOLERANCE) {return fabs(a) > tolerance;} +inline bool FEQZ(double a, double tolerance = TIGHT_TOLERANCE) +{ + return fabs(a) <= tolerance; +} +inline bool FNEZ(double a, double tolerance = TIGHT_TOLERANCE) +{ + return fabs(a) > tolerance; +} #define PI 3.1415926535897932384626433832795e0 #define DegreesToRadians (PI / 180.0e0) #define RadiansToDegrees (180.0e0 / PI) #define NEARLY_ONE 0.99999999999e0 -#define CPTANGENTTOL 1.0e-04 // normalised vector crossproduct tolerance sin A so A = .0057deg +#define CPTANGENTTOL 1.0e-04 // normalised vector crossproduct tolerance sin A so A = .0057deg -#define TANTO -1 -#define ANTITANTO 1 +#define TANTO -1 +#define ANTITANTO 1 -#define TANGENT 0 +#define TANGENT 0 -#define NEARINT 1 -#define FARINT -1 +#define NEARINT 1 +#define FARINT -1 -#define LEFTINT 1 -#define RIGHTINT -1 +#define LEFTINT 1 +#define RIGHTINT -1 -#define CFILLET 0 // corner fillet -#define CHAMFER 1 // chamfer +#define CFILLET 0 // corner fillet +#define CHAMFER 1 // chamfer #define GEOFF_LEFT 1 #define NONE 0 #define GEOFF_RIGHT -1 -#define LINEAR 0 // linear -#define ACW 1 // anti-clockwise -#define CW -1 // clockwise - - const wchar_t* getMessage(const wchar_t* original); // dummy - void FAILURE(const wchar_t* str); - void FAILURE(const std::wstring& str); - - enum MESSAGE_GROUPS { - GENERAL_MESSAGES, - GEOMETRY_ERROR_MESSAGES, - PARAMSPMP - }; - - enum GENERAL_MESSAGES { - MES_TITLE = 0, - MES_UNFINISHEDCODING, - MES_ERRORFILENAME, - MES_LOGFILE, - MES_LOGFILE1, - MES_P4CMENU, - MES_P4CMENUHINT - }; - - enum GEOMETRY_ERROR_MESSAGES{ // For geometry.lib - MES_DIFFSCALE = 1000, - MES_POINTONCENTRE, - MES_INVALIDARC, - MES_LOFTUNEQUALSPANCOUNT, - MES_EQUALSPANCOUNTFAILED, - MES_CANNOTTRIMSPAN, - MES_INDEXOUTOFRANGE, - MES_BAD_VERTEX_NUMBER, - MES_BAD_REF_OFFSET, - MES_BAD_SEC_OFFSET, - MES_ROLLINGBALL4AXIS_ERROR, - MES_INPUT_EQUALSPANCOUNT, - MES_INVALIDPLANE - }; - - // homogeneous 4 x 4 Matrix class - class Matrix - { - protected: - public: - double e[16]; - bool m_unit; // true if unit matrix - int m_mirrored; // 1 if mirrored, 0 if not and -1 if unknown - - public: - // constructors etc... - Matrix(); // create a unit matrix - Matrix(double m[16]); // from an array - // Matrix(const Matrix& m); // copy constructor - - ~Matrix() {}; - - //operators - bool operator==(const Matrix &m)const; - bool operator!=(const Matrix &m)const { return !(*this == m);} - - // methods - void Unit(); // unit matrix - void Get(double* p) const; // get the matrix into p - void Put(double*p); // put p[16] into matrix - void Translate(double x, double y, double z=0); // Translation - - void Rotate(double sinang, double cosang, Vector3d *rotAxis); // Rotation about rotAxis - void Rotate(double angle, Vector3d *rotAxis); // Rotation about rotAxis - - void Rotate(double sinang, double cosang, int Axis); // Rotation with cp & dp - void Rotate(double angle, int Axis); // Rotation with angle - - void Scale(double scale); // Scale - void Scale(double scalex, double scaley, double scalez); - - void Multiply(Matrix& m); // Multiply 2 Matrices - // void Transform(Point& p); - void Transform(double p0[3]) const; // Transform p0 thro' this matrix - void Transform(double p0[3], double p1[3]) const; // Transform p0 to p1 thro' this matrix - void Transform2d(double p0[2], double p1[2]) const; // Transform p0 to p1 thro' this matrix - - int IsMirrored(); // true if matrix has a mirror transformation - int IsUnit(); // true if matrix is unit matrix - void GetTranslate(double& x, double& y, double& z) const; // get translation from matrix - void GetScale(double& sx, double& sy, double& sz) const; // get scale from matrix - bool GetScale(double& sx) const; // get scale from matrix (true if uniform scale) - void GetRotation(double& ax, double& ay, double& az) const; // get rotation from matrix - - Matrix Inverse(); // inverts this matrix - }; - - extern Matrix UnitMatrix; // a Unit Matrix - - - // 2d Point class - class Point { - friend wostream& operator << (wostream& op, Point& p); - - public: - bool ok; // true if this point is defined correctly - double x; // x value - double y; // y value - - // constructors etc... - inline Point(){x=0; y=0; ok=false;} // Point p1 - inline Point( double xord, double yord, bool okay = true) { // Point p1(10,30); - x = xord; y = yord; ok = okay;} - - // inline Point(const Point& p) - // { // copy constructor Point p1(p2); - // x = p.x; - // y = p.y; - // ok = p.ok; - // } - - Point(const Point3d& p); // copy constructor Point p1(p2); - Point(const Vector2d& v); - - // operators - bool operator==(const Point &p)const; - bool operator!=(const Point &p)const { return !(*this == p);} - inline Point operator+(const Point& p) const - { - return Point(x + p.x, y + p.y); - } // p0 = p1 + p2; - inline Point operator+=(const Point& p) - { - return Point(x += p.x, y += p.y); - } // p0 += p1; - Point operator+(const Vector2d& v) const; // p1 = p0 + v0; - - // destructor - //~Point(){}; - - // methods - Point Transform(const Matrix& m); // transform point - double Dist(const Point& p)const; // distance between 2 points - double DistSq(const Point& p)const; // distance squared - double Dist(const CLine& cl)const; // distance p to cl - Point Mid(const Point& p, double factor=.5)const; // mid point - void get(double xyz[2]) {xyz[0] = x; xyz[1] = y;} // return to array - }; - - -#define INVALID_POINT Point(9.9999999e50, 0, false) -#define INVALID_POINT3D Point3d(9.9999999e50, 0, 0, false) -#define INVALID_CLINE CLine(INVALID_POINT, 1, 0, false) -#define INVALID_CIRCLE Circle(INVALID_POINT, 0) - - // 3d point class - class Point3d { - friend wostream& operator <<(wostream& op, Point3d& p); - public: - // bool ok; // true if this point is defined correctly - double x; // x value - double y; // y value - double z; // z value - - // constructors - inline Point3d(){x = 0; y = 0; z = 0;}// {z=0; /*ok=false;*/}; // Point p1 - inline Point3d(const double* xyz) {x = xyz[0], y = xyz[1]; z = xyz[2];} - inline Point3d( double xord, double yord, double zord = 0/*, bool okay = true*/) { // Point p1(10,30.5); - x = xord; y = yord; z = zord;/* ok = okay;*/} - // copy constructor Point p1(p2); - //inline Point3d( const Point3d& p ) { - //x = p.x; y = p.y; z = p.z;[> ok = p.ok;<]} - // copy constructor Point p1(p2); - inline Point3d( const Point& p ) { - x = p.x; y = p.y; z = 0; /*ok = p.ok;*/} - // copy constructor Point p1(p2, z); - inline Point3d( const Point& p, double zord ) { - x = p.x; y = p.y; z = zord;/* ok = p.ok;*/} - Point3d(const Vector3d& v); - - // destructor -// ~Point3d(); - - // operators - bool operator==(const Point3d &p)const; - bool operator!=(const Point3d &p)const { return !(*this == p);} - Point3d operator+(const Vector3d &v)const; // p1 = p0 + v0; - - - // methods -#ifdef PEPSDLL - void ToPeps(int id, bool draw = true); // copy Point to Peps -#endif - Point3d Transform(const Matrix& m); - double Dist(const Point3d& p)const; // distance between 2 points - double DistSq(const Point3d& p)const; // distance squared between 2 points - Point3d Mid(const Point3d& p, double factor = 0.5)const; // midpoint - void get(double xyz[3]) {xyz[0] = x; xyz[1] = y; xyz[2] = z;} - double* getBuffer(){return &this->x;}; // returns ptr to data - const double* getBuffer()const{return &this->x;}; // returns ptr to data - - }; - - // 2d vector class - class Vector2d{ - friend wostream& operator <<(wostream& op, Vector2d& v); - private: - double dx, dy; - public: - - // constructors - inline Vector2d() {dx = 0; dy = 0;} - //inline Vector2d(const Vector2d &v) { dx = v.dx; dy = v.dy;} - Vector2d(const Vector3d &v); // careful - inline Vector2d(double x, double y) {dx = x, dy = y;} - inline Vector2d(const Point& p0, const Point& p1) {dx = p1.x - p0.x; dy = p1.y - p0.y;} - inline Vector2d(const Point *p0, const Point *p1) {dx = p1->x - p0->x; dy = p1->y - p0->y;} - inline Vector2d(const Point& p) { dx = p.x; dy = p.y;} // from 0,0 to p - inline Vector2d(double angle) {dx = cos(angle *= DegreesToRadians); dy = sin(angle);} // constructs a vector from an angle (0° - 360°) - - - // operators - // inline const Vector2d& operator=(const Vector2d& v) - // { - // dx = v.dx; - // dy = v.dy; - // return *this; - // } // v1 = v2; - inline Vector2d operator+(const Vector2d& v) const - { - return Vector2d(dx + v.dx, dy + v.dy); - } // v2 = v0 + v1; - inline Point operator+(const Point& p) const - { - return Point(this->dx + p.x, this->dy + p.y); - } // p1 = v0 + p0; - inline Vector2d operator+(const double d) - { - return Vector2d(dx + d, dy + d); - }; - - inline const Vector2d& operator+=(const Vector2d &v){dx += v.dx; dy += v.dy; return *this;} // v1 += v0; - inline Vector2d operator-(const Vector2d &v)const{return Vector2d( dx - v.dx, dy - v.dy);} // v2 = v0 - v1; - inline const Vector2d& operator-=(const Vector2d &v){dx -= v.dx; dy -= v.dy; return *this;} // v1 -= v0; - inline Vector2d operator-(const double d){ return Vector2d(dx - d, dy - d); }; - - inline const Vector2d operator-(void)const{return Vector2d(-dx, -dy);} // v1 = -v0; (unary minus) - - inline double operator*(const Vector2d &v)const{return (dx * v.dx + dy * v.dy);} // dot product m0.m1.cos a = v0 * v1 - inline Vector2d operator*(double c)const{return Vector2d(dx*c, dy*c);} // scalar product - inline const Vector2d& operator*=(double c){dx *= c; dy *= c; return *this;} // scalar product - inline Vector2d operator*(int c)const{return Vector2d(dx*(double)c, dy*(double)c);} // scalar product - - inline double operator^(const Vector2d &v)const{return (dx * v.dy - dy * v.dx);} // cross product m0.m1.sin a = v0 ^ v1 - inline Vector2d operator~(void)const{return Vector2d(-dy, dx);} // perp to left - - bool operator==(const Vector2d &v)const; // v1 == v2 - inline bool operator!=(const Vector2d &v)const { return !(*this == v);} // v1 != v2 - - - - // methods - void get(double xyz[2]) {xyz[0] = dx; xyz[1] = dy;} // return to array - inline double getx()const{return dx;} - inline double gety()const{return dy;} - inline void putx(double x){dx = x;} - inline void puty(double y){dy = y;} - double normalise() - {double m = magnitude(); if(m < TIGHT_TOLERANCE) {dx=dy=0; return 0;} dx/=m; dy/=m; return m;} // normalise & returns magnitude - inline double magnitudesqd(void) const - { - return (dx * dx + dy * dy); - } // magnitude squared - inline double magnitude(void)const{return(sqrt(magnitudesqd()));} // magnitude - void Rotate(double cosa, double sina){ // rotate vector by angle - double temp = -dy * sina + dx * cosa; - dy = dx * sina + cosa * dy; - dx = temp; - } - inline void Rotate(double angle) { if(FEQZ(angle) == true) return; Rotate(cos(angle), sin(angle));} - void Transform( const Matrix& m); // transform vector - - // destructor - //~Vector2d(){} - - }; - - - // 3d vector class - class Vector3d{ - friend wostream& operator <<(wostream& op, Vector3d& v); - private: - double dx, dy, dz; - public: - - // constructors - Vector3d() {dx = 0; dy = 0; dz = 0;} - //Vector3d(const Vector3d &v) { dx = v.dx; dy = v.dy; dz = v.dz;} - Vector3d(double x, double y, double z = 0) {dx = x, dy = y; dz = z;} - Vector3d(const double* x) {dx = x[0], dy = x[1]; dz = x[2];} - Vector3d(const double* x0, const double* x1) {dx = x1[0] - x0[0], dy = x1[1] - x0[1]; dz = x1[2] - x0[2];} - Vector3d(const Point3d& p0, const Point3d& p1) {dx = p1.x - p0.x; dy = p1.y - p0.y; dz = p1.z - p0.z;} - Vector3d(const Point3d& p) { dx = p.x; dy = p.y; dz = p.z;} // from 0,0,0 to p - Vector3d(const Vector2d& v) {dx = v.getx(); dy = v.gety(); dz = 0;} - - // operators - bool operator==(const Vector3d& v) const - { - return (FEQ(dx, v.dx, UNIT_VECTOR_TOLERANCE) && FEQ(dy, v.dy, UNIT_VECTOR_TOLERANCE) - && FEQ(dz, v.dz, UNIT_VECTOR_TOLERANCE)); - } // v1 == v2 (unit only!) - bool operator!=(const Vector3d& v) const - { - return (!(*this == v)); - } // v1 != v2 - // const Vector3d& operator=(const Vector3d& v) - // { - // dx = v.dx; - // dy = v.dy; - // dz = v.dz; - // return *this; - // } // v1 = v2; - // const Vector3d& operator=(const Vector2d& v) - // { - // dx = v.getx(); - // dy = v.gety(); - // dz = 0.0; - // return *this; - // } // v1 = v2; - inline Point3d operator+(const Point3d& p) const - { - return Point3d(dx + p.x, dy + p.y, dz + p.z); - } // p1 = v0 + p0; - Vector3d operator+(const Vector3d& v) const - { - return Vector3d(dx + v.dx, dy + v.dy, dz + v.dz); - } // v2 = v0 + v1; - const Vector3d& operator+=(const Vector3d& v) - { - dx += v.dx; - dy += v.dy; - dz += v.dz; - return *this; - } // v1 += v0; - Vector3d operator-(const Vector3d& v) const - { - return Vector3d(dx - v.dx, dy - v.dy, dz - v.dz); - } // v2 = v0 - v1; - const Vector3d& operator-=(const Vector3d &v){ - dx -= v.dx; dy -= v.dy; dz -= v.dz; return *this;} // v1 -= v0; - - const Vector3d operator-(void)const{return Vector3d(-dx, -dy, -dz);} // v1 = -v0; (unary minus) - - double operator*(const Vector3d &v)const{return (dx * v.dx + dy * v.dy + dz * v.dz);} // dot product m0 m1 cos a = v0 * v1 - - const Vector3d& operator*=(double c){dx *= c; dy *= c; dz *= c; return *this;} // scalar products - friend const Vector3d operator*(const Vector3d &v, double c){return Vector3d(v.dx*c, v.dy*c, v.dz*c);} - friend const Vector3d operator*(double c, const Vector3d &v){return Vector3d(v.dx*c, v.dy*c, v.dz*c);} - friend const Vector3d operator/(const Vector3d &v, double c){return Vector3d(v.dx/c, v.dy/c, v.dz/c);} - - const Vector3d operator^(const Vector3d &v)const{ - return Vector3d(dy * v.dz - dz * v.dy, dz * v.dx - dx * v.dz, dx * v.dy - dy * v.dx);} // cross product vector - - // = the vector perp to the plane of the 2 vectors - // the z component magnitude is m0.m1.sin a - // methods - inline void get(double xyz[3])const {xyz[0] = dx; xyz[1] = dy; xyz[2] = dz;} // return to array - inline double getx()const{return dx;} - inline double gety()const{return dy;} - inline double getz()const{return dz;} - inline void putx(double x){dx = x;} - inline void puty(double y){dy = y;} - inline void putz(double z){dz = z;} - double normalise(){double m = magnitude(); if(m < 1.0e-09) {dx=dy=dz=0; return 0;} dx/=m; dy/=m; dz/=m; // normalise & returns magnitude - return m;} - inline double magnitude(void) const - { - return (sqrt(dx * dx + dy * dy + dz * dz)); - } // magnitude - inline double magnitudeSq(void) const - { - return (dx * dx + dy * dy + dz * dz); - } // magnitude squared - void Transform( const Matrix& m); // transform vector - void arbitrary_axes(Vector3d& x, Vector3d& y); - int setCartesianAxes(Vector3d& b, Vector3d& c); - double* getBuffer(){return &this->dx;}; // returns ptr to data - const double* getBuffer()const{return &this->dx;}; // returns ptr to data - - // destructor - //~Vector3d(){} - - }; - -#define ORIGIN Point3d(0,0,0) -#define NULL_VECTOR Vector3d(0,0,0) -#define Z_VECTOR Vector3d(0,0,1) -#define Y_VECTOR Vector3d(0,1,0) -#define X_VECTOR Vector3d(1,0,0) - - // 2D cline x = x0 + t * dx; y = y0 + t * dy - class CLine{ - friend wostream& operator <<(wostream& op, CLine& cl); - public: - bool ok; - Point p; - Vector2d v; - - // constructors - inline CLine() {ok = false;}; - inline CLine(const Point& p0, double dx, double dy, bool normalise = true){ p = p0; v = Vector2d(dx, dy); if(normalise) Normalise();}; - inline CLine(const Point& p0, const Vector2d& v0, bool normalise = true) {p = p0; v = v0; if(normalise) Normalise();}; - // inline CLine(const CLine& s) - // { - // p = s.p; - // v = s.v; - // ok = s.ok; - // } // copy constructor CLine s1(s2); - inline CLine(const Point& p0, const Point& p1) {p = p0; v = Vector2d(p0, p1); Normalise();}; - CLine(const Span& sp); - - // operators - const CLine operator~(void);// perp to left - const CLine& operator=(const Point& p0){p.x=p0.x; p.y=p0.y; return *this;}; // s = p; - - // methods - double c(); // returns c - void Normalise(); // normalise dx,dy -#ifdef PEPSDLL - void ToPeps(int id, bool draw = true); // to Peps - void DelPeps(int id); // delete Peps CLine -#endif - CLine Transform(Matrix& m); // transform a CLine - Point Intof(const CLine& s); // intersection of 2 clines - Point Intof(int NF, const Circle& c); // intersection of cline & circle - Point Intof(int NF, const Circle& c, Point& otherInters); double Dist(const Point& p1)const; // ditto & other intersection - CLine Bisector(const CLine& s); // Bisector of 2 Clines - - // destructor -// ~CLine(); - }; - -#define HORIZ_CLINE CLine(geoff_geometry::Point(0,0), 1.0, 0.0, true) - - - // 2D circle - class Circle{ - friend wostream& operator <<(wostream& op, Circle& c); - public: - bool ok; - Point pc; - double radius; - - // constructors etc... - inline Circle() - { - ok = false; - radius = 0; - } - Circle(const Point& p, double r); // Circle c1(Point(10,30), 20); - Circle(const Point& p, const Point& pc); // Circle c1(p[222], p[223]); - // Circle(const Circle& c) - // { - // *this = c; - // } // copy constructor Circle c1(c2); - Circle(const Span& sp); // constructor - - // methods -#ifdef PEPSDLL - void ToPeps(int id, bool draw = true); // to Peps - void DelPeps(int id); // delete Peps Circle -#endif - bool operator==(const Circle &c)const; // c == cc - bool operator!=(const Circle &c)const { return !(*this == c);} - Circle Transform(Matrix& m); // transform a Circle - Point Intof(int LR, const Circle& c1); // intof 2 circles - Point Intof(int LR, const Circle& c1, Point& otherInters); // intof 2 circles, (returns the other intersection) - int Intof(const Circle& c1, Point& leftInters, Point& rightInters); // intof 2 circles (returns number of intersections & left/right inters) - CLine Tanto(int AT, double angle, const CLine& s0)const; // a cline tanto this circle at angle - // ~Circle(); // destructor - }; - - // 2d box class - class Box{ - public: - Point min; - Point max; - bool ok; - - Box() { min.x = min.y = 1.0e61; max.x = max.y = -1.0e61; ok = false;}; - Box(Point& pmin, Point& pmax) { min = pmin; max = pmax; ok = true;}; - - bool outside(const Box& b)const; // returns true if box is outside box - void combine(const Box& b); // combines this with b - }; - - // 3d box class - class Box3d{ - public: - Point3d min; - Point3d max; - bool ok; - - Box3d() { min.x = min.y = min.z = 1.0e61; max.x = max.y = max.z = -1.0e61; ok = false;}; - Box3d(const Point3d& pmin, const Point3d& pmax) { min = pmin; max = pmax; ok = true;}; - - bool outside(const Box3d& b)const; // returns true if box is outside box - void combine(const Box3d& b); // combines this with b - }; - - inline void MinMax(const Point& p, Point& pmin, Point& pmax) { - if(p.x > pmax.x) pmax.x = p.x; - if(p.y > pmax.y) pmax.y = p.y; - if(p.x < pmin.x) pmin.x = p.x; - if(p.y < pmin.y) pmin.y = p.y; - } - - inline void MinMax(const Point3d& p, Point3d& pmin, Point3d& pmax) { - if(p.x > pmax.x) pmax.x = p.x; - if(p.y > pmax.y) pmax.y = p.y; - if(p.z > pmax.z) pmax.z = p.z; - if(p.x < pmin.x) pmin.x = p.x; - if(p.y < pmin.y) pmin.y = p.y; - if(p.z < pmin.z) pmin.z = p.z; - } - - - - - // 2D line arc span - class Span{ - friend wostream& operator <<(wostream& op, Span& span); - public: - Point p0; // start - Point p1; // end - Point pc; // centre - int dir; // arc direction (CW or ACW or 0 for straight) - int ID; // ID (for offset in wire - stores spanID etc. from original kurve) - bool ok; - - bool returnSpanProperties; // set if properties below are set - Vector2d vs; // direction at start or for straight - Vector2d ve; // direction at span end - - double length; // span length - double radius; // arc radius - double angle; // included arc angle ( now arc is parameterised start -> start + angle - - Box box; // span box - - bool NullSpan; // true if small span - - // methods - void SetProperties(bool returnProperties); // set span properties - Span Offset(double offset); // offset span method - int Split(double tolerance); // returns number of splits - void SplitMatrix(int num_vectors, Matrix* matrix); // returns incremental matrix from split - void minmax(Box& box, bool start = true); // minmax of span - void minmax(Point& pmin, Point& pmax, bool start = true); // minmax of span - int Intof(const Span& sp, Point& pInt1, Point& pInt2, double t[4])const; - void Transform(const Matrix& m, bool setprops = true); - Point Near(const Point& p)const; // returns the near point to span from p (on or off) - Point NearOn(const Point& p)const; // returns the near point to span from p (on span) - Point Mid()const; // midpoint of a span - Point MidPerim(double d)const; // interior point of Span (param 0 - d) - Point MidParam(double param)const; // interior point of Span (param 0 - 1) - bool OnSpan(const Point& p)const; // tests if p is on sp *** FAST TEST p MUST LIE on unbounded span - bool OnSpan(const Point& p, double* t)const; // tests if p is on sp *** FAST TEST p MUST LIE on unbounded span - bool JoinSeparateSpans(Span& sp); - Span BlendTwoSpans(Span& sp2, double radius, double maxt); // Blends 2 Spans - bool isJoinable(const Span& sp)const; // is this & sp joinable to 1 span? - Vector2d GetVector(double fraction)const; // the direction along the span, 0.0 for start, 1.0 for end - - // constructor - Span() {dir = 0; ID = 0; ok = false; returnSpanProperties = false; length = 0; radius = 0; angle = 0; NullSpan = false;} - Span(int spandir, const Point& pn, const Point& pf, const Point& c) { dir = spandir; p0 = pn, p1 = pf, pc = c; ID = 0; SetProperties(true); ok = p0.ok;}; - - // operators - // bool operator==(const Span &sp)const; - // bool operator!=(const Span &sp)const { return !(*this == sp);} - }; - - // general - double atn360(double dx, double dy); // angle 0 to 2pi - - // distance functions - // double Dist(double px, double py, double p1x, double p1y); // distance between 2 points (2d) - // double Dist(Point& p0, Point& p1); // distance between 2 points (3d) - // double Dist(CLine& s, Point& p1); // distance between cline & point - - double Dist(const Point3d *p, const Vector3d *vl, const Point3d *pf); // distance from line (p, vl) and pf - double DistSq(const Point3d *p, const Vector3d *vl, const Point3d *pf); // distance squared from line (p, vl) and pf - double Dist(const Circle& c, const Point& p); // distance between c & p - double Dist(const Point& p0, const Circle& c, const Point& p1); // clockwise distance around c from p0 to p1 - double Dist(const CLine& s, const Circle& c); // distance between line and circle - double Dist(const Circle& c0, const Circle& c1); // distance between 2 circles - double IncludedAngle(const Vector2d& v0, const Vector2d& v1, int dir = 1); // angle between 2 vectors - double IncludedAngle(const Vector3d& v0, const Vector3d& v1, const Vector3d& normal, int dir = 1); - inline double IncludedAngle(const CLine& s0, const CLine& s1, int dir = 1) { // angle between 2 Clines - return IncludedAngle(s0.v, s1.v, dir); - } - - - // point definitions - Point Mid(const Point& p0, const Point& p1, double factor = 0.5); // midpoint - Point Mid(const Span& sp); // midpoint of a span - Point Rel(const Point& p, double x, double y); // relative point - Point Polar(const Point& p, double angle, double r); // polar from this point - Point AtAngle(const Circle& c, double angle); // Point at angle on a circle - Point XonCLine(const CLine& s, double xval); // returns point that has X on this line - Point YonCLine(const CLine& s, double yval); // returns point that has Y on this line - Point Intof(const CLine& s0, const CLine& s1); // intof 2 clines - Point Intof(int NF, const CLine& s, const Circle& c); // intof of circle & a cline - Point Intof(int NF, const CLine& s, const Circle& c, Point& otherInters); // intof of circle & a cline (returns the other intersection) - Point Intof(int LR, const Circle& c0, const Circle& c1); // intof 2 circles - Point Intof(int LR, const Circle& c0, const Circle& c1, Point& otherInters); // intof 2 circles, (returns the other intersection) - int Intof(const Circle& c0, const Circle& c1, Point& pLeft, Point& pRight); // ditto - Point Along(const CLine& s, double d); // distance along Cline - Point Along(const CLine& s, double d, const Point& p); // distance along Cline from point - Point Around(const Circle& c, double d, const Point& p); // distance around a circle from point - Point On(const CLine& s, const Point& p); // returns a point on s nearest to p - Point On(const Circle& c, const Point& p); // returns a point on c nearest to p - - // cline definitions - - CLine AtAngle(double angle, const Point& p, const CLine& s = HORIZ_CLINE); // cline at angle to line thro' point - CLine Tanto(int AT, const Circle& c, double angle, const CLine& s0 = HORIZ_CLINE);// cline tanto circle at angle to optional cline - CLine Tanto(int AT, const Circle& c, const Point& p); // cline tanto circle thro' a point - CLine Tanto(int AT0, const Circle& c0, int AT1, const Circle& c1); // cline tanto 2 circles - CLine Normal(const CLine& s); // noirmal to cline - CLine Normal(const CLine& s, const Point& p); // normal to cline thro' p - CLine Parallel(int LR, const CLine& s, double distance); // parallel to cline by distance - CLine Parallel(const CLine& cl, const Point& p); // parallel to cline thro' a point - - - // circle definitions - Circle Thro(const Point& p0, const Point& p1); // circle thro 2 points (diametric) - Circle Thro(const Point& p0, const Point& p1, const Point& p2); // circle thro 3 points - Circle Tanto(int NF, const CLine& s0, const Point& p, double rad); // circle tanto a CLine thro' a point with radius - Circle Thro(int LR, const Point& p0, const Point& p1, double rad); // circle thro' 2 points with radius - Circle Tanto(int AT1, const CLine& s1, int AT2, const CLine& s2, double rad); // circle tanto 2 clines with radius - Circle Tanto(int AT1, const CLine& s1, int AT2, const CLine& s2, int AT3, const CLine& s3); // circle tanto 3 clines - Circle Tanto(int LR, int AT, const Circle& c, const Point& p, double rad); // circle tanto circle & thro' a point - Circle Tanto(int NF, int AT0, const CLine& s0, int AT1, const Circle& c1, double rad);// circle tanto cline & circle with radius - Circle Tanto(int LR, int AT0, const Circle& c0, int AT1, const Circle& c1, double rad);// circle tanto 2 circles with radius - Circle Tanto(int LR, int AT1 , const Circle& c1 , int AT2 , const Circle& c2, int AT3 , const Circle c3); // tanto 3 circles - int apolloniusProblem(int AT1 , const Circle& c1 , int AT2 , const Circle& c2, int AT3 , const Circle& c3, Circle& Solution1, Circle& Solution2); - int apolloniusProblem(int AT1 , const Circle& c1 , int AT2 , const Circle& c2, int AT3 , const CLine& cl3, Circle& Solution1, Circle& Solution2); - int apolloniusProblem(int AT1 , const Circle& c1 , int AT2 , const CLine& cl2, int AT3 , const CLine& cl3, Circle& Solution1, Circle& Solution2); - - // Circle Tanto(int AT0, - // int NF, - // int AT1, - // CLine s1, - // int AT2, - // CLine s2); // circle tanto circle, and 2 clines - Circle Parallel(int LR, const Circle& c, double distance); // parallel to circle by a distance - - - // misc - inline double Radians(double degrees) {return degrees * PI / 180;} - inline double Degrees(double radians) { return radians * 180 / PI;} - int quadratic(double a, double b, double c, double& x0, double& x1); // solve quadratic - - int corner(const Vector2d& v0, const Vector2d& v1, double cpTol = CPTANGENTTOL); // corner (TANGENT, LEFT, RIGHT) - inline int corner(const Span& span, const Span& next, double cpTol = CPTANGENTTOL) { - return corner((Vector2d)span.ve, (Vector2d)next.vs, cpTol);} - - Line IsPtsLine(const double* a, int n, double tolerance, double* deviation); -// Span3d IsPtsSpan3d(const double* a, int n, double tolerance, double* deviation); - - class Plane { - friend wostream& operator <<(wostream& op, Plane& pl); - - public: // ax + by + cz + d = 0 - bool ok; - double d; // distance of plane to origin - Vector3d normal; // normal to plane a = n.dx, b = n.dy, c = n.dz - // constructors - Plane(){ok = false; d = 0;} - Plane(double dist, const Vector3d& n); - Plane(const Point3d& p0, const Point3d& p1, const Point3d& p2); - Plane(const Point3d& p0, const Vector3d& n, bool normalise = true); - - // methods - double Dist(const Point3d& p)const; // signed distance of point to plane - bool Intof(const Line& l, Point3d& intof, double& t)const; // intersection of plane & line (0 >= t <= 1 if intersect within line) - bool Intof(const Plane& pl, Line& intof)const; // intersection of 2 planes - bool Intof(const Plane& pl0, const Plane& pl1, Point3d& intof)const; // intersection of 3 planes - Point3d Near(const Point3d& p)const; // returns near point to p on the plane - void Mirrored(Matrix* m); // returns a matrix for a mirror about this - }; - - - - -#define SPANSTORAGE 32 // lessens number of object pointers - - class spVertex { - friend wostream& operator <<(wostream& op, spVertex& sp); - - public: - int type; - int spanid; - Point p; - Point pc; - spVertex(){type = 0; spanid = 0;} - spVertex(int t, const Point& point, const Point& centre): type(t), spanid(0), p(point), pc(centre){}; - - bool operator==(spVertex &spv){ - // vertex == spvertex (vertex check - doesn't check spannid!) - if(this->type != spv.type) return false; - if(this->p != spv.p) return false; - if(this->type != LINEAR) { - if(this->pc != spv.pc) return false; - } - return true; - } - - bool operator!=(spVertex &spv){ return !(*this == spv);} - - }; - - - class SpanDataObject { - // holds everything needed for Post-Processing/Simulation - public: - int method; // holds method type - - SpanDataObject(int meth){method = meth;}; - SpanDataObject(const SpanDataObject* obj){method = obj->method;}; - }; - - class SpanVertex{ - public: - int type[SPANSTORAGE]; // LINEAR CW or ACW // 0 straight (cw = -1 (T) acw = 1 (A) ) - int spanid[SPANSTORAGE]; // identification (eg wire offset span info) - const SpanDataObject* index[SPANSTORAGE]; // other - pointer to - double x[SPANSTORAGE], y[SPANSTORAGE]; // vertex - double xc[SPANSTORAGE], yc[SPANSTORAGE]; // centre of arc - public: - // methods - void Add(int offset, int type, const Point& p0, const Point& pc, int ID = UNMARKED); - const SpanDataObject* GetIndex(int offset)const; - void AddSpanID(int offset, int ID); - SpanVertex(); - ~SpanVertex(); - const SpanVertex& operator= (const SpanVertex& spv ); - - void Add(int offset, const SpanDataObject* Index ); - const SpanDataObject* Get(int offset); - int Get(int offset, Point& pe, Point& pc); - int GetSpanID(int offset); - }; - - - - - -#ifdef _MSC_VER -#pragma warning(disable:4522) -#endif - - class Kurve : public Matrix{ - friend wofstream& operator << (wofstream& op, Kurve& k); - friend wifstream& operator >> (wifstream& op, Kurve& k); - - protected: - vector m_spans; - bool m_started; - int m_nVertices; // number of vertices in Kurve - bool m_isReversed; // true if get spans reversed - - public: - // for comparing kurves - struct spanCompare { - int dir; // LINEAR, CW or ACW - double length; // length of the span - double cp; // cross-product to next span (sina) - double dp; - }; - // constructors etc... - Kurve() { - m_started = false; - m_nVertices = 0; - m_isReversed = false; - }; - Kurve(const Kurve& k0); - const Kurve& operator= (const Kurve& k ); - const Kurve& operator=(const Matrix &m); - - bool operator==(const Kurve &k)const; // k == kk (vertex check) - bool operator!=(const Kurve &k)const { return !(*this == k);} - - - // destructor - ~Kurve(); - - // methods - inline int nSpans() const - { - return (m_nVertices) ? m_nVertices - 1 : 0; - } // returns the number of spans - bool Closed() const; // returns true if kurve is closed - inline bool Started()const {return m_started;}; - void FullCircle(int dir, const Point& c, double radius); // make a full circle - void Start(); // start a new kurve - void Start(const Point& p); // start a new kurve with start point - bool Add(const spVertex& spv, bool AddNullSpans = true); // add a vertex - void Get(int vertex, spVertex& spv) const; // get a vertex - bool Add(const Span& sp, bool AddNullSpans = true); // add a span - bool Add(int type, const Point& p0, const Point& pc, bool AddNullSpans = true); // a span - void AddSpanID(int ID); - bool Add(const Point& p0, bool AddNullSpans = true); // linear - void Add(); // add a null span - void Add(const Kurve* k, bool AddNullSpans = true); // a kurve - void StoreAllSpans(std::vector& kSpans)const; // store all kurve spans in array, normally when fast access is reqd - void Clear(); // remove all the spans - - void Replace(int vertexnumber, const spVertex& spv); - void Replace(int vertexnumber, int type, const Point& p, const Point& pc, int ID = UNMARKED); - int GetSpanID(int spanVertexNumber) const; // for spanID (wire offset) - int Get(int spanVertexNumber, Point& p, Point& pc) const; - void Get(std::vector *all, bool ignoreNullSpans) const; // get all spans to vector - int Get(int spanVertexNumber, Point3d& p, Point3d& pc) const - { Point p2d, pc2d; int d = Get(spanVertexNumber, p2d, pc2d); p = p2d; pc = pc2d; return d;} - int Get(int spannumber, Span& sp, bool returnSpanProperties = false, bool transform = false) const; - // int Get(int spannumber, - // Span3d& sp, - // bool returnSpanProperties = false, - // bool transform = false) const; - void Get(Point &ps,Point &pe) const; // returns the start- and endpoint of the kurve - const SpanDataObject* GetIndex(int vertexNumber)const; - inline double GetLength()const{ return Perim();}; // returns the length of a kurve - - void minmax(Point& pmin, Point& pmax); // minmax of span - void minmax(Box& b); - - Point NearToVertex(const Point& p, int& nearSpanNumber)const; - Point NearToVertex(const Point& p)const { int nearSpanNumber; return NearToVertex(p, nearSpanNumber);}; - Point Near(const Point& p, int& nearSpanNumber)const; - Point Near(const Point& p) const{ int nearSpanNumber; return Near(p, nearSpanNumber);}; - double Perim()const; // perimeter of kurve - double Area()const; // area of closed kurve - void Reverse(); // reverse kurve direction - obsolete - bool Reverse(bool isReversed) { // reverse kurve direction - later better method - bool tmp = m_isReversed; - m_isReversed = isReversed; - return tmp; - }; - int Reduce(double tolerance); // reduce spans which are in tolerance - - int Offset(vector &OffsetKurves, double offset, int direction, int method, int& ret)const; // offset methods - int OffsetMethod1(Kurve& kOffset, double off, int direction, int method, int& ret)const; - int OffsetISOMethod(Kurve& kOffset, double off, int direction, bool BlendAll)const; // special offset (ISO radius - no span elimination) - int Intof(const Span& sp, vector& p)const; // intof span - int Intof(const Kurve&k, vector& p)const; // intof kurve - bool Compare(const Kurve* k, Matrix* m, bool bAllowMirror = true)const; // compare 2 Kurves - void ChangeStart(const Point *pNewStart, int startSpanno); // change the Kurve's startpoint - void ChangeEnd(const Point *pNewEnd, int endSpanno); // change the Kurve's endpoint - - private: - bool compareKurves(const std::vector &first, const std::vector &second, int &nOffset/*, Kurve *k, Matrix *m*/)const; - bool calculateMatrix(const Kurve *k, Matrix *m, int nOffset, bool bMirror = false)const; - public: - - - void AddIndex(int vertexNumber, const SpanDataObject* data); - bool Split(double MaximumRadius, double reslution); // split arcs larger than MaximumRadius to resolution - int IntExtWire( Kurve& kSec, double Ref, double Sec, double height, Kurve* kOut); // interpolate / extrapolate a mid height kurve (wire) - void SetZ(double z) { e[11] = z; if(fabs(z) > 1.0e-6) m_unit = false;} // assigns kurve to fixed height (wire) - - void Part(int startVertex, int EndVertex, Kurve *part); - Kurve Part(int fromSpanno, const Point& fromPt, int toSpanno, const Point& toPt); // make a Part Kurve - int Break(double atParam, const Kurve *secInput, Kurve *refOut, Kurve *secOut);// break kurve perimeter parameterisation with synchronised Kurve (wire) - void Part(double fromParam, double toParam, const Kurve *secInput, Kurve *refOut, Kurve *secOut);// part kurve perimeter parameterisation with synchronised Kurve (wire) - Kurve Part(double fromParam, double toParam); // part kurve perimeter parameterisation - void AddSections(const Kurve* k, bool endOfSection); // special add kurves for rollingball - void AddEllipse(int dir, const Point& pStart, const Point& pEnd, const Point& pCentre, const Vector2d& majorAxis, double majorRadius, double minorRadius, double tolerance); - // void Kurve::AddEllipse(int dir, - // Plane* plEllipse, - // Vector3d* cylAxis, - // Point3d* cylCentre, - // double cylradius, - // Point3d* pStart, - // Point3d* pEnd, - // double tolerance); // elliptical curve - biarc in tolerance - - void Spiral(const Point& centre, double startAngle, double startRadius, double radiusRisePerRevolution, double endRadius); -#ifdef PARASOLID - int ToPKcurve(PK_CURVE_t *curves, PK_INTERVAL_t *ranges, int start_spanno, int n_spans); // Convert to PK Curve - - PK_BODY_t ToPKwire(); // Convert to PK Wire Body - PK_BODY_t ToPKwire(int start_spanno, int n_spans); - - PK_BODY_t ToPKsheet( ); // Convert to PK Sheet Body - PK_BODY_t ToPKextrudedBody(PK_VECTOR1_t path, bool solidbody = true); - // Convert to PK Body (open kurve >> sheet) - PK_BODY_t ToPKlofted_sheet_body(Kurve &sec); // Convert 2 kurves to lofted sheet body - PK_BODY_t ToPKlofted_thickened_body(Kurve &sec, double thickness); -#endif - }; -#ifdef _MSC_VER -#pragma warning(default:4522) -#endif - - void tangential_arc(const Point &p0, const Point &p1, const Vector2d &v0, Point &c, int &dir); - - int EqualiseSpanCount(Kurve& k1, Kurve& k2, Kurve& k1equal, Kurve& k2equal, bool equalise_same_span_count); // span count equalisation - void EqualiseSpanCountAfterOffset(Kurve& k1, Kurve&k2, Kurve& k1Out, Kurve& k2Out);// span equalisation after offset - void EqualiseSpanCountAfterOffsetFromRollAround(Kurve& k1, Kurve&k2, Kurve& k1Out, Kurve& k2Out/*, double offset, int arc_direction*/);// span equalisation after offset - - Point IntofIso(Span& one, Span& two, Span& three); // for iso blend radiuses - calc intersection - - inline double CPTOL(double offset, double maxOffset) { - // this returns a suitable tolerance for a cross product - // the cp for normalised vectors is the sin of the included angle between the vectors - // - // this function takes the machine resolution from RESOLUTION - - offset = fabs(offset); - - if(offset <= RESOLUTION) offset = maxOffset; // no known offset so guess one from the application - - return RESOLUTION / offset; - } - - - - // finite Span routines - int Intof(const Span& sp0 , const Span& sp1, Point& p0, Point& p1, double t[4]); - int LineLineIntof(const Span& L0 , const Span& L1, Point& p, double t[2]); - int LineArcIntof(const Span& line, const Span& arc, Point& p0, Point& p1, double t[4]); - int ArcArcIntof(const Span& arc0, const Span& arc1, Point& pLeft, Point& pRight); - - bool OnSpan(const Span& sp, const Point& p); - bool OnSpan(const Span& sp, const Point& p, bool nearPoints, Point& pNear, Point& pOnSpan); // function returns true if pNear == pOnSpan - // pNear (nearest on unbound span) - // pOnSpan (nearest on finite span) - - - int Intof(const Line& v0, const Line& v1, Point3d& intof); // intof 2 lines - double Dist(const Line& l, const Point3d& p, Point3d& pnear, double& t); // distance from a point to a line - Point3d Near(const Line& l, const Point3d& p, double& t ); // near point to a line & t in 0-length range - double Dist(const Span& sp, const Point& p , Point& pnear ); // distance from p to sp, nearpoint returned as pnear - -// Kurve splineUsingBiarc(CLine& cl0, CLine& cl1, std::vector); - - int biarc(CLine& cl0, CLine& cl1, Span* sp0, Span* sp1 ); - - // 3d line segment - class Line{ - public: - Point3d p0; // start - Vector3d v; // vector (not normalised) - double length; // line length - Box3d box; - bool ok; - - // constructors - Line() {ok = false; length = 0;} - Line(const Point3d& p0, const Vector3d& v0, bool boxed = true); - Line(const Point3d& p0, const Point3d& p1); - Line(const Span& sp); - - // methods - void minmax(); - Point3d Near(const Point3d& p, - double& t) const; // near point to line from point (0 >= t <= 1) in range - int Intof(const Line& l, Point3d& intof) const - { - return geoff_geometry::Intof(*this, l, intof); - }; // intof 2 lines - bool atZ(double z, Point3d& p) const; // returns p at z on line - bool Shortest(const Line& l2, - Line& lshort, - double& t1, - double& t2) const; // calculate shortest line between this & l2 - }; - - -class Triangle3d { - Point3d vert1; // first vertex - Point3d vert2; // second vertex - Point3d vert3; // third vertex - Vector3d v0; // vector from vert1 to vert2 - Vector3d v1; // vector from vert1 to vert3 - bool ok; - - Box3d box; // box around triangle +#define LINEAR 0 // linear +#define ACW 1 // anti-clockwise +#define CW -1 // clockwise + +const wchar_t* getMessage(const wchar_t* original); // dummy +void FAILURE(const wchar_t* str); +void FAILURE(const std::wstring& str); + +enum MESSAGE_GROUPS +{ + GENERAL_MESSAGES, + GEOMETRY_ERROR_MESSAGES, + PARAMSPMP +}; + +enum GENERAL_MESSAGES +{ + MES_TITLE = 0, + MES_UNFINISHEDCODING, + MES_ERRORFILENAME, + MES_LOGFILE, + MES_LOGFILE1, + MES_P4CMENU, + MES_P4CMENUHINT +}; + +enum GEOMETRY_ERROR_MESSAGES +{ // For geometry.lib + MES_DIFFSCALE = 1000, + MES_POINTONCENTRE, + MES_INVALIDARC, + MES_LOFTUNEQUALSPANCOUNT, + MES_EQUALSPANCOUNTFAILED, + MES_CANNOTTRIMSPAN, + MES_INDEXOUTOFRANGE, + MES_BAD_VERTEX_NUMBER, + MES_BAD_REF_OFFSET, + MES_BAD_SEC_OFFSET, + MES_ROLLINGBALL4AXIS_ERROR, + MES_INPUT_EQUALSPANCOUNT, + MES_INVALIDPLANE +}; + +// homogeneous 4 x 4 Matrix class +class Matrix +{ +protected: +public: + double e[16]; + bool m_unit; // true if unit matrix + int m_mirrored; // 1 if mirrored, 0 if not and -1 if unknown public: - // constructor - Triangle3d(){ ok = false;}; - Triangle3d(const Point3d& vert1, const Point3d& vert2, const Point3d& vert3); + // constructors etc... + Matrix(); // create a unit matrix + Matrix(double m[16]); // from an array + // Matrix(const Matrix& m); // copy constructor - // methods - bool Intof(const Line& l, Point3d& intof)const; // returns intersection triangle to line + ~Matrix() {}; + + // operators + bool operator==(const Matrix& m) const; + bool operator!=(const Matrix& m) const + { + return !(*this == m); + } + + // methods + void Unit(); // unit matrix + void Get(double* p) const; // get the matrix into p + void Put(double* p); // put p[16] into matrix + void Translate(double x, double y, double z = 0); // Translation + + void Rotate(double sinang, double cosang, Vector3d* rotAxis); // Rotation about rotAxis + void Rotate(double angle, Vector3d* rotAxis); // Rotation about rotAxis + + void Rotate(double sinang, double cosang, int Axis); // Rotation with cp & dp + void Rotate(double angle, int Axis); // Rotation with angle + + void Scale(double scale); // Scale + void Scale(double scalex, double scaley, double scalez); + + void Multiply(Matrix& m); // Multiply 2 Matrices + // void Transform(Point& p); + void Transform(double p0[3]) const; // Transform p0 thro' this matrix + void Transform(double p0[3], double p1[3]) const; // Transform p0 to p1 thro' this matrix + void Transform2d(double p0[2], double p1[2]) const; // Transform p0 to p1 thro' this matrix + + int IsMirrored(); // true if matrix has a mirror transformation + int IsUnit(); // true if matrix is unit matrix + void GetTranslate(double& x, double& y, double& z) const; // get translation from matrix + void GetScale(double& sx, double& sy, double& sz) const; // get scale from matrix + bool GetScale(double& sx) const; // get scale from matrix (true if uniform scale) + void GetRotation(double& ax, double& ay, double& az) const; // get rotation from matrix + + Matrix Inverse(); // inverts this matrix +}; + +extern Matrix UnitMatrix; // a Unit Matrix + + +// 2d Point class +class Point +{ + friend wostream& operator<<(wostream& op, Point& p); + +public: + bool ok; // true if this point is defined correctly + double x; // x value + double y; // y value + + // constructors etc... + inline Point() + { + x = 0; + y = 0; + ok = false; + } // Point p1 + inline Point(double xord, double yord, bool okay = true) + { // Point p1(10,30); + x = xord; + y = yord; + ok = okay; + } + + // inline Point(const Point& p) + // { // copy constructor Point p1(p2); + // x = p.x; + // y = p.y; + // ok = p.ok; + // } + + Point(const Point3d& p); // copy constructor Point p1(p2); + Point(const Vector2d& v); + + // operators + bool operator==(const Point& p) const; + bool operator!=(const Point& p) const + { + return !(*this == p); + } + inline Point operator+(const Point& p) const + { + return Point(x + p.x, y + p.y); + } // p0 = p1 + p2; + inline Point operator+=(const Point& p) + { + return Point(x += p.x, y += p.y); + } // p0 += p1; + Point operator+(const Vector2d& v) const; // p1 = p0 + v0; + + // destructor + //~Point(){}; + + // methods + Point Transform(const Matrix& m); // transform point + double Dist(const Point& p) const; // distance between 2 points + double DistSq(const Point& p) const; // distance squared + double Dist(const CLine& cl) const; // distance p to cl + Point Mid(const Point& p, double factor = .5) const; // mid point + void get(double xyz[2]) + { + xyz[0] = x; + xyz[1] = y; + } // return to array }; +#define INVALID_POINT Point(9.9999999e50, 0, false) +#define INVALID_POINT3D Point3d(9.9999999e50, 0, 0, false) +#define INVALID_CLINE CLine(INVALID_POINT, 1, 0, false) +#define INVALID_CIRCLE Circle(INVALID_POINT, 0) -} // End namespace geoff_geometry +// 3d point class +class Point3d +{ + friend wostream& operator<<(wostream& op, Point3d& p); + +public: + // bool ok; // true if this point is defined correctly + double x; // x value + double y; // y value + double z; // z value + + // constructors + inline Point3d() + { + x = 0; + y = 0; + z = 0; + } // {z=0; /*ok=false;*/}; // Point p1 + inline Point3d(const double* xyz) + { + x = xyz[0], y = xyz[1]; + z = xyz[2]; + } + inline Point3d(double xord, double yord, double zord = 0 /*, bool okay = true*/) + { // Point p1(10,30.5); + x = xord; + y = yord; + z = zord; /* ok = okay;*/ + } + // copy constructor Point p1(p2); + // inline Point3d( const Point3d& p ) { + // x = p.x; y = p.y; z = p.z;[> ok = p.ok;<]} + // copy constructor Point p1(p2); + inline Point3d(const Point& p) + { + x = p.x; + y = p.y; + z = 0; /*ok = p.ok;*/ + } + // copy constructor Point p1(p2, z); + inline Point3d(const Point& p, double zord) + { + x = p.x; + y = p.y; + z = zord; /* ok = p.ok;*/ + } + Point3d(const Vector3d& v); + + // destructor + // ~Point3d(); + + // operators + bool operator==(const Point3d& p) const; + bool operator!=(const Point3d& p) const + { + return !(*this == p); + } + Point3d operator+(const Vector3d& v) const; // p1 = p0 + v0; + + + // methods +#ifdef PEPSDLL + void ToPeps(int id, bool draw = true); // copy Point to Peps +#endif + Point3d Transform(const Matrix& m); + double Dist(const Point3d& p) const; // distance between 2 points + double DistSq(const Point3d& p) const; // distance squared between 2 points + Point3d Mid(const Point3d& p, double factor = 0.5) const; // midpoint + void get(double xyz[3]) + { + xyz[0] = x; + xyz[1] = y; + xyz[2] = z; + } + double* getBuffer() + { + return &this->x; + }; // returns ptr to data + const double* getBuffer() const + { + return &this->x; + }; // returns ptr to data +}; + +// 2d vector class +class Vector2d +{ + friend wostream& operator<<(wostream& op, Vector2d& v); + +private: + double dx, dy; + +public: + // constructors + inline Vector2d() + { + dx = 0; + dy = 0; + } + // inline Vector2d(const Vector2d &v) { dx = v.dx; dy = v.dy;} + Vector2d(const Vector3d& v); // careful + inline Vector2d(double x, double y) + { + dx = x, dy = y; + } + inline Vector2d(const Point& p0, const Point& p1) + { + dx = p1.x - p0.x; + dy = p1.y - p0.y; + } + inline Vector2d(const Point* p0, const Point* p1) + { + dx = p1->x - p0->x; + dy = p1->y - p0->y; + } + inline Vector2d(const Point& p) + { + dx = p.x; + dy = p.y; + } // from 0,0 to p + inline Vector2d(double angle) + { + dx = cos(angle *= DegreesToRadians); + dy = sin(angle); + } // constructs a vector from an angle (0° - 360°) + + + // operators + // inline const Vector2d& operator=(const Vector2d& v) + // { + // dx = v.dx; + // dy = v.dy; + // return *this; + // } // v1 = v2; + inline Vector2d operator+(const Vector2d& v) const + { + return Vector2d(dx + v.dx, dy + v.dy); + } // v2 = v0 + v1; + inline Point operator+(const Point& p) const + { + return Point(this->dx + p.x, this->dy + p.y); + } // p1 = v0 + p0; + inline Vector2d operator+(const double d) + { + return Vector2d(dx + d, dy + d); + }; + + inline const Vector2d& operator+=(const Vector2d& v) + { + dx += v.dx; + dy += v.dy; + return *this; + } // v1 += v0; + inline Vector2d operator-(const Vector2d& v) const + { + return Vector2d(dx - v.dx, dy - v.dy); + } // v2 = v0 - v1; + inline const Vector2d& operator-=(const Vector2d& v) + { + dx -= v.dx; + dy -= v.dy; + return *this; + } // v1 -= v0; + inline Vector2d operator-(const double d) + { + return Vector2d(dx - d, dy - d); + }; + + inline const Vector2d operator-(void) const + { + return Vector2d(-dx, -dy); + } // v1 = -v0; (unary minus) + + inline double operator*(const Vector2d& v) const + { + return (dx * v.dx + dy * v.dy); + } // dot product m0.m1.cos a = v0 * v1 + inline Vector2d operator*(double c) const + { + return Vector2d(dx * c, dy * c); + } // scalar product + inline const Vector2d& operator*=(double c) + { + dx *= c; + dy *= c; + return *this; + } // scalar product + inline Vector2d operator*(int c) const + { + return Vector2d(dx * (double)c, dy * (double)c); + } // scalar product + + inline double operator^(const Vector2d& v) const + { + return (dx * v.dy - dy * v.dx); + } // cross product m0.m1.sin a = v0 ^ v1 + inline Vector2d operator~(void) const + { + return Vector2d(-dy, dx); + } // perp to left + + bool operator==(const Vector2d& v) const; // v1 == v2 + inline bool operator!=(const Vector2d& v) const + { + return !(*this == v); + } // v1 != v2 + + + // methods + void get(double xyz[2]) + { + xyz[0] = dx; + xyz[1] = dy; + } // return to array + inline double getx() const + { + return dx; + } + inline double gety() const + { + return dy; + } + inline void putx(double x) + { + dx = x; + } + inline void puty(double y) + { + dy = y; + } + double normalise() + { + double m = magnitude(); + if (m < TIGHT_TOLERANCE) { + dx = dy = 0; + return 0; + } + dx /= m; + dy /= m; + return m; + } // normalise & returns magnitude + inline double magnitudesqd(void) const + { + return (dx * dx + dy * dy); + } // magnitude squared + inline double magnitude(void) const + { + return (sqrt(magnitudesqd())); + } // magnitude + void Rotate(double cosa, double sina) + { // rotate vector by angle + double temp = -dy * sina + dx * cosa; + dy = dx * sina + cosa * dy; + dx = temp; + } + inline void Rotate(double angle) + { + if (FEQZ(angle) == true) { + return; + } + Rotate(cos(angle), sin(angle)); + } + void Transform(const Matrix& m); // transform vector + + // destructor + //~Vector2d(){} +}; + + +// 3d vector class +class Vector3d +{ + friend wostream& operator<<(wostream& op, Vector3d& v); + +private: + double dx, dy, dz; + +public: + // constructors + Vector3d() + { + dx = 0; + dy = 0; + dz = 0; + } + // Vector3d(const Vector3d &v) { dx = v.dx; dy = v.dy; dz = v.dz;} + Vector3d(double x, double y, double z = 0) + { + dx = x, dy = y; + dz = z; + } + Vector3d(const double* x) + { + dx = x[0], dy = x[1]; + dz = x[2]; + } + Vector3d(const double* x0, const double* x1) + { + dx = x1[0] - x0[0], dy = x1[1] - x0[1]; + dz = x1[2] - x0[2]; + } + Vector3d(const Point3d& p0, const Point3d& p1) + { + dx = p1.x - p0.x; + dy = p1.y - p0.y; + dz = p1.z - p0.z; + } + Vector3d(const Point3d& p) + { + dx = p.x; + dy = p.y; + dz = p.z; + } // from 0,0,0 to p + Vector3d(const Vector2d& v) + { + dx = v.getx(); + dy = v.gety(); + dz = 0; + } + + // operators + bool operator==(const Vector3d& v) const + { + return (FEQ(dx, v.dx, UNIT_VECTOR_TOLERANCE) && FEQ(dy, v.dy, UNIT_VECTOR_TOLERANCE) + && FEQ(dz, v.dz, UNIT_VECTOR_TOLERANCE)); + } // v1 == v2 (unit only!) + bool operator!=(const Vector3d& v) const + { + return (!(*this == v)); + } // v1 != v2 + // const Vector3d& operator=(const Vector3d& v) + // { + // dx = v.dx; + // dy = v.dy; + // dz = v.dz; + // return *this; + // } // v1 = v2; + // const Vector3d& operator=(const Vector2d& v) + // { + // dx = v.getx(); + // dy = v.gety(); + // dz = 0.0; + // return *this; + // } // v1 = v2; + inline Point3d operator+(const Point3d& p) const + { + return Point3d(dx + p.x, dy + p.y, dz + p.z); + } // p1 = v0 + p0; + Vector3d operator+(const Vector3d& v) const + { + return Vector3d(dx + v.dx, dy + v.dy, dz + v.dz); + } // v2 = v0 + v1; + const Vector3d& operator+=(const Vector3d& v) + { + dx += v.dx; + dy += v.dy; + dz += v.dz; + return *this; + } // v1 += v0; + Vector3d operator-(const Vector3d& v) const + { + return Vector3d(dx - v.dx, dy - v.dy, dz - v.dz); + } // v2 = v0 - v1; + const Vector3d& operator-=(const Vector3d& v) + { + dx -= v.dx; + dy -= v.dy; + dz -= v.dz; + return *this; + } // v1 -= v0; + + const Vector3d operator-(void) const + { + return Vector3d(-dx, -dy, -dz); + } // v1 = -v0; (unary minus) + + double operator*(const Vector3d& v) const + { + return (dx * v.dx + dy * v.dy + dz * v.dz); + } // dot product m0 m1 cos a = v0 * v1 + + const Vector3d& operator*=(double c) + { + dx *= c; + dy *= c; + dz *= c; + return *this; + } // scalar products + friend const Vector3d operator*(const Vector3d& v, double c) + { + return Vector3d(v.dx * c, v.dy * c, v.dz * c); + } + friend const Vector3d operator*(double c, const Vector3d& v) + { + return Vector3d(v.dx * c, v.dy * c, v.dz * c); + } + friend const Vector3d operator/(const Vector3d& v, double c) + { + return Vector3d(v.dx / c, v.dy / c, v.dz / c); + } + + const Vector3d operator^(const Vector3d& v) const + { + return Vector3d(dy * v.dz - dz * v.dy, dz * v.dx - dx * v.dz, dx * v.dy - dy * v.dx); + } // cross product vector + + // = the vector perp to the plane of the 2 vectors + // the z component magnitude is m0.m1.sin a + // methods + inline void get(double xyz[3]) const + { + xyz[0] = dx; + xyz[1] = dy; + xyz[2] = dz; + } // return to array + inline double getx() const + { + return dx; + } + inline double gety() const + { + return dy; + } + inline double getz() const + { + return dz; + } + inline void putx(double x) + { + dx = x; + } + inline void puty(double y) + { + dy = y; + } + inline void putz(double z) + { + dz = z; + } + double normalise() + { + double m = magnitude(); + if (m < 1.0e-09) { + dx = dy = dz = 0; + return 0; + } + dx /= m; + dy /= m; + dz /= m; // normalise & returns magnitude + return m; + } + inline double magnitude(void) const + { + return (sqrt(dx * dx + dy * dy + dz * dz)); + } // magnitude + inline double magnitudeSq(void) const + { + return (dx * dx + dy * dy + dz * dz); + } // magnitude squared + void Transform(const Matrix& m); // transform vector + void arbitrary_axes(Vector3d& x, Vector3d& y); + int setCartesianAxes(Vector3d& b, Vector3d& c); + double* getBuffer() + { + return &this->dx; + }; // returns ptr to data + const double* getBuffer() const + { + return &this->dx; + }; // returns ptr to data + + // destructor + //~Vector3d(){} +}; + +#define ORIGIN Point3d(0, 0, 0) +#define NULL_VECTOR Vector3d(0, 0, 0) +#define Z_VECTOR Vector3d(0, 0, 1) +#define Y_VECTOR Vector3d(0, 1, 0) +#define X_VECTOR Vector3d(1, 0, 0) + +// 2D cline x = x0 + t * dx; y = y0 + t * dy +class CLine +{ + friend wostream& operator<<(wostream& op, CLine& cl); + +public: + bool ok; + Point p; + Vector2d v; + + // constructors + inline CLine() + { + ok = false; + }; + inline CLine(const Point& p0, double dx, double dy, bool normalise = true) + { + p = p0; + v = Vector2d(dx, dy); + if (normalise) { + Normalise(); + } + }; + inline CLine(const Point& p0, const Vector2d& v0, bool normalise = true) + { + p = p0; + v = v0; + if (normalise) { + Normalise(); + } + }; + // inline CLine(const CLine& s) + // { + // p = s.p; + // v = s.v; + // ok = s.ok; + // } // copy constructor CLine s1(s2); + inline CLine(const Point& p0, const Point& p1) + { + p = p0; + v = Vector2d(p0, p1); + Normalise(); + }; + CLine(const Span& sp); + + // operators + const CLine operator~(void); // perp to left + const CLine& operator=(const Point& p0) + { + p.x = p0.x; + p.y = p0.y; + return *this; + }; // s = p; + + // methods + double c(); // returns c + void Normalise(); // normalise dx,dy +#ifdef PEPSDLL + void ToPeps(int id, bool draw = true); // to Peps + void DelPeps(int id); // delete Peps CLine +#endif + CLine Transform(Matrix& m); // transform a CLine + Point Intof(const CLine& s); // intersection of 2 clines + Point Intof(int NF, const Circle& c); // intersection of cline & circle + Point Intof(int NF, const Circle& c, Point& otherInters); + double Dist(const Point& p1) const; // ditto & other intersection + CLine Bisector(const CLine& s); // Bisector of 2 Clines + + // destructor + // ~CLine(); +}; + +#define HORIZ_CLINE CLine(geoff_geometry::Point(0, 0), 1.0, 0.0, true) + + +// 2D circle +class Circle +{ + friend wostream& operator<<(wostream& op, Circle& c); + +public: + bool ok; + Point pc; + double radius; + + // constructors etc... + inline Circle() + { + ok = false; + radius = 0; + } + Circle(const Point& p, double r); // Circle c1(Point(10,30), 20); + Circle(const Point& p, const Point& pc); // Circle c1(p[222], p[223]); + // Circle(const Circle& c) + // { + // *this = c; + // } // copy constructor Circle c1(c2); + Circle(const Span& sp); // constructor + + // methods +#ifdef PEPSDLL + void ToPeps(int id, bool draw = true); // to Peps + void DelPeps(int id); // delete Peps Circle +#endif + bool operator==(const Circle& c) const; // c == cc + bool operator!=(const Circle& c) const + { + return !(*this == c); + } + Circle Transform(Matrix& m); // transform a Circle + Point Intof(int LR, const Circle& c1); // intof 2 circles + Point Intof(int LR, + const Circle& c1, + Point& otherInters); // intof 2 circles, (returns the other intersection) + int Intof(const Circle& c1, + Point& leftInters, + Point& rightInters); // intof 2 circles (returns number of intersections & left/right + // inters) + CLine Tanto(int AT, double angle, const CLine& s0) const; // a cline tanto this circle at angle + // ~Circle(); // destructor +}; + +// 2d box class +class Box +{ +public: + Point min; + Point max; + bool ok; + + Box() + { + min.x = min.y = 1.0e61; + max.x = max.y = -1.0e61; + ok = false; + }; + Box(Point& pmin, Point& pmax) + { + min = pmin; + max = pmax; + ok = true; + }; + + bool outside(const Box& b) const; // returns true if box is outside box + void combine(const Box& b); // combines this with b +}; + +// 3d box class +class Box3d +{ +public: + Point3d min; + Point3d max; + bool ok; + + Box3d() + { + min.x = min.y = min.z = 1.0e61; + max.x = max.y = max.z = -1.0e61; + ok = false; + }; + Box3d(const Point3d& pmin, const Point3d& pmax) + { + min = pmin; + max = pmax; + ok = true; + }; + + bool outside(const Box3d& b) const; // returns true if box is outside box + void combine(const Box3d& b); // combines this with b +}; + +inline void MinMax(const Point& p, Point& pmin, Point& pmax) +{ + if (p.x > pmax.x) { + pmax.x = p.x; + } + if (p.y > pmax.y) { + pmax.y = p.y; + } + if (p.x < pmin.x) { + pmin.x = p.x; + } + if (p.y < pmin.y) { + pmin.y = p.y; + } +} + +inline void MinMax(const Point3d& p, Point3d& pmin, Point3d& pmax) +{ + if (p.x > pmax.x) { + pmax.x = p.x; + } + if (p.y > pmax.y) { + pmax.y = p.y; + } + if (p.z > pmax.z) { + pmax.z = p.z; + } + if (p.x < pmin.x) { + pmin.x = p.x; + } + if (p.y < pmin.y) { + pmin.y = p.y; + } + if (p.z < pmin.z) { + pmin.z = p.z; + } +} + + +// 2D line arc span +class Span +{ + friend wostream& operator<<(wostream& op, Span& span); + +public: + Point p0; // start + Point p1; // end + Point pc; // centre + int dir; // arc direction (CW or ACW or 0 for straight) + int ID; // ID (for offset in wire - stores spanID etc. from original kurve) + bool ok; + + bool returnSpanProperties; // set if properties below are set + Vector2d vs; // direction at start or for straight + Vector2d ve; // direction at span end + + double length; // span length + double radius; // arc radius + double angle; // included arc angle ( now arc is parameterised start -> start + angle + + Box box; // span box + + bool NullSpan; // true if small span + + // methods + void SetProperties(bool returnProperties); // set span properties + Span Offset(double offset); // offset span method + int Split(double tolerance); // returns number of splits + void SplitMatrix(int num_vectors, Matrix* matrix); // returns incremental matrix from split + void minmax(Box& box, bool start = true); // minmax of span + void minmax(Point& pmin, Point& pmax, bool start = true); // minmax of span + int Intof(const Span& sp, Point& pInt1, Point& pInt2, double t[4]) const; + void Transform(const Matrix& m, bool setprops = true); + Point Near(const Point& p) const; // returns the near point to span from p (on or off) + Point NearOn(const Point& p) const; // returns the near point to span from p (on span) + Point Mid() const; // midpoint of a span + Point MidPerim(double d) const; // interior point of Span (param 0 - d) + Point MidParam(double param) const; // interior point of Span (param 0 - 1) + bool OnSpan( + const Point& p) const; // tests if p is on sp *** FAST TEST p MUST LIE on unbounded span + bool + OnSpan(const Point& p, + double* t) const; // tests if p is on sp *** FAST TEST p MUST LIE on unbounded span + bool JoinSeparateSpans(Span& sp); + Span BlendTwoSpans(Span& sp2, double radius, double maxt); // Blends 2 Spans + bool isJoinable(const Span& sp) const; // is this & sp joinable to 1 span? + Vector2d + GetVector(double fraction) const; // the direction along the span, 0.0 for start, 1.0 for end + + // constructor + Span() + { + dir = 0; + ID = 0; + ok = false; + returnSpanProperties = false; + length = 0; + radius = 0; + angle = 0; + NullSpan = false; + } + Span(int spandir, const Point& pn, const Point& pf, const Point& c) + { + dir = spandir; + p0 = pn, p1 = pf, pc = c; + ID = 0; + SetProperties(true); + ok = p0.ok; + }; + + // operators + // bool operator==(const Span &sp)const; + // bool operator!=(const Span &sp)const { return !(*this == sp);} +}; + +// general +double atn360(double dx, double dy); // angle 0 to 2pi + +// distance functions +// double Dist(double px, double py, double p1x, double p1y); // distance between 2 points (2d) +// double Dist(Point& p0, Point& p1); // distance between 2 points (3d) +// double Dist(CLine& s, Point& p1); // distance between cline & point + +double +Dist(const Point3d* p, const Vector3d* vl, const Point3d* pf); // distance from line (p, vl) and pf +double DistSq(const Point3d* p, + const Vector3d* vl, + const Point3d* pf); // distance squared from line (p, vl) and pf +double Dist(const Circle& c, const Point& p); // distance between c & p +double Dist(const Point& p0, + const Circle& c, + const Point& p1); // clockwise distance around c from p0 to p1 +double Dist(const CLine& s, const Circle& c); // distance between line and circle +double Dist(const Circle& c0, const Circle& c1); // distance between 2 circles +double +IncludedAngle(const Vector2d& v0, const Vector2d& v1, int dir = 1); // angle between 2 vectors +double IncludedAngle(const Vector3d& v0, const Vector3d& v1, const Vector3d& normal, int dir = 1); +inline double IncludedAngle(const CLine& s0, const CLine& s1, int dir = 1) +{ // angle between 2 Clines + return IncludedAngle(s0.v, s1.v, dir); +} + + +// point definitions +Point Mid(const Point& p0, const Point& p1, double factor = 0.5); // midpoint +Point Mid(const Span& sp); // midpoint of a span +Point Rel(const Point& p, double x, double y); // relative point +Point Polar(const Point& p, double angle, double r); // polar from this point +Point AtAngle(const Circle& c, double angle); // Point at angle on a circle +Point XonCLine(const CLine& s, double xval); // returns point that has X on this line +Point YonCLine(const CLine& s, double yval); // returns point that has Y on this line +Point Intof(const CLine& s0, const CLine& s1); // intof 2 clines +Point Intof(int NF, const CLine& s, const Circle& c); // intof of circle & a cline +Point Intof(int NF, + const CLine& s, + const Circle& c, + Point& otherInters); // intof of circle & a cline (returns the other intersection) +Point Intof(int LR, const Circle& c0, const Circle& c1); // intof 2 circles +Point Intof(int LR, + const Circle& c0, + const Circle& c1, + Point& otherInters); // intof 2 circles, (returns the other intersection) +int Intof(const Circle& c0, const Circle& c1, Point& pLeft, Point& pRight); // ditto +Point Along(const CLine& s, double d); // distance along Cline +Point Along(const CLine& s, double d, const Point& p); // distance along Cline from point +Point Around(const Circle& c, double d, const Point& p); // distance around a circle from point +Point On(const CLine& s, const Point& p); // returns a point on s nearest to p +Point On(const Circle& c, const Point& p); // returns a point on c nearest to p + +// cline definitions + +CLine AtAngle(double angle, + const Point& p, + const CLine& s = HORIZ_CLINE); // cline at angle to line thro' point +CLine Tanto(int AT, + const Circle& c, + double angle, + const CLine& s0 = HORIZ_CLINE); // cline tanto circle at angle to optional cline +CLine Tanto(int AT, const Circle& c, const Point& p); // cline tanto circle thro' a point +CLine Tanto(int AT0, const Circle& c0, int AT1, const Circle& c1); // cline tanto 2 circles +CLine Normal(const CLine& s); // noirmal to cline +CLine Normal(const CLine& s, const Point& p); // normal to cline thro' p +CLine Parallel(int LR, const CLine& s, double distance); // parallel to cline by distance +CLine Parallel(const CLine& cl, const Point& p); // parallel to cline thro' a point + + +// circle definitions +Circle Thro(const Point& p0, const Point& p1); // circle thro 2 points (diametric) +Circle Thro(const Point& p0, const Point& p1, const Point& p2); // circle thro 3 points +Circle Tanto(int NF, + const CLine& s0, + const Point& p, + double rad); // circle tanto a CLine thro' a point with radius +Circle +Thro(int LR, const Point& p0, const Point& p1, double rad); // circle thro' 2 points with radius +Circle Tanto(int AT1, + const CLine& s1, + int AT2, + const CLine& s2, + double rad); // circle tanto 2 clines with radius +Circle Tanto(int AT1, + const CLine& s1, + int AT2, + const CLine& s2, + int AT3, + const CLine& s3); // circle tanto 3 clines +Circle Tanto(int LR, + int AT, + const Circle& c, + const Point& p, + double rad); // circle tanto circle & thro' a point +Circle Tanto(int NF, + int AT0, + const CLine& s0, + int AT1, + const Circle& c1, + double rad); // circle tanto cline & circle with radius +Circle Tanto(int LR, + int AT0, + const Circle& c0, + int AT1, + const Circle& c1, + double rad); // circle tanto 2 circles with radius +Circle Tanto(int LR, + int AT1, + const Circle& c1, + int AT2, + const Circle& c2, + int AT3, + const Circle c3); // tanto 3 circles +int apolloniusProblem(int AT1, + const Circle& c1, + int AT2, + const Circle& c2, + int AT3, + const Circle& c3, + Circle& Solution1, + Circle& Solution2); +int apolloniusProblem(int AT1, + const Circle& c1, + int AT2, + const Circle& c2, + int AT3, + const CLine& cl3, + Circle& Solution1, + Circle& Solution2); +int apolloniusProblem(int AT1, + const Circle& c1, + int AT2, + const CLine& cl2, + int AT3, + const CLine& cl3, + Circle& Solution1, + Circle& Solution2); + +// Circle Tanto(int AT0, +// int NF, +// int AT1, +// CLine s1, +// int AT2, +// CLine s2); // circle tanto circle, and 2 clines +Circle Parallel(int LR, const Circle& c, double distance); // parallel to circle by a distance + + +// misc +inline double Radians(double degrees) +{ + return degrees * PI / 180; +} +inline double Degrees(double radians) +{ + return radians * 180 / PI; +} +int quadratic(double a, double b, double c, double& x0, double& x1); // solve quadratic + +int corner(const Vector2d& v0, + const Vector2d& v1, + double cpTol = CPTANGENTTOL); // corner (TANGENT, LEFT, RIGHT) +inline int corner(const Span& span, const Span& next, double cpTol = CPTANGENTTOL) +{ + return corner((Vector2d)span.ve, (Vector2d)next.vs, cpTol); +} + +Line IsPtsLine(const double* a, int n, double tolerance, double* deviation); +// Span3d IsPtsSpan3d(const double* a, int n, double tolerance, double* deviation); + +class Plane +{ + friend wostream& operator<<(wostream& op, Plane& pl); + +public: // ax + by + cz + d = 0 + bool ok; + double d; // distance of plane to origin + Vector3d normal; // normal to plane a = n.dx, b = n.dy, c = n.dz + // constructors + Plane() + { + ok = false; + d = 0; + } + Plane(double dist, const Vector3d& n); + Plane(const Point3d& p0, const Point3d& p1, const Point3d& p2); + Plane(const Point3d& p0, const Vector3d& n, bool normalise = true); + + // methods + double Dist(const Point3d& p) const; // signed distance of point to plane + bool Intof(const Line& l, Point3d& intof, double& t) + const; // intersection of plane & line (0 >= t <= 1 if intersect within line) + bool Intof(const Plane& pl, Line& intof) const; // intersection of 2 planes + bool + Intof(const Plane& pl0, const Plane& pl1, Point3d& intof) const; // intersection of 3 planes + Point3d Near(const Point3d& p) const; // returns near point to p on the plane + void Mirrored(Matrix* m); // returns a matrix for a mirror about this +}; + + +#define SPANSTORAGE 32 // lessens number of object pointers + +class spVertex +{ + friend wostream& operator<<(wostream& op, spVertex& sp); + +public: + int type; + int spanid; + Point p; + Point pc; + spVertex() + { + type = 0; + spanid = 0; + } + spVertex(int t, const Point& point, const Point& centre) + : type(t) + , spanid(0) + , p(point) + , pc(centre) {}; + + bool operator==(spVertex& spv) + { + // vertex == spvertex (vertex check - doesn't check spannid!) + if (this->type != spv.type) { + return false; + } + if (this->p != spv.p) { + return false; + } + if (this->type != LINEAR) { + if (this->pc != spv.pc) { + return false; + } + } + return true; + } + + bool operator!=(spVertex& spv) + { + return !(*this == spv); + } +}; + + +class SpanDataObject +{ + // holds everything needed for Post-Processing/Simulation +public: + int method; // holds method type + + SpanDataObject(int meth) + { + method = meth; + }; + SpanDataObject(const SpanDataObject* obj) + { + method = obj->method; + }; +}; + +class SpanVertex +{ +public: + int type[SPANSTORAGE]; // LINEAR CW or ACW // 0 straight (cw = -1 (T) acw = 1 (A) ) + int spanid[SPANSTORAGE]; // identification (eg wire offset span info) + const SpanDataObject* index[SPANSTORAGE]; // other - pointer to + double x[SPANSTORAGE], y[SPANSTORAGE]; // vertex + double xc[SPANSTORAGE], yc[SPANSTORAGE]; // centre of arc +public: + // methods + void Add(int offset, int type, const Point& p0, const Point& pc, int ID = UNMARKED); + const SpanDataObject* GetIndex(int offset) const; + void AddSpanID(int offset, int ID); + SpanVertex(); + ~SpanVertex(); + const SpanVertex& operator=(const SpanVertex& spv); + + void Add(int offset, const SpanDataObject* Index); + const SpanDataObject* Get(int offset); + int Get(int offset, Point& pe, Point& pc); + int GetSpanID(int offset); +}; + + +#ifdef _MSC_VER +#pragma warning(disable : 4522) +#endif + +class Kurve: public Matrix +{ + friend wofstream& operator<<(wofstream& op, Kurve& k); + friend wifstream& operator>>(wifstream& op, Kurve& k); + +protected: + vector m_spans; + bool m_started; + int m_nVertices; // number of vertices in Kurve + bool m_isReversed; // true if get spans reversed + +public: + // for comparing kurves + struct spanCompare + { + int dir; // LINEAR, CW or ACW + double length; // length of the span + double cp; // cross-product to next span (sina) + double dp; + }; + // constructors etc... + Kurve() + { + m_started = false; + m_nVertices = 0; + m_isReversed = false; + }; + Kurve(const Kurve& k0); + const Kurve& operator=(const Kurve& k); + const Kurve& operator=(const Matrix& m); + + bool operator==(const Kurve& k) const; // k == kk (vertex check) + bool operator!=(const Kurve& k) const + { + return !(*this == k); + } + + + // destructor + ~Kurve(); + + // methods + inline int nSpans() const + { + return (m_nVertices) ? m_nVertices - 1 : 0; + } // returns the number of spans + bool Closed() const; // returns true if kurve is closed + inline bool Started() const + { + return m_started; + }; + void FullCircle(int dir, const Point& c, double radius); // make a full circle + void Start(); // start a new kurve + void Start(const Point& p); // start a new kurve with start point + bool Add(const spVertex& spv, bool AddNullSpans = true); // add a vertex + void Get(int vertex, spVertex& spv) const; // get a vertex + bool Add(const Span& sp, bool AddNullSpans = true); // add a span + bool Add(int type, const Point& p0, const Point& pc, bool AddNullSpans = true); // a span + void AddSpanID(int ID); + bool Add(const Point& p0, bool AddNullSpans = true); // linear + void Add(); // add a null span + void Add(const Kurve* k, bool AddNullSpans = true); // a kurve + void StoreAllSpans(std::vector& kSpans) + const; // store all kurve spans in array, normally when fast access is reqd + void Clear(); // remove all the spans + + void Replace(int vertexnumber, const spVertex& spv); + void Replace(int vertexnumber, int type, const Point& p, const Point& pc, int ID = UNMARKED); + int GetSpanID(int spanVertexNumber) const; // for spanID (wire offset) + int Get(int spanVertexNumber, Point& p, Point& pc) const; + void Get(std::vector* all, bool ignoreNullSpans) const; // get all spans to vector + int Get(int spanVertexNumber, Point3d& p, Point3d& pc) const + { + Point p2d, pc2d; + int d = Get(spanVertexNumber, p2d, pc2d); + p = p2d; + pc = pc2d; + return d; + } + int + Get(int spannumber, Span& sp, bool returnSpanProperties = false, bool transform = false) const; + // int Get(int spannumber, + // Span3d& sp, + // bool returnSpanProperties = false, + // bool transform = false) const; + void Get(Point& ps, Point& pe) const; // returns the start- and endpoint of the kurve + const SpanDataObject* GetIndex(int vertexNumber) const; + inline double GetLength() const + { + return Perim(); + }; // returns the length of a kurve + + void minmax(Point& pmin, Point& pmax); // minmax of span + void minmax(Box& b); + + Point NearToVertex(const Point& p, int& nearSpanNumber) const; + Point NearToVertex(const Point& p) const + { + int nearSpanNumber; + return NearToVertex(p, nearSpanNumber); + }; + Point Near(const Point& p, int& nearSpanNumber) const; + Point Near(const Point& p) const + { + int nearSpanNumber; + return Near(p, nearSpanNumber); + }; + double Perim() const; // perimeter of kurve + double Area() const; // area of closed kurve + void Reverse(); // reverse kurve direction - obsolete + bool Reverse(bool isReversed) + { // reverse kurve direction - later better method + bool tmp = m_isReversed; + m_isReversed = isReversed; + return tmp; + }; + int Reduce(double tolerance); // reduce spans which are in tolerance + + int Offset(vector& OffsetKurves, + double offset, + int direction, + int method, + int& ret) const; // offset methods + int OffsetMethod1(Kurve& kOffset, double off, int direction, int method, int& ret) const; + int OffsetISOMethod(Kurve& kOffset, + double off, + int direction, + bool BlendAll) const; // special offset (ISO radius - no span elimination) + int Intof(const Span& sp, vector& p) const; // intof span + int Intof(const Kurve& k, vector& p) const; // intof kurve + bool Compare(const Kurve* k, Matrix* m, bool bAllowMirror = true) const; // compare 2 Kurves + void ChangeStart(const Point* pNewStart, int startSpanno); // change the Kurve's startpoint + void ChangeEnd(const Point* pNewEnd, int endSpanno); // change the Kurve's endpoint + +private: + bool compareKurves(const std::vector& first, + const std::vector& second, + int& nOffset /*, Kurve *k, Matrix *m*/) const; + bool calculateMatrix(const Kurve* k, Matrix* m, int nOffset, bool bMirror = false) const; + +public: + void AddIndex(int vertexNumber, const SpanDataObject* data); + bool Split(double MaximumRadius, + double reslution); // split arcs larger than MaximumRadius to resolution + int IntExtWire(Kurve& kSec, + double Ref, + double Sec, + double height, + Kurve* kOut); // interpolate / extrapolate a mid height kurve (wire) + void SetZ(double z) + { + e[11] = z; + if (fabs(z) > 1.0e-6) { + m_unit = false; + } + } // assigns kurve to fixed height (wire) + + void Part(int startVertex, int EndVertex, Kurve* part); + Kurve Part(int fromSpanno, + const Point& fromPt, + int toSpanno, + const Point& toPt); // make a Part Kurve + int + Break(double atParam, + const Kurve* secInput, + Kurve* refOut, + Kurve* secOut); // break kurve perimeter parameterisation with synchronised Kurve (wire) + void + Part(double fromParam, + double toParam, + const Kurve* secInput, + Kurve* refOut, + Kurve* secOut); // part kurve perimeter parameterisation with synchronised Kurve (wire) + Kurve Part(double fromParam, double toParam); // part kurve perimeter parameterisation + void AddSections(const Kurve* k, bool endOfSection); // special add kurves for rollingball + void AddEllipse(int dir, + const Point& pStart, + const Point& pEnd, + const Point& pCentre, + const Vector2d& majorAxis, + double majorRadius, + double minorRadius, + double tolerance); + // void Kurve::AddEllipse(int dir, + // Plane* plEllipse, + // Vector3d* cylAxis, + // Point3d* cylCentre, + // double cylradius, + // Point3d* pStart, + // Point3d* pEnd, + // double tolerance); // elliptical curve - biarc in tolerance + + void Spiral(const Point& centre, + double startAngle, + double startRadius, + double radiusRisePerRevolution, + double endRadius); +#ifdef PARASOLID + int ToPKcurve(PK_CURVE_t* curves, + PK_INTERVAL_t* ranges, + int start_spanno, + int n_spans); // Convert to PK Curve + + PK_BODY_t ToPKwire(); // Convert to PK Wire Body + PK_BODY_t ToPKwire(int start_spanno, int n_spans); + + PK_BODY_t ToPKsheet(); // Convert to PK Sheet Body + PK_BODY_t ToPKextrudedBody(PK_VECTOR1_t path, bool solidbody = true); + // Convert to PK Body (open kurve >> sheet) + PK_BODY_t ToPKlofted_sheet_body(Kurve& sec); // Convert 2 kurves to lofted sheet body + PK_BODY_t ToPKlofted_thickened_body(Kurve& sec, double thickness); +#endif +}; +#ifdef _MSC_VER +#pragma warning(default : 4522) +#endif + +void tangential_arc(const Point& p0, const Point& p1, const Vector2d& v0, Point& c, int& dir); + +int EqualiseSpanCount(Kurve& k1, + Kurve& k2, + Kurve& k1equal, + Kurve& k2equal, + bool equalise_same_span_count); // span count equalisation +void EqualiseSpanCountAfterOffset(Kurve& k1, + Kurve& k2, + Kurve& k1Out, + Kurve& k2Out); // span equalisation after offset +void EqualiseSpanCountAfterOffsetFromRollAround( + Kurve& k1, + Kurve& k2, + Kurve& k1Out, + Kurve& k2Out /*, double offset, int arc_direction*/); // span equalisation after offset + +Point IntofIso(Span& one, Span& two, Span& three); // for iso blend radiuses - calc intersection + +inline double CPTOL(double offset, double maxOffset) +{ + // this returns a suitable tolerance for a cross product + // the cp for normalised vectors is the sin of the included angle between the vectors + // + // this function takes the machine resolution from RESOLUTION + + offset = fabs(offset); + + if (offset <= RESOLUTION) { + offset = maxOffset; // no known offset so guess one from the application + } + + return RESOLUTION / offset; +} + + +// finite Span routines +int Intof(const Span& sp0, const Span& sp1, Point& p0, Point& p1, double t[4]); +int LineLineIntof(const Span& L0, const Span& L1, Point& p, double t[2]); +int LineArcIntof(const Span& line, const Span& arc, Point& p0, Point& p1, double t[4]); +int ArcArcIntof(const Span& arc0, const Span& arc1, Point& pLeft, Point& pRight); + +bool OnSpan(const Span& sp, const Point& p); +bool OnSpan(const Span& sp, + const Point& p, + bool nearPoints, + Point& pNear, + Point& pOnSpan); // function returns true if pNear == pOnSpan +// pNear (nearest on unbound span) +// pOnSpan (nearest on finite span) + + +int Intof(const Line& v0, const Line& v1, Point3d& intof); // intof 2 lines +double Dist(const Line& l, + const Point3d& p, + Point3d& pnear, + double& t); // distance from a point to a line +Point3d +Near(const Line& l, const Point3d& p, double& t); // near point to a line & t in 0-length range +double Dist(const Span& sp, + const Point& p, + Point& pnear); // distance from p to sp, nearpoint returned as pnear + +// Kurve splineUsingBiarc(CLine& cl0, CLine& cl1, std::vector); + +int biarc(CLine& cl0, CLine& cl1, Span* sp0, Span* sp1); + +// 3d line segment +class Line +{ +public: + Point3d p0; // start + Vector3d v; // vector (not normalised) + double length; // line length + Box3d box; + bool ok; + + // constructors + Line() + { + ok = false; + length = 0; + } + Line(const Point3d& p0, const Vector3d& v0, bool boxed = true); + Line(const Point3d& p0, const Point3d& p1); + Line(const Span& sp); + + // methods + void minmax(); + Point3d Near(const Point3d& p, + double& t) const; // near point to line from point (0 >= t <= 1) in range + int Intof(const Line& l, Point3d& intof) const + { + return geoff_geometry::Intof(*this, l, intof); + }; // intof 2 lines + bool atZ(double z, Point3d& p) const; // returns p at z on line + bool Shortest(const Line& l2, + Line& lshort, + double& t1, + double& t2) const; // calculate shortest line between this & l2 +}; + + +class Triangle3d +{ + Point3d vert1; // first vertex + Point3d vert2; // second vertex + Point3d vert3; // third vertex + Vector3d v0; // vector from vert1 to vert2 + Vector3d v1; // vector from vert1 to vert3 + bool ok; + + Box3d box; // box around triangle + +public: + // constructor + Triangle3d() + { + ok = false; + }; + Triangle3d(const Point3d& vert1, const Point3d& vert2, const Point3d& vert3); + + // methods + bool Intof(const Line& l, Point3d& intof) const; // returns intersection triangle to line +}; + + +} // End namespace geoff_geometry diff --git a/src/Mod/CAM/libarea/kurve/kurve.cpp b/src/Mod/CAM/libarea/kurve/kurve.cpp index c0cfb4f61e..5e1a3c28ba 100644 --- a/src/Mod/CAM/libarea/kurve/kurve.cpp +++ b/src/Mod/CAM/libarea/kurve/kurve.cpp @@ -7,7 +7,7 @@ using namespace geoff_geometry; #ifdef PEPSPOST - #include "postoutput.h" +#include "postoutput.h" #endif @@ -15,170 +15,183 @@ using namespace geoff_geometry; // kurve //////////////////////////////////////////////////////////////////////////////////////////////// -namespace geoff_geometry { +namespace geoff_geometry +{ - SpanVertex::SpanVertex() { - for(int i = 0; i < SPANSTORAGE; i++) index[i] = NULL; - } +SpanVertex::SpanVertex() +{ + for (int i = 0; i < SPANSTORAGE; i++) { + index[i] = NULL; + } +} - SpanVertex::~SpanVertex() { +SpanVertex::~SpanVertex() +{ #ifndef PEPSDLL - // don't know what peps did about this? - for(int i = 0; i < SPANSTORAGE; i++) { - if(index[i] != NULL) { - delete index[i]; - } - } + // don't know what peps did about this? + for (int i = 0; i < SPANSTORAGE; i++) { + if (index[i] != NULL) { + delete index[i]; + } + } #endif - } +} - const SpanVertex& SpanVertex::operator= (const SpanVertex& spv ){ - /// - if (this == &spv) - return *this; +const SpanVertex& SpanVertex::operator=(const SpanVertex& spv) +{ + /// + if (this == &spv) { + return *this; + } - memcpy(x, spv.x, SPANSTORAGE * sizeof(double)); - memcpy(y, spv.y, SPANSTORAGE * sizeof(double)); - memcpy(xc, spv.xc, SPANSTORAGE * sizeof(double)); - memcpy(yc, spv.yc, SPANSTORAGE * sizeof(double)); + memcpy(x, spv.x, SPANSTORAGE * sizeof(double)); + memcpy(y, spv.y, SPANSTORAGE * sizeof(double)); + memcpy(xc, spv.xc, SPANSTORAGE * sizeof(double)); + memcpy(yc, spv.yc, SPANSTORAGE * sizeof(double)); - for(unsigned int i = 0; i < SPANSTORAGE; i++) { - type[i] = spv.type[i]; - spanid[i] = spv.spanid[i]; - index[i] = spv.index[i]; + for (unsigned int i = 0; i < SPANSTORAGE; i++) { + type[i] = spv.type[i]; + spanid[i] = spv.spanid[i]; + index[i] = spv.index[i]; #ifndef PEPSDLL - if(index[i] != NULL) { - SpanDataObject* obj = new SpanDataObject(index[i]); - index[i] = obj; - } + if (index[i] != NULL) { + SpanDataObject* obj = new SpanDataObject(index[i]); + index[i] = obj; + } #endif - } - return *this; - } + } + return *this; +} - void SpanVertex::Add(int offset, int spantype, const Point& p, const Point& pc, int ID) - { - type[offset] = spantype; -// index[offset] = NULL; - x[offset] = p.x; - y[offset] = p.y; - xc[offset] = pc.x; - yc[offset] = pc.y; - spanid[offset] = ID; - } - void SpanVertex::AddSpanID(int offset, int ID) - { - spanid[offset] = ID; - } +void SpanVertex::Add(int offset, int spantype, const Point& p, const Point& pc, int ID) +{ + type[offset] = spantype; + // index[offset] = NULL; + x[offset] = p.x; + y[offset] = p.y; + xc[offset] = pc.x; + yc[offset] = pc.y; + spanid[offset] = ID; +} +void SpanVertex::AddSpanID(int offset, int ID) +{ + spanid[offset] = ID; +} #if PEPSDLL - void SpanVertex::Add(int offset, WireExtraData* Index ) - { - index[offset] = Index; - } - WireExtraData* SpanVertex::Get(int offset) - { - return index[offset]; - } +void SpanVertex::Add(int offset, WireExtraData* Index) +{ + index[offset] = Index; +} +WireExtraData* SpanVertex::Get(int offset) +{ + return index[offset]; +} #else - void SpanVertex::Add(int offset, const SpanDataObject* Index ) { - index[offset] = Index; - } +void SpanVertex::Add(int offset, const SpanDataObject* Index) +{ + index[offset] = Index; +} - const SpanDataObject* SpanVertex::GetIndex(int offset) const{ - return index[offset]; - } +const SpanDataObject* SpanVertex::GetIndex(int offset) const +{ + return index[offset]; +} #endif - int SpanVertex::Get(int offset, Point& pe, Point& pc) - { - pe = Point(x[offset], y[offset]); - pc = Point(xc[offset], yc[offset]); +int SpanVertex::Get(int offset, Point& pe, Point& pc) +{ + pe = Point(x[offset], y[offset]); + pc = Point(xc[offset], yc[offset]); - return type[offset]; - } - int SpanVertex::GetSpanID(int offset) - { - return spanid[offset]; - } + return type[offset]; +} +int SpanVertex::GetSpanID(int offset) +{ + return spanid[offset]; +} - Span Span::Offset(double offset) - { - Span Offsp = *this; - if(FNEZ(offset) && !NullSpan) { - if ( !dir ) { - // straight - Offsp.p0.x -= offset * vs.gety(); - Offsp.p0.y += offset * vs.getx(); +Span Span::Offset(double offset) +{ + Span Offsp = *this; + if (FNEZ(offset) && !NullSpan) { + if (!dir) { + // straight + Offsp.p0.x -= offset * vs.gety(); + Offsp.p0.y += offset * vs.getx(); - Offsp.p1.x -= offset * vs.gety(); - Offsp.p1.y += offset * vs.getx(); - } - else { - // circular span - // double coffset = (double) dir * offset; - Offsp.p0.x -= vs.gety() * offset; - Offsp.p0.y += vs.getx() * offset; + Offsp.p1.x -= offset * vs.gety(); + Offsp.p1.y += offset * vs.getx(); + } + else { + // circular span + // double coffset = (double) dir * offset; + Offsp.p0.x -= vs.gety() * offset; + Offsp.p0.y += vs.getx() * offset; - Offsp.p1.x -= ve.gety() * offset; - Offsp.p1.y += ve.getx() * offset; + Offsp.p1.x -= ve.gety() * offset; + Offsp.p1.y += ve.getx() * offset; -// Offsp.radius -= dir * offset; - } - Offsp.SetProperties(true); - } - return Offsp; - } + // Offsp.radius -= dir * offset; + } + Offsp.SetProperties(true); + } + return Offsp; +} - bool Span::JoinSeparateSpans(Span& sp) { - // this method joins this span to sp where they are separated normally by an offset from original - // - // parameters:- - // Input sp near span - // Output this->p1 and sp.p0 assigned to the spans intersection - Point inters; - int turnLeft = ((this->ve ^ sp.vs) > 0)? 1 : -1; - if(!this->dir) { - CLine one(*this); - if(!sp.dir) { - // line line - CLine two(sp); - inters = one.Intof(two); - } - else { - // line arc - Circle two(sp); - inters = one.Intof(-turnLeft * sp.dir, two); - } - } - else { - Circle one(*this); - if(!sp.dir) { - // arc line - CLine two(sp); - inters = two.Intof(turnLeft * this->dir, one); - } - else { - // arc arc - Circle two(sp); - inters = one.Intof(-turnLeft * this->dir * sp.dir, two); - } - } - if(inters.ok) { - this->p1 = sp.p0 = inters; - this->SetProperties(true); - sp.SetProperties(true); - } - return inters.ok; - } - static int Split(double tolerance, double angle, double radius, int dir); - int Span::Split(double tolerance) { - // returns the number of divisions required to keep in tolerance - if(!returnSpanProperties) - this->SetProperties(true); - return geoff_geometry::Split(tolerance, angle, radius, dir); - } +bool Span::JoinSeparateSpans(Span& sp) +{ + // this method joins this span to sp where they are separated normally by an offset from + // original + // + // parameters:- + // Input sp near span + // Output this->p1 and sp.p0 assigned to the spans intersection + Point inters; + int turnLeft = ((this->ve ^ sp.vs) > 0) ? 1 : -1; + if (!this->dir) { + CLine one(*this); + if (!sp.dir) { + // line line + CLine two(sp); + inters = one.Intof(two); + } + else { + // line arc + Circle two(sp); + inters = one.Intof(-turnLeft * sp.dir, two); + } + } + else { + Circle one(*this); + if (!sp.dir) { + // arc line + CLine two(sp); + inters = two.Intof(turnLeft * this->dir, one); + } + else { + // arc arc + Circle two(sp); + inters = one.Intof(-turnLeft * this->dir * sp.dir, two); + } + } + if (inters.ok) { + this->p1 = sp.p0 = inters; + this->SetProperties(true); + sp.SetProperties(true); + } + return inters.ok; +} +static int Split(double tolerance, double angle, double radius, int dir); +int Span::Split(double tolerance) +{ + // returns the number of divisions required to keep in tolerance + if (!returnSpanProperties) { + this->SetProperties(true); + } + return geoff_geometry::Split(tolerance, angle, radius, dir); +} #if 0 int Span3d::Split(double tolerance) { // returns the number of divisions required to keep in tolerance @@ -187,33 +200,39 @@ namespace geoff_geometry { return geoff_geometry::Split(tolerance, angle, radius, dir); } #endif - static int Split(double tolerance, double angle, double radius, int dir) { - if(dir == LINEAR) // straight span - return 0; - double cosa = 1 - tolerance / radius; - if(cosa > NEARLY_ONE) cosa = NEARLY_ONE; - cosa = 2 * cosa * cosa - 1 ; /* double angle */ - double sina = sqrt(1 - cosa * cosa) * dir; - double tempang = atan2(sina, cosa); - int num_vectors = (int)(fabs (angle / tempang )) + 1 ; - return num_vectors; - } +static int Split(double tolerance, double angle, double radius, int dir) +{ + if (dir == LINEAR) { // straight span + return 0; + } + double cosa = 1 - tolerance / radius; + if (cosa > NEARLY_ONE) { + cosa = NEARLY_ONE; + } + cosa = 2 * cosa * cosa - 1; /* double angle */ + double sina = sqrt(1 - cosa * cosa) * dir; + double tempang = atan2(sina, cosa); + int num_vectors = (int)(fabs(angle / tempang)) + 1; + return num_vectors; +} - void Span::SplitMatrix(int num_vectors, Matrix* matrix) { - // returns the incremental matrix - matrix->Unit(); - if(dir) { - // arc span - double incang = angle / (double) num_vectors ; +void Span::SplitMatrix(int num_vectors, Matrix* matrix) +{ + // returns the incremental matrix + matrix->Unit(); + if (dir) { + // arc span + double incang = angle / (double)num_vectors; - matrix->Translate(-pc.x, -pc.y, 0); - matrix->Rotate(incang, 3); - matrix->Translate(pc.x, pc.y, 0); - } else { - // linear span - matrix->Translate(length / num_vectors * vs.getx(), length / num_vectors * vs.gety(), 0); - } - } + matrix->Translate(-pc.x, -pc.y, 0); + matrix->Rotate(incang, 3); + matrix->Translate(pc.x, pc.y, 0); + } + else { + // linear span + matrix->Translate(length / num_vectors * vs.getx(), length / num_vectors * vs.gety(), 0); + } +} #if 0 void Span3d::SplitMatrix(int num_vectors, Matrix* matrix) { @@ -235,49 +254,59 @@ namespace geoff_geometry { } #endif - void Span::minmax(Box& box, bool start) { - minmax(box.min, box.max, start); - } +void Span::minmax(Box& box, bool start) +{ + minmax(box.min, box.max, start); +} #if 0 void Span3d::minmax(Box3d& box, bool start) { minmax(box.min, box.max, start); } #endif - void Span::minmax(Point& min, Point& max, bool start) { - // box a span (min/max) - if(start) { - MinMax(p0, min, max); - } - MinMax(p1, min, max); +void Span::minmax(Point& min, Point& max, bool start) +{ + // box a span (min/max) + if (start) { + MinMax(p0, min, max); + } + MinMax(p1, min, max); - if(dir) { - // check the quadrant points - double dx1 = p1.x - p0.x; - double dy1 = p1.y - p0.y; + if (dir) { + // check the quadrant points + double dx1 = p1.x - p0.x; + double dy1 = p1.y - p0.y; - double dx = pc.x - p0.x; - double dy = pc.y - p0.y; + double dx = pc.x - p0.x; + double dy = pc.y - p0.y; - double dx0 = dx + radius; // 0deg + double dx0 = dx + radius; // 0deg - if( dir * (dx0 * dy1 - dx1 * dy) > 0) { - if(pc.x + radius > max.x) max.x = pc.x + radius; - } - dx0 = dx - radius; // 180deg - if( dir * (dx0 * dy1 - dx1 * dy) > 0) { - if(pc.x - radius < min.x) min.x = pc.x - radius; - } - double dy0 = dy + radius; // 90deg - if( dir * (dx * dy1 - dx1 * dy0) > 0) { - if(pc.y + radius > max.y) max.y = pc.y + radius; - } + if (dir * (dx0 * dy1 - dx1 * dy) > 0) { + if (pc.x + radius > max.x) { + max.x = pc.x + radius; + } + } + dx0 = dx - radius; // 180deg + if (dir * (dx0 * dy1 - dx1 * dy) > 0) { + if (pc.x - radius < min.x) { + min.x = pc.x - radius; + } + } + double dy0 = dy + radius; // 90deg + if (dir * (dx * dy1 - dx1 * dy0) > 0) { + if (pc.y + radius > max.y) { + max.y = pc.y + radius; + } + } - dy0 = dy - radius; // 270deg - if( dir * (dx * dy1 - dx1 * dy0) > 0) { - if(pc.y - radius < min.y) min.y = pc.y - radius; - } - } - } + dy0 = dy - radius; // 270deg + if (dir * (dx * dy1 - dx1 * dy0) > 0) { + if (pc.y - radius < min.y) { + min.y = pc.y - radius; + } + } + } +} #if 0 void Span3d::minmax(Point3d& min, Point3d& max, bool start) { @@ -317,46 +346,58 @@ namespace geoff_geometry { } #endif - int Span::Intof(const Span& sp, Point& pInt1, Point& pInt2, double t[4])const { - // Intof 2 spans - return geoff_geometry::Intof(*this, sp, pInt1, pInt2, t); - } +int Span::Intof(const Span& sp, Point& pInt1, Point& pInt2, double t[4]) const +{ + // Intof 2 spans + return geoff_geometry::Intof(*this, sp, pInt1, pInt2, t); +} - Point Span::Near(const Point& p)const{ - // returns the near point to span from p - if(this->dir == LINEAR) { - double t; - t = (Vector2d(this->p0, p) * this->vs); // t parametrised 0 - line length - return this->vs * t + this->p0; - } else { - double r = p.Dist(this->pc); - if(r < geoff_geometry::TOLERANCE) - return (p.Dist(this->p0) < p.Dist(this->p1))?this->p0 : this->p1; - return(p.Mid(this->pc, (r - this->radius) / r)); - } - } - Point Span::NearOn(const Point& p)const{ - // returns the near point to span from p - returned point is always on the span - Point pn; - pn = Near(p); - if(this->OnSpan(pn)) - return pn; +Point Span::Near(const Point& p) const +{ + // returns the near point to span from p + if (this->dir == LINEAR) { + double t; + t = (Vector2d(this->p0, p) * this->vs); // t parametrised 0 - line length + return this->vs * t + this->p0; + } + else { + double r = p.Dist(this->pc); + if (r < geoff_geometry::TOLERANCE) { + return (p.Dist(this->p0) < p.Dist(this->p1)) ? this->p0 : this->p1; + } + return (p.Mid(this->pc, (r - this->radius) / r)); + } +} +Point Span::NearOn(const Point& p) const +{ + // returns the near point to span from p - returned point is always on the span + Point pn; + pn = Near(p); + if (this->OnSpan(pn)) { + return pn; + } - // return nearest endpoint - return (pn.Dist(p0) < pn.Dist(p1))?p0 : p1; - } + // return nearest endpoint + return (pn.Dist(p0) < pn.Dist(p1)) ? p0 : p1; +} - void Span::Transform(const Matrix& m, bool setprops) { - p0 = p0.Transform(m); - p1 = p1.Transform(m); - if(dir != LINEAR) { - pc = pc.Transform(m); - if(m.m_mirrored == -1) FAILURE(L"Don't know mirror - use IsMirrored method on object"); - if(m.m_mirrored) dir = -dir; - } - if(setprops) - SetProperties(true); - } +void Span::Transform(const Matrix& m, bool setprops) +{ + p0 = p0.Transform(m); + p1 = p1.Transform(m); + if (dir != LINEAR) { + pc = pc.Transform(m); + if (m.m_mirrored == -1) { + FAILURE(L"Don't know mirror - use IsMirrored method on object"); + } + if (m.m_mirrored) { + dir = -dir; + } + } + if (setprops) { + SetProperties(true); + } +} #if 0 void Span3d::Transform(const Matrix& m, bool setprops) { @@ -373,100 +414,109 @@ namespace geoff_geometry { } #endif - Point Span::Mid()const { - // midpoint of a span +Point Span::Mid() const +{ + // midpoint of a span - return geoff_geometry::Mid(*this); - - } + return geoff_geometry::Mid(*this); +} - Point Span::MidPerim(double d)const { - /// returns a point which is 0-d along span - Point p; - if(this->dir == LINEAR) { - p = this->vs * d + this->p0; - } - else { - Vector2d v(pc, p0); - v.Rotate(d * dir / this->radius); - p = v + pc; - } - return p; - } +Point Span::MidPerim(double d) const +{ + /// returns a point which is 0-d along span + Point p; + if (this->dir == LINEAR) { + p = this->vs * d + this->p0; + } + else { + Vector2d v(pc, p0); + v.Rotate(d * dir / this->radius); + p = v + pc; + } + return p; +} - Point Span::MidParam(double param)const { - /// returns a point which is 0-1 along span - if(fabs(param) < 0.00000000000001) - return p0; - if(fabs(param - 1.0) < 0.00000000000001) - return p1; - return MidPerim(param * this->length); - } +Point Span::MidParam(double param) const +{ + /// returns a point which is 0-1 along span + if (fabs(param) < 0.00000000000001) { + return p0; + } + if (fabs(param - 1.0) < 0.00000000000001) { + return p1; + } + return MidPerim(param * this->length); +} - Vector2d Span::GetVector(double fraction)const { - /// returns the direction vector at point which is 0-1 along span - if(dir == 0){ - Vector2d v(p0, p1); - v.normalise(); - return v; - } +Vector2d Span::GetVector(double fraction) const +{ + /// returns the direction vector at point which is 0-1 along span + if (dir == 0) { + Vector2d v(p0, p1); + v.normalise(); + return v; + } - Point p= MidParam(fraction); - Vector2d v(pc, p); - v.normalise(); - if(dir == ACW) - { - return Vector2d(-v.gety(), v.getx()); - } - else - { - return Vector2d(v.gety(), -v.getx()); - } - } + Point p = MidParam(fraction); + Vector2d v(pc, p); + v.normalise(); + if (dir == ACW) { + return Vector2d(-v.gety(), v.getx()); + } + else { + return Vector2d(v.gety(), -v.getx()); + } +} - Kurve::Kurve(const Kurve& k) :Matrix(){ - /// copy constructor - this->m_nVertices = k.m_nVertices; - memcpy(this->e, k.e, 16 * sizeof(double)); - this->m_unit = k.m_unit; - this->m_mirrored = k.m_mirrored; - this->m_isReversed = k.m_isReversed; - this->m_started = k.m_started; - for(unsigned int i = 0; i < k.m_spans.size(); i++) { - SpanVertex* spv = new SpanVertex; - *spv = *k.m_spans[i]; - this->m_spans.push_back(spv); - } - } +Kurve::Kurve(const Kurve& k) + : Matrix() +{ + /// copy constructor + this->m_nVertices = k.m_nVertices; + memcpy(this->e, k.e, 16 * sizeof(double)); + this->m_unit = k.m_unit; + this->m_mirrored = k.m_mirrored; + this->m_isReversed = k.m_isReversed; + this->m_started = k.m_started; + for (unsigned int i = 0; i < k.m_spans.size(); i++) { + SpanVertex* spv = new SpanVertex; + *spv = *k.m_spans[i]; + this->m_spans.push_back(spv); + } +} - const Kurve& Kurve::operator=( const Kurve &k) { - if (this == &k) - return *this; +const Kurve& Kurve::operator=(const Kurve& k) +{ + if (this == &k) { + return *this; + } - memcpy(e, k.e, 16 * sizeof(double)); - m_unit = k.m_unit; - m_mirrored = k.m_mirrored; - m_isReversed = k.m_isReversed; + memcpy(e, k.e, 16 * sizeof(double)); + m_unit = k.m_unit; + m_mirrored = k.m_mirrored; + m_isReversed = k.m_isReversed; - this->Clear(); + this->Clear(); - if(k.m_nVertices) m_started = true; -// m_nVertices = 0; + if (k.m_nVertices) { + m_started = true; + } + // m_nVertices = 0; -// spVertex spv; -// for(int i = 0; i < k.m_nVertices; i++) { -// k.Get(i, spv); -// Add(spv); -// } - for(unsigned int i = 0; i < k.m_spans.size(); i++) { - SpanVertex* spv = new SpanVertex; - *spv = *k.m_spans[i]; - this->m_spans.push_back(spv); - } - m_nVertices = k.m_nVertices; - return *this; - } + // spVertex spv; + // for(int i = 0; i < k.m_nVertices; i++) { + // k.Get(i, spv); + // Add(spv); + // } + for (unsigned int i = 0; i < k.m_spans.size(); i++) { + SpanVertex* spv = new SpanVertex; + *spv = *k.m_spans[i]; + this->m_spans.push_back(spv); + } + m_nVertices = k.m_nVertices; + return *this; +} #if 0 @@ -504,296 +554,345 @@ return; } #endif - const Kurve& Kurve::operator=(const Matrix &m) - { -// *this = Matrix(m); -// return *this; +const Kurve& Kurve::operator=(const Matrix& m) +{ + // *this = Matrix(m); + // return *this; - for(int i = 0; i < 16; i++) e[i] = m.e[i]; - m_unit = m.m_unit; - m_mirrored = m.m_mirrored; - return *this; - } + for (int i = 0; i < 16; i++) { + e[i] = m.e[i]; + } + m_unit = m.m_unit; + m_mirrored = m.m_mirrored; + return *this; +} - Kurve::~Kurve() - { - this->Clear(); - } +Kurve::~Kurve() +{ + this->Clear(); +} +bool Kurve::Closed() const +{ + // returns true if kurve closed + if (m_nVertices > 1) { + Point ps, pe, pc; + Get(0, ps, pc); + Get(m_nVertices - 1, pe, pc); + return (ps == pe); + } + else { + return false; + } +} - bool Kurve::Closed()const - { - // returns true if kurve closed - if(m_nVertices > 1) { - Point ps, pe, pc; - Get(0, ps, pc); - Get(m_nVertices - 1, pe, pc); - return (ps == pe); - } - else - return false; - } +void Kurve::FullCircle(int dir, const Point& c, double radius) +{ + /// make a full circle Kurve (2 spans) + /// mark the first span for later + this->Clear(); + Point ps = c; + ps.x = c.x + radius; + this->Start(ps); + this->AddSpanID(FULL_CIRCLE_KURVE); + ps.x = c.x - radius; + this->Add(dir, ps, c, true); + ps.x = c.x + radius; + this->Add(dir, ps, c, true); +} - void Kurve::FullCircle(int dir, const Point& c, double radius) { - /// make a full circle Kurve (2 spans) - /// mark the first span for later - this->Clear(); - Point ps = c; - ps.x = c.x + radius; - this->Start(ps); - this->AddSpanID(FULL_CIRCLE_KURVE); - ps.x = c.x - radius; - this->Add(dir, ps, c, true); - ps.x = c.x + radius; - this->Add(dir, ps, c, true); - } - - void Kurve::Start() - { - if(m_started) this->Clear(); - m_started = true; - } +void Kurve::Start() +{ + if (m_started) { + this->Clear(); + } + m_started = true; +} - void Kurve::Start(const Point& p) - { - Start(); - Add(0, p, Point(0,0)); - } +void Kurve::Start(const Point& p) +{ + Start(); + Add(0, p, Point(0, 0)); +} - bool Kurve::Add(const Span& sp, bool AddNullSpans) { - // add a span, including ID - if(!this->m_started) - this->Start(sp.p0); - if(this->Add(sp.dir, sp.p1, sp.pc, AddNullSpans)) { - this->AddSpanID(sp.ID); - return true; - } - return false; - } +bool Kurve::Add(const Span& sp, bool AddNullSpans) +{ + // add a span, including ID + if (!this->m_started) { + this->Start(sp.p0); + } + if (this->Add(sp.dir, sp.p1, sp.pc, AddNullSpans)) { + this->AddSpanID(sp.ID); + return true; + } + return false; +} - bool Kurve::Add(const spVertex& spv, bool AddNullSpans) { - if(Add(spv.type, spv.p, spv.pc, AddNullSpans)) { - AddSpanID(spv.spanid); - return true; - } - return false; - } +bool Kurve::Add(const spVertex& spv, bool AddNullSpans) +{ + if (Add(spv.type, spv.p, spv.pc, AddNullSpans)) { + AddSpanID(spv.spanid); + return true; + } + return false; +} - bool Kurve::Add(int span_type, const Point& p0, const Point& pc, bool AddNullSpans) - { - // add a span (cw = -1 (T) acw = 1 (A) ) +bool Kurve::Add(int span_type, const Point& p0, const Point& pc, bool AddNullSpans) +{ + // add a span (cw = -1 (T) acw = 1 (A) ) #ifdef _DEBUG - //if(this == NULL) FAILURE(L"Kurve::Add - No Kurve Object"); + // if(this == NULL) FAILURE(L"Kurve::Add - No Kurve Object"); #endif - if(!m_started) { - Start(p0); - return true; - } + if (!m_started) { + Start(p0); + return true; + } - if(m_nVertices) { - // see if a null span would result by the addition of this span - // double xl, yl, cxl, cyl; - Point pv, pcc; - Get(m_nVertices - 1, pv, pcc); - if(pv.Dist(p0) < geoff_geometry::TOLERANCE) { - if(!AddNullSpans) - return false; - span_type = LINEAR; // linear span - } - } + if (m_nVertices) { + // see if a null span would result by the addition of this span + // double xl, yl, cxl, cyl; + Point pv, pcc; + Get(m_nVertices - 1, pv, pcc); + if (pv.Dist(p0) < geoff_geometry::TOLERANCE) { + if (!AddNullSpans) { + return false; + } + span_type = LINEAR; // linear span + } + } - SpanVertex* p; - if(m_nVertices % SPANSTORAGE == 0) { - p = new SpanVertex; - m_spans.push_back(p); - } - else - p = (SpanVertex*) m_spans[m_nVertices / SPANSTORAGE]; + SpanVertex* p; + if (m_nVertices % SPANSTORAGE == 0) { + p = new SpanVertex; + m_spans.push_back(p); + } + else { + p = (SpanVertex*)m_spans[m_nVertices / SPANSTORAGE]; + } - p->Add(m_nVertices % SPANSTORAGE, span_type, p0, pc); - m_nVertices++; - return true; - } - void Kurve::AddSpanID(int ID) - { - // add a extra data - must be called after Add - int vertex = this->m_nVertices - 1; - SpanVertex* p = (SpanVertex*) m_spans[vertex / SPANSTORAGE]; - p->AddSpanID(vertex % SPANSTORAGE, ID); - } + p->Add(m_nVertices % SPANSTORAGE, span_type, p0, pc); + m_nVertices++; + return true; +} +void Kurve::AddSpanID(int ID) +{ + // add a extra data - must be called after Add + int vertex = this->m_nVertices - 1; + SpanVertex* p = (SpanVertex*)m_spans[vertex / SPANSTORAGE]; + p->AddSpanID(vertex % SPANSTORAGE, ID); +} - void Kurve::Add() { - // null span - if(m_nVertices == 0) FAILURE(L"Invalid attempt to add null span - no start"); - Point p, pc; - Get(m_nVertices - 1, p, pc); - Add(p, true); - } +void Kurve::Add() +{ + // null span + if (m_nVertices == 0) { + FAILURE(L"Invalid attempt to add null span - no start"); + } + Point p, pc; + Get(m_nVertices - 1, p, pc); + Add(p, true); +} - bool Kurve::Add(const Point& p0, bool AddNullSpans) { - return Add(0, p0, Point(0,0), AddNullSpans); - } +bool Kurve::Add(const Point& p0, bool AddNullSpans) +{ + return Add(0, p0, Point(0, 0), AddNullSpans); +} - void Kurve::Add(const Kurve* k, bool AddNullSpans) { - Span sp; - Matrix m; - if(!this->m_unit) { - m = *k; - Matrix im = this->Inverse(); - m.Multiply(im); - m.IsUnit(); - } - for(int i = 1; i <= k->nSpans(); i++) { - k->Get(i, sp, false, this->m_unit); - #ifndef PEPSDLL - const SpanDataObject* obj = k->GetIndex(i-1); - #endif - if(!this->m_unit) - sp.Transform(m); - - if(i == 1) { - // check if this is the same as last point in kurve - bool AddFirstVertex = true; - if(nSpans()) { - Span spLast; - Get(nSpans(), spLast, false, false); - if(spLast.p1.Dist(sp.p0) <= geoff_geometry::TOLERANCE) AddFirstVertex = false; - } - if(AddFirstVertex) { - Add(sp.p0, AddNullSpans); - #ifndef PEPSDLL - if(obj != NULL) { - SpanDataObject* objnew = new SpanDataObject(obj); - AddIndex(nSpans() - 1, objnew); - } - #endif - } - } - - Add(sp.dir, sp.p1, sp.pc, AddNullSpans); - #ifndef PEPSDLL - if(obj != NULL) { - SpanDataObject* objnew = new SpanDataObject(obj); - AddIndex(nSpans() - 1, objnew); - } - #endif - } - } - - void Kurve::Replace(int vertexnumber, const spVertex& spv) { - // replace a span - Replace(vertexnumber, spv.type, spv.p, spv.pc, spv.spanid); - } - - - void Kurve::Replace(int vertexnumber, int type, const Point& p0, const Point& pc, int ID) { - // replace a span -#ifdef _DEBUG - if(vertexnumber > m_nVertices) FAILURE(getMessage(L"Kurve::Replace - vertexNumber out of range")); +void Kurve::Add(const Kurve* k, bool AddNullSpans) +{ + Span sp; + Matrix m; + if (!this->m_unit) { + m = *k; + Matrix im = this->Inverse(); + m.Multiply(im); + m.IsUnit(); + } + for (int i = 1; i <= k->nSpans(); i++) { + k->Get(i, sp, false, this->m_unit); +#ifndef PEPSDLL + const SpanDataObject* obj = k->GetIndex(i - 1); #endif - SpanVertex* p = (SpanVertex*) m_spans[vertexnumber / SPANSTORAGE]; - p->Add(vertexnumber % SPANSTORAGE, type, p0, pc, ID); - } + if (!this->m_unit) { + sp.Transform(m); + } + + if (i == 1) { + // check if this is the same as last point in kurve + bool AddFirstVertex = true; + if (nSpans()) { + Span spLast; + Get(nSpans(), spLast, false, false); + if (spLast.p1.Dist(sp.p0) <= geoff_geometry::TOLERANCE) { + AddFirstVertex = false; + } + } + if (AddFirstVertex) { + Add(sp.p0, AddNullSpans); +#ifndef PEPSDLL + if (obj != NULL) { + SpanDataObject* objnew = new SpanDataObject(obj); + AddIndex(nSpans() - 1, objnew); + } +#endif + } + } + + Add(sp.dir, sp.p1, sp.pc, AddNullSpans); +#ifndef PEPSDLL + if (obj != NULL) { + SpanDataObject* objnew = new SpanDataObject(obj); + AddIndex(nSpans() - 1, objnew); + } +#endif + } +} + +void Kurve::Replace(int vertexnumber, const spVertex& spv) +{ + // replace a span + Replace(vertexnumber, spv.type, spv.p, spv.pc, spv.spanid); +} + + +void Kurve::Replace(int vertexnumber, int type, const Point& p0, const Point& pc, int ID) +{ + // replace a span +#ifdef _DEBUG + if (vertexnumber > m_nVertices) { + FAILURE(getMessage(L"Kurve::Replace - vertexNumber out of range")); + } +#endif + SpanVertex* p = (SpanVertex*)m_spans[vertexnumber / SPANSTORAGE]; + p->Add(vertexnumber % SPANSTORAGE, type, p0, pc, ID); +} #ifdef PEPSDLL - void Kurve::ModifyIndex(int vertexnumber, WireExtraData* i) { - // replace an index +void Kurve::ModifyIndex(int vertexnumber, WireExtraData* i) +{ + // replace an index #ifdef _DEBUG - if(vertexnumber > m_nVertices) FAILURE(getMessage(L"Kurve::ModifyIndex - vertexNumber out of range")); + if (vertexnumber > m_nVertices) { + FAILURE(getMessage(L"Kurve::ModifyIndex - vertexNumber out of range")); + } #endif - SpanVertex* p = (SpanVertex*) m_spans[vertexnumber / SPANSTORAGE]; - p->Add(vertexnumber % SPANSTORAGE, i); - } + SpanVertex* p = (SpanVertex*)m_spans[vertexnumber / SPANSTORAGE]; + p->Add(vertexnumber % SPANSTORAGE, i); +} #else - void Kurve::AddIndex(int vertexNumber, const SpanDataObject* data) { - if(vertexNumber > m_nVertices - 1) FAILURE(L"Kurve::AddIndex - vertexNumber out of range"); - SpanVertex* p = (SpanVertex*) m_spans[vertexNumber / SPANSTORAGE]; - p->Add(vertexNumber % SPANSTORAGE, data); - } +void Kurve::AddIndex(int vertexNumber, const SpanDataObject* data) +{ + if (vertexNumber > m_nVertices - 1) { + FAILURE(L"Kurve::AddIndex - vertexNumber out of range"); + } + SpanVertex* p = (SpanVertex*)m_spans[vertexNumber / SPANSTORAGE]; + p->Add(vertexNumber % SPANSTORAGE, data); +} - const SpanDataObject* Kurve::GetIndex(int vertexNumber)const { - if(vertexNumber > m_nVertices - 1) FAILURE(L"Kurve::GetIndex - vertexNumber out of range"); - SpanVertex* p = (SpanVertex*) m_spans[vertexNumber / SPANSTORAGE]; - return p->GetIndex(vertexNumber % SPANSTORAGE); - } +const SpanDataObject* Kurve::GetIndex(int vertexNumber) const +{ + if (vertexNumber > m_nVertices - 1) { + FAILURE(L"Kurve::GetIndex - vertexNumber out of range"); + } + SpanVertex* p = (SpanVertex*)m_spans[vertexNumber / SPANSTORAGE]; + return p->GetIndex(vertexNumber % SPANSTORAGE); +} #endif - void Kurve::Get(std::vector *all, bool igNoreNullSpans)const { - /// put all spans to vector - for(int i = 1; i <= nSpans(); i++) { - Span sp; - Get(i, sp, true); - if(igNoreNullSpans && sp.NullSpan) - continue; - all->push_back(sp); - } - } +void Kurve::Get(std::vector* all, bool igNoreNullSpans) const +{ + /// put all spans to vector + for (int i = 1; i <= nSpans(); i++) { + Span sp; + Get(i, sp, true); + if (igNoreNullSpans && sp.NullSpan) { + continue; + } + all->push_back(sp); + } +} - void Kurve::Get(int vertexnumber, spVertex& spv) const { - spv.type = Get(vertexnumber, spv.p, spv.pc); - spv.spanid = GetSpanID(vertexnumber); - } +void Kurve::Get(int vertexnumber, spVertex& spv) const +{ + spv.type = Get(vertexnumber, spv.p, spv.pc); + spv.spanid = GetSpanID(vertexnumber); +} - int Kurve::Get(int vertexnumber, Point& pe, Point& pc) const { - // returns spantype with end / centre by reference - if(vertexnumber < 0 || vertexnumber >= m_nVertices) FAILURE(getMessage(L"Kurve::Get - vertexNumber out of range")); - if(m_isReversed) { - int revVertexnumber = m_nVertices - 1 - vertexnumber; - SpanVertex* p = (SpanVertex*)m_spans[revVertexnumber / SPANSTORAGE]; - int offset = revVertexnumber % SPANSTORAGE; - pe = Point(p->x[offset], p->y[offset]); - if(vertexnumber > 0) { - revVertexnumber++; - offset = revVertexnumber % SPANSTORAGE; - p = (SpanVertex*)m_spans[revVertexnumber / SPANSTORAGE]; - pc = Point(p->xc[offset], p->yc[offset]); - return -p->type[offset]; - } - else return LINEAR; - } - else { - SpanVertex* p = (SpanVertex*)m_spans[vertexnumber / SPANSTORAGE]; - return p->Get(vertexnumber % SPANSTORAGE, pe, pc); - } - } - int Kurve::GetSpanID(int vertexnumber) const { - // for spanID (wire offset) - if(vertexnumber < 0 || vertexnumber >= m_nVertices) FAILURE(getMessage(L"Kurve::Get - vertexNumber out of range")); - if(m_isReversed) - vertexnumber = m_nVertices - 1 - vertexnumber; - SpanVertex* p = (SpanVertex*)m_spans[vertexnumber / SPANSTORAGE]; - return p->GetSpanID(vertexnumber % SPANSTORAGE); - } - int Kurve::Get(int spannumber, Span& sp, bool returnSpanProperties, bool transform) const { - // returns span data and optional properties - the function returns as the span type - if(spannumber < 1 || spannumber > m_nVertices) FAILURE(getMessage(L"Kurve::Get - vertexNumber out of range")); - if(m_nVertices < 2) - return -99; +int Kurve::Get(int vertexnumber, Point& pe, Point& pc) const +{ + // returns spantype with end / centre by reference + if (vertexnumber < 0 || vertexnumber >= m_nVertices) { + FAILURE(getMessage(L"Kurve::Get - vertexNumber out of range")); + } + if (m_isReversed) { + int revVertexnumber = m_nVertices - 1 - vertexnumber; + SpanVertex* p = (SpanVertex*)m_spans[revVertexnumber / SPANSTORAGE]; + int offset = revVertexnumber % SPANSTORAGE; + pe = Point(p->x[offset], p->y[offset]); + if (vertexnumber > 0) { + revVertexnumber++; + offset = revVertexnumber % SPANSTORAGE; + p = (SpanVertex*)m_spans[revVertexnumber / SPANSTORAGE]; + pc = Point(p->xc[offset], p->yc[offset]); + return -p->type[offset]; + } + else { + return LINEAR; + } + } + else { + SpanVertex* p = (SpanVertex*)m_spans[vertexnumber / SPANSTORAGE]; + return p->Get(vertexnumber % SPANSTORAGE, pe, pc); + } +} +int Kurve::GetSpanID(int vertexnumber) const +{ + // for spanID (wire offset) + if (vertexnumber < 0 || vertexnumber >= m_nVertices) { + FAILURE(getMessage(L"Kurve::Get - vertexNumber out of range")); + } + if (m_isReversed) { + vertexnumber = m_nVertices - 1 - vertexnumber; + } + SpanVertex* p = (SpanVertex*)m_spans[vertexnumber / SPANSTORAGE]; + return p->GetSpanID(vertexnumber % SPANSTORAGE); +} +int Kurve::Get(int spannumber, Span& sp, bool returnSpanProperties, bool transform) const +{ + // returns span data and optional properties - the function returns as the span type + if (spannumber < 1 || spannumber > m_nVertices) { + FAILURE(getMessage(L"Kurve::Get - vertexNumber out of range")); + } + if (m_nVertices < 2) { + return -99; + } - int spanVertexNumber = spannumber - 1; - if(m_isReversed) spanVertexNumber = m_nVertices - 1 - spanVertexNumber; - SpanVertex* p = (SpanVertex*)m_spans[spanVertexNumber / SPANSTORAGE]; - sp.p0.x = p->x[spanVertexNumber % SPANSTORAGE]; - sp.p0.y = p->y[spanVertexNumber % SPANSTORAGE]; - sp.p0.ok = 1; + int spanVertexNumber = spannumber - 1; + if (m_isReversed) { + spanVertexNumber = m_nVertices - 1 - spanVertexNumber; + } + SpanVertex* p = (SpanVertex*)m_spans[spanVertexNumber / SPANSTORAGE]; + sp.p0.x = p->x[spanVertexNumber % SPANSTORAGE]; + sp.p0.y = p->y[spanVertexNumber % SPANSTORAGE]; + sp.p0.ok = 1; - sp.dir = Get(spannumber, sp.p1, sp.pc); - sp.ID = GetSpanID(spannumber); + sp.dir = Get(spannumber, sp.p1, sp.pc); + sp.ID = GetSpanID(spannumber); - if(transform && !m_unit) { - const Matrix *m = this; - sp.Transform(*m, false); - } + if (transform && !m_unit) { + const Matrix* m = this; + sp.Transform(*m, false); + } - sp.SetProperties(returnSpanProperties); + sp.SetProperties(returnSpanProperties); - return sp.dir; - } + return sp.dir; +} #if 0 int Kurve::Get(int spannumber, Span3d& sp, bool returnSpanProperties, bool transform) const { @@ -822,61 +921,63 @@ return; } #endif - void Kurve::Get(Point &ps,Point &pe) const - { - // returns the start- and endpoint of the kurve - Span sp; - Get(1,sp,true,true); - ps = sp.p0; - Get(m_nVertices-1,sp,true,true); - pe = sp.p1; - } +void Kurve::Get(Point& ps, Point& pe) const +{ + // returns the start- and endpoint of the kurve + Span sp; + Get(1, sp, true, true); + ps = sp.p0; + Get(m_nVertices - 1, sp, true, true); + pe = sp.p1; +} - void Span::SetProperties(bool returnProperties) { - returnSpanProperties = returnProperties; - if(returnSpanProperties) { - // return span properties - if(dir) { - // arc properties - vs = ~Vector2d(pc, p0); // tangent at start ( perp to radial vector) - ve = ~Vector2d(pc, p1); // tangent at end ( perp to radial vector) - if(dir == CW) { - vs = -vs; // reverse directions for CW arc - ve = -ve; - } +void Span::SetProperties(bool returnProperties) +{ + returnSpanProperties = returnProperties; + if (returnSpanProperties) { + // return span properties + if (dir) { + // arc properties + vs = ~Vector2d(pc, p0); // tangent at start ( perp to radial vector) + ve = ~Vector2d(pc, p1); // tangent at end ( perp to radial vector) + if (dir == CW) { + vs = -vs; // reverse directions for CW arc + ve = -ve; + } - radius = vs.normalise(); - double radCheck = ve.normalise(); -// if(FNE(radius, radCheck, geoff_geometry::TOLERANCE * 0.5)){ - if(FNE(radius, radCheck, geoff_geometry::TOLERANCE)){ - FAILURE(getMessage(L"Invalid Geometry - Radii mismatch - SetProperties")); - } + radius = vs.normalise(); + double radCheck = ve.normalise(); + // if(FNE(radius, radCheck, geoff_geometry::TOLERANCE * 0.5)){ + if (FNE(radius, radCheck, geoff_geometry::TOLERANCE)) { + FAILURE(getMessage(L"Invalid Geometry - Radii mismatch - SetProperties")); + } - length = 0.0; - angle = 0.0; - if(radius > geoff_geometry::TOLERANCE) { - if((NullSpan = (p0.Dist(p1)) <= geoff_geometry::TOLERANCE)) { - dir = LINEAR; - } - else { - // arc length & included angle - length = fabs(angle = IncludedAngle(vs, ve, dir)) * radius; - } - } - else - NullSpan = true; - } - else { - // straight properties - vs = Vector2d(p0, p1); + length = 0.0; + angle = 0.0; + if (radius > geoff_geometry::TOLERANCE) { + if ((NullSpan = (p0.Dist(p1)) <= geoff_geometry::TOLERANCE)) { + dir = LINEAR; + } + else { + // arc length & included angle + length = fabs(angle = IncludedAngle(vs, ve, dir)) * radius; + } + } + else { + NullSpan = true; + } + } + else { + // straight properties + vs = Vector2d(p0, p1); - length = vs.normalise(); - NullSpan = (length <= geoff_geometry::TOLERANCE); - ve = vs; - } - minmax(box, true); - } - } + length = vs.normalise(); + NullSpan = (length <= geoff_geometry::TOLERANCE); + ve = vs; + } + minmax(box, true); + } +} #if 0 void Span3d::SetProperties(bool returnProperties) { @@ -922,426 +1023,486 @@ return; #endif - Point Mid(const Span& span) { - // mid point of a span - if(span.dir) { - CLine chord(span.p0, span.p1); - if(chord.ok) { - CLine bisector(Mid(span.p0, span.p1), ~chord.v, false); - return Intof((span.dir == CW) ?FARINT : NEARINT, bisector, Circle(span)); - } - else - return span.p0; - } - else - return Mid(span.p0, span.p1); - } +Point Mid(const Span& span) +{ + // mid point of a span + if (span.dir) { + CLine chord(span.p0, span.p1); + if (chord.ok) { + CLine bisector(Mid(span.p0, span.p1), ~chord.v, false); + return Intof((span.dir == CW) ? FARINT : NEARINT, bisector, Circle(span)); + } + else { + return span.p0; + } + } + else { + return Mid(span.p0, span.p1); + } +} - Point Kurve::Near(const Point& p, int& nearSpanNumber)const { - // finds the nearest span on kurve to the given point, nearSpanNumber is the spannumber - double minDist = 1.0e100; - Point pNear, pn; +Point Kurve::Near(const Point& p, int& nearSpanNumber) const +{ + // finds the nearest span on kurve to the given point, nearSpanNumber is the spannumber + double minDist = 1.0e100; + Point pNear, pn; - nearSpanNumber = 0; - for(int i = 1; i <= nSpans(); i++) { - Span sp; - Get(i, sp, true, true); - pNear = sp.NearOn(p); - double d = pNear.Dist(p); - if(minDist > d) { - nearSpanNumber = i; - pn = pNear; - minDist = d; - if(minDist < geoff_geometry::TOLERANCE) break; // p must be on the span - } - } - return pn; - } + nearSpanNumber = 0; + for (int i = 1; i <= nSpans(); i++) { + Span sp; + Get(i, sp, true, true); + pNear = sp.NearOn(p); + double d = pNear.Dist(p); + if (minDist > d) { + nearSpanNumber = i; + pn = pNear; + minDist = d; + if (minDist < geoff_geometry::TOLERANCE) { + break; // p must be on the span + } + } + } + return pn; +} - Point Kurve::NearToVertex(const Point& p, int& nearSpanNumber)const { - // finds the nearest span endpoint on kurve to the given point, nearSpanNumber is the spannumber - double minDistSquared = 1.0e100; - Point pn; +Point Kurve::NearToVertex(const Point& p, int& nearSpanNumber) const +{ + // finds the nearest span endpoint on kurve to the given point, nearSpanNumber is the spannumber + double minDistSquared = 1.0e100; + Point pn; - Matrix inv_mat = *this; - inv_mat.Inverse(); + Matrix inv_mat = *this; + inv_mat.Inverse(); - Point tp = p; - if(!m_unit) tp = tp.Transform(inv_mat); // Inverse transform point (rather than transform each vertex!) + Point tp = p; + if (!m_unit) { + tp = tp.Transform(inv_mat); // Inverse transform point (rather than transform each vertex!) + } - nearSpanNumber = 0; + nearSpanNumber = 0; - for(int i = 0; i < m_nVertices; i++) { - Point ps, pc; - Get(i, ps, pc); - double DistSquared = Vector2d(ps, tp).magnitudesqd(); - if(DistSquared < minDistSquared) { - minDistSquared = DistSquared; - nearSpanNumber = i; - pn = ps; - } - } - return pn.Transform(*this); - } + for (int i = 0; i < m_nVertices; i++) { + Point ps, pc; + Get(i, ps, pc); + double DistSquared = Vector2d(ps, tp).magnitudesqd(); + if (DistSquared < minDistSquared) { + minDistSquared = DistSquared; + nearSpanNumber = i; + pn = ps; + } + } + return pn.Transform(*this); +} - void Kurve::ChangeStart(const Point *pNewStart, int startSpanno) { - // changes the start position of the Kurve - if(startSpanno == 1) { - Span spFirst; - this->Get(1, spFirst, false, true); - if(spFirst.p0 == *pNewStart) - return; - } - else if(startSpanno == this->nSpans()) { - Span spLast; - this->Get(this->nSpans(), spLast, false, true); - if(spLast.p1 == *pNewStart) - return; - } - Kurve temp; +void Kurve::ChangeStart(const Point* pNewStart, int startSpanno) +{ + // changes the start position of the Kurve + if (startSpanno == 1) { + Span spFirst; + this->Get(1, spFirst, false, true); + if (spFirst.p0 == *pNewStart) { + return; + } + } + else if (startSpanno == this->nSpans()) { + Span spLast; + this->Get(this->nSpans(), spLast, false, true); + if (spLast.p1 == *pNewStart) { + return; + } + } + Kurve temp; - bool wrapped = false; - int spanno = startSpanno; - Span sp; - for(int nSpans = 0; nSpans <= this->nSpans(); nSpans++) - { - this->Get(spanno, sp, false, true); - if(spanno == startSpanno && !wrapped) { - temp.Start(*pNewStart); - temp.Add(sp.dir, sp.p1, sp.pc, true); - } - else { - if(nSpans == this->nSpans() && this->Closed()) { - sp.p1 = *pNewStart; - } - temp.Add(sp, true); - } + bool wrapped = false; + int spanno = startSpanno; + Span sp; + for (int nSpans = 0; nSpans <= this->nSpans(); nSpans++) { + this->Get(spanno, sp, false, true); + if (spanno == startSpanno && !wrapped) { + temp.Start(*pNewStart); + temp.Add(sp.dir, sp.p1, sp.pc, true); + } + else { + if (nSpans == this->nSpans() && this->Closed()) { + sp.p1 = *pNewStart; + } + temp.Add(sp, true); + } - spanno++; + spanno++; - if(spanno > this->nSpans()) { - if(!this->Closed()) - break; - spanno = 1; - wrapped = true; - } - } + if (spanno > this->nSpans()) { + if (!this->Closed()) { + break; + } + spanno = 1; + wrapped = true; + } + } - *this = temp; - } + *this = temp; +} - void Kurve::ChangeEnd(const Point *pNewEnd, int endSpanno) { - // changes the end position of the Kurve, doesn't keep closed kurves closed - if(endSpanno == 1) { - Span spFirst; - this->Get(1, spFirst, false, true); - if(spFirst.p0 == *pNewEnd) - return; - } - else if(endSpanno == this->nSpans()) { - Span spLast; - this->Get(this->nSpans(), spLast, false, true); - if(spLast.p1 == *pNewEnd) - return; - } - Kurve temp; +void Kurve::ChangeEnd(const Point* pNewEnd, int endSpanno) +{ + // changes the end position of the Kurve, doesn't keep closed kurves closed + if (endSpanno == 1) { + Span spFirst; + this->Get(1, spFirst, false, true); + if (spFirst.p0 == *pNewEnd) { + return; + } + } + else if (endSpanno == this->nSpans()) { + Span spLast; + this->Get(this->nSpans(), spLast, false, true); + if (spLast.p1 == *pNewEnd) { + return; + } + } + Kurve temp; - Span sp; + Span sp; - for(int spanno = 1; spanno != (endSpanno + 1); spanno++) - { - this->Get(spanno, sp, false, true); - if(spanno == 1) { - temp.Start(sp.p0); - } + for (int spanno = 1; spanno != (endSpanno + 1); spanno++) { + this->Get(spanno, sp, false, true); + if (spanno == 1) { + temp.Start(sp.p0); + } - if(spanno == endSpanno)sp.p1 = *pNewEnd; + if (spanno == endSpanno) { + sp.p1 = *pNewEnd; + } - temp.Add(sp.dir, sp.p1, sp.pc, true); - if(spanno == endSpanno)break; + temp.Add(sp.dir, sp.p1, sp.pc, true); + if (spanno == endSpanno) { + break; + } - //spanno++; - } + // spanno++; + } - *this = temp; - } + *this = temp; +} - void Kurve::minmax(Point& min, Point& max) { - // boxes kurve - double xscale = 1.0; - min = Point(1.0e61, 1.0e61); - max = Point(-1.0e61, -1.0e61); +void Kurve::minmax(Point& min, Point& max) +{ + // boxes kurve + double xscale = 1.0; + min = Point(1.0e61, 1.0e61); + max = Point(-1.0e61, -1.0e61); - if(!GetScale(xscale)) FAILURE(getMessage(L"Differential Scale not allowed for this method")); // differential scale - Span sp; - for(int i = 1; i < m_nVertices; i++) { - Get(i, sp, true, true); - if(i == 1) MinMax(sp.p0, min, max); - sp.minmax(min, max, false); - } - } + if (!GetScale(xscale)) { + FAILURE( + getMessage(L"Differential Scale not allowed for this method")); // differential scale + } + Span sp; + for (int i = 1; i < m_nVertices; i++) { + Get(i, sp, true, true); + if (i == 1) { + MinMax(sp.p0, min, max); + } + sp.minmax(min, max, false); + } +} - void Kurve::minmax(Box& b) { - minmax(b.min, b.max); - } +void Kurve::minmax(Box& b) +{ + minmax(b.min, b.max); +} - void Kurve::StoreAllSpans(std::vector& kSpans)const { // store all kurve spans in array, normally when fast access is reqd - Span span; - for(int i = 1; i <= this->nSpans(); i++) { - this->Get(i, span, true, false); - kSpans.push_back(span); - } - } +void Kurve::StoreAllSpans(std::vector& kSpans) const +{ // store all kurve spans in array, normally when fast access is reqd + Span span; + for (int i = 1; i <= this->nSpans(); i++) { + this->Get(i, span, true, false); + kSpans.push_back(span); + } +} - void Kurve::Clear() - { - for(vector::iterator It = m_spans.begin(); It != m_spans.end(); It++) - { - SpanVertex* spv = *It; - delete spv; - } - m_spans.clear(); - m_started = false; - m_nVertices = 0; - m_isReversed = false; - } +void Kurve::Clear() +{ + for (vector::iterator It = m_spans.begin(); It != m_spans.end(); It++) { + SpanVertex* spv = *It; + delete spv; + } + m_spans.clear(); + m_started = false; + m_nVertices = 0; + m_isReversed = false; +} - bool Kurve::operator==(const Kurve &k)const{ - // k = kk (vertex check) - if(nSpans() != k.nSpans()) - return false; - spVertex thisvertex, vertex; - for(int i = 0; i <= nSpans(); i++) { - this->Get(i, thisvertex); - k.Get(i, vertex); - if(thisvertex != vertex) - return false; - } - return true; - } +bool Kurve::operator==(const Kurve& k) const +{ + // k = kk (vertex check) + if (nSpans() != k.nSpans()) { + return false; + } + spVertex thisvertex, vertex; + for (int i = 0; i <= nSpans(); i++) { + this->Get(i, thisvertex); + k.Get(i, vertex); + if (thisvertex != vertex) { + return false; + } + } + return true; +} - double Kurve::Perim() const{ - // returns perimeter of kurve - double perim = 0; - Span sp; - double xscale = 1.0; - if(!GetScale(xscale)) FAILURE(getMessage(L"Differential Scale not allowed for this method")); // differential scale +double Kurve::Perim() const +{ + // returns perimeter of kurve + double perim = 0; + Span sp; + double xscale = 1.0; + if (!GetScale(xscale)) { + FAILURE( + getMessage(L"Differential Scale not allowed for this method")); // differential scale + } - if(m_nVertices > 1) { - for(int i = 1; i < m_nVertices; i++) - perim += (Get(i, sp, true))? fabs(sp.angle) * sp.radius : sp.length; - } - return perim * xscale; - } - double Kurve::Area() const{ - // returns Area of kurve (+ve clockwise , -ve anti-clockwise sense) - double xscale = 1.0; - double area = 0; - Span sp; + if (m_nVertices > 1) { + for (int i = 1; i < m_nVertices; i++) { + perim += (Get(i, sp, true)) ? fabs(sp.angle) * sp.radius : sp.length; + } + } + return perim * xscale; +} +double Kurve::Area() const +{ + // returns Area of kurve (+ve clockwise , -ve anti-clockwise sense) + double xscale = 1.0; + double area = 0; + Span sp; - if(Closed()) { - if(!GetScale(xscale)) FAILURE(getMessage(L"Differential Scale not allowed for this method")); // differential scale - for(int i = 1; i < m_nVertices; i++) { - if(Get(i, sp, true)) - area += ( 0.5 * ((sp.pc.x - sp.p0.x) * (sp.pc.y + sp.p0.y) - (sp.pc.x - sp.p1.x) * (sp.pc.y + sp.p1.y) - sp.angle * sp.radius * sp.radius)); - else - area += 0.5 * (sp.p1.x - sp.p0.x) * (sp.p0.y + sp.p1.y); - } - } - return area * xscale * xscale; - } + if (Closed()) { + if (!GetScale(xscale)) { + FAILURE(getMessage( + L"Differential Scale not allowed for this method")); // differential scale + } + for (int i = 1; i < m_nVertices; i++) { + if (Get(i, sp, true)) { + area += (0.5 + * ((sp.pc.x - sp.p0.x) * (sp.pc.y + sp.p0.y) + - (sp.pc.x - sp.p1.x) * (sp.pc.y + sp.p1.y) + - sp.angle * sp.radius * sp.radius)); + } + else { + area += 0.5 * (sp.p1.x - sp.p0.x) * (sp.p0.y + sp.p1.y); + } + } + } + return area * xscale * xscale; +} - static void bubblesort(vector&p, vector& d); +static void bubblesort(vector& p, vector& d); - int Kurve::Intof(const Span& spin, vector& p)const { - // returns a vector (array) of intersection points - int totalPoints = 0; - for(int i = 1; i <= nSpans(); i++) { - Span sp; - Get(i, sp, true, true); +int Kurve::Intof(const Span& spin, vector& p) const +{ + // returns a vector (array) of intersection points + int totalPoints = 0; + for (int i = 1; i <= nSpans(); i++) { + Span sp; + Get(i, sp, true, true); - Point pInt1, pInt2; - double t[4]; - int numint = sp.Intof(spin, pInt1, pInt2, t); - if(numint) p.push_back(pInt1); - if(numint == 2) p.push_back(pInt2); - totalPoints += numint; - } - if(totalPoints) { - // sort intersects along span - vector d; - Span temp(spin); + Point pInt1, pInt2; + double t[4]; + int numint = sp.Intof(spin, pInt1, pInt2, t); + if (numint) { + p.push_back(pInt1); + } + if (numint == 2) { + p.push_back(pInt2); + } + totalPoints += numint; + } + if (totalPoints) { + // sort intersects along span + vector d; + Span temp(spin); - for(int i = 0; i < (int)p.size(); i++) { - temp.p1 = p[i]; - temp.SetProperties(true); + for (int i = 0; i < (int)p.size(); i++) { + temp.p1 = p[i]; + temp.SetProperties(true); - d.push_back(temp.length); - } - bubblesort(p, d); - } - return totalPoints; - } + d.push_back(temp.length); + } + bubblesort(p, d); + } + return totalPoints; +} - static void bubblesort(vector&p, vector& d) { +static void bubblesort(vector& p, vector& d) +{ - for(int pass = 1; pass < (int)p.size() ; pass++) { - for(int j = 0; j < (int)p.size() - 1; j++) { - if(d[j] > d[j+1] ) { - // swap - Point temp = p[j]; - p[j] = p[j+1]; - p[j+1] = temp; - double dtemp = d[j]; - d[j] = d[j+1]; - d[j+1] = dtemp; - } - } - } - } + for (int pass = 1; pass < (int)p.size(); pass++) { + for (int j = 0; j < (int)p.size() - 1; j++) { + if (d[j] > d[j + 1]) { + // swap + Point temp = p[j]; + p[j] = p[j + 1]; + p[j + 1] = temp; + double dtemp = d[j]; + d[j] = d[j + 1]; + d[j + 1] = dtemp; + } + } + } +} - int Kurve::Intof(const Kurve&k, vector& p)const { - vector all; +int Kurve::Intof(const Kurve& k, vector& p) const +{ + vector all; - int totalPoints = 0; - for(int i = 1; i <= nSpans(); i++) { - Span sp; - Get(i, sp, true, true); - vector p0; - totalPoints += k.Intof(sp, p0); + int totalPoints = 0; + for (int i = 1; i <= nSpans(); i++) { + Span sp; + Get(i, sp, true, true); + vector p0; + totalPoints += k.Intof(sp, p0); - for(int j = 0; j < (int)p0.size(); j++) all.push_back(p0[j]); - } - (void)totalPoints; - //FILE* d; - //d = fopen("\\temp\\test.txt", "w"); - // for(int l = 0; l < all.size(); l++) all[l].print(d, "all","\n"); + for (int j = 0; j < (int)p0.size(); j++) { + all.push_back(p0[j]); + } + } + (void)totalPoints; + // FILE* d; + // d = fopen("\\temp\\test.txt", "w"); + // for(int l = 0; l < all.size(); l++) all[l].print(d, "all","\n"); - for(int i = 0; i < (int)all.size(); i++) { - if(i == 0) - p.push_back(all[0]); - else - if(all[i-1].Dist(all[i]) > geoff_geometry::TOLERANCE) p.push_back(all[i]); - } + for (int i = 0; i < (int)all.size(); i++) { + if (i == 0) { + p.push_back(all[0]); + } + else if (all[i - 1].Dist(all[i]) > geoff_geometry::TOLERANCE) { + p.push_back(all[i]); + } + } - //fclose(d); - return (int)p.size(); - } + // fclose(d); + return (int)p.size(); +} - bool Kurve::Split(double MaximumRadius, double resolution) { +bool Kurve::Split(double MaximumRadius, double resolution) +{ - Span sp; - bool changed = false; - Kurve ko; + Span sp; + bool changed = false; + Kurve ko; - Get(0, sp.p0, sp.pc); - ko.Start(sp.p0); + Get(0, sp.p0, sp.pc); + ko.Start(sp.p0); - for(int i = 1 ; i < m_nVertices; i++) { - sp.dir = Get(i, sp.p1, sp.pc); - if(sp.dir) { - sp.SetProperties(true); - if(sp.radius >= MaximumRadius) { - // split this arc - int nSplits = sp.Split(resolution); - if(nSplits > 1) { - Matrix m; - sp.SplitMatrix(nSplits, &m); - for(int j = 1; j < nSplits; j++) { - sp.p0 = sp.p0.Transform(m); - ko.Add(sp.p0); - } + for (int i = 1; i < m_nVertices; i++) { + sp.dir = Get(i, sp.p1, sp.pc); + if (sp.dir) { + sp.SetProperties(true); + if (sp.radius >= MaximumRadius) { + // split this arc + int nSplits = sp.Split(resolution); + if (nSplits > 1) { + Matrix m; + sp.SplitMatrix(nSplits, &m); + for (int j = 1; j < nSplits; j++) { + sp.p0 = sp.p0.Transform(m); + ko.Add(sp.p0); + } - sp.dir = LINEAR; - changed = true; - } - } - } + sp.dir = LINEAR; + changed = true; + } + } + } - ko.Add(sp.dir, sp.p1, sp.pc); + ko.Add(sp.dir, sp.p1, sp.pc); - sp.p0 = sp.p1; + sp.p0 = sp.p1; + } + // copy kurve + if (changed) { + *this = ko; + } + return changed; +} - } - // copy kurve - if(changed) *this = ko; - return changed; - } +void Kurve::Reverse() +{ + // reverse the direction of a kurve + int nSwaps = (m_nVertices - 1) / 2; + if (nSwaps == 0) { + return; + } + Point p0, pc0; // near + Point pend, pcend; // far - void Kurve::Reverse() { - // reverse the direction of a kurve - int nSwaps = (m_nVertices - 1) / 2; - if(nSwaps == 0) - return; - Point p0, pc0; // near - Point pend, pcend; // far + int i = 0, j = m_nVertices - 1; + int dir0 = Get(i, p0, pc0); + int spanID0 = GetSpanID(i); + int dirend = Get(j, pend, pcend); + int spanIDend = GetSpanID(j); - int i = 0, j = m_nVertices - 1; - int dir0 = Get(i, p0, pc0); - int spanID0 = GetSpanID(i); - int dirend = Get(j, pend, pcend); - int spanIDend = GetSpanID(j); + while (i <= nSwaps) { + Point p1, pc1; + int dir1 = Get(i + 1, p1, pc1); + int spanID1 = GetSpanID(i + 1); + Point pendp, pcendp; // far previous + int direndp = Get(j - 1, pendp, pcendp); + int spanIDendp = GetSpanID(j - 1); + // end point + Replace(i, dir0, pend, pc0, spanID0); + Replace(j, dirend, p0, pcend, spanIDend); - while(i <= nSwaps) { - Point p1, pc1; - int dir1 = Get(i+1, p1, pc1); - int spanID1 = GetSpanID(i+1); - Point pendp, pcendp; // far previous - int direndp = Get(j-1, pendp, pcendp); - int spanIDendp = GetSpanID(j-1); - // end point - Replace(i, dir0, pend, pc0, spanID0); - Replace(j, dirend, p0, pcend, spanIDend); + dir0 = dir1; + p0 = p1; + pc0 = pc1; + dirend = direndp; + pend = pendp; + pcend = pcendp; + spanID0 = spanID1; + spanIDend = spanIDendp; - dir0 = dir1; - p0 = p1; - pc0 = pc1; - dirend = direndp; - pend = pendp; - pcend = pcendp; - spanID0 = spanID1; - spanIDend = spanIDendp; + i++; + j--; + } - i++; - j--; - } + // now circle data - but it should be easy to modify centre data in the loop above (for another + // day) + i = 0; + j = m_nVertices - 1; + dir0 = Get(i, p0, pc0); + dirend = Get(j, pend, pcend); - // now circle data - but it should be easy to modify centre data in the loop above (for another day) - i = 0; - j = m_nVertices - 1; - dir0 = Get(i, p0, pc0); - dirend = Get(j, pend, pcend); + while (i < nSwaps) { + Point p1, pc1; + Point pendp, pcendp; // far previous - while(i < nSwaps) { - Point p1, pc1; - Point pendp, pcendp; // far previous + int dir1 = Get(i + 1, p1, pc1); + int direndp = Get(j - 1, pendp, pcendp); - int dir1 = Get(i+1, p1, pc1); - int direndp = Get(j-1, pendp, pcendp); + Replace(i + 1, -dirend, p1, pcend); + Replace(j, -dir1, pend, pc1); + dir0 = dir1; + p0 = p1; + pc0 = pc1; + dirend = direndp; + pend = pendp; + pcend = pcendp; + i++; + j--; + } +} - Replace(i+1, -dirend, p1, pcend); - Replace(j, -dir1, pend, pc1); - dir0 = dir1; - p0 = p1; - pc0 = pc1; - dirend = direndp; - pend = pendp; - pcend = pcendp; - i++; - j--; - } - } - - int Kurve::Reduce(double tolerance) { - // remove spans that lie within tolerance - // returns the number of spans removed - if(nSpans() <= 2) // too few spans for this method - return 0; - Kurve kReduced; - kReduced = Matrix(*this); +int Kurve::Reduce(double tolerance) +{ + // remove spans that lie within tolerance + // returns the number of spans removed + if (nSpans() <= 2) { // too few spans for this method + return 0; + } + Kurve kReduced; + kReduced = Matrix(*this); #if 0 for(int i = 1; i <= this->nSpans(); i++) { @@ -1357,191 +1518,191 @@ return; return m_nVertices - kReduced.m_nVertices; #else - int dir1, dir2 = 0; - Point p0, p1, p2, pc0, pc1, pc2; - int vertex = 0; - int dir0 = Get(vertex++, p0, pc0); // first vertex - kReduced.Start(p0); - int lvertex = vertex++; + int dir1, dir2 = 0; + Point p0, p1, p2, pc0, pc1, pc2; + int vertex = 0; + int dir0 = Get(vertex++, p0, pc0); // first vertex + kReduced.Start(p0); + int lvertex = vertex++; - while(vertex < m_nVertices) { - while(vertex < m_nVertices) { - int savelvertex = lvertex; - int addvertex = vertex - 1; - dir2 = Get(vertex++, p2, pc2); - CLine cl(p0, p2); - if(cl.ok) { - bool outoftol = false; - while(lvertex < vertex - 1) { // interior loop, p1 after p0 up to vertex before p2 - dir1 = Get(lvertex++, p1, pc1); + while (vertex < m_nVertices) { + while (vertex < m_nVertices) { + int savelvertex = lvertex; + int addvertex = vertex - 1; + dir2 = Get(vertex++, p2, pc2); + CLine cl(p0, p2); + if (cl.ok) { + bool outoftol = false; + while (lvertex < vertex - 1) { // interior loop, p1 after p0 up to vertex before p2 + dir1 = Get(lvertex++, p1, pc1); - if(dir1 || fabs(cl.Dist(p1)) > tolerance) { - outoftol = true; - break; - } - } - if(outoftol) { - dir0 = Get(addvertex, p0, pc0); - kReduced.Add(dir0, p0, pc0); - lvertex = addvertex + 1; - } - else { - lvertex = savelvertex; - } - } - } - } - kReduced.Add(dir2, p2, pc2); + if (dir1 || fabs(cl.Dist(p1)) > tolerance) { + outoftol = true; + break; + } + } + if (outoftol) { + dir0 = Get(addvertex, p0, pc0); + kReduced.Add(dir0, p0, pc0); + lvertex = addvertex + 1; + } + else { + lvertex = savelvertex; + } + } + } + } + kReduced.Add(dir2, p2, pc2); - if(m_nVertices != kReduced.m_nVertices) *this = kReduced; - return m_nVertices - kReduced.m_nVertices; + if (m_nVertices != kReduced.m_nVertices) { + *this = kReduced; + } + return m_nVertices - kReduced.m_nVertices; #endif - } +} -void Kurve::Part(int startVertex, int EndVertex, Kurve *part) { - // make a part kurve - spVertex spv; - for(int i = startVertex; i <= EndVertex; i++) { - Get(i, spv); - part->Add(spv, true); - } - return; +void Kurve::Part(int startVertex, int EndVertex, Kurve* part) +{ + // make a part kurve + spVertex spv; + for (int i = startVertex; i <= EndVertex; i++) { + Get(i, spv); + part->Add(spv, true); + } + return; } -Kurve Kurve::Part(int fromSpanno, const Point& fromPt, int toSpanno, const Point& toPt) { - // make a Part Kurve - // if spanno are known containing from/to Points then this is used, otherwise set = 0 - Kurve kPart; - Span span; - Point ps,pe; - int iStartSpanNr,iEndSpanNr,i; +Kurve Kurve::Part(int fromSpanno, const Point& fromPt, int toSpanno, const Point& toPt) +{ + // make a Part Kurve + // if spanno are known containing from/to Points then this is used, otherwise set = 0 + Kurve kPart; + Span span; + Point ps, pe; + int iStartSpanNr, iEndSpanNr, i; - // get start point and start spannumber - if(fromSpanno == 0) - ps = Near(fromPt,iStartSpanNr); - else - { - Get(fromSpanno,span,true,true); - ps = span.p0; - iStartSpanNr = fromSpanno; - } - // get end point and end spannumber - if(toSpanno == 0) - pe = Near(toPt,iEndSpanNr); - else - { - Get(toSpanno,span,true,true); - pe = span.p1; - iEndSpanNr = toSpanno; - } + // get start point and start spannumber + if (fromSpanno == 0) { + ps = Near(fromPt, iStartSpanNr); + } + else { + Get(fromSpanno, span, true, true); + ps = span.p0; + iStartSpanNr = fromSpanno; + } + // get end point and end spannumber + if (toSpanno == 0) { + pe = Near(toPt, iEndSpanNr); + } + else { + Get(toSpanno, span, true, true); + pe = span.p1; + iEndSpanNr = toSpanno; + } - kPart.Start(ps); - Get(iStartSpanNr,span,true,true); + kPart.Start(ps); + Get(iStartSpanNr, span, true, true); - if(iStartSpanNr == iEndSpanNr) - { - kPart.Add(span.dir,pe,span.pc); - return kPart; - } - - if(iStartSpanNr < iEndSpanNr) - { - for(i=iStartSpanNr;i iEndSpanNr) - { - for(i=iStartSpanNr;i<=nSpans();i++) - { - Get(i,span,true,true); - kPart.Add(span.dir,span.p1,span.pc); - } - if(!Closed()) - { - Get(1,span,true,true); - kPart.Add(0,span.p0,Point(0.0,0.0)); // Add new span from kend to kstart - } - for(i=1;iPerim(); - double fromPerim = fromParam * perimTotal; - double toPerim = toParam * perimTotal; - double perim = 0.; - double perimLast = 0.; - for(int i = 1; i <= this->nSpans(); i++) { - Span sp; - this->Get(i, sp, true, true); - perim += sp.length; - if(fromPerim <= perim && !k.m_started) { - // start - if(FEQ(fromPerim, perim)) - k.Start(sp.p0); - else { - double d = fromPerim - perimLast; - k.Start(sp.MidPerim(d)); - } - } - - if(perim >= toPerim) { - // end - if(FEQ(toPerim, perim)) - k.Add(sp); - else { - double d = toPerim - perimLast; - sp.p1 = sp.MidPerim(d); - k.Add(sp); - } - break; - } - if(k.m_started) - k.Add(sp); - perimLast = perim; - } - return k; - } - - void tangential_arc(const Point &p0, const Point &p1, const Vector2d &v0, Point &c, int &dir) - { - // sets dir to 0, if a line is needed, else to 1 or -1 for acw or cw arc and sets c - dir = 0; - - if(p0.Dist(p1) > 0.0000000001 && v0.magnitude() > 0.0000000001){ - Vector2d v1(p0, p1); - Point halfway(p0 + Point(v1 * 0.5)); - Plane pl1(halfway, v1); - Plane pl2(p0, v0); - Line plane_line; - if(pl1.Intof(pl2, plane_line)) - { - Line l1(halfway, v1); - double t1, t2; - Line lshort; - plane_line.Shortest(l1, lshort, t1, t2); - c = lshort.p0; - Vector3d cross = Vector3d(v0) ^ Vector3d(v1); - dir = (cross.getz() > 0) ? 1:-1; - } - } - } + if (iStartSpanNr == iEndSpanNr) { + kPart.Add(span.dir, pe, span.pc); + return kPart; + } + if (iStartSpanNr < iEndSpanNr) { + for (i = iStartSpanNr; i < iEndSpanNr; i++) { + Get(i, span, true, true); + kPart.Add(span.dir, span.p1, span.pc); + } + Get(iEndSpanNr, span, true, true); + kPart.Add(span.dir, pe, span.pc); + } + if (iStartSpanNr > iEndSpanNr) { + for (i = iStartSpanNr; i <= nSpans(); i++) { + Get(i, span, true, true); + kPart.Add(span.dir, span.p1, span.pc); + } + if (!Closed()) { + Get(1, span, true, true); + kPart.Add(0, span.p0, Point(0.0, 0.0)); // Add new span from kend to kstart + } + for (i = 1; i < iEndSpanNr; i++) { + Get(i, span, true, true); + kPart.Add(span.dir, span.p1, span.pc); + } + Get(iEndSpanNr, span, true, true); + kPart.Add(span.dir, pe, span.pc); + } + return kPart; } + +Kurve Kurve::Part(double fromParam, double toParam) +{ + /// return a part Kurve - perimeter parameterisation + /// fromParam & toParam 0 - 1 perimeter parameter + Kurve k; + + double perimTotal = this->Perim(); + double fromPerim = fromParam * perimTotal; + double toPerim = toParam * perimTotal; + double perim = 0.; + double perimLast = 0.; + for (int i = 1; i <= this->nSpans(); i++) { + Span sp; + this->Get(i, sp, true, true); + perim += sp.length; + if (fromPerim <= perim && !k.m_started) { + // start + if (FEQ(fromPerim, perim)) { + k.Start(sp.p0); + } + else { + double d = fromPerim - perimLast; + k.Start(sp.MidPerim(d)); + } + } + + if (perim >= toPerim) { + // end + if (FEQ(toPerim, perim)) { + k.Add(sp); + } + else { + double d = toPerim - perimLast; + sp.p1 = sp.MidPerim(d); + k.Add(sp); + } + break; + } + if (k.m_started) { + k.Add(sp); + } + perimLast = perim; + } + return k; +} + +void tangential_arc(const Point& p0, const Point& p1, const Vector2d& v0, Point& c, int& dir) +{ + // sets dir to 0, if a line is needed, else to 1 or -1 for acw or cw arc and sets c + dir = 0; + + if (p0.Dist(p1) > 0.0000000001 && v0.magnitude() > 0.0000000001) { + Vector2d v1(p0, p1); + Point halfway(p0 + Point(v1 * 0.5)); + Plane pl1(halfway, v1); + Plane pl2(p0, v0); + Line plane_line; + if (pl1.Intof(pl2, plane_line)) { + Line l1(halfway, v1); + double t1, t2; + Line lshort; + plane_line.Shortest(l1, lshort, t1, t2); + c = lshort.p0; + Vector3d cross = Vector3d(v0) ^ Vector3d(v1); + dir = (cross.getz() > 0) ? 1 : -1; + } + } +} + +} // namespace geoff_geometry diff --git a/src/Mod/CAM/libarea/kurve/offset.cpp b/src/Mod/CAM/libarea/kurve/offset.cpp index 3b808782b0..4f05f8959e 100644 --- a/src/Mod/CAM/libarea/kurve/offset.cpp +++ b/src/Mod/CAM/libarea/kurve/offset.cpp @@ -9,370 +9,420 @@ #include "geometry.h" using namespace geoff_geometry; -namespace geoff_geometry { - static Kurve eliminateLoops(const Kurve& k , const Kurve& originalk, double offset, int& ret); - static bool DoesIntersInterfere(const Point& pInt, const Kurve& k, double offset); +namespace geoff_geometry +{ +static Kurve eliminateLoops(const Kurve& k, const Kurve& originalk, double offset, int& ret); +static bool DoesIntersInterfere(const Point& pInt, const Kurve& k, double offset); - int Kurve::Offset(vector&OffsetKurves, double offset, int direction, int method, int& ret)const { +int Kurve::Offset(vector& OffsetKurves, + double offset, + int direction, + int method, + int& ret) const +{ - switch(method) { - case NO_ELIMINATION: - case BASIC_OFFSET: - { - Kurve* ko = new Kurve; - int n = OffsetMethod1(*ko, offset, direction, method, ret); - OffsetKurves.push_back(ko); - return n; - } + switch (method) { + case NO_ELIMINATION: + case BASIC_OFFSET: { + Kurve* ko = new Kurve; + int n = OffsetMethod1(*ko, offset, direction, method, ret); + OffsetKurves.push_back(ko); + return n; + } - default: - FAILURE(L"Requested Offsetting Method not available"); - } - return 0; - } + default: + FAILURE(L"Requested Offsetting Method not available"); + } + return 0; +} - int Kurve::OffsetMethod1(Kurve& kOffset, double off, int direction, int method, int& ret)const - { - // offset kurve with simple span elimination - // direction 1 = left, -1 = right +int Kurve::OffsetMethod1(Kurve& kOffset, double off, int direction, int method, int& ret) const +{ + // offset kurve with simple span elimination + // direction 1 = left, -1 = right - // ret = 0 - kurve offset ok - // = 1 - kurve has differential scale (not allowed) - // = 2 - offset failed - // = 3 - offset too large - if(this == &kOffset) FAILURE(L"Illegal Call - 'this' must not be kOffset"); - double offset = (direction == GEOFF_LEFT)?off : -off; + // ret = 0 - kurve offset ok + // = 1 - kurve has differential scale (not allowed) + // = 2 - offset failed + // = 3 - offset too large + if (this == &kOffset) { + FAILURE(L"Illegal Call - 'this' must not be kOffset"); + } + double offset = (direction == GEOFF_LEFT) ? off : -off; - if(fabs(offset) < geoff_geometry::TOLERANCE || m_nVertices < 2) { - kOffset = *this; - ret = 0; - return 1; - } + if (fabs(offset) < geoff_geometry::TOLERANCE || m_nVertices < 2) { + kOffset = *this; + ret = 0; + return 1; + } - Span curSpan, curSpanOff; // current & offset spans - Span prevSpanOff; // previous offset span - Point p0, p1; // Offset span intersections + Span curSpan, curSpanOff; // current & offset spans + Span prevSpanOff; // previous offset span + Point p0, p1; // Offset span intersections - // offset Kurve - kOffset = Matrix(*this); + // offset Kurve + kOffset = Matrix(*this); - if(m_mirrored) offset = -offset; - int RollDir = ( off < 0 ) ? direction : - direction; // Roll arc direction + if (m_mirrored) { + offset = -offset; + } + int RollDir = (off < 0) ? direction : -direction; // Roll arc direction - double scalex; - if(!GetScale(scalex)) { - ret = 1; - return 0; // differential scale - } - offset /= scalex; + double scalex; + if (!GetScale(scalex)) { + ret = 1; + return 0; // differential scale + } + offset /= scalex; - bool bClosed = Closed(); - int nspans = nSpans(); - if(bClosed) { - Get(nspans, curSpan, true); // assign previous span for closed + bool bClosed = Closed(); + int nspans = nSpans(); + if (bClosed) { + Get(nspans, curSpan, true); // assign previous span for closed - prevSpanOff = curSpan.Offset(offset); - nspans++; // read first again - } + prevSpanOff = curSpan.Offset(offset); + nspans++; // read first again + } - for(int spannumber = 1; spannumber <= nspans; spannumber++) { - if(spannumber > nSpans()) - Get(1, curSpan, true); // closed kurve - read first span again - else - Get(spannumber, curSpan, true); + for (int spannumber = 1; spannumber <= nspans; spannumber++) { + if (spannumber > nSpans()) { + Get(1, curSpan, true); // closed kurve - read first span again + } + else { + Get(spannumber, curSpan, true); + } - if(!curSpan.NullSpan) { - int numint = 0; - curSpanOff = curSpan.Offset(offset); - curSpanOff.ID = 0; - if(!kOffset.m_started) { - kOffset.Start(curSpanOff.p0); - kOffset.AddSpanID(0); - } + if (!curSpan.NullSpan) { + int numint = 0; + curSpanOff = curSpan.Offset(offset); + curSpanOff.ID = 0; + if (!kOffset.m_started) { + kOffset.Start(curSpanOff.p0); + kOffset.AddSpanID(0); + } - if(spannumber > 1) { - // see if tangent - double d = curSpanOff.p0.Dist(prevSpanOff.p1); - if((d > geoff_geometry::TOLERANCE) && (!curSpanOff.NullSpan && !prevSpanOff.NullSpan)) { - // see if offset spans intersect + if (spannumber > 1) { + // see if tangent + double d = curSpanOff.p0.Dist(prevSpanOff.p1); + if ((d > geoff_geometry::TOLERANCE) + && (!curSpanOff.NullSpan && !prevSpanOff.NullSpan)) { + // see if offset spans intersect - double cp = prevSpanOff.ve ^ curSpanOff.vs; - bool inters = (cp > 0 && direction == GEOFF_LEFT) || (cp < 0 && direction == GEOFF_RIGHT); + double cp = prevSpanOff.ve ^ curSpanOff.vs; + bool inters = + (cp > 0 && direction == GEOFF_LEFT) || (cp < 0 && direction == GEOFF_RIGHT); - if(inters) { - double t[4]; - numint = prevSpanOff.Intof(curSpanOff, p0, p1, t); - } + if (inters) { + double t[4]; + numint = prevSpanOff.Intof(curSpanOff, p0, p1, t); + } - if(numint == 1) { - // intersection - modify previous endpoint - kOffset.Replace(kOffset.m_nVertices-1, prevSpanOff.dir, p0, prevSpanOff.pc, prevSpanOff.ID); - } - else { - // 0 or 2 intersections, add roll around (remove -ve loops in elimination function) - if(kOffset.Add(RollDir, curSpanOff.p0, curSpan.p0, false)) kOffset.AddSpanID(ROLL_AROUND); - } - } - } + if (numint == 1) { + // intersection - modify previous endpoint + kOffset.Replace(kOffset.m_nVertices - 1, + prevSpanOff.dir, + p0, + prevSpanOff.pc, + prevSpanOff.ID); + } + else { + // 0 or 2 intersections, add roll around (remove -ve loops in elimination + // function) + if (kOffset.Add(RollDir, curSpanOff.p0, curSpan.p0, false)) { + kOffset.AddSpanID(ROLL_AROUND); + } + } + } + } - // add span - if(spannumber < m_nVertices) { - curSpanOff.ID = spannumber; - kOffset.Add(curSpanOff, false); - } - else if(numint == 1) // or replace the closed first span - kOffset.Replace(0, 0, p0, Point(0, 0), 0); - - } - if(!curSpanOff.NullSpan)prevSpanOff = curSpanOff; - } // end of main pre-offsetting loop + // add span + if (spannumber < m_nVertices) { + curSpanOff.ID = spannumber; + kOffset.Add(curSpanOff, false); + } + else if (numint == 1) { // or replace the closed first span + kOffset.Replace(0, 0, p0, Point(0, 0), 0); + } + } + if (!curSpanOff.NullSpan) { + prevSpanOff = curSpanOff; + } + } // end of main pre-offsetting loop #ifdef _DEBUG -//testDraw->AddKurve("", &kOffset, 0, GREEN); +// testDraw->AddKurve("", &kOffset, 0, GREEN); // outXML oxml(L"c:\\temp\\eliminateLoops.xml"); // oxml.startElement(L"eliminateLoops"); // oxml.Write(kOffset, L"kOffset"); // oxml.endElement(); #endif - // eliminate loops - if(method == NO_ELIMINATION) { - ret = 0; - return 1; - } - kOffset = eliminateLoops(kOffset, *this, offset, ret); + // eliminate loops + if (method == NO_ELIMINATION) { + ret = 0; + return 1; + } + kOffset = eliminateLoops(kOffset, *this, offset, ret); - if(ret == 0 && bClosed) { - // check for inverted offsets of closed kurves - if(kOffset.Closed()) { - double a = Area(); - int dir = (a < 0); - double ao = kOffset.Area(); - int dirOffset = ao < 0; + if (ret == 0 && bClosed) { + // check for inverted offsets of closed kurves + if (kOffset.Closed()) { + double a = Area(); + int dir = (a < 0); + double ao = kOffset.Area(); + int dirOffset = ao < 0; - if(dir != dirOffset) - ret = 3; - else { - // check area change compatible with offset direction - catastrophic failure - bool bigger = (a > 0 && offset > 0) || (a < 0 && offset < 0); - if(bigger && fabs(ao) < fabs(a)) ret = 2; - } - } - else - ret = 2; // started closed but now open?? - } - return (ret == 0)?1 : 0; - } - - - static Kurve eliminateLoops(const Kurve& k , const Kurve& originalk, double offset, int& ret) { - // a simple loop elimination routine based on first offset ideas in Peps - // this needs extensive work for future - // start point mustn't disappear & only one valid offset is determined - // - // ret = 0 for ok - // ret = 2 for impossible geometry - - Span sp0, sp1; - Point pInt, pIntOther; - - Kurve ko; // eliminated output - ko = Matrix(k); - int kinVertex = 0; - - while(kinVertex <= k.nSpans()) { - bool clipped = false ; // not in a clipped section (assumption with this simple method) - - sp0.dir = k.Get(kinVertex, sp0.p0, sp0.pc); - sp0.ID = k.GetSpanID(kinVertex++); - if (kinVertex == 1) { - ko.Start(sp0.p0); // start point mustn't disappear for this simple method - ko.AddSpanID(sp0.ID); - } - if (kinVertex <= k.nSpans()) { // any more? - int ksaveVertex = kinVertex ; - sp0.dir = k.Get(kinVertex, sp0.p1, sp0.pc); // first span - sp0.ID = k.GetSpanID(kinVertex++); - - sp0.SetProperties(true); - - int ksaveVertex1 = kinVertex; // mark position AA - if (kinVertex <= k.nSpans()) { // get the next but one span - sp1.dir = k.Get(kinVertex, sp1.p0, sp1.pc); - sp1.ID = k.GetSpanID(kinVertex++); - int ksaveVertex2 = kinVertex; // mark position BB - - int fwdCount = 0; - while(kinVertex <= k.nSpans()) { - sp1.dir = k.Get(kinVertex, sp1.p1, sp1.pc); // check span - sp1.ID = k.GetSpanID(kinVertex++); - sp1.SetProperties(true); - - double t[4]; - int numint = sp0.Intof(sp1, pInt, pIntOther, t); // find span intersections - if(numint && sp0.p0.Dist(pInt) < geoff_geometry::TOLERANCE ) numint=0; // check that intersection is not at the start of the check span - if(numint ) { - - if(numint == 2) { - // choose first intercept on sp0 - Span spd = sp0; - spd.p1 = pInt; - spd.SetProperties(true); - double dd = spd.length; - - spd.p1 = pIntOther; - spd.SetProperties(true); - if(dd > spd.length) pInt = pIntOther; - numint = 1; - - } - ksaveVertex = ksaveVertex1 ; - - clipped = true ; // in a clipped section - if(!DoesIntersInterfere(pInt, originalk, offset)) { - sp0.p1 = pInt; // ok so truncate this span to the intersection - clipped = false; // end of clipped section - break; - } - // no valid intersection found so carry on - } - sp1.p0 = sp1.p1 ; // next - ksaveVertex1 = ksaveVertex2 ; // pos AA = BB - ksaveVertex2 = kinVertex; // mark - - if((kinVertex > k.nSpans() || fwdCount++ > 25) && !clipped) - break; - } - } - - if(clipped) { - ret = 2; // still in a clipped section - error - - return ko; - } - - ko.Add(sp0, false); - - kinVertex = ksaveVertex; - } - } - ret = 0; - - return ko; // no more spans - seems ok - } - - - static bool DoesIntersInterfere(const Point& pInt, const Kurve& k, double offset) { - // check that intersections don't interfere with the original kurve - Span sp; - Point dummy; - int kCheckVertex = 0; - k.Get(kCheckVertex++, sp.p0, sp.pc); - - offset = fabs(offset) - geoff_geometry::TOLERANCE; - while(kCheckVertex <= k.nSpans()) { - sp.dir = k.Get(kCheckVertex++, sp.p1, sp.pc); - sp.SetProperties(true); - // check for interference - if(Dist(sp, pInt, dummy) < offset) - return true; - sp.p0 = sp.p1; - } - return false; // intersection is ok - } + if (dir != dirOffset) { + ret = 3; + } + else { + // check area change compatible with offset direction - catastrophic failure + bool bigger = (a > 0 && offset > 0) || (a < 0 && offset < 0); + if (bigger && fabs(ao) < fabs(a)) { + ret = 2; + } + } + } + else { + ret = 2; // started closed but now open?? + } + } + return (ret == 0) ? 1 : 0; } -static struct iso { - Span sp; - Span off; - } isodata; +static Kurve eliminateLoops(const Kurve& k, const Kurve& originalk, double offset, int& ret) +{ + // a simple loop elimination routine based on first offset ideas in Peps + // this needs extensive work for future + // start point mustn't disappear & only one valid offset is determined + // + // ret = 0 for ok + // ret = 2 for impossible geometry + + Span sp0, sp1; + Point pInt, pIntOther; + + Kurve ko; // eliminated output + ko = Matrix(k); + int kinVertex = 0; + + while (kinVertex <= k.nSpans()) { + bool clipped = false; // not in a clipped section (assumption with this simple method) + + sp0.dir = k.Get(kinVertex, sp0.p0, sp0.pc); + sp0.ID = k.GetSpanID(kinVertex++); + if (kinVertex == 1) { + ko.Start(sp0.p0); // start point mustn't disappear for this simple method + ko.AddSpanID(sp0.ID); + } + if (kinVertex <= k.nSpans()) { // any more? + int ksaveVertex = kinVertex; + sp0.dir = k.Get(kinVertex, sp0.p1, sp0.pc); // first span + sp0.ID = k.GetSpanID(kinVertex++); + + sp0.SetProperties(true); + + int ksaveVertex1 = kinVertex; // mark position AA + if (kinVertex <= k.nSpans()) { // get the next but one span + sp1.dir = k.Get(kinVertex, sp1.p0, sp1.pc); + sp1.ID = k.GetSpanID(kinVertex++); + int ksaveVertex2 = kinVertex; // mark position BB + + int fwdCount = 0; + while (kinVertex <= k.nSpans()) { + sp1.dir = k.Get(kinVertex, sp1.p1, sp1.pc); // check span + sp1.ID = k.GetSpanID(kinVertex++); + sp1.SetProperties(true); + + double t[4]; + int numint = sp0.Intof(sp1, pInt, pIntOther, t); // find span intersections + if (numint && sp0.p0.Dist(pInt) < geoff_geometry::TOLERANCE) { + numint = + 0; // check that intersection is not at the start of the check span + } + if (numint) { + + if (numint == 2) { + // choose first intercept on sp0 + Span spd = sp0; + spd.p1 = pInt; + spd.SetProperties(true); + double dd = spd.length; + + spd.p1 = pIntOther; + spd.SetProperties(true); + if (dd > spd.length) { + pInt = pIntOther; + } + numint = 1; + } + ksaveVertex = ksaveVertex1; + + clipped = true; // in a clipped section + if (!DoesIntersInterfere(pInt, originalk, offset)) { + sp0.p1 = pInt; // ok so truncate this span to the intersection + clipped = false; // end of clipped section + break; + } + // no valid intersection found so carry on + } + sp1.p0 = sp1.p1; // next + ksaveVertex1 = ksaveVertex2; // pos AA = BB + ksaveVertex2 = kinVertex; // mark + + if ((kinVertex > k.nSpans() || fwdCount++ > 25) && !clipped) { + break; + } + } + } + + if (clipped) { + ret = 2; // still in a clipped section - error + + return ko; + } + + ko.Add(sp0, false); + + kinVertex = ksaveVertex; + } + } + ret = 0; + + return ko; // no more spans - seems ok +} + + +static bool DoesIntersInterfere(const Point& pInt, const Kurve& k, double offset) +{ + // check that intersections don't interfere with the original kurve + Span sp; + Point dummy; + int kCheckVertex = 0; + k.Get(kCheckVertex++, sp.p0, sp.pc); + + offset = fabs(offset) - geoff_geometry::TOLERANCE; + while (kCheckVertex <= k.nSpans()) { + sp.dir = k.Get(kCheckVertex++, sp.p1, sp.pc); + sp.SetProperties(true); + // check for interference + if (Dist(sp, pInt, dummy) < offset) { + return true; + } + sp.p0 = sp.p1; + } + return false; // intersection is ok +} +} // namespace geoff_geometry + + +static struct iso +{ + Span sp; + Span off; +} isodata; static void isoRadius(Span& before, Span& blend, Span& after, double radius); -int Kurve::OffsetISOMethod(Kurve& kOut, double off, int direction, bool BlendAll)const { - // produces a special offset Kurve - observing so-called ISO radii - // eg line/arc/line tangent - keep arc radius constant - // this method also considers arc/arc/arc etc. - // interior radius must be smallest of triplet for above. +int Kurve::OffsetISOMethod(Kurve& kOut, double off, int direction, bool BlendAll) const +{ + // produces a special offset Kurve - observing so-called ISO radii + // eg line/arc/line tangent - keep arc radius constant + // this method also considers arc/arc/arc etc. + // interior radius must be smallest of triplet for above. - // parameters:- - // Output kOut resulting kurve - // Input off offset amount - // Input direction offset direction (LEFT or RIGHT) - // Input BlendAall if false only consider ISO radius for LINE/ARC/LINE - // if true consider all blended radii (ARC/ARC/ARC etc.) - double offset = (direction == GEOFF_LEFT)?off : -off; - if(FEQZ(off) || nSpans() < 1) { - kOut = *this; - return 1; - } - double cptol = 1.0e-05; - std::vector spans; - for(int i = 0; i < nSpans(); i++) { // store all spans and offsets - Get(i+1, isodata.sp, true, true); - isodata.off = isodata.sp.Offset(offset); - spans.push_back(isodata); - } + // parameters:- + // Output kOut resulting kurve + // Input off offset amount + // Input direction offset direction (LEFT or RIGHT) + // Input BlendAall if false only consider ISO radius for LINE/ARC/LINE + // if true consider all blended radii (ARC/ARC/ARC etc.) + double offset = (direction == GEOFF_LEFT) ? off : -off; + if (FEQZ(off) || nSpans() < 1) { + kOut = *this; + return 1; + } + double cptol = 1.0e-05; + std::vector spans; + for (int i = 0; i < nSpans(); i++) { // store all spans and offsets + Get(i + 1, isodata.sp, true, true); + isodata.off = isodata.sp.Offset(offset); + spans.push_back(isodata); + } - for(int i = 0; i < nSpans() - 1; i++) // calculate intersections for none tangent spans - if(fabs(spans[i].off.ve ^ spans[i+1].off.vs) > cptol) spans[i].off.JoinSeparateSpans(spans[i+1].off); + for (int i = 0; i < nSpans() - 1; i++) { // calculate intersections for none tangent spans + if (fabs(spans[i].off.ve ^ spans[i + 1].off.vs) > cptol) { + spans[i].off.JoinSeparateSpans(spans[i + 1].off); + } + } - for(int i = 1; i < nSpans() - 1; i++) { // deal with isoradii - if(spans[i].off.dir) { - if(BlendAll) { // interior radius should be smaller than neighbours - if(spans[i-1].sp.dir) - if(spans[i-1].sp.radius < spans[i].sp.radius) continue; - if(spans[i+1].sp.dir) - if(spans[i+1].sp.radius < spans[i].sp.radius) continue; - } - else { - if((spans[i-1].off.dir || spans[i+1].off.dir)) continue; // linear neighbours only - } + for (int i = 1; i < nSpans() - 1; i++) { // deal with isoradii + if (spans[i].off.dir) { + if (BlendAll) { // interior radius should be smaller than neighbours + if (spans[i - 1].sp.dir) { + if (spans[i - 1].sp.radius < spans[i].sp.radius) { + continue; + } + } + if (spans[i + 1].sp.dir) { + if (spans[i + 1].sp.radius < spans[i].sp.radius) { + continue; + } + } + } + else { + if ((spans[i - 1].off.dir || spans[i + 1].off.dir)) { + continue; // linear neighbours only + } + } - if((fabs(spans[i-1].sp.ve ^ spans[i].sp.vs) < cptol) && (fabs(spans[i].sp.ve ^ spans[i+1].sp.vs) < cptol)) { - // isoradius - calculate the new offset radius and modify neighbouring spans - isoRadius(spans[i-1].off, spans[i].off, spans[i+1].off, spans[i].sp.radius); - } - } - } + if ((fabs(spans[i - 1].sp.ve ^ spans[i].sp.vs) < cptol) + && (fabs(spans[i].sp.ve ^ spans[i + 1].sp.vs) < cptol)) { + // isoradius - calculate the new offset radius and modify neighbouring spans + isoRadius(spans[i - 1].off, spans[i].off, spans[i + 1].off, spans[i].sp.radius); + } + } + } - kOut.Start(spans[0].off.p0); // start point - for(int i = 0; i < nSpans(); i++) - kOut.Add(spans[i].off.dir, spans[i].off.p1, spans[i].off.pc); // output all spans - return 1; - } - -static void isoRadius(Span& before, Span& blend, Span& after, double radius) { - // calculate the new offset radius and modify neighbouring spans - int direction = ((before.ve ^ after.vs) > 0)? 1 : -1; // offset direction - Span beforeOff = before.Offset(direction * radius); - Span afterOff = after.Offset(direction * radius); - int turnLeft = ((before.ve ^ after.vs) > 0)? 1 : -1; - if(before.dir == LINEAR) { - CLine b(beforeOff); - if(after.dir == LINEAR) { - CLine a(afterOff); - blend.pc = b.Intof(a); - } - else { - Circle a(afterOff); - b.Intof(turnLeft * after.dir, a, blend.pc); - } - } - else { - Circle b(beforeOff); - - if(after.dir == LINEAR) { - CLine a(afterOff); - a.Intof(-turnLeft * before.dir, b, blend.pc); - } - else { - // arc arc - Circle a(afterOff); - int leftright = ((Vector2d(b.pc, blend.pc) ^ Vector2d(b.pc, a.pc)) < 0)? 1 : -1; - b.Intof(leftright, a, blend.pc); - } - } - before.p1 = blend.p0 = before.Near(blend.pc); - after.p0 = blend.p1 = after.Near(blend.pc); + kOut.Start(spans[0].off.p0); // start point + for (int i = 0; i < nSpans(); i++) { + kOut.Add(spans[i].off.dir, spans[i].off.p1, spans[i].off.pc); // output all spans + } + return 1; +} + +static void isoRadius(Span& before, Span& blend, Span& after, double radius) +{ + // calculate the new offset radius and modify neighbouring spans + int direction = ((before.ve ^ after.vs) > 0) ? 1 : -1; // offset direction + Span beforeOff = before.Offset(direction * radius); + Span afterOff = after.Offset(direction * radius); + int turnLeft = ((before.ve ^ after.vs) > 0) ? 1 : -1; + if (before.dir == LINEAR) { + CLine b(beforeOff); + if (after.dir == LINEAR) { + CLine a(afterOff); + blend.pc = b.Intof(a); + } + else { + Circle a(afterOff); + b.Intof(turnLeft * after.dir, a, blend.pc); + } + } + else { + Circle b(beforeOff); + + if (after.dir == LINEAR) { + CLine a(afterOff); + a.Intof(-turnLeft * before.dir, b, blend.pc); + } + else { + // arc arc + Circle a(afterOff); + int leftright = ((Vector2d(b.pc, blend.pc) ^ Vector2d(b.pc, a.pc)) < 0) ? 1 : -1; + b.Intof(leftright, a, blend.pc); + } + } + before.p1 = blend.p0 = before.Near(blend.pc); + after.p0 = blend.p1 = after.Near(blend.pc); } diff --git a/src/Mod/CAM/libarea/pyarea.cpp b/src/Mod/CAM/libarea/pyarea.cpp index 1527c8c595..50aaabd64b 100644 --- a/src/Mod/CAM/libarea/pyarea.cpp +++ b/src/Mod/CAM/libarea/pyarea.cpp @@ -4,7 +4,7 @@ #ifdef _MSC_VER - #define strdup _strdup +#define strdup _strdup #endif #include "Area.h" @@ -21,24 +21,25 @@ #include - namespace py = pybind11; -std::list getVertices(const CCurve& curve) { +std::list getVertices(const CCurve& curve) +{ return curve.m_vertices; } -std::list getCurves(const CArea& area) { +std::list getCurves(const CArea& area) +{ return area.m_curves; } -py::tuple transformed_point(const geoff_geometry::Matrix &matrix, double x, double y, double z) +py::tuple transformed_point(const geoff_geometry::Matrix& matrix, double x, double y, double z) { - geoff_geometry::Point3d p(x,y,z); + geoff_geometry::Point3d p(x, y, z); p = p.Transform(matrix); - return py::make_tuple(p.x,p.y,p.z); + return py::make_tuple(p.x, p.y, p.z); } static void print_curve(const CCurve& c) @@ -52,19 +53,26 @@ static void print_curve(const CCurve& c) printf("number of vertices = %lu\n", nvertices); #endif int i = 0; - for(std::list::const_iterator It = c.m_vertices.begin(); It != c.m_vertices.end(); It++, i++) - { + for (std::list::const_iterator It = c.m_vertices.begin(); It != c.m_vertices.end(); + It++, i++) { const CVertex& vertex = *It; - printf("vertex %d type = %d, x = %g, y = %g", i+1, vertex.m_type, vertex.m_p.x / CArea::get_units(), vertex.m_p.y / CArea::get_units()); - if(vertex.m_type)printf(", xc = %g, yc = %g", vertex.m_c.x / CArea::get_units(), vertex.m_c.y / CArea::get_units()); + printf("vertex %d type = %d, x = %g, y = %g", + i + 1, + vertex.m_type, + vertex.m_p.x / CArea::get_units(), + vertex.m_p.y / CArea::get_units()); + if (vertex.m_type) { + printf(", xc = %g, yc = %g", + vertex.m_c.x / CArea::get_units(), + vertex.m_c.y / CArea::get_units()); + } printf("\n"); } } -static void print_area(const CArea &a) +static void print_area(const CArea& a) { - for(std::list::const_iterator It = a.m_curves.begin(); It != a.m_curves.end(); It++) - { + for (std::list::const_iterator It = a.m_curves.begin(); It != a.m_curves.end(); It++) { const CCurve& curve = *It; print_curve(curve); } @@ -121,11 +129,22 @@ static py::tuple nearest_point_to_curve(CCurve& c1, const CCurve& c2) return py::make_tuple(p, dist); } -std::list MakePocketToolpath(const CArea& a, double tool_radius, double extra_offset, double stepover, bool from_center, bool use_zig_zag, double zig_angle) +std::list MakePocketToolpath(const CArea& a, + double tool_radius, + double extra_offset, + double stepover, + bool from_center, + bool use_zig_zag, + double zig_angle) { std::list toolpath; - CAreaPocketParams params(tool_radius, extra_offset, stepover, from_center, use_zig_zag ? ZigZagPocketMode : SpiralPocketMode, zig_angle); + CAreaPocketParams params(tool_radius, + extra_offset, + stepover, + from_center, + use_zig_zag ? ZigZagPocketMode : SpiralPocketMode, + zig_angle); a.SplitAndMakePocketToolpath(toolpath, params); return toolpath; @@ -147,14 +166,13 @@ void dxfArea(CArea& area, const char* /*str*/) py::list getCurveSpans(const CCurve& c) { py::list span_list; - const Point *prev_p = NULL; + const Point* prev_p = NULL; - for(std::list::const_iterator VIt = c.m_vertices.begin(); VIt != c.m_vertices.end(); VIt++) - { + for (std::list::const_iterator VIt = c.m_vertices.begin(); VIt != c.m_vertices.end(); + VIt++) { const CVertex& vertex = *VIt; - if(prev_p) - { + if (prev_p) { span_list.append(Span(*prev_p, vertex)); } prev_p = &(vertex.m_p); @@ -165,67 +183,76 @@ py::list getCurveSpans(const CCurve& c) Span getFirstCurveSpan(const CCurve& c) { - if(c.m_vertices.size() < 2) + if (c.m_vertices.size() < 2) { return Span(); + } std::list::const_iterator VIt = c.m_vertices.begin(); - const Point &p = (*VIt).m_p; + const Point& p = (*VIt).m_p; VIt++; return Span(p, *VIt, true); } Span getLastCurveSpan(const CCurve& c) { - if(c.m_vertices.size() < 2) + if (c.m_vertices.size() < 2) { return Span(); + } std::list::const_reverse_iterator VIt = c.m_vertices.rbegin(); - const CVertex &v = (*VIt); + const CVertex& v = (*VIt); VIt++; return Span((*VIt).m_p, v, c.m_vertices.size() == 2); } -py::tuple TangentialArc(const Point &p0, const Point &p1, const Point &v0) +py::tuple TangentialArc(const Point& p0, const Point& p1, const Point& v0) { - Point c; - int dir; - tangential_arc(p0, p1, v0, c, dir); + Point c; + int dir; + tangential_arc(p0, p1, v0, c, dir); - return py::make_tuple(c, dir); + return py::make_tuple(c, dir); } -std::list spanIntersect(const Span& span1, const Span& span2) { +std::list spanIntersect(const Span& span1, const Span& span2) +{ std::list pts; span1.Intersect(span2, pts); return pts; } -geoff_geometry::Matrix* MatrixFromVector(std::vector v){ +geoff_geometry::Matrix* MatrixFromVector(std::vector v) +{ double array[16]; int i = 0; - for (double vi: v){ + for (double vi : v) { array[i] = vi; i++; - if(i>=16) break; + if (i >= 16) { + break; + } } return new geoff_geometry::Matrix(array); } -std::list InsideCurves(const CArea& a, const CCurve& curve) { +std::list InsideCurves(const CArea& a, const CCurve& curve) +{ std::list curves_inside; a.InsideCurves(curve, curves_inside); return curves_inside; } -std::list CurveIntersections(const CCurve& c1, const CCurve& c2) { +std::list CurveIntersections(const CCurve& c1, const CCurve& c2) +{ std::list pts; c1.CurveIntersections(c2, pts); return pts; } -std::list AreaIntersections(const CArea& a, const CCurve& c2) { +std::list AreaIntersections(const CArea& a, const CCurve& c2) +{ std::list pts; a.CurveIntersections(c2, pts); return pts; @@ -237,8 +264,9 @@ double AreaGetArea(const CArea& a) } -void init_pyarea(py::module &m){ - py::class_(m, "Point") +void init_pyarea(py::module& m) +{ + py::class_(m, "Point") .def(py::init()) .def(py::init()) .def(float() * py::self) @@ -255,14 +283,13 @@ void init_pyarea(py::module &m){ .def("dist", &Point::dist) .def("length", &Point::length) .def("normalize", &Point::normalize) - .def("Rotate", static_cast< void (Point::*)(double, double) >(&Point::Rotate)) - .def("Rotate", static_cast< void (Point::*)(double) >(&Point::Rotate)) + .def("Rotate", static_cast(&Point::Rotate)) + .def("Rotate", static_cast(&Point::Rotate)) .def_readwrite("x", &Point::x) .def_readwrite("y", &Point::y) - .def("Transform", &Point::Transform) - ; + .def("Transform", &Point::Transform); - py::class_(m, "Vertex") + py::class_(m, "Vertex") .def(py::init()) .def(py::init()) .def(py::init()) @@ -270,14 +297,15 @@ void init_pyarea(py::module &m){ .def_readwrite("type", &CVertex::m_type) .def_readwrite("p", &CVertex::m_p) .def_readwrite("c", &CVertex::m_c) - .def_readwrite("user_data", &CVertex::m_user_data) - ; + .def_readwrite("user_data", &CVertex::m_user_data); - py::class_(m, "Span") + py::class_(m, "Span") .def(py::init()) .def(py::init()) - .def("NearestPoint", static_cast< Point (Span::*)(const Point& p)const >(&Span::NearestPoint)) - .def("NearestPoint", static_cast< Point (Span::*)(const Span& p, double *d)const >(&Span::NearestPoint)) + .def("NearestPoint", + static_cast(&Span::NearestPoint)) + .def("NearestPoint", + static_cast(&Span::NearestPoint)) .def("GetBox", &Span::GetBox) .def("IncludedAngle", &Span::IncludedAngle) .def("GetArea", &Span::GetArea) @@ -288,16 +316,16 @@ void init_pyarea(py::module &m){ .def("GetVector", &Span::GetVector) .def("Intersect", &spanIntersect) .def_readwrite("p", &Span::m_p) - .def_readwrite("v", &Span::m_v) - ; + .def_readwrite("v", &Span::m_v); - py::class_(m, "Curve") + py::class_(m, "Curve") .def(py::init<>()) .def("getVertices", &getVertices) - .def("append",&CCurve::append) - .def("append",&append_point) + .def("append", &CCurve::append) + .def("append", &append_point) .def("text", &print_curve) - .def("NearestPoint", static_cast< Point (CCurve::*)(const Point& p)const >(&CCurve::NearestPoint)) + .def("NearestPoint", + static_cast(&CCurve::NearestPoint)) .def("NearestPoint", &nearest_point_to_curve) .def("Reverse", &CCurve::Reverse) .def("getNumVertices", &num_vertices) @@ -306,39 +334,37 @@ void init_pyarea(py::module &m){ .def("GetArea", &CCurve::GetArea) .def("IsClockwise", &CCurve::IsClockwise) .def("IsClosed", &CCurve::IsClosed) - .def("ChangeStart",&CCurve::ChangeStart) - .def("ChangeEnd",&CCurve::ChangeEnd) - .def("Offset",&CCurve::Offset) - .def("OffsetForward",&CCurve::OffsetForward) - .def("GetSpans",&getCurveSpans) - .def("GetFirstSpan",&getFirstCurveSpan) - .def("GetLastSpan",&getLastCurveSpan) - .def("Break",&CCurve::Break) - .def("Perim",&CCurve::Perim) - .def("PerimToPoint",&CCurve::PerimToPoint) - .def("PointToPerim",&CCurve::PointToPerim) - .def("FitArcs",&CCurve::FitArcs) - .def("UnFitArcs",&CCurve::UnFitArcs) - .def("Intersections",&CurveIntersections) - ; + .def("ChangeStart", &CCurve::ChangeStart) + .def("ChangeEnd", &CCurve::ChangeEnd) + .def("Offset", &CCurve::Offset) + .def("OffsetForward", &CCurve::OffsetForward) + .def("GetSpans", &getCurveSpans) + .def("GetFirstSpan", &getFirstCurveSpan) + .def("GetLastSpan", &getLastCurveSpan) + .def("Break", &CCurve::Break) + .def("Perim", &CCurve::Perim) + .def("PerimToPoint", &CCurve::PerimToPoint) + .def("PointToPerim", &CCurve::PointToPerim) + .def("FitArcs", &CCurve::FitArcs) + .def("UnFitArcs", &CCurve::UnFitArcs) + .def("Intersections", &CurveIntersections); - py::class_(m, "Box") + py::class_(m, "Box") .def(py::init()) .def("MinX", &CBox2D::MinX) .def("MaxX", &CBox2D::MaxX) .def("MinY", &CBox2D::MinY) - .def("MaxY", &CBox2D::MaxY) - ; + .def("MaxY", &CBox2D::MaxY); - py::class_(m, "Area") + py::class_(m, "Area") .def(py::init<>()) .def("getCurves", &getCurves) - .def("append",&CArea::append) - .def("Subtract",&CArea::Subtract) - .def("Intersect",&CArea::Intersect) - .def("Union",&CArea::Union) - .def("Offset",&CArea::Offset) - .def("FitArcs",&CArea::FitArcs) + .def("append", &CArea::append) + .def("Subtract", &CArea::Subtract) + .def("Intersect", &CArea::Intersect) + .def("Union", &CArea::Union) + .def("Offset", &CArea::Offset) + .def("FitArcs", &CArea::FitArcs) .def("text", &print_area) .def("num_curves", &CArea::num_curves) .def("NearestPoint", &CArea::NearestPoint) @@ -348,16 +374,14 @@ void init_pyarea(py::module &m){ .def("Split", &SplitArea) .def("InsideCurves", &InsideCurves) .def("Thicken", &CArea::Thicken) - .def("Intersections",&AreaIntersections) - .def("GetArea",&AreaGetArea) - ; + .def("Intersections", &AreaIntersections) + .def("GetArea", &AreaGetArea); - py::class_ > (m, "Matrix") + py::class_>(m, "Matrix") .def(py::init()) .def(py::init(&MatrixFromVector)) .def("TransformedPoint", &transformed_point) - .def("Multiply", &geoff_geometry::Matrix::Multiply) - ; + .def("Multiply", &geoff_geometry::Matrix::Multiply); m.def("set_units", set_units); m.def("get_units", get_units); @@ -365,44 +389,43 @@ void init_pyarea(py::module &m){ m.def("AreaFromDxf", AreaFromDxf); m.def("TangentialArc", TangentialArc); - using namespace AdaptivePath; - py::enum_(m, "AdaptiveMotionType") - .value("Cutting", MotionType::mtCutting) - .value("LinkClear", MotionType::mtLinkClear) - .value("LinkNotClear", MotionType::mtLinkNotClear) - .value("LinkClearAtPrevPass", MotionType::mtLinkClearAtPrevPass); + using namespace AdaptivePath; + py::enum_(m, "AdaptiveMotionType") + .value("Cutting", MotionType::mtCutting) + .value("LinkClear", MotionType::mtLinkClear) + .value("LinkNotClear", MotionType::mtLinkNotClear) + .value("LinkClearAtPrevPass", MotionType::mtLinkClearAtPrevPass); - py::enum_(m, "AdaptiveOperationType") - .value("ClearingInside", OperationType::otClearingInside) - .value("ClearingOutside", OperationType::otClearingOutside) - .value("ProfilingInside", OperationType::otProfilingInside) - .value("ProfilingOutside", OperationType::otProfilingOutside); + py::enum_(m, "AdaptiveOperationType") + .value("ClearingInside", OperationType::otClearingInside) + .value("ClearingOutside", OperationType::otClearingOutside) + .value("ProfilingInside", OperationType::otProfilingInside) + .value("ProfilingOutside", OperationType::otProfilingOutside); - py::class_(m, "AdaptiveOutput") - .def(py::init<>()) - .def_readwrite("HelixCenterPoint",&AdaptiveOutput::HelixCenterPoint) - .def_readwrite("StartPoint",&AdaptiveOutput::StartPoint) - .def_readwrite("AdaptivePaths",&AdaptiveOutput::AdaptivePaths) - .def_readwrite("ReturnMotionType",&AdaptiveOutput::ReturnMotionType); + py::class_(m, "AdaptiveOutput") + .def(py::init<>()) + .def_readwrite("HelixCenterPoint", &AdaptiveOutput::HelixCenterPoint) + .def_readwrite("StartPoint", &AdaptiveOutput::StartPoint) + .def_readwrite("AdaptivePaths", &AdaptiveOutput::AdaptivePaths) + .def_readwrite("ReturnMotionType", &AdaptiveOutput::ReturnMotionType); - py::class_(m, "Adaptive2d") - .def(py::init<>()) - .def("Execute",&Adaptive2d::Execute) - .def_readwrite("stepOverFactor", &Adaptive2d::stepOverFactor) - .def_readwrite("toolDiameter", &Adaptive2d::toolDiameter) + py::class_(m, "Adaptive2d") + .def(py::init<>()) + .def("Execute", &Adaptive2d::Execute) + .def_readwrite("stepOverFactor", &Adaptive2d::stepOverFactor) + .def_readwrite("toolDiameter", &Adaptive2d::toolDiameter) .def_readwrite("stockToLeave", &Adaptive2d::stockToLeave) - .def_readwrite("helixRampDiameter", &Adaptive2d::helixRampDiameter) + .def_readwrite("helixRampDiameter", &Adaptive2d::helixRampDiameter) .def_readwrite("forceInsideOut", &Adaptive2d::forceInsideOut) .def_readwrite("finishingProfile", &Adaptive2d::finishingProfile) - //.def_readwrite("polyTreeNestingLimit", &Adaptive2d::polyTreeNestingLimit) - .def_readwrite("tolerance", &Adaptive2d::tolerance) + //.def_readwrite("polyTreeNestingLimit", &Adaptive2d::polyTreeNestingLimit) + .def_readwrite("tolerance", &Adaptive2d::tolerance) .def_readwrite("keepToolDownDistRatio", &Adaptive2d::keepToolDownDistRatio) - .def_readwrite("opType", &Adaptive2d::opType); + .def_readwrite("opType", &Adaptive2d::opType); } -PYBIND11_MODULE(area, m){ - m.doc()= "not yet"; +PYBIND11_MODULE(area, m) +{ + m.doc() = "not yet"; init_pyarea(m); }; - -