├── CMakeLists.txt ├── LICENSE ├── README.md ├── cam-icon.png ├── cam.desktop ├── color_pallete.xml ├── dxf ├── contourtypes.dxf └── contourtypes.dxf~ ├── gcode.ngc ├── icons.qrc ├── icons ├── 3d.svg ├── angle_2p.svg ├── angle_3p.svg ├── applications-system.png ├── arc.svg ├── arrow-down.png ├── back.svg ├── bottom.svg ├── cad.svg ├── cam.svg ├── camcam.svg ├── chamfer.svg ├── circle.svg ├── circle_3p.svg ├── circle_4p.svg ├── circle_4p_off.svg ├── circle_4p_on.svg ├── circlecenter.svg ├── circlecenter_off.svg ├── circlecenter_on.svg ├── copy.svg ├── cubicbezcurve.svg ├── debug.svg ├── delete.svg ├── diameter.svg ├── dimension_edit.svg ├── document-edit.png ├── document-new.png ├── document-open.png ├── document-save.png ├── draw-arrow-back.png ├── draw-arrow-down.png ├── draw-arrow-forward.png ├── draw-arrow-up.png ├── edit-clear.png ├── ellipse.svg ├── emergency-stop ├── empty.svg ├── endpoint.svg ├── endpoint_off.svg ├── endpoint_on.svg ├── extend.svg ├── filled.svg ├── front.svg ├── grid.svg ├── grid_off.svg ├── grid_on.svg ├── help-browser.png ├── horizontal.svg ├── intersection.svg ├── intersection_off.svg ├── intersection_on.svg ├── layer.svg ├── left.svg ├── line.svg ├── linestrip.svg ├── linetype.svg ├── linewidth.svg ├── match_properties.svg ├── midpoint.svg ├── midpoint_off.svg ├── midpoint_on.svg ├── mirror.svg ├── move.svg ├── move_down.svg ├── move_left.svg ├── move_left_down.svg ├── move_left_up.svg ├── move_right.svg ├── move_right_down.svg ├── move_right_up.svg ├── move_up.svg ├── nearest.svg ├── nearest_off.svg ├── nearest_on.svg ├── new.svg ├── non_horizontal.svg ├── offset.svg ├── open.svg ├── opinion-no.png ├── opinion-okay.png ├── ortho.svg ├── ortho_off.svg ├── ortho_on.svg ├── perpendicular.svg ├── perpendicular_off.svg ├── perpendicular_on.svg ├── point.svg ├── polygon.svg ├── preferences-other.png ├── radius.svg ├── rectangle.svg ├── refresh.png ├── right.svg ├── rotate.svg ├── save.svg ├── save_as.svg ├── scale.svg ├── spline.svg ├── stretch.svg └── test ├── libcavalier ├── CMakeLists.txt ├── LICENSE ├── README.md ├── c_api_include │ └── cavaliercontours.h ├── examples │ ├── CMakeLists.txt │ ├── basicpolylinefunctions.cpp │ ├── polylinecombine.cpp │ ├── polylineoffset.cpp │ └── windingnumber.cpp ├── include │ └── cavc │ │ ├── internal │ │ ├── common.hpp │ │ └── diagnostics.hpp │ │ ├── intrcircle2circle2.hpp │ │ ├── intrlineseg2circle2.hpp │ │ ├── intrlineseg2lineseg2.hpp │ │ ├── mathutils.hpp │ │ ├── plinesegment.hpp │ │ ├── polyline.hpp │ │ ├── polylinecombine.hpp │ │ ├── polylineintersects.hpp │ │ ├── polylineoffset.hpp │ │ ├── polylineoffsetislands.hpp │ │ ├── staticspatialindex.hpp │ │ ├── vector.hpp │ │ └── vector2.hpp ├── offsets.cpp ├── offsets.h ├── src │ └── cavaliercontours.cpp └── tests │ ├── CMakeLists.txt │ ├── benchmarks │ ├── CMakeLists.txt │ ├── areabenchmarks.cpp │ ├── benchmarkprofiles.h │ ├── clipper.cmake │ ├── clipperbenchmarks.cpp │ ├── combinebenchmarks.cpp │ ├── extentsbenchmarks.cpp │ ├── googlebenchmark.cmake │ ├── offsetbenchmarks.cpp │ ├── pathlengthbenchmarks.cpp │ ├── spatialindexbenchmarks.cpp │ └── windingnumberbenchmarks.cpp │ ├── polylinefactory │ ├── CMakeLists.txt │ ├── include │ │ └── polylinefactory.hpp │ └── src │ │ └── polylinefactory.cpp │ └── tests │ ├── CMakeLists.txt │ ├── cavc_combine_plines_tests.cpp │ ├── cavc_parallel_offset_tests.cpp │ ├── cavc_pline_function_tests.cpp │ ├── cavc_pline_tests.cpp │ ├── googletest.cmake │ ├── include │ ├── c_api_test_helpers.hpp │ └── testhelpers.hpp │ └── staticspatialindex_tests.cpp ├── libcontour ├── contours.cpp └── contours.h ├── libdata ├── variable.cpp └── variable.h ├── libdialog ├── CMakeLists.txt ├── COPYING ├── README.md ├── doc │ ├── message.md │ ├── notify.md │ ├── open_file.md │ ├── pfd.md │ ├── save_file.md │ └── select_folder.md ├── examples │ ├── Makefile │ ├── example.cpp │ ├── example.vcxproj │ ├── kill.cpp │ └── kill.vcxproj └── portable-file-dialogs.h ├── libdxfrw ├── Makefile.am ├── Makefile.in ├── drw_base.h ├── drw_classes.cpp ├── drw_classes.h ├── drw_entities.cpp ├── drw_entities.h ├── drw_header.cpp ├── drw_header.h ├── drw_interface.h ├── drw_objects.cpp ├── drw_objects.h ├── dx_data.h ├── dx_iface.cpp ├── dx_iface.h ├── intern │ ├── drw_cptable932.h │ ├── drw_cptable936.h │ ├── drw_cptable949.h │ ├── drw_cptable950.h │ ├── drw_cptables.h │ ├── drw_dbg.cpp │ ├── drw_dbg.h │ ├── drw_textcodec.cpp │ ├── drw_textcodec.h │ ├── dwgbuffer.cpp │ ├── dwgbuffer.h │ ├── dwgreader.cpp │ ├── dwgreader.h │ ├── dwgreader15.cpp │ ├── dwgreader15.h │ ├── dwgreader18.cpp │ ├── dwgreader18.h │ ├── dwgreader21.cpp │ ├── dwgreader21.h │ ├── dwgreader24.cpp │ ├── dwgreader24.h │ ├── dwgreader27.cpp │ ├── dwgreader27.h │ ├── dwgutil.cpp │ ├── dwgutil.h │ ├── dxfreader.cpp │ ├── dxfreader.h │ ├── dxfwriter.cpp │ ├── dxfwriter.h │ ├── rscodec.cpp │ └── rscodec.h ├── libdwgr.cpp ├── libdwgr.h ├── libdxfrw.cpp ├── libdxfrw.h ├── main.txt └── main_doc.h ├── libgcode ├── gcode.cpp └── gcode.h ├── libocc ├── draw_primitives.cpp ├── draw_primitives.h ├── opencascade.cpp └── opencascade.h ├── libspline ├── bezier_spline.cpp ├── bezier_spline.h ├── cubic_spline.cpp ├── cubic_spline.h ├── spline.cpp └── spline.h ├── main.cpp ├── mainwindow.cpp ├── mainwindow.cpp.autosave ├── mainwindow.h ├── mainwindow.ui └── qt-dxf.pro /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | set(PROJECT "cam") # The name of the file excluding .c or .h 3 | project(${PROJECT} C CXX) 4 | 5 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 6 | 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_AUTORCC ON) 10 | 11 | set(CMAKE_CXX_STANDARD 20) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | # Set variables. 15 | set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 16 | set(BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}") 17 | 18 | # Set includepaths for header files etc. 19 | include_directories(${SRC_DIR}) 20 | include_directories(${SRC_DIR}/libspline) 21 | include_directories(${SRC_DIR}/libocc) 22 | include_directories(${SRC_DIR}/libgcode) 23 | include_directories(${SRC_DIR}/libdxfrw) 24 | include_directories(${SRC_DIR}/libdialog) 25 | include_directories(${SRC_DIR}/libdata) 26 | include_directories(${SRC_DIR}/libcontour) 27 | include_directories(${SRC_DIR}/libcavalier) 28 | include_directories(${SRC_DIR}/libcavalier/src) 29 | include_directories(${SRC_DIR}/libcavalier/include/cavc) 30 | include_directories(${SRC_DIR}/libcavalier/include/cavc/internal) 31 | include_directories(${SRC_DIR}/icons) 32 | 33 | # Set path to your opencascade lib. 34 | # https://github.com/tpaviot/oce/releases/download/official-upstream-packages/opencascade-7.4.0.tgz 35 | # 36 | # Do the build process, and make install. Then set filepath. 37 | 38 | include_directories(/home/user/linuxcnc/cmake/vendor/oce-upstream-V7_5_0beta/inc) 39 | include_directories(/home/user/linuxcnc/cmake/vendor/oce-upstream-V7_5_0beta/oce-upstream-V7_5_0beta/src) 40 | 41 | 42 | find_package(OpenGL REQUIRED) 43 | find_package(GLUT REQUIRED) 44 | 45 | include_directories("/usr/include/eigen3") 46 | find_package (Eigen3 3.3 REQUIRED) 47 | 48 | # Opencascade 49 | find_package (OpenCASCADE REQUIRED) 50 | 51 | SET(OpenCASCADE_LIBS 52 | TKGeomAlgo TKMesh TKHLR TKBO TKShHealing 53 | TKPrim 54 | TKernel TKMath TKTopAlgo TKService 55 | TKG2d TKG3d TKV3d TKOpenGl 56 | TKBRep TKXSBase TKGeomBase TKGeomAlgo 57 | TKXSDRAW 58 | TKLCAF TKXCAF TKCAF TKVCAF 59 | TKCDF TKBin TKBinL TKBinXCAF TKXml TKXmlL TKXmlXCAF 60 | # -- IGES support 61 | TKIGES 62 | # -- STEP support 63 | TKSTEP TKXDESTEP TKXDEIGES TKSTEPAttr TKSTEPBase TKSTEP209 64 | # -- STL support 65 | TKSTL 66 | # -- OBJ/glTF support 67 | TKRWMesh TKMeshVS 68 | # -- VRML support 69 | TKVRML 70 | # -- ViewerTest 71 | TKViewerTest 72 | ) 73 | 74 | # Qt 75 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 76 | set(CMAKE_AUTOUIC ON) 77 | set(CMAKE_AUTOMOC ON) 78 | set(CMAKE_AUTORCC ON) 79 | set(CMAKE_CXX_STANDARD 17) 80 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 81 | set(CMAKE_PREFIX_PATH "/opt/qt-creator/5.15.1/gcc_64/lib/cmake") 82 | include_directories("/opt/qt-creator/5.15.1/gcc_64/include/QtWidgets") 83 | include_directories("/opt/qt-creator/5.15.1/gcc_64/include/QtGui") 84 | include_directories("/opt/qt-creator/5.15.1/gcc_64/include") 85 | include_directories("/opt/qt-creator/5.15.1/gcc_64/include/QtCore") 86 | 87 | find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets OpenGL REQUIRED) 88 | find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets OpenGL REQUIRED) 89 | 90 | set(PROJECT_SOURCES 91 | ${SRC_DIR}/main.cpp 92 | ${SRC_DIR}/mainwindow.cpp 93 | ${SRC_DIR}/mainwindow.h 94 | ${SRC_DIR}/mainwindow.ui 95 | ${SRC_DIR}/libcavalier/offsets.cpp 96 | ${SRC_DIR}/libcontour/contours.cpp 97 | ${SRC_DIR}/libdata/variable.cpp 98 | ${SRC_DIR}/libdxfrw/drw_classes.cpp 99 | ${SRC_DIR}/libdxfrw/drw_entities.cpp 100 | ${SRC_DIR}/libdxfrw/drw_header.cpp 101 | ${SRC_DIR}/libdxfrw/drw_objects.cpp 102 | ${SRC_DIR}/libdxfrw/dx_iface.cpp 103 | ${SRC_DIR}/libdxfrw/intern/drw_dbg.cpp 104 | ${SRC_DIR}/libdxfrw/intern/drw_textcodec.cpp 105 | ${SRC_DIR}/libdxfrw/intern/dwgbuffer.cpp 106 | ${SRC_DIR}/libdxfrw/intern/dwgreader.cpp 107 | ${SRC_DIR}/libdxfrw/intern/dwgreader15.cpp 108 | ${SRC_DIR}/libdxfrw/intern/dwgreader18.cpp 109 | ${SRC_DIR}/libdxfrw/intern/dwgreader21.cpp 110 | ${SRC_DIR}/libdxfrw/intern/dwgreader24.cpp 111 | ${SRC_DIR}/libdxfrw/intern/dwgreader27.cpp 112 | ${SRC_DIR}/libdxfrw/intern/dwgutil.cpp 113 | ${SRC_DIR}/libdxfrw/intern/dxfreader.cpp 114 | ${SRC_DIR}/libdxfrw/intern/dxfwriter.cpp 115 | ${SRC_DIR}/libdxfrw/intern/rscodec.cpp 116 | ${SRC_DIR}/libdxfrw/libdwgr.cpp 117 | ${SRC_DIR}/libdxfrw/libdxfrw.cpp 118 | ${SRC_DIR}/libgcode/gcode.cpp 119 | ${SRC_DIR}/libocc/draw_primitives.cpp 120 | ${SRC_DIR}/libspline/bezier_spline.cpp 121 | ${SRC_DIR}/libspline/cubic_spline.cpp 122 | ${SRC_DIR}/libspline/spline.cpp 123 | ${SRC_DIR}/libocc/opencascade.cpp 124 | ) 125 | 126 | if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) 127 | qt_add_executable(${PROJECT} 128 | ${PROJECT_SOURCES} 129 | ) 130 | else() 131 | if(ANDROID) 132 | add_library(${PROJECT} SHARED 133 | ${PROJECT_SOURCES} 134 | ) 135 | else() 136 | add_executable(${PROJECT} 137 | ${PROJECT_SOURCES} 138 | ) 139 | endif() 140 | endif() 141 | 142 | 143 | # Link. 144 | target_link_libraries(${PROJECT_NAME} PRIVATE pthread 145 | ${OpenCASCADE_LIBS} Qt5::Widgets Qt5::OpenGL ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} 146 | ) 147 | 148 | # Make install 149 | # install(TARGETS ${PROJECT} DESTINATION ${BUILD_DIR}/) 150 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Github All Releases](https://img.shields.io/github/downloads/grotius-cnc/cam/total.svg)]() 2 | 3 | ![joco-power](https://user-images.githubusercontent.com/44880102/126598963-eb5e78d0-e62d-4cf1-8585-2610579a28bb.jpg) 4 | 5 | Now available as .deb package for linux, including desktop launcher. 6 | https://github.com/grotius-cnc/simple_cam/releases/tag/1.0.0 7 | 8 | Currently implemented: 9 | 10 | - Dxf read, write and save example. 11 | - Opencascade cad view, selecting base contours by mouse click. 12 | - Supports offset by cad-layer. 13 | - Supports contour offset values: -, + or 0 (no offset). 14 | - Depth sequence, "keep parts together" kpt output algorimte. 15 | - Lead-in, lead-out for offsets. 16 | - Supports single-open, multiple-open, single-closed and multiple-closed primitive offsets. 17 | - Generates a gcode.ngc output file located in build directory. 18 | - Can add line-numbers to the gcode.ngc file. 19 | - Supports pockets with or without islands. Base offset + Internal pocket offset. 20 | - Supports multiple operation output. 21 | - Supports second head + xyz tool offsets. 22 | - Shows rapids. 23 | 24 | 25 | -------------------------------------------------------------------------------- /cam-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/cam-icon.png -------------------------------------------------------------------------------- /cam.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Cam 3 | Exec=./cam 4 | Type=Application 5 | Categories=Development; 6 | Comment="You can clean up hal with : Halrun -U" 7 | Icon=/opt/cam/cam-icon.png 8 | Path=/opt/cam/build-qt-dxf-Desktop-Debug 9 | -------------------------------------------------------------------------------- /icons.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | icons/3d.svg 4 | icons/angle_2p.svg 5 | icons/angle_3p.svg 6 | icons/applications-system.png 7 | icons/arc.svg 8 | icons/arrow-down.png 9 | icons/back.svg 10 | icons/bottom.svg 11 | icons/cad.svg 12 | icons/cam.svg 13 | icons/camcam.svg 14 | icons/chamfer.svg 15 | icons/circle_3p.svg 16 | icons/circle_4p_off.svg 17 | icons/circle_4p_on.svg 18 | icons/circle_4p.svg 19 | icons/circle.svg 20 | icons/circlecenter_off.svg 21 | icons/circlecenter_on.svg 22 | icons/circlecenter.svg 23 | icons/copy.svg 24 | icons/cubicbezcurve.svg 25 | icons/debug.svg 26 | icons/delete.svg 27 | icons/diameter.svg 28 | icons/dimension_edit.svg 29 | icons/document-edit.png 30 | icons/document-new.png 31 | icons/document-open.png 32 | icons/document-save.png 33 | icons/draw-arrow-back.png 34 | icons/draw-arrow-down.png 35 | icons/draw-arrow-forward.png 36 | icons/draw-arrow-up.png 37 | icons/edit-clear.png 38 | icons/ellipse.svg 39 | icons/emergency-stop 40 | icons/empty.svg 41 | icons/endpoint_off.svg 42 | icons/endpoint_on.svg 43 | icons/endpoint.svg 44 | icons/extend.svg 45 | icons/filled.svg 46 | icons/front.svg 47 | icons/grid_off.svg 48 | icons/grid_on.svg 49 | icons/grid.svg 50 | icons/help-browser.png 51 | icons/horizontal.svg 52 | icons/intersection_off.svg 53 | icons/intersection_on.svg 54 | icons/intersection.svg 55 | icons/layer.svg 56 | icons/left.svg 57 | icons/line.svg 58 | icons/linestrip.svg 59 | icons/linetype.svg 60 | icons/linewidth.svg 61 | icons/match_properties.svg 62 | icons/midpoint_off.svg 63 | icons/midpoint_on.svg 64 | icons/midpoint.svg 65 | icons/mirror.svg 66 | icons/move_down.svg 67 | icons/move_left_down.svg 68 | icons/move_left_up.svg 69 | icons/move_left.svg 70 | icons/move_right_down.svg 71 | icons/move_right_up.svg 72 | icons/move_right.svg 73 | icons/move_up.svg 74 | icons/move.svg 75 | icons/nearest_off.svg 76 | icons/nearest_on.svg 77 | icons/nearest.svg 78 | icons/new.svg 79 | icons/non_horizontal.svg 80 | icons/offset.svg 81 | icons/open.svg 82 | icons/opinion-no.png 83 | icons/opinion-okay.png 84 | icons/ortho_off.svg 85 | icons/ortho_on.svg 86 | icons/ortho.svg 87 | icons/perpendicular_off.svg 88 | icons/perpendicular_on.svg 89 | icons/perpendicular.svg 90 | icons/point.svg 91 | icons/polygon.svg 92 | icons/preferences-other.png 93 | icons/radius.svg 94 | icons/rectangle.svg 95 | icons/refresh.png 96 | icons/right.svg 97 | icons/rotate.svg 98 | icons/save_as.svg 99 | icons/save.svg 100 | icons/scale.svg 101 | icons/spline.svg 102 | icons/stretch.svg 103 | icons/test 104 | 105 | 106 | -------------------------------------------------------------------------------- /icons/applications-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/applications-system.png -------------------------------------------------------------------------------- /icons/arrow-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/arrow-down.png -------------------------------------------------------------------------------- /icons/document-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/document-edit.png -------------------------------------------------------------------------------- /icons/document-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/document-new.png -------------------------------------------------------------------------------- /icons/document-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/document-open.png -------------------------------------------------------------------------------- /icons/document-save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/document-save.png -------------------------------------------------------------------------------- /icons/draw-arrow-back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/draw-arrow-back.png -------------------------------------------------------------------------------- /icons/draw-arrow-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/draw-arrow-down.png -------------------------------------------------------------------------------- /icons/draw-arrow-forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/draw-arrow-forward.png -------------------------------------------------------------------------------- /icons/draw-arrow-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/draw-arrow-up.png -------------------------------------------------------------------------------- /icons/edit-clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/edit-clear.png -------------------------------------------------------------------------------- /icons/emergency-stop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/emergency-stop -------------------------------------------------------------------------------- /icons/help-browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/help-browser.png -------------------------------------------------------------------------------- /icons/opinion-no.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/opinion-no.png -------------------------------------------------------------------------------- /icons/opinion-okay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/opinion-okay.png -------------------------------------------------------------------------------- /icons/preferences-other.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/preferences-other.png -------------------------------------------------------------------------------- /icons/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grotius-cnc/cam/27d1270f6d2936b33bc34ff7299f6a6180c9cf87/icons/refresh.png -------------------------------------------------------------------------------- /icons/test: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /libcavalier/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | # detect if CavalierContours is a subproject or not 4 | # do not include examples, tests, and benchmarks in that case 5 | if (NOT DEFINED PROJECT_NAME) 6 | set(NOT_SUBPROJECT ON) 7 | endif() 8 | 9 | 10 | project(CavalierContours VERSION 0.1) 11 | set(CMAKE_CXX_STANDARD 14) 12 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 13 | 14 | option(CAVC_HEADER_ONLY "C++ header only library of CavalierContours, if ON then no library is built" OFF) 15 | option(CAVC_BUILD_SHARED_LIB "Build the C API CavalierContours dynamic shared library (SET OFF for static library)" ON) 16 | 17 | if(CAVC_HEADER_ONLY) 18 | set(CAVC_CPP_HEADER_ONLY_LIB ${PROJECT_NAME}) 19 | else() 20 | set(CAVC_CPP_HEADER_ONLY_LIB ${PROJECT_NAME}_header_only) 21 | set(CAVC_C_API_LIB ${PROJECT_NAME}) 22 | endif() 23 | 24 | 25 | 26 | add_library(${CAVC_CPP_HEADER_ONLY_LIB} INTERFACE) 27 | target_include_directories(${CAVC_CPP_HEADER_ONLY_LIB} 28 | INTERFACE include/) 29 | 30 | if(NOT CAVC_HEADER_ONLY) 31 | if(CAVC_BUILD_SHARED_LIB) 32 | add_library(${CAVC_C_API_LIB} 33 | SHARED src/cavaliercontours.cpp) 34 | else() 35 | add_library(${CAVC_C_API_LIB} 36 | STATIC src/cavaliercontours.cpp) 37 | target_compile_definitions(${CAVC_C_API_LIB} 38 | PUBLIC CAVC_STATIC_LIB) 39 | endif() 40 | # compiler warnings, note: not using /W4 on MSVC since it emits warning due to default of /W3 41 | # from cmake 42 | if(MSVC) 43 | if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") 44 | target_compile_options(${CAVC_C_API_LIB} PRIVATE 45 | /clang:-Werror /clang:-Wall /clang:-Wextra /clang:-pedantic-errors /clang:-Wsign-conversion /clang:-Wconversion) 46 | endif() 47 | target_compile_options(${CAVC_C_API_LIB} PRIVATE 48 | /WX) 49 | else() 50 | target_compile_options(${CAVC_C_API_LIB} PRIVATE 51 | -Werror -Wall -Wextra -pedantic-errors -Wsign-conversion -Wconversion) 52 | endif() 53 | target_compile_definitions(${CAVC_C_API_LIB} 54 | PRIVATE CAVC_EXPORTS) 55 | target_include_directories(${CAVC_C_API_LIB} 56 | PUBLIC c_api_include/) 57 | target_link_libraries(${CAVC_C_API_LIB} 58 | PRIVATE ${CAVC_CPP_HEADER_ONLY_LIB}) 59 | endif() 60 | 61 | if (NOT_SUBPROJECT AND NOT CAVC_HEADER_ONLY) 62 | # output all libraries and executables to the root build dir for simplicity in running tests with dynamic libs 63 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) 64 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) 65 | add_subdirectory(examples) 66 | include(CTest) 67 | enable_testing() 68 | add_subdirectory(tests) 69 | endif() 70 | -------------------------------------------------------------------------------- /libcavalier/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Jedidiah Buck McCready 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /libcavalier/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | macro(add_example name) 3 | add_executable(${name} ${name}.cpp) 4 | target_link_libraries(${name} 5 | PRIVATE ${CAVC_CPP_HEADER_ONLY_LIB}) 6 | endmacro() 7 | 8 | add_example(polylinecombine) 9 | add_example(polylineoffset) 10 | add_example(windingnumber) 11 | add_example(basicpolylinefunctions) 12 | -------------------------------------------------------------------------------- /libcavalier/examples/basicpolylinefunctions.cpp: -------------------------------------------------------------------------------- 1 | #include "cavc/polyline.hpp" 2 | 3 | using namespace cavc; 4 | 5 | int main(int argc, char *argv[]) { 6 | (void)argc; 7 | (void)argv; 8 | 9 | // closed polyline representing a circle going counter clockwise 10 | double radius = 10.0; 11 | Polyline ccwCircle; 12 | ccwCircle.addVertex(0, 0, 1); 13 | ccwCircle.addVertex(2.0 * radius, 0, 1); 14 | ccwCircle.isClosed() = true; 15 | 16 | // closed polyline representing a circle going clockwise 17 | Polyline cwCircle; 18 | cwCircle.addVertex(0, 0, -1); 19 | cwCircle.addVertex(2.0 * radius, 0, -1); 20 | cwCircle.isClosed() = true; 21 | 22 | // path length of polyline 23 | double length = getPathLength(ccwCircle); 24 | assert(utils::fuzzyEqual(length, 2.0 * utils::pi() * radius)); 25 | 26 | // signed area of closed polyline (area is positive if counter clockwise, negative if clockwise) 27 | double area = getArea(ccwCircle); 28 | assert(utils::fuzzyEqual(area, utils::pi() * radius * radius)); 29 | assert(utils::fuzzyEqual(getArea(cwCircle), -area)); 30 | 31 | // polyline extents 32 | AABB extents = getExtents(ccwCircle); 33 | assert(utils::fuzzyEqual(extents.xMin, 0.0)); 34 | assert(utils::fuzzyEqual(extents.yMin, -radius)); 35 | assert(utils::fuzzyEqual(extents.xMax, 2.0 * radius)); 36 | assert(utils::fuzzyEqual(extents.yMax, radius)); 37 | 38 | // Closest point on polyline to a point given 39 | ClosestPoint closestPoint(ccwCircle, Vector2(radius, 10.0 * radius)); 40 | // index is the starting vertex index of the closest segment (going clockwise so arc starting at 41 | // the second vertex is closest) 42 | assert(closestPoint.index() == 1); 43 | assert(fuzzyEqual(closestPoint.point(), Vector2(radius, radius))); 44 | assert(utils::fuzzyEqual(closestPoint.distance(), 9.0 * radius)); 45 | } 46 | -------------------------------------------------------------------------------- /libcavalier/examples/polylinecombine.cpp: -------------------------------------------------------------------------------- 1 | #include "cavc/polylinecombine.hpp" 2 | 3 | using namespace cavc; 4 | 5 | int main(int argc, char *argv[]) { 6 | (void)argc; 7 | (void)argv; 8 | 9 | // closed polyline representing a circle 10 | Polyline circle; 11 | circle.addVertex(0, 1, 1); 12 | circle.addVertex(10, 1, 1); 13 | circle.isClosed() = true; 14 | 15 | // closed polyline representing a rectangle (overlaps with the circle) 16 | Polyline rectangle; 17 | rectangle.addVertex(3, -10, 0); 18 | rectangle.addVertex(6, -10, 0); 19 | rectangle.addVertex(6, 10, 0); 20 | rectangle.addVertex(3, 10, 0); 21 | rectangle.isClosed() = true; 22 | 23 | CombineResult unionResult = combinePolylines(circle, rectangle, PlineCombineMode::Union); 24 | CombineResult excludeResult = 25 | combinePolylines(circle, rectangle, PlineCombineMode::Exclude); 26 | CombineResult intersectResult = 27 | combinePolylines(circle, rectangle, PlineCombineMode::Intersect); 28 | CombineResult xorResult = combinePolylines(circle, rectangle, PlineCombineMode::XOR); 29 | } 30 | -------------------------------------------------------------------------------- /libcavalier/examples/polylineoffset.cpp: -------------------------------------------------------------------------------- 1 | #include "cavc/polylineoffset.hpp" 2 | 3 | int main(int argc, char *argv[]) { 4 | (void)argc; 5 | (void)argv; 6 | // input polyline 7 | cavc::Polyline input; 8 | // add vertexes as (x, y, bulge) 9 | input.addVertex(0, 25, 1); 10 | input.addVertex(0, 0, 0); 11 | input.addVertex(2, 0, 1); 12 | input.addVertex(10, 0, -0.5); 13 | input.addVertex(8, 9, 0.374794619217547); 14 | input.addVertex(21, 0, 0); 15 | input.addVertex(23, 0, 1); 16 | input.addVertex(32, 0, -0.5); 17 | input.addVertex(28, 0, 0.5); 18 | input.addVertex(39, 21, 0); 19 | input.addVertex(28, 12, 0); 20 | input.isClosed() = true; 21 | 22 | // compute the resulting offset polylines, offset = 3 23 | std::vector> results = cavc::parallelOffset(input, 3.0); 24 | } 25 | -------------------------------------------------------------------------------- /libcavalier/examples/windingnumber.cpp: -------------------------------------------------------------------------------- 1 | #include "cavc/polyline.hpp" 2 | 3 | using namespace cavc; 4 | 5 | int main(int argc, char *argv[]) { 6 | (void)argc; 7 | (void)argv; 8 | 9 | // rectangle going counter clockwise 10 | Polyline ccwRectangle; 11 | ccwRectangle.addVertex(-10, -10, 0); 12 | ccwRectangle.addVertex(10, -10, 0); 13 | ccwRectangle.addVertex(10, 10, 0); 14 | ccwRectangle.addVertex(-10, 10, 0); 15 | ccwRectangle.isClosed() = true; 16 | 17 | int wn = getWindingNumber(ccwRectangle, Vector2(1, 1)); 18 | assert(wn == 1); 19 | wn = getWindingNumber(ccwRectangle, Vector2(12, 12)); 20 | assert(wn == 0); 21 | 22 | // make rectangle go clockwise 23 | Polyline cwRectangle = ccwRectangle; 24 | invertDirection(cwRectangle); 25 | wn = getWindingNumber(cwRectangle, Vector2(1, 1)); 26 | assert(wn == -1); 27 | 28 | // wrap around the point twice (self intersecting polyline) 29 | Polyline ccwTwiceWrapping = ccwRectangle; 30 | ccwTwiceWrapping.addVertex(-12, -12, 1); 31 | ccwTwiceWrapping.addVertex(12, -12, 0); 32 | ccwTwiceWrapping.addVertex(12, 12, 0); 33 | ccwTwiceWrapping.addVertex(-12, 12, 0); 34 | wn = getWindingNumber(ccwTwiceWrapping, Vector2(1, 1)); 35 | assert(wn == 2); 36 | 37 | Polyline cwTwiceWrapping = ccwTwiceWrapping; 38 | invertDirection(cwTwiceWrapping); 39 | wn = getWindingNumber(cwTwiceWrapping, Vector2(1, 1)); 40 | assert(wn == -2); 41 | 42 | // winding number function always returns 0 for open polylines whose start and end points do not 43 | // touch (even if geometrically it does wrap) 44 | ccwTwiceWrapping.isClosed() = false; 45 | wn = getWindingNumber(ccwTwiceWrapping, Vector2(1, 1)); 46 | assert(wn == 0); 47 | } 48 | -------------------------------------------------------------------------------- /libcavalier/include/cavc/internal/common.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CAVC_INTERNAL_COMMON_HPP 2 | #define CAVC_INTERNAL_COMMON_HPP 3 | #include 4 | #include 5 | #include 6 | 7 | namespace cavc { 8 | namespace internal { 9 | #define CAVC_ASSERT(cond, msg) assert(cond &&msg) 10 | 11 | template inline void hashCombine(std::size_t &seed, const T &val) { 12 | // copied from boost hash_combine, it's not the best hash combine but it's very simple 13 | // https://stackoverflow.com/questions/35985960/c-why-is-boosthash-combine-the-best-way-to-combine-hash-values 14 | seed ^= std::hash()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 15 | } 16 | 17 | struct IndexPairHash { 18 | inline std::size_t operator()(std::pair const &pair) const { 19 | std::size_t seed = 0; 20 | hashCombine(seed, pair.first); 21 | hashCombine(seed, pair.second); 22 | return seed; 23 | } 24 | }; 25 | } // namespace internal 26 | } // namespace cavc 27 | 28 | #endif // CAVC_INTERNAL_COMMON_HPP 29 | -------------------------------------------------------------------------------- /libcavalier/include/cavc/internal/diagnostics.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CAVC_INTERNAL_DIAGNOSTICS_HPP 2 | #define CAVC_INTERNAL_DIAGNOSTICS_HPP 3 | #include "../polyline.hpp" 4 | #include 5 | #include 6 | #include 7 | namespace cavc { 8 | namespace internal { 9 | template 10 | std::string printVertexesToInitializerList(::cavc::Polyline const &pline) { 11 | std::stringstream ss; 12 | ss << std::setprecision(14) << "{ "; 13 | for (auto const &v : pline.vertexes()) { 14 | ss << "{ " << v.x() << ", " << v.y() << ", " << v.bulge() << " },\n"; 15 | } 16 | std::string result = ss.str(); 17 | result.pop_back(); 18 | result.pop_back(); 19 | result.push_back(' '); 20 | result.push_back('}'); 21 | return result; 22 | } 23 | } // namespace internal 24 | } // namespace cavc 25 | #endif // CAVC_INTERNAL_DIAGNOSTICS_HPP 26 | -------------------------------------------------------------------------------- /libcavalier/include/cavc/intrcircle2circle2.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CAVC_INTRCIRCLE2CIRCLE2_HPP 2 | #define CAVC_INTRCIRCLE2CIRCLE2_HPP 3 | #include "vector2.hpp" 4 | namespace cavc { 5 | enum class Circle2Circle2IntrType { 6 | // no intersect between circles 7 | NoIntersect, 8 | // one intersect between circles (tangent) 9 | OneIntersect, 10 | // two intersects between circles 11 | TwoIntersects, 12 | // circles are coincident 13 | Coincident 14 | }; 15 | 16 | template struct IntrCircle2Circle2Result { 17 | // type of intersect 18 | Circle2Circle2IntrType intrType; 19 | // first intersect point if intrType is OneIntersect or TwoIntersects, undefined otherwise 20 | Vector2 point1; 21 | // second intersect point if intrType is TwoIntersects, undefined otherwise 22 | Vector2 point2; 23 | }; 24 | 25 | // Find intersect between two circles in 2D. 26 | template 27 | IntrCircle2Circle2Result intrCircle2Circle2(Real radius1, Vector2 const ¢er1, 28 | Real radius2, Vector2 const ¢er2) { 29 | // Reference algorithm: http://paulbourke.net/geometry/circlesphere/ 30 | 31 | IntrCircle2Circle2Result result; 32 | Vector2 cv = center2 - center1; 33 | Real d2 = dot(cv, cv); 34 | Real d = std::sqrt(d2); 35 | if (d < utils::realThreshold()) { 36 | // same center position 37 | if (utils::fuzzyEqual(radius1, radius2)) { 38 | result.intrType = Circle2Circle2IntrType::Coincident; 39 | } else { 40 | result.intrType = Circle2Circle2IntrType::NoIntersect; 41 | } 42 | } else { 43 | // different center position 44 | if (d > radius1 + radius2 + utils::realThreshold() || 45 | d + utils::realThreshold() < std::abs(radius1 - radius2)) { 46 | result.intrType = Circle2Circle2IntrType::NoIntersect; 47 | } else { 48 | Real rad1Sq = radius1 * radius1; 49 | Real a = (rad1Sq - radius2 * radius2 + d2) / (Real(2) * d); 50 | Vector2 midPoint = center1 + a * cv / d; 51 | Real diff = rad1Sq - a * a; 52 | if (diff < Real(0)) { 53 | result.intrType = Circle2Circle2IntrType::OneIntersect; 54 | result.point1 = midPoint; 55 | } else { 56 | Real h = std::sqrt(diff); 57 | Real hOverD = h / d; 58 | Real xTerm = hOverD * cv.y(); 59 | Real yTerm = hOverD * cv.x(); 60 | Real x1 = midPoint.x() + xTerm; 61 | Real y1 = midPoint.y() - yTerm; 62 | Real x2 = midPoint.x() - xTerm; 63 | Real y2 = midPoint.y() + yTerm; 64 | result.point1 = Vector2(x1, y1); 65 | result.point2 = Vector2(x2, y2); 66 | if (fuzzyEqual(result.point1, result.point2)) { 67 | result.intrType = Circle2Circle2IntrType::OneIntersect; 68 | } else { 69 | result.intrType = Circle2Circle2IntrType::TwoIntersects; 70 | } 71 | } 72 | } 73 | } 74 | 75 | return result; 76 | } 77 | } // namespace cavc 78 | 79 | #endif // CAVC_INTRCIRCLE2CIRCLE2_HPP 80 | -------------------------------------------------------------------------------- /libcavalier/include/cavc/intrlineseg2circle2.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CAVC_INTRLINESEG2CIRCLE2_HPP 2 | #define CAVC_INTRLINESEG2CIRCLE2_HPP 3 | #include "vector2.hpp" 4 | namespace cavc { 5 | template struct IntrLineSeg2Circle2Result { 6 | // number of interescts found (0, 1, or 2) 7 | int numIntersects; 8 | // parametric value for first intersect (if numIntersects > 0) otherwise undefined 9 | Real t0; 10 | // parametric value for second intersect (if numintersects > 1) otherwise undefined 11 | Real t1; 12 | }; 13 | 14 | // Gets the intersect between a segment and a circle, returning the parametric solution t to the 15 | // segment equation P(t) = v1 + t * (v2 - v1) for t = 0 to t = 1, if t < 0 or t > 1 then intersect 16 | // occurs only when extending the segment out past the points given (if t < 0 intersect nearest v1, 17 | // if t > 0 then intersect nearest v2), intersects are "sticky" and "snap" to tangent points, e.g. a 18 | // segment very close to being a tangent will be returned as a single intersect point 19 | template 20 | IntrLineSeg2Circle2Result intrLineSeg2Circle2(Vector2 const &p0, 21 | Vector2 const &p1, Real radius, 22 | Vector2 const &circleCenter) { 23 | // This function solves for t by substituting the parametric equations for the segment x = v1.X + 24 | // t * (v2.X - v1.X) and y = v1.Y + t * (v2.Y - v1.Y) for t = 0 to t = 1 into the circle equation 25 | // (x-h)^2 + (y-k)^2 = r^2 and then solving the resulting equation in the form a*t^2 + b*t + c = 0 26 | // using the quadratic formula 27 | IntrLineSeg2Circle2Result result; 28 | Real dx = p1.x() - p0.x(); 29 | Real dy = p1.y() - p0.y(); 30 | Real h = circleCenter.x(); 31 | Real k = circleCenter.y(); 32 | 33 | Real a = dx * dx + dy * dy; 34 | if (std::abs(a) < utils::realThreshold()) { 35 | // v1 = v2, test if point is on the circle 36 | Real xh = p0.x() - h; 37 | Real yk = p0.y() - k; 38 | if (utils::fuzzyEqual(xh * xh + yk * yk, radius * radius)) { 39 | result.numIntersects = 1; 40 | result.t0 = Real(0); 41 | } else { 42 | result.numIntersects = 0; 43 | } 44 | } else { 45 | Real b = Real(2) * (dx * (p0.x() - h) + dy * (p0.y() - k)); 46 | Real c = (p0.x() * p0.x() - 2.0 * h * p0.x() + h * h) + 47 | (p0.y() * p0.y() - 2.0 * k * p0.y() + k * k) - radius * radius; 48 | Real discr = b * b - 4.0 * a * c; 49 | 50 | if (std::abs(discr) < utils::realThreshold()) { 51 | // 1 solution (tangent line) 52 | result.numIntersects = 1; 53 | result.t0 = -b / (Real(2) * a); 54 | } else if (discr < Real(0)) { 55 | result.numIntersects = 0; 56 | } else { 57 | result.numIntersects = 2; 58 | std::pair sols = utils::quadraticSolutions(a, b, c, discr); 59 | result.t0 = sols.first; 60 | result.t1 = sols.second; 61 | } 62 | } 63 | 64 | CAVC_ASSERT(result.numIntersects >= 0 && result.numIntersects <= 2, "invalid intersect count"); 65 | return result; 66 | } 67 | } // namespace cavc 68 | 69 | #endif // CAVC_INTRLINESEG2CIRCLE2_HPP 70 | -------------------------------------------------------------------------------- /libcavalier/include/cavc/mathutils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CAVC_MATHUTILS_HPP 2 | #define CAVC_MATHUTILS_HPP 3 | 4 | #include "internal/common.hpp" 5 | #include 6 | #include 7 | namespace cavc { 8 | namespace utils { 9 | // absolute threshold to be used for comparing reals generally 10 | template constexpr Real realThreshold() { return Real(1e-8); } 11 | 12 | // absolute threshold to be used for reals in common geometric computation (e.g. to check for 13 | // singularities) 14 | template constexpr Real realPrecision() { return Real(1e-5); } 15 | 16 | // absolute threshold to be used for joining slices together at end points 17 | template constexpr Real sliceJoinThreshold() { return Real(1e-4); } 18 | 19 | // absolute threshold to be used for pruning invalid slices for offset 20 | template constexpr Real offsetThreshold() { return Real(1e-4); } 21 | 22 | template constexpr Real pi() { return Real(3.14159265358979323846264338327950288); } 23 | 24 | template constexpr Real tau() { return Real(2) * pi(); } 25 | 26 | template bool fuzzyEqual(Real x, Real y, Real epsilon = realThreshold()) { 27 | return std::abs(x - y) < epsilon; 28 | } 29 | 30 | template 31 | bool fuzzyInRange(Real minValue, Real value, Real maxValue, Real epsilon = realThreshold()) { 32 | return (value + epsilon > minValue) && (value < maxValue + epsilon); 33 | } 34 | 35 | /// Normalize radius to be between 0 and 2PI, e.g. -PI/4 becomes 7PI/8 and 5PI becomes PI. 36 | template Real normalizeRadians(Real angle) { 37 | if (angle >= Real(0) && angle <= tau()) { 38 | return angle; 39 | } 40 | 41 | return angle - std::floor(angle / tau()) * tau(); 42 | } 43 | 44 | /// Returns the smaller difference between two angles, result is negative if angle2 < angle1. 45 | template Real deltaAngle(Real angle1, Real angle2) { 46 | Real diff = normalizeRadians(angle2 - angle1); 47 | if (diff > pi()) { 48 | diff -= tau(); 49 | } 50 | 51 | return diff; 52 | } 53 | 54 | /// Tests if angle is between a start and end angle (counter clockwise start to end, inclusive). 55 | template 56 | bool angleIsBetween(Real startAngle, Real endAngle, Real testAngle, 57 | Real epsilon = realThreshold()) { 58 | Real endSweep = normalizeRadians(endAngle - startAngle); 59 | Real midSweep = normalizeRadians(testAngle - startAngle); 60 | 61 | return midSweep < endSweep + epsilon; 62 | } 63 | 64 | template 65 | bool angleIsWithinSweep(Real startAngle, Real sweepAngle, Real testAngle, 66 | Real epsilon = realThreshold()) { 67 | Real endAngle = startAngle + sweepAngle; 68 | if (sweepAngle < Real(0)) { 69 | return angleIsBetween(endAngle, startAngle, testAngle, epsilon); 70 | } 71 | 72 | return angleIsBetween(startAngle, endAngle, testAngle, epsilon); 73 | } 74 | 75 | /// Returns the solutions to for the quadratic equation -b +/- sqrt (b * b - 4 * a * c) / (2 * a). 76 | template 77 | std::pair quadraticSolutions(Real a, Real b, Real c, Real discr) { 78 | // Function avoids loss in precision due to taking the difference of two floating point values 79 | // that are very near each other in value. 80 | // See: 81 | // https://math.stackexchange.com/questions/311382/solving-a-quadratic-equation-with-precision-when-using-floating-point-variables 82 | CAVC_ASSERT(fuzzyEqual(b * b - Real(4) * a * c, discr), "discriminate is not correct"); 83 | Real sqrtDiscr = std::sqrt(discr); 84 | Real denom = Real(2) * a; 85 | Real sol1; 86 | if (b < Real(0)) { 87 | sol1 = (-b + sqrtDiscr) / denom; 88 | } else { 89 | sol1 = (-b - sqrtDiscr) / denom; 90 | } 91 | 92 | Real sol2 = (c / a) / sol1; 93 | 94 | return std::make_pair(sol1, sol2); 95 | } 96 | 97 | template std::size_t nextWrappingIndex(std::size_t index, const T &container) { 98 | if (index == container.size() - 1) { 99 | return 0; 100 | } 101 | 102 | return index + 1; 103 | } 104 | 105 | template std::size_t prevWrappingIndex(std::size_t index, const T &container) { 106 | if (index == 0) { 107 | return container.size() - 1; 108 | } 109 | 110 | return index - 1; 111 | } 112 | } // namespace utils 113 | } // namespace cavc 114 | 115 | #endif // CAVC_MATHUTILS_HPP 116 | -------------------------------------------------------------------------------- /libcavalier/include/cavc/vector2.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CAVC_VECTOR2_HPP 2 | #define CAVC_VECTOR2_HPP 3 | #include "mathutils.hpp" 4 | #include "vector.hpp" 5 | #include 6 | namespace cavc { 7 | template using Vector2 = Vector; 8 | 9 | /// Perpendicular vector to v (rotating counter clockwise). 10 | template Vector2 perp(Vector2 const &v) { 11 | return Vector2{-v.y(), v.x()}; 12 | } 13 | 14 | /// Normalized perpendicular vector to v (rotating counter clockwise). 15 | template Vector2 unitPerp(Vector2 const &v) { 16 | Vector2 result{-v.y(), v.x()}; 17 | normalize(result); 18 | return result; 19 | } 20 | 21 | /// Perpendicular dot product. Equivalent to dot(v0, perp(v1)). 22 | template Real perpDot(Vector2 const &v0, Vector2 const &v1) { 23 | return v0.x() * v1.y() - v0.y() * v1.x(); 24 | } 25 | 26 | /// Returns the distance squared between p0 and p1. Equivalent to dot(p1 - p0, p1 - p0). 27 | template Real distSquared(Vector2 const &p0, Vector2 const &p1) { 28 | Vector2 d = p1 - p0; 29 | return dot(d, d); 30 | } 31 | 32 | /// Counter clockwise angle of the vector going from p0 to p1. 33 | template Real angle(Vector2 const &p0, Vector2 const &p1) { 34 | return std::atan2(p1.y() - p0.y(), p1.x() - p0.x()); 35 | } 36 | 37 | /// Returns the midpoint between p0 and p1. 38 | template Vector2 midpoint(Vector2 const &p0, Vector2 const &p1) { 39 | return Vector2{(p0.x() + p1.x()) / Real(2), (p0.y() + p1.y()) / Real(2)}; 40 | } 41 | 42 | /// Computes the point on the circle with radius, center, and polar angle given. 43 | template 44 | Vector2 pointOnCircle(Real radius, Vector2 const ¢er, Real angle) { 45 | return Vector2{center.x() + radius * std::cos(angle), 46 | center.y() + radius * std::sin(angle)}; 47 | } 48 | 49 | /// Return the point on the segment going from p0 to p1 at parametric value t. 50 | template 51 | Vector2 pointFromParametric(Vector2 const &p0, Vector2 const &p1, Real t) { 52 | return p0 + t * (p1 - p0); 53 | } 54 | 55 | /// Returns the closest point that lies on the line segment from p0 to p1 to the point given. 56 | template 57 | Vector2 closestPointOnLineSeg(Vector2 const &p0, Vector2 const &p1, 58 | Vector2 const &point) { 59 | // Dot product used to find angles 60 | // See: http://geomalgorithms.com/a02-_lines.html 61 | Vector2 v = p1 - p0; 62 | Vector2 w = point - p0; 63 | Real c1 = dot(w, v); 64 | if (c1 < utils::realThreshold()) { 65 | return p0; 66 | } 67 | 68 | Real c2 = dot(v, v); 69 | if (c2 < c1 + utils::realThreshold()) { 70 | return p1; 71 | } 72 | 73 | Real b = c1 / c2; 74 | return p0 + b * v; 75 | } 76 | 77 | /// Returns true if point is left of the line pointing in the direction of the vector (p1 - p0). 78 | template 79 | bool isLeft(Vector2 const &p0, Vector2 const &p1, Vector2 const &point) { 80 | return (p1.x() - p0.x()) * (point.y() - p0.y()) - (p1.y() - p0.y()) * (point.x() - p0.x()) > 81 | Real(0); 82 | } 83 | 84 | /// Same as isLeft but uses <= operator rather than < for boundary inclusion. 85 | template 86 | bool isLeftOrEqual(Vector2 const &p0, Vector2 const &p1, Vector2 const &point) { 87 | return (p1.x() - p0.x()) * (point.y() - p0.y()) - (p1.y() - p0.y()) * (point.x() - p0.x()) >= 88 | Real(0); 89 | } 90 | 91 | /// Returns true if point is left or fuzzy coincident with the line pointing in the direction of the 92 | /// vector (p1 - p0). 93 | template 94 | bool isLeftOrCoincident(Vector2 const &p0, Vector2 const &p1, 95 | Vector2 const &point, Real epsilon = utils::realThreshold()) { 96 | return (p1.x() - p0.x()) * (point.y() - p0.y()) - (p1.y() - p0.y()) * (point.x() - p0.x()) > 97 | -epsilon; 98 | } 99 | 100 | /// Returns true if point is right or fuzzy coincident with the line pointing in the direction of 101 | /// the vector (p1 - p0). 102 | template 103 | bool isRightOrCoincident(Vector2 const &p0, Vector2 const &p1, 104 | Vector2 const &point, Real epsilon = utils::realThreshold()) { 105 | return (p1.x() - p0.x()) * (point.y() - p0.y()) - (p1.y() - p0.y()) * (point.x() - p0.x()) < 106 | epsilon; 107 | } 108 | 109 | /// Test if a point is within a arc sweep angle region defined by center, start, end, and bulge. 110 | template 111 | bool pointWithinArcSweepAngle(Vector2 const ¢er, Vector2 const &arcStart, 112 | Vector2 const &arcEnd, Real bulge, Vector2 const &point) { 113 | CAVC_ASSERT(std::abs(bulge) > utils::realThreshold(), "expected arc"); 114 | CAVC_ASSERT(std::abs(bulge) <= Real(1), "bulge should always be between -1 and 1"); 115 | 116 | if (bulge > Real(0)) { 117 | return isLeftOrCoincident(center, arcStart, point) && 118 | isRightOrCoincident(center, arcEnd, point); 119 | } 120 | 121 | return isRightOrCoincident(center, arcStart, point) && isLeftOrCoincident(center, arcEnd, point); 122 | } 123 | } // namespace cavc 124 | 125 | #endif // CAVC_VECTOR2_HPP 126 | -------------------------------------------------------------------------------- /libcavalier/offsets.h: -------------------------------------------------------------------------------- 1 | #ifndef OFFSETS_H 2 | #define OFFSETS_H 3 | 4 | #include 5 | 6 | struct POINTS{ // To be replaced by gp_Pnt. 7 | double x,y,z; 8 | }; 9 | 10 | class offsets 11 | { 12 | public: 13 | offsets(); 14 | 15 | //! Example of standard offset use -abs value for negative offset. 16 | void do_offset(double offset, enum offset_action action, double lead_in, double lead_out); 17 | void rotate_primairy_contour(unsigned int i /* contourvec[i] */); 18 | void create_lead_in_out(double lead_in, double lead_out); 19 | 20 | //! Helper functions, grabbed from old code example : 21 | std::vector arc_bulge(datas p /* primitive */); 22 | double arc_determinant(POINTS a /* arc startpoint */, POINTS b /* a arc circumfence point*/, POINTS c /* arc endpoint*/); 23 | POINTS arc_center(POINTS a /* arc startpoint */, POINTS b /* arc controlpoint*/, POINTS c /* arc endpoint */); 24 | POINTS offset_point_on_line(double xs, double ys, double xe, double ye, double offset_from_xs_ys); 25 | POINTS bulge_to_arc_controlpoint(POINTS p1, POINTS p2, double bulge); //find the arc center 26 | POINTS rotate_3d(double x_to_rotate,double y_to_rotate, double z_to_rotate, double rotate_degrees_x, double rotate_degrees_y, double rotate_degrees_z); 27 | void swap_contour(unsigned int i /*contourvec.at(i)*/); // A copy function from contour class. 28 | 29 | //! Create pockets, with or without islands. 30 | void do_pocket(); 31 | //void process_pocket(cavc::Polyline outerloop, std::vector> islands, unsigned int contourvec_i); 32 | //void draw_pocket(cavc::OffsetLoopSet results, unsigned int contourvec_i); 33 | 34 | }; 35 | 36 | 37 | #endif // OFFSETS_H 38 | -------------------------------------------------------------------------------- /libcavalier/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | add_subdirectory(polylinefactory) 3 | add_subdirectory(tests) 4 | add_subdirectory(benchmarks) 5 | -------------------------------------------------------------------------------- /libcavalier/tests/benchmarks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | 3 | include(googlebenchmark.cmake) 4 | include(clipper.cmake) 5 | 6 | macro(add_benchmark name) 7 | add_executable(${name} ${name}.cpp) 8 | target_link_libraries(${name} 9 | PRIVATE ${CAVC_CPP_HEADER_ONLY_LIB}) 10 | target_link_libraries(${name} 11 | PRIVATE PolylineFactory) 12 | target_link_libraries(${name} 13 | PRIVATE benchmark::benchmark) 14 | if (MSVC) 15 | target_link_options(${name} PRIVATE $<$:/PROFILE>) 16 | endif() 17 | endmacro() 18 | 19 | add_benchmark(offsetbenchmarks) 20 | add_benchmark(spatialindexbenchmarks) 21 | add_benchmark(extentsbenchmarks) 22 | add_benchmark(areabenchmarks) 23 | add_benchmark(pathlengthbenchmarks) 24 | add_benchmark(windingnumberbenchmarks) 25 | add_benchmark(combinebenchmarks) 26 | 27 | add_benchmark(clipperbenchmarks) 28 | target_link_libraries(clipperbenchmarks 29 | PRIVATE clipper_static) 30 | -------------------------------------------------------------------------------- /libcavalier/tests/benchmarks/areabenchmarks.cpp: -------------------------------------------------------------------------------- 1 | #include "benchmarkprofiles.h" 2 | #include "cavc/polyline.hpp" 3 | #include 4 | 5 | static void area(NoSetup, TestProfile const &profile) { 6 | cavc::getArea(profile.pline); 7 | } 8 | CAVC_CREATE_BENCHMARKS(area, NoSetup,area, benchmark::kNanosecond) 9 | CAVC_CREATE_NO_ARCS_BENCHMARKS(area, NoSetup, area, 0.01, benchmark::kNanosecond) 10 | 11 | BENCHMARK_MAIN(); 12 | -------------------------------------------------------------------------------- /libcavalier/tests/benchmarks/clipper.cmake: -------------------------------------------------------------------------------- 1 | include(FetchContent) 2 | FetchContent_Declare( 3 | clipper_static 4 | GIT_REPOSITORY https://github.com/jbuckmccready/clipper-lib 5 | GIT_TAG origin/master 6 | ) 7 | 8 | fetchcontent_getproperties(clipper_static) 9 | if(NOT clipper_static_POPULATED) 10 | fetchcontent_populate(clipper_static) 11 | add_subdirectory(${clipper_static_SOURCE_DIR} ${clipper_static_BINARY_DIR} 12 | EXCLUDE_FROM_ALL) 13 | endif() 14 | -------------------------------------------------------------------------------- /libcavalier/tests/benchmarks/clipperbenchmarks.cpp: -------------------------------------------------------------------------------- 1 | #include "clipper/clipper.hpp" 2 | #include "benchmarkprofiles.h" 3 | #include "cavc/polyline.hpp" 4 | #include 5 | 6 | const double clipperScaleFactor = 1e8; 7 | const double unscaledArcError = 0.01; 8 | const double clipperRoundPrecision = clipperScaleFactor * unscaledArcError; 9 | 10 | static ClipperLib::Path polylineToClipperPath(const cavc::Polyline &pline, 11 | double unscaledArcError) { 12 | auto noArcsPline = cavc::convertArcsToLines(pline, unscaledArcError); 13 | 14 | ClipperLib::Path clipperPath; 15 | clipperPath.reserve(noArcsPline.size()); 16 | for (const auto &v : noArcsPline.vertexes()) { 17 | ClipperLib::cInt xInt = static_cast(v.x() * clipperScaleFactor); 18 | ClipperLib::cInt yInt = static_cast(v.y() * clipperScaleFactor); 19 | clipperPath.push_back(ClipperLib::IntPoint(xInt, yInt)); 20 | } 21 | 22 | return clipperPath; 23 | } 24 | 25 | static void clipperOffset(const ClipperLib::Path &path, double delta, double roundPrecision, 26 | ClipperLib::Paths &results) { 27 | ClipperLib::ClipperOffset clipperOffset(2, roundPrecision); 28 | clipperOffset.AddPath(path, ClipperLib::JoinType::jtRound, ClipperLib::EndType::etClosedPolygon); 29 | clipperOffset.Execute(results, delta); 30 | } 31 | 32 | struct ClipperSetup { 33 | ClipperLib::Path clipperPath; 34 | ClipperSetup(TestProfile const &profile) 35 | : clipperPath(polylineToClipperPath(profile.pline, unscaledArcError)) {} 36 | }; 37 | 38 | static void offset(ClipperSetup const &setup, TestProfile const &profile) { 39 | // negate delta to match orientation that cavc uses 40 | double offsetDelta = -clipperScaleFactor * profile.offsetDelta; 41 | 42 | for (std::size_t i = 1; i <= profile.offsetCount; ++i) { 43 | double offset = i * offsetDelta; 44 | { 45 | ClipperLib::Paths results; 46 | clipperOffset(setup.clipperPath, offset, clipperRoundPrecision, results); 47 | } 48 | { 49 | ClipperLib::Paths results; 50 | clipperOffset(setup.clipperPath, -offset, clipperRoundPrecision, results); 51 | } 52 | } 53 | } 54 | 55 | CAVC_CREATE_BENCHMARKS(clipperOffset, ClipperSetup, offset, benchmark::kMillisecond) 56 | 57 | BENCHMARK_MAIN(); 58 | -------------------------------------------------------------------------------- /libcavalier/tests/benchmarks/combinebenchmarks.cpp: -------------------------------------------------------------------------------- 1 | #include "benchmarkprofiles.h" 2 | #include "cavc/polylinecombine.hpp" 3 | #include 4 | 5 | struct CombineShiftedSetup { 6 | std::vector> shiftedProfiles; 7 | 8 | CombineShiftedSetup(TestProfile const &profile) { 9 | auto extents = cavc::getExtents(profile.pline); 10 | double halfWidth = (extents.xMax - extents.xMin) / 2.0; 11 | double halfHeight = (extents.yMax - extents.yMin) / 2.0; 12 | 13 | auto createShifted = [&](double angle) { 14 | auto shifted = profile.pline; 15 | double xOffset = halfWidth * std::cos(angle); 16 | double yOffset = halfHeight * std::sin(angle); 17 | cavc::translatePolyline(shifted, {xOffset, yOffset}); 18 | return shifted; 19 | }; 20 | 21 | std::size_t shiftedCount = 16; 22 | shiftedProfiles.reserve(shiftedCount); 23 | for (std::size_t i = 0; i < shiftedCount; ++i) { 24 | double angle = static_cast(i) / shiftedCount * cavc::utils::tau(); 25 | shiftedProfiles.push_back(createShifted(angle)); 26 | } 27 | } 28 | }; 29 | 30 | static void combineShifted(CombineShiftedSetup const &setup, TestProfile const &profile) { 31 | for (auto const &shifted : setup.shiftedProfiles) { 32 | cavc::combinePolylines(profile.pline, shifted, cavc::PlineCombineMode::Union); 33 | cavc::combinePolylines(profile.pline, shifted, cavc::PlineCombineMode::Exclude); 34 | cavc::combinePolylines(profile.pline, shifted, cavc::PlineCombineMode::Intersect); 35 | cavc::combinePolylines(profile.pline, shifted, cavc::PlineCombineMode::XOR); 36 | } 37 | } 38 | 39 | CAVC_CREATE_BENCHMARKS(combine16Shifted, CombineShiftedSetup, combineShifted, 40 | benchmark::kMicrosecond) 41 | CAVC_CREATE_NO_ARCS_BENCHMARKS(combine16Shifted, CombineShiftedSetup, combineShifted, 0.01, 42 | benchmark::kMicrosecond) 43 | 44 | static void combineCoincident(NoSetup, TestProfile const &profile) { 45 | cavc::combinePolylines(profile.pline, profile.pline, cavc::PlineCombineMode::Union); 46 | cavc::combinePolylines(profile.pline, profile.pline, cavc::PlineCombineMode::Exclude); 47 | cavc::combinePolylines(profile.pline, profile.pline, cavc::PlineCombineMode::Intersect); 48 | cavc::combinePolylines(profile.pline, profile.pline, cavc::PlineCombineMode::XOR); 49 | } 50 | 51 | CAVC_CREATE_BENCHMARKS(combineCoincident, NoSetup, combineCoincident, benchmark::kMicrosecond) 52 | CAVC_CREATE_NO_ARCS_BENCHMARKS(combineCoincident, NoSetup, combineCoincident, 0.01, 53 | benchmark::kMicrosecond) 54 | 55 | BENCHMARK_MAIN(); 56 | -------------------------------------------------------------------------------- /libcavalier/tests/benchmarks/extentsbenchmarks.cpp: -------------------------------------------------------------------------------- 1 | #include "benchmarkprofiles.h" 2 | #include "cavc/polyline.hpp" 3 | #include 4 | 5 | static void extents(NoSetup, TestProfile const &profile) { 6 | cavc::getExtents(profile.pline); 7 | } 8 | CAVC_CREATE_BENCHMARKS(extents, NoSetup, extents, benchmark::kNanosecond) 9 | CAVC_CREATE_NO_ARCS_BENCHMARKS(extents, NoSetup, extents, 0.01, benchmark::kNanosecond) 10 | 11 | BENCHMARK_MAIN(); 12 | -------------------------------------------------------------------------------- /libcavalier/tests/benchmarks/googlebenchmark.cmake: -------------------------------------------------------------------------------- 1 | include(FetchContent) 2 | FetchContent_Declare( 3 | benchmark 4 | GIT_REPOSITORY https://github.com/google/benchmark.git 5 | GIT_TAG origin/master 6 | ) 7 | 8 | fetchcontent_getproperties(benchmark) 9 | if(NOT benchmark_POPULATED) 10 | set(BENCHMARK_ENABLE_TESTING OFF 11 | CACHE BOOL "Enable testing of the benchmark library." 12 | FORCE) 13 | set(BENCHMARK_ENABLE_GTEST_TESTS OFF 14 | CACHE BOOL "Enable building the unit tests which depend on gtest" 15 | FORCE) 16 | fetchcontent_populate(benchmark) 17 | add_subdirectory(${benchmark_SOURCE_DIR} ${benchmark_BINARY_DIR} 18 | EXCLUDE_FROM_ALL) 19 | endif() 20 | -------------------------------------------------------------------------------- /libcavalier/tests/benchmarks/offsetbenchmarks.cpp: -------------------------------------------------------------------------------- 1 | #include "benchmarkprofiles.h" 2 | #include "cavc/polylineoffset.hpp" 3 | #include 4 | 5 | const double arcError = 0.01; 6 | 7 | static void offset(NoSetup, TestProfile const &profile) { 8 | for (std::size_t i = 1; i <= profile.offsetCount; ++i) { 9 | double offset = i * profile.offsetDelta; 10 | cavc::parallelOffset(profile.pline, offset); 11 | cavc::parallelOffset(profile.pline, -offset); 12 | } 13 | } 14 | 15 | CAVC_CREATE_BENCHMARKS(offset, NoSetup, offset, benchmark::kMillisecond) 16 | 17 | CAVC_CREATE_NO_ARCS_BENCHMARKS(offset, NoSetup, offset, arcError, benchmark::kMillisecond) 18 | 19 | BENCHMARK_MAIN(); 20 | -------------------------------------------------------------------------------- /libcavalier/tests/benchmarks/pathlengthbenchmarks.cpp: -------------------------------------------------------------------------------- 1 | #include "benchmarkprofiles.h" 2 | #include "cavc/polyline.hpp" 3 | #include 4 | 5 | static void pathLength(NoSetup, TestProfile const &profile) { 6 | cavc::getPathLength(profile.pline); 7 | } 8 | CAVC_CREATE_BENCHMARKS(pathLength, NoSetup, pathLength, benchmark::kNanosecond) 9 | CAVC_CREATE_NO_ARCS_BENCHMARKS(pathLength, NoSetup, pathLength, 0.01, benchmark::kNanosecond) 10 | 11 | BENCHMARK_MAIN(); 12 | -------------------------------------------------------------------------------- /libcavalier/tests/benchmarks/spatialindexbenchmarks.cpp: -------------------------------------------------------------------------------- 1 | #include "benchmarkprofiles.h" 2 | #include "cavc/staticspatialindex.hpp" 3 | #include 4 | 5 | static void createIndex(NoSetup, TestProfile const &profile) { 6 | cavc::createApproxSpatialIndex(profile.pline); 7 | } 8 | 9 | CAVC_CREATE_BENCHMARKS(createIndex, NoSetup, createIndex, benchmark::kMicrosecond) 10 | CAVC_CREATE_NO_ARCS_BENCHMARKS(createIndex, NoSetup, createIndex, 0.01, benchmark::kMicrosecond) 11 | 12 | struct QuerySetup { 13 | std::vector queryResults; 14 | std::vector queryStack; 15 | cavc::StaticSpatialIndex spatialIndex; 16 | QuerySetup(TestProfile const &profile) 17 | : spatialIndex(cavc::createApproxSpatialIndex(profile.pline)) {} 18 | }; 19 | 20 | static void queryIndexReuseStack(QuerySetup &setup, TestProfile const &profile) { 21 | profile.pline.visitSegIndices([&](std::size_t i, std::size_t j) { 22 | cavc::AABB bb = cavc::createFastApproxBoundingBox(profile.pline[i], profile.pline[j]); 23 | setup.queryResults.clear(); 24 | bb.expand(0.1); 25 | setup.spatialIndex.query(bb.xMin, bb.yMin, bb.xMax, bb.yMax, setup.queryResults, 26 | setup.queryStack); 27 | return true; 28 | }); 29 | } 30 | 31 | CAVC_CREATE_BENCHMARKS(queryIndexReuseStack, QuerySetup, queryIndexReuseStack, 32 | benchmark::kMicrosecond) 33 | CAVC_CREATE_NO_ARCS_BENCHMARKS(queryIndexReuseStack, QuerySetup, queryIndexReuseStack, 0.01, 34 | benchmark::kMicrosecond) 35 | 36 | BENCHMARK_MAIN(); 37 | -------------------------------------------------------------------------------- /libcavalier/tests/benchmarks/windingnumberbenchmarks.cpp: -------------------------------------------------------------------------------- 1 | #include "benchmarkprofiles.h" 2 | #include "cavc/polyline.hpp" 3 | #include 4 | 5 | struct WindingNumberSetup { 6 | std::vector> testPts; 7 | WindingNumberSetup(TestProfile const &profile) { 8 | auto extents = cavc::getExtents(profile.pline); 9 | // expand out all directions by half the polyline width for some of the test points to for sure 10 | // be outside the polyline 11 | extents.expand((extents.xMax - extents.xMin) / 2.0); 12 | double width = extents.xMax - extents.xMin; 13 | double height = extents.yMax - extents.yMin; 14 | 15 | std::size_t gridDim = 10; 16 | testPts.reserve(gridDim * gridDim); 17 | // grid is inclusive at ends so we go from 0 to gridDim - 1 18 | for (std::size_t i = 0; i < gridDim; ++i) { 19 | for (std::size_t j = 0; j < gridDim; ++j) { 20 | // scale by gridDim - 1 (max iteration value) 21 | double x = static_cast(i) / (gridDim - 1) * width + extents.xMin; 22 | double y = static_cast(j) / (gridDim - 1) * height + extents.yMin; 23 | testPts.emplace_back(x, y); 24 | } 25 | } 26 | } 27 | }; 28 | 29 | static void windingNumber(WindingNumberSetup const &setup, TestProfile const &profile) { 30 | for (auto const &pt : setup.testPts) { 31 | cavc::getWindingNumber(profile.pline, pt); 32 | } 33 | } 34 | 35 | CAVC_CREATE_BENCHMARKS(windingNumber100PtGrid, WindingNumberSetup, windingNumber, 36 | benchmark::kMicrosecond) 37 | CAVC_CREATE_NO_ARCS_BENCHMARKS(windingNumber100PtGrid, WindingNumberSetup, windingNumber, 0.01, 38 | benchmark::kMicrosecond) 39 | 40 | BENCHMARK_MAIN(); 41 | -------------------------------------------------------------------------------- /libcavalier/tests/polylinefactory/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(PolylineFactory src/polylinefactory.cpp) 2 | 3 | target_include_directories(PolylineFactory 4 | PUBLIC include/) 5 | 6 | target_link_libraries(PolylineFactory 7 | PUBLIC ${CAVC_CPP_HEADER_ONLY_LIB}) 8 | 9 | target_link_libraries(PolylineFactory 10 | PUBLIC ${CAVC_C_API_LIB}) 11 | -------------------------------------------------------------------------------- /libcavalier/tests/polylinefactory/include/polylinefactory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CAVC_POLYLINEFACTORY_HPP 2 | #define CAVC_POLYLINEFACTORY_HPP 3 | #include "cavaliercontours.h" 4 | #include "cavc/polyline.hpp" 5 | 6 | struct cavc_pline_deleter { 7 | void operator()(cavc_pline *pline) { cavc_pline_delete(pline); } 8 | }; 9 | 10 | using cavc_pline_ptr = std::unique_ptr; 11 | 12 | class PolylineFactory { 13 | public: 14 | // Create a circle with radius and center, vertexRotAngle rotates the vertexes about the circle 15 | // center, if isCW is true then circle goes clockwise else counter clockwise. 16 | static std::vector createCircle(cavc_real radius, cavc_point center, 17 | cavc_real vertexRotAngle, bool isCW); 18 | static cavc_pline_ptr vertexesToPline(std::vector const &vertexes, bool isClosed); 19 | }; 20 | 21 | #endif // CAVC_POLYLINEPATHFACTORY_HPP 22 | -------------------------------------------------------------------------------- /libcavalier/tests/polylinefactory/src/polylinefactory.cpp: -------------------------------------------------------------------------------- 1 | #include "polylinefactory.hpp" 2 | 3 | static cavc_point pointOnCircle(cavc_real radius, cavc_point center, cavc_real angle) { 4 | return {center.x + radius * std::cos(angle), center.y + radius * std::sin(angle)}; 5 | } 6 | 7 | inline static cavc_real PI() { return 3.14159265358979323846264338327950288; } 8 | 9 | std::vector PolylineFactory::createCircle(cavc_real radius, cavc_point center, 10 | cavc_real vertexRotAngle, bool isCW) { 11 | std::vector result; 12 | result.reserve(2); 13 | 14 | cavc_point point1 = pointOnCircle(radius, center, vertexRotAngle); 15 | cavc_point point2 = pointOnCircle(radius, center, vertexRotAngle + PI()); 16 | cavc_real bulge = isCW ? -1.0 : 1.0; 17 | result.push_back({point1.x, point1.y, bulge}); 18 | result.push_back({point2.x, point2.y, bulge}); 19 | 20 | return result; 21 | } 22 | 23 | cavc_pline_ptr PolylineFactory::vertexesToPline(std::vector const &vertexes, 24 | bool isClosed) { 25 | return cavc_pline_ptr( 26 | cavc_pline_new(&vertexes[0], static_cast(vertexes.size()), isClosed)); 27 | } 28 | -------------------------------------------------------------------------------- /libcavalier/tests/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | include (googletest.cmake) 3 | 4 | macro(cavc_add_test name) 5 | add_executable(${name} ${name}.cpp) 6 | 7 | target_include_directories(${name} 8 | PRIVATE include/) 9 | 10 | target_link_libraries(${name} 11 | PRIVATE PolylineFactory) 12 | 13 | target_link_libraries(${name} 14 | PRIVATE ${CAVC_C_API_LIB}) 15 | 16 | target_link_libraries(${name} 17 | PRIVATE gtest_main gtest gmock) 18 | 19 | # note: adding executable as single test rather than discovering tests via gtest_discover_tests 20 | # because it adds parmeterized tests as individual tests and ctest runs them one by one which is 21 | # quite slow 22 | add_test(NAME ${name} COMMAND ${name}) 23 | endmacro() 24 | 25 | cavc_add_test(cavc_pline_tests) 26 | cavc_add_test(cavc_pline_function_tests) 27 | cavc_add_test(cavc_parallel_offset_tests) 28 | cavc_add_test(cavc_combine_plines_tests) 29 | cavc_add_test(staticspatialindex_tests) 30 | -------------------------------------------------------------------------------- /libcavalier/tests/tests/cavc_pline_tests.cpp: -------------------------------------------------------------------------------- 1 | #include "c_api_test_helpers.hpp" 2 | #include "cavaliercontours.h" 3 | #include "gmock/gmock.h" 4 | #include "gtest/gtest.h" 5 | #include 6 | 7 | namespace t = testing; 8 | 9 | class cavc_plineTests : public t::Test { 10 | protected: 11 | void SetUp() override; 12 | 13 | void TearDown() override; 14 | 15 | std::vector pline1Vertexes; 16 | cavc_pline *pline1 = nullptr; 17 | cavc_pline *pline2 = nullptr; 18 | std::size_t origPline1Size = 0; 19 | uint32_t initialPline1Size() { return static_cast(origPline1Size); } 20 | }; 21 | 22 | void cavc_plineTests::SetUp() { 23 | pline1Vertexes = {{1, 2, 0.1}, {33, 3, 0.2}, {34, 35, 0.3}, {2, 36, 0.4}}; 24 | origPline1Size = pline1Vertexes.size(); 25 | pline1 = cavc_pline_new(&pline1Vertexes[0], initialPline1Size(), 0); 26 | pline2 = cavc_pline_new(nullptr, 0, 1); 27 | } 28 | 29 | void cavc_plineTests::TearDown() { 30 | cavc_pline_delete(pline1); 31 | cavc_pline_delete(pline2); 32 | } 33 | 34 | TEST_F(cavc_plineTests, cavc_pline_new) { 35 | 36 | // test capacity 37 | EXPECT_EQ(cavc_pline_capacity(pline1), initialPline1Size()); 38 | 39 | // test is_closed 40 | EXPECT_EQ(cavc_pline_is_closed(pline1), 0); 41 | 42 | // test vertex_count 43 | auto pline1Count = cavc_pline_vertex_count(pline1); 44 | ASSERT_EQ(pline1Count, initialPline1Size()); 45 | 46 | // test vertex_data 47 | std::vector read_vertexes(pline1Count); 48 | cavc_pline_vertex_data(pline1, &read_vertexes[0]); 49 | ASSERT_THAT(pline1Vertexes, t::Pointwise(VertexEqual(), read_vertexes)); 50 | 51 | // test on empty pline 52 | // test capacity 53 | EXPECT_EQ(cavc_pline_capacity(pline2), 0); 54 | 55 | // test is_closed 56 | EXPECT_EQ(cavc_pline_is_closed(pline2), 1); 57 | 58 | // test vertex_count 59 | auto pline2Count = cavc_pline_vertex_count(pline2); 60 | ASSERT_EQ(pline2Count, 0); 61 | 62 | // test vertex_data 63 | cavc_pline_vertex_data(pline2, &read_vertexes[0]); 64 | // nothing should have been written to the buffer 65 | ASSERT_THAT(read_vertexes, t::Pointwise(VertexEqual(), pline1Vertexes)); 66 | } 67 | 68 | TEST_F(cavc_plineTests, cavc_pline_set_capacity) { 69 | // setting capacity less than current does nothing 70 | cavc_pline_set_capacity(pline1, 1); 71 | ASSERT_EQ(cavc_pline_capacity(pline1), 4); 72 | 73 | cavc_pline_set_capacity(pline1, 11); 74 | ASSERT_EQ(cavc_pline_capacity(pline1), 11); 75 | } 76 | 77 | TEST_F(cavc_plineTests, cavc_pline_set_vertex_data) { 78 | cavc_pline_set_vertex_data(pline2, &pline1Vertexes[0], initialPline1Size()); 79 | ASSERT_EQ(cavc_pline_vertex_count(pline2), initialPline1Size()); 80 | 81 | std::vector readVertexes(initialPline1Size()); 82 | cavc_pline_vertex_data(pline2, &readVertexes[0]); 83 | ASSERT_THAT(readVertexes, t::Pointwise(VertexEqual(), pline1Vertexes)); 84 | } 85 | 86 | TEST_F(cavc_plineTests, cavc_pline_add_vertex) { 87 | cavc_vertex v{555, 666, 0.777}; 88 | cavc_pline_add_vertex(pline1, v); 89 | ASSERT_EQ(cavc_pline_vertex_count(pline1), initialPline1Size() + 1); 90 | 91 | std::vector readVertexes(initialPline1Size() + 1); 92 | cavc_pline_vertex_data(pline1, &readVertexes[0]); 93 | pline1Vertexes.push_back(v); 94 | ASSERT_THAT(readVertexes, t::Pointwise(VertexEqual(), pline1Vertexes)); 95 | 96 | cavc_pline_add_vertex(pline2, v); 97 | ASSERT_EQ(cavc_pline_vertex_count(pline2), 1); 98 | 99 | readVertexes.resize(1); 100 | cavc_pline_vertex_data(pline2, &readVertexes[0]); 101 | ASSERT_THAT(readVertexes, t::Pointwise(VertexEqual(), {v})); 102 | } 103 | 104 | TEST_F(cavc_plineTests, cavc_pline_remove_range) { 105 | // remove first vertex 106 | cavc_pline_remove_range(pline1, 0, 1); 107 | ASSERT_EQ(cavc_pline_vertex_count(pline1), initialPline1Size() - 1); 108 | 109 | std::vector readVertexes(initialPline1Size() - 1); 110 | cavc_pline_vertex_data(pline1, &readVertexes[0]); 111 | pline1Vertexes.erase(pline1Vertexes.begin()); 112 | ASSERT_THAT(readVertexes, t::Pointwise(VertexEqual(), pline1Vertexes)); 113 | 114 | // remove 2nd and 3rd vertex 115 | cavc_pline_remove_range(pline1, 1, 2); 116 | ASSERT_EQ(cavc_pline_vertex_count(pline1), initialPline1Size() - 3); 117 | readVertexes.resize(1); 118 | cavc_pline_vertex_data(pline1, &readVertexes[0]); 119 | pline1Vertexes.erase(pline1Vertexes.begin() + 1, pline1Vertexes.begin() + 3); 120 | ASSERT_THAT(readVertexes, t::Pointwise(VertexEqual(), pline1Vertexes)); 121 | 122 | // remove last vertex 123 | cavc_pline_remove_range(pline1, 0, 1); 124 | ASSERT_EQ(cavc_pline_vertex_count(pline1), initialPline1Size() - 4); 125 | 126 | readVertexes.resize(10); 127 | std::fill(readVertexes.begin(), readVertexes.end(), cavc_vertex{-1, -2, -3}); 128 | auto copy = readVertexes; 129 | cavc_pline_vertex_data(pline1, &readVertexes[0]); 130 | // nothing should have been written to the buffer 131 | ASSERT_THAT(readVertexes, t::Pointwise(VertexEqual(), copy)); 132 | } 133 | 134 | TEST_F(cavc_plineTests, cavc_pline_clear) { 135 | cavc_pline_clear(pline1); 136 | ASSERT_EQ(cavc_pline_vertex_count(pline1), 0); 137 | 138 | cavc_pline_clear(pline2); 139 | ASSERT_EQ(cavc_pline_vertex_count(pline2), 0); 140 | } 141 | 142 | int main(int argc, char **argv) { 143 | t::InitGoogleTest(&argc, argv); 144 | return RUN_ALL_TESTS(); 145 | } 146 | -------------------------------------------------------------------------------- /libcavalier/tests/tests/googletest.cmake: -------------------------------------------------------------------------------- 1 | include(FetchContent) 2 | FetchContent_Declare( 3 | googletest 4 | GIT_REPOSITORY https://github.com/google/googletest.git 5 | GIT_TAG origin/master 6 | ) 7 | 8 | fetchcontent_getproperties(googletest) 9 | if(NOT googletest_POPULATED) 10 | # this is required for msvc or we get linker errors 11 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 12 | fetchcontent_populate(googletest) 13 | add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} 14 | EXCLUDE_FROM_ALL) 15 | endif() 16 | -------------------------------------------------------------------------------- /libcavalier/tests/tests/include/c_api_test_helpers.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CAVC_API_TEST_HELPERS_HPP 2 | #define CAVC_API_TEST_HELPERS_HPP 3 | #include "cavaliercontours.h" 4 | #include "testhelpers.hpp" 5 | #include "gmock/gmock.h" 6 | #include "gtest/gtest.h" 7 | #include 8 | 9 | inline bool vertexesFuzzyEqual(cavc_vertex const &left, cavc_vertex const &right) { 10 | return fuzzyEqual(left.x, right.x) && fuzzyEqual(left.y, right.y) && 11 | fuzzyEqual(left.bulge, right.bulge); 12 | } 13 | 14 | template 15 | inline std::size_t nextWrappingIndex(Container const &container, std::size_t index) { 16 | if (index == container.size() - 1) { 17 | return 0; 18 | } 19 | return index + 1; 20 | } 21 | 22 | MATCHER(VertexFuzzyEqual, "") { 23 | auto const &left = std::get<0>(arg); 24 | auto const &right = std::get<1>(arg); 25 | return vertexesFuzzyEqual(left, right); 26 | } 27 | 28 | MATCHER(VertexEqual, "") { 29 | auto const &left = std::get<0>(arg); 30 | auto const &right = std::get<1>(arg); 31 | return left.x == right.x && left.y == right.y && left.bulge == right.bulge; 32 | } 33 | 34 | MATCHER(PointFuzzyEqual, "") { 35 | auto const &left = std::get<0>(arg); 36 | auto const &right = std::get<1>(arg); 37 | return fuzzyEqual(left.x, right.x) && fuzzyEqual(left.y, right.y); 38 | } 39 | 40 | MATCHER_P(VertexListsFuzzyEqual, isClosed, "") { 41 | auto const &left = std::get<0>(arg); 42 | auto const &right = std::get<1>(arg); 43 | if (left.size() != right.size()) { 44 | *result_listener << "sizes of vertex lists do not match "; 45 | return false; 46 | } 47 | 48 | std::size_t const vertexCount = left.size(); 49 | 50 | if (!isClosed) { 51 | // open polyline indexes much match up 52 | for (std::size_t i = 0; i < vertexCount; ++i) { 53 | if (!vertexesFuzzyEqual(left[i], right[i])) { 54 | *result_listener << "vertexes not equal at index: " << i << " "; 55 | return false; 56 | } 57 | } 58 | return true; 59 | } 60 | 61 | // vertexes may not have same indexes in the case of a closed polyline, find first matching and 62 | // start matching from there 63 | std::size_t startIndex = 0; 64 | for (; startIndex < vertexCount; ++startIndex) { 65 | if (vertexesFuzzyEqual(left[0], right[startIndex])) { 66 | break; 67 | } 68 | } 69 | 70 | if (startIndex == vertexCount) { 71 | *result_listener << "did not find matching vertex to start with "; 72 | return false; 73 | } 74 | 75 | *result_listener << " started matching at index: " << startIndex << " "; 76 | // first one already matched, start at next index 77 | std::size_t index = nextWrappingIndex(left, startIndex); 78 | for (std::size_t i = 1; i < vertexCount; ++i) { 79 | if (!vertexesFuzzyEqual(left[i], right[index])) { 80 | *result_listener << "vertexes not equal at index: " << index << " "; 81 | return false; 82 | } 83 | index = nextWrappingIndex(left, index); 84 | } 85 | 86 | return true; 87 | } 88 | 89 | inline std::ostream &operator<<(std::ostream &os, cavc_vertex const &v) { 90 | os << '[' << v.x << "," << v.y << "," << v.bulge << ']'; 91 | return os; 92 | } 93 | 94 | inline std::ostream &operator<<(std::ostream &os, cavc_point const &p) { 95 | os << '[' << p.x << "," << p.y << ']'; 96 | return os; 97 | } 98 | 99 | // helper to just create a cavc_pline from vertexes 100 | cavc_pline *plineFromVertexes(std::vector const &vertexes, bool isClosed) { 101 | return cavc_pline_new(&vertexes[0], static_cast(vertexes.size()), isClosed ? 1 : 0); 102 | } 103 | 104 | // reverses the direction of the polyline defined by vertexes 105 | void reverseDirection(std::vector &vertexes) { 106 | if (vertexes.size() < 2) { 107 | return; 108 | } 109 | 110 | std::reverse(vertexes.begin(), vertexes.end()); 111 | cavc_real firstBulge = vertexes[0].bulge; 112 | for (std::size_t i = 1; i < vertexes.size(); ++i) { 113 | vertexes[i - 1].bulge = -vertexes[i].bulge; 114 | } 115 | 116 | vertexes.back().bulge = -firstBulge; 117 | } 118 | 119 | // create a reversed polyline from the given pline (caller must delete the created pline) 120 | cavc_pline *createRevseredPline(cavc_pline *pline) { 121 | uint32_t count = cavc_pline_vertex_count(pline); 122 | std::vector vertexes(count); 123 | cavc_pline_vertex_data(pline, &vertexes[0]); 124 | reverseDirection(vertexes); 125 | return cavc_pline_new(&vertexes[0], count, cavc_pline_is_closed(pline)); 126 | } 127 | 128 | #endif // CAVC_API_TEST_HELPERS_HPP 129 | -------------------------------------------------------------------------------- /libcavalier/tests/tests/include/testhelpers.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CAVC_TESTHELPERS_HPP 2 | #define CAVC_TESTHELPERS_HPP 3 | #include "cavaliercontours.h" 4 | #include 5 | #include 6 | constexpr inline cavc_real PI() { return 3.14159265358979323846264338327950288; } 7 | constexpr inline cavc_real TEST_EPSILON() { return 1e-5; } 8 | template inline bool fuzzyEqual(Real const &left, cavc_real const &right) { 9 | return std::abs(left - right) < TEST_EPSILON(); 10 | } 11 | 12 | // type to hold summary properties of a polyline for test comparing, acts as a sort of geometric 13 | // hash of the polyline, it is very unlikely that two polylines have the same PolylineProperties 14 | // without being the same polyline, especially accidentally via generation in an algorithm 15 | struct PolylineProperties { 16 | std::size_t vertexCount; 17 | cavc_real area; 18 | cavc_real pathLength; 19 | cavc_real minX; 20 | cavc_real minY; 21 | cavc_real maxX; 22 | cavc_real maxY; 23 | 24 | PolylineProperties(std::size_t vertexCount, cavc_real area, cavc_real pathLength, cavc_real minX, 25 | cavc_real minY, cavc_real maxX, cavc_real maxY) 26 | : vertexCount(vertexCount), area(area), pathLength(pathLength), minX(minX), minY(minY), 27 | maxX(maxX), maxY(maxY) {} 28 | 29 | PolylineProperties(cavc_pline *pline) { 30 | vertexCount = cavc_pline_vertex_count(pline); 31 | area = cavc_get_area(pline); 32 | pathLength = cavc_get_path_length(pline); 33 | cavc_get_extents(pline, &minX, &minY, &maxX, &maxY); 34 | } 35 | }; 36 | 37 | // fuzzy equality operator== for testing 38 | inline bool operator==(PolylineProperties const &left, PolylineProperties const &right) { 39 | return left.vertexCount == right.vertexCount && fuzzyEqual(left.area, right.area) && 40 | fuzzyEqual(left.pathLength, right.pathLength) && fuzzyEqual(left.minX, right.minX) && 41 | fuzzyEqual(left.minY, right.minY) && fuzzyEqual(left.maxX, right.maxX) && 42 | fuzzyEqual(left.maxY, right.maxY); 43 | } 44 | 45 | inline std::ostream &operator<<(std::ostream &os, PolylineProperties const &p) { 46 | os << "{ vertexCount: " << p.vertexCount << ", area: " << p.area 47 | << ", pathLength: " << p.pathLength << ", minX: " << p.minX << ", minY: " << p.minY 48 | << ", maxX: " << p.maxX << ", maxY: " << p.maxY << " }"; 49 | return os; 50 | } 51 | #endif // CAVC_TESTHELPERS_HPP 52 | -------------------------------------------------------------------------------- /libcontour/contours.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTOURS_H 2 | #define CONTOURS_H 3 | 4 | #include 5 | #include "opencascade.h" 6 | #include "draw_primitives.h" 7 | using namespace occ; 8 | 9 | class contours 10 | { 11 | public: 12 | contours(); 13 | 14 | void main(double tol, std::string layer); 15 | 16 | //! Wich layer to cut? 17 | void init_primitives(std::string layer); 18 | 19 | //! Check if open contours are open or closed. For example a spline can be closed if startpoint = endpoint. 20 | //! tol = tollerance to classify a startpoint-endpoint match. 21 | void check_for_single_closed_contours(double tol); 22 | void check_for_multi_contours(double tol); 23 | void check_for_single_open_contours(double tol); 24 | 25 | //! Add contour depth squence. This is not a "keep parts together" algoritme. It cut's depth for depth. 26 | //! It algoritme is preferred to be used to avoid thermal distortion. 27 | void add_contour_depth_sequence(); 28 | void add_contour_ccw(); 29 | std::vector get_childs(std::vector list); 30 | std::vector get_toplevel(std::vector list); 31 | std::vector lista_min_listb(std::vector lista, std::vector listb); 32 | 33 | //! Helper functions 34 | void area(); 35 | void swap(unsigned int i); 36 | void swap_contour(unsigned int i /*contourvec.at(i)*/); 37 | int find_next(unsigned int i /*source*/, unsigned int &target /*target*/, double tol); 38 | 39 | int find_start_start_match(unsigned int i /*source*/, unsigned int j /*target*/, double tol); 40 | int find_start_end_match(unsigned int i /*source*/, unsigned int j /*target*/, double tol); 41 | int find_end_start_match(unsigned int i /*source*/, unsigned int j /*target*/, double tol); 42 | int find_end_end_match(unsigned int i /*source*/, unsigned int j /*target*/, double tol); 43 | 44 | void print_result(); 45 | void print_depth_sequence(); 46 | 47 | int point_in_polygon(std::vector polygon, gp_Pnt point); 48 | 49 | //! A toplevel contour is depth=0. A inside contour of depth=0 would be depth=1. How deep parts are nested is saved by the maxdepth value. 50 | int get_max_depth(); 51 | 52 | //! Keep parts together algorimte, shortened "kpt". 53 | //! Return a organized list in cut seauence of contourvec.at[i] 54 | std::vector keep_parts_together(); 55 | 56 | private: 57 | 58 | }; 59 | 60 | #endif // CONTOURS_H 61 | -------------------------------------------------------------------------------- /libdata/variable.cpp: -------------------------------------------------------------------------------- 1 | #include "variable.h" 2 | 3 | std::vector datavec, dxfvec, rapidvec; 4 | std::vector contourvec, pocketvec; 5 | gcode_setup gc; 6 | double last_x=0,last_y=0,last_z=0; 7 | int linenumber; 8 | std::vector gcvec; 9 | std::vector kpt_sequence; // Keep parts together list. 10 | int maxdepth; 11 | 12 | variable::variable() 13 | { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /libdata/variable.h: -------------------------------------------------------------------------------- 1 | #ifndef VARIABLE_H 2 | #define VARIABLE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | enum primitive_type { 9 | point=0, 10 | line=1, 11 | lwpolyline=2, // Wire, linestrip 12 | circle=3, 13 | arc=4, 14 | spline=5, 15 | ellipse=6, 16 | }; 17 | 18 | enum contour_type { 19 | none=0, 20 | single_open=1, 21 | single_closed=2, 22 | multi_open=3, 23 | multi_closed=4, 24 | }; 25 | 26 | enum contour_dir { 27 | cw=0, 28 | ccw=1, 29 | }; 30 | 31 | enum offset_action { 32 | offset_contour=0, 33 | lead_base_contour=1, 34 | lead_in_contour=2, 35 | lead_out_contour=3, 36 | pocket=4, 37 | }; 38 | 39 | struct datas { 40 | Handle(AIS_Shape) ashape; 41 | primitive_type primitivetype; 42 | contour_type contourtype=contour_type::none; 43 | std::string acad_layer; 44 | //! Startpoint, endpoint 45 | gp_Pnt start{0,0,0}, end{0,0,0}, center{0,0,0}; // Center is used by cavalier functions. 46 | std::vector control, arcmid; // Arcmid is used by cavalier function and is the point at half way arc circumfence. 47 | double radius=0; // Radius is used by cavalier functions. 48 | double bulge=0; // For arc's to define if the arc is [cw] or [ccw]. bulge<0=g2 49 | bool select=0; // Helper for contour algoritme. 50 | }; 51 | //! Datavec contains the filtered cad_layers to cut, dxfvec is the complete dxf data. 52 | extern std::vector datavec, dxfvec, rapidvec; 53 | 54 | struct lead_in_out { 55 | //! The lead-in, lead-out shape (line, arc, etc). 56 | Handle(AIS_Shape) ashape; 57 | //! Choose one of the parallel Points to draw the lead-in, lead-out. 58 | std::vector points; 59 | }; 60 | 61 | struct contour { 62 | std::vector primitive_sequence; 63 | contour_dir dir; 64 | double area=0; 65 | 66 | //! Lead_base=base points circumfence contour, Lead_in=circumfence points at lead_in offset, Lead_out=circumfence points at lead_out offset. 67 | lead_in_out lead_in, lead_out, lead_base; 68 | //! Current lead_base point position. If the lead_in-out is shifted to another position, this value stores the current lead_in-out index position. 69 | // unsigned int lead_index=0; 70 | 71 | std::vector offset_sequence; // Primitives in cw order. 72 | 73 | // Contour depth. 74 | std::vector childcontours; 75 | bool select=false; 76 | int depth=0; 77 | }; 78 | extern std::vector contourvec, pocketvec; 79 | 80 | struct gcode_setup{ 81 | std::string filename="gcode.ngc"; 82 | std::string linenumber_format="N"; 83 | std::string z_axis_format="Z"; 84 | std::string tool_on_macro=""; 85 | 86 | bool print_linenumbers=true; 87 | double lead_in; 88 | double lead_out; 89 | int lead_start_i; 90 | double offset; 91 | double travelheight; 92 | double pierceheight; 93 | double piercespeed; 94 | double piercedelay; 95 | double cutheight; 96 | double power; 97 | double feedrate; 98 | double internal_pocket_offset; 99 | double tooloffset_x, tooloffset_y, tooloffset_z; 100 | 101 | 102 | std::string layer; 103 | std::vector intro; 104 | std::vector outtro; 105 | 106 | std::string operation_type; // Offset, pocket, drill. 107 | }; 108 | extern gcode_setup gc; 109 | extern std::vector gcvec; 110 | extern double last_x,last_y,last_z; // Used for displaying rapids. Can be used for toolhomepos. 111 | 112 | extern int linenumber; 113 | 114 | extern std::vector kpt_sequence; // Keep parts together list. 115 | 116 | extern int maxdepth; 117 | 118 | class variable 119 | { 120 | public: 121 | variable(); 122 | }; 123 | 124 | #endif // VARIABLE_H 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /libdialog/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1.0) 2 | 3 | project(portable_file_dialogs VERSION 1.00 LANGUAGES CXX) 4 | 5 | add_library(${PROJECT_NAME} INTERFACE) 6 | target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) -------------------------------------------------------------------------------- /libdialog/COPYING: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | 15 | -------------------------------------------------------------------------------- /libdialog/README.md: -------------------------------------------------------------------------------- 1 | # Portable File Dialogs 2 | 3 | A free C++11 file dialog library. 4 | 5 | - works on Windows, Mac OS X, Linux 6 | - **single-header**, no extra library dependencies 7 | - **synchronous *or* asynchronous** (does not block the rest of your program!) 8 | - **cancelable** (kill asynchronous dialogues without user interaction) 9 | - **secure** (immune to shell-quote vulnerabilities) 10 | 11 | [![Codacy Badge](https://app.codacy.com/project/badge/Grade/a25d3fd6959a4333871f630ac70b6e09)](https://www.codacy.com/manual/samhocevar/portable-file-dialogs?utm_source=github.com&utm_medium=referral&utm_content=samhocevar/portable-file-dialogs&utm_campaign=Badge_Grade) 12 | 13 | ## Status 14 | 15 | The library is now pretty robust. It is not as feature-complete as 16 | [Tiny File Dialogs](https://sourceforge.net/projects/tinyfiledialogs/), 17 | but has asynchonous dialogs, more maintainable code, and fewer potential 18 | security issues. 19 | 20 | The currently available backends are: 21 | 22 | - Win32 API (all known versions of Windows) 23 | - Mac OS X (using AppleScript) 24 | - GNOME desktop (using [Zenity](https://en.wikipedia.org/wiki/Zenity) or its clones Matedialog and Qarma) 25 | - KDE desktop (using [KDialog](https://github.com/KDE/kdialog)) 26 | 27 | Experimental support for Emscripten is on its way. 28 | 29 | ## Documentation 30 | 31 | - [`pfd`](doc/pfd.md) general documentation 32 | - [`pfd::message`](doc/message.md) message box 33 | - [`pfd::notify`](doc/notify.md) notification 34 | - [`pfd::open_file`](doc/open_file.md) file open 35 | - [`pfd::save_file`](doc/save_file.md) file save 36 | - [`pfd::select_folder`](doc/select_folder.md) folder selection 37 | 38 | ## History 39 | 40 | - 0.1.0 (July 16, 2020): first public release 41 | 42 | ## Screenshots (Windows 10) 43 | 44 | ![warning-win32](https://user-images.githubusercontent.com/245089/47136607-76919a00-d2b4-11e8-8f42-e2d62c4f9570.png) 45 | ![notify-win32](https://user-images.githubusercontent.com/245089/47142453-2ff76c00-d2c3-11e8-871a-1a110ac91eb2.png) 46 | ![open-win32](https://user-images.githubusercontent.com/245089/47155865-0f8cd900-d2e6-11e8-8041-1e20b6f77dee.png) 47 | 48 | ## Screenshots (Mac OS X, dark theme) 49 | 50 | ![warning-osxdark](https://user-images.githubusercontent.com/245089/56053001-22dba700-5d53-11e9-8233-ca7a2c58188d.png) 51 | ![notify-osxdark](https://user-images.githubusercontent.com/245089/56053188-bc0abd80-5d53-11e9-8298-68aa96315c6c.png) 52 | ![open-osxdark](https://user-images.githubusercontent.com/245089/56053378-39363280-5d54-11e9-9583-9f1c978fa0db.png) 53 | 54 | ## Screenshots (Linux, GNOME desktop) 55 | 56 | ![warning-gnome](https://user-images.githubusercontent.com/245089/47136608-772a3080-d2b4-11e8-9e1d-60a7e743e908.png) 57 | ![notify-gnome](https://user-images.githubusercontent.com/245089/47142455-30900280-d2c3-11e8-8b76-ea16c7e502d4.png) 58 | ![open-gnome](https://user-images.githubusercontent.com/245089/47155867-0f8cd900-d2e6-11e8-93af-275636491ec4.png) 59 | 60 | ## Screenshots (Linux, KDE Plasma desktop) 61 | 62 | ![warning-kde](https://user-images.githubusercontent.com/245089/47149255-4dcccd00-d2d3-11e8-84c9-f85612784680.png) 63 | ![notify-kde](https://user-images.githubusercontent.com/245089/47149206-27a72d00-d2d3-11e8-8f1b-96e462f08c2b.png) 64 | ![open-kde](https://user-images.githubusercontent.com/245089/47155866-0f8cd900-d2e6-11e8-8006-f14b948afc55.png) 65 | -------------------------------------------------------------------------------- /libdialog/doc/message.md: -------------------------------------------------------------------------------- 1 | ## Message Box API 2 | 3 | Displaying a message box is done using the `pfd::message` class. It can be provided a title, a 4 | message text, a `choice` representing which buttons need to be rendered, and an `icon` for the 5 | message: 6 | 7 | ```cpp 8 | pfd::message::message(std::string const &title, 9 | std::string const &text, 10 | pfd::choice choice = pfd::choice::ok_cancel, 11 | pfd::icon icon = pfd::icon::info); 12 | 13 | enum class pfd::choice { ok, ok_cancel, yes_no, yes_no_cancel }; 14 | 15 | enum class pfd::icon { info, warning, error, question }; 16 | ``` 17 | 18 | The pressed button is queried using `pfd::message::result()`. If the dialog box is closed by any 19 | other means, the `pfd::button::cancel` is assumed: 20 | 21 | ```cpp 22 | pfd::button pfd::message::result(); 23 | 24 | enum class pfd::button { ok, cancel, yes, no }; 25 | ``` 26 | 27 | It is possible to ask the dialog box whether the user took action using the `pfd::message::ready()` 28 | method, with an optional `timeout` argument. If the user did not press a button within `timeout` 29 | milliseconds, the function will return `false`: 30 | 31 | ```cpp 32 | bool pfd::message::ready(int timeout = pfd::default_wait_timeout); 33 | ``` 34 | 35 | ## Example 1: simple notification 36 | 37 | The `pfd::message` destructor waits for user action, so this operation will block until the user 38 | closes the message box: 39 | 40 | ```cpp 41 | pfd::message("Problem", "An error occurred while doing things", 42 | pfd::choice::ok, pfd::icon::error); 43 | ``` 44 | 45 | ## Example 2: retrieving the pressed button 46 | 47 | Using `pfd::message::result()` will also wait for user action before returning. This operation will block and return the user choice: 48 | 49 | ```cpp 50 | // Ask for user opinion 51 | auto button = pfd::message("Action requested", "Do you want to proceed with things?", 52 | pfd::choice::yes_no, pfd::icon::question).result(); 53 | // Do something with button… 54 | ``` 55 | 56 | ## Example 3: asynchronous message box 57 | 58 | Using `pfd::message::ready()` allows the application to perform other tasks while waiting for 59 | user input: 60 | 61 | ```cpp 62 | // Message box with nice message 63 | auto box = pfd::message("Unsaved Files", "Do you want to save the current " 64 | "document before closing the application?", 65 | pfd::choice::yes_no_cancel, 66 | pfd::icon::warning); 67 | 68 | // Do something while waiting for user input 69 | while (!box.ready(1000)) 70 | std::cout << "Waited 1 second for user input...\n"; 71 | 72 | // Act depending on the selected button 73 | switch (box.result()) 74 | { 75 | case pfd::button::yes: std::cout << "User agreed.\n"; break; 76 | case pfd::button::no: std::cout << "User disagreed.\n"; break; 77 | case pfd::button::cancel: std::cout << "User freaked out.\n"; break; 78 | } 79 | ``` 80 | 81 | ## Screenshots 82 | 83 | #### Windows 10 84 | 85 | ![warning-win32](https://user-images.githubusercontent.com/245089/47136607-76919a00-d2b4-11e8-8f42-e2d62c4f9570.png) 86 | 87 | #### Mac OS X 88 | 89 | ![warning-osx-dark](https://user-images.githubusercontent.com/245089/56053001-22dba700-5d53-11e9-8233-ca7a2c58188d.png) ![warning-osx-light](https://user-images.githubusercontent.com/245089/56053055-49014700-5d53-11e9-8306-e9a03a25e044.png) 90 | 91 | #### Linux (GNOME desktop) 92 | 93 | ![warning-gnome](https://user-images.githubusercontent.com/245089/47140824-8662ab80-d2bf-11e8-9c87-2742dd5b58af.png) 94 | 95 | #### Linux (KDE desktop) 96 | 97 | ![warning-kde](https://user-images.githubusercontent.com/245089/47149255-4dcccd00-d2d3-11e8-84c9-f85612784680.png) 98 | -------------------------------------------------------------------------------- /libdialog/doc/notify.md: -------------------------------------------------------------------------------- 1 | ## Notification API 2 | 3 | Displaying a desktop notification is done using the `pfd::notify` class. It can be provided a 4 | title, a message text, and an `icon` for the notification style: 5 | 6 | ```cpp 7 | pfd::notify::notify(std::string const &title, 8 | std::string const &text, 9 | pfd::icon icon = pfd::icon::info); 10 | 11 | enum class pfd::icon { info, warning, error }; 12 | ``` 13 | 14 | ## Example 15 | 16 | Displaying a notification is straightforward. Emoji are supported: 17 | 18 | ```cpp 19 | pfd::notify("System event", "Something might be on fire 🔥", 20 | pfd::icon::warning); 21 | ``` 22 | 23 | The `pfd::notify` object needs not be kept around, letting the object clean up itself is enough. 24 | 25 | ## Screenshots 26 | 27 | Windows 10: 28 | ![notify-win32](https://user-images.githubusercontent.com/245089/47142453-2ff76c00-d2c3-11e8-871a-1a110ac91eb2.png) 29 | 30 | Mac OS X (dark theme): 31 | ![image](https://user-images.githubusercontent.com/245089/56053188-bc0abd80-5d53-11e9-8298-68aa96315c6c.png) 32 | 33 | Mac OS X (light theme): 34 | ![image](https://user-images.githubusercontent.com/245089/56053137-92ea2d00-5d53-11e9-8cf2-049486c45713.png) 35 | 36 | Linux (GNOME desktop): 37 | ![notify-gnome](https://user-images.githubusercontent.com/245089/47142455-30900280-d2c3-11e8-8b76-ea16c7e502d4.png) 38 | 39 | Linux (KDE desktop): 40 | ![notify-kde](https://user-images.githubusercontent.com/245089/47149206-27a72d00-d2d3-11e8-8f1b-96e462f08c2b.png) 41 | -------------------------------------------------------------------------------- /libdialog/doc/open_file.md: -------------------------------------------------------------------------------- 1 | ## File Open API 2 | 3 | The `pfd::open_file` class handles file opening dialogs. It can be provided a title, a starting 4 | directory and/or pre-selected file, an optional filter for recognised file types, and an optional 5 | flag to allow multiple selection: 6 | 7 | ```cpp 8 | pfd::open_file::open_file(std::string const &title, 9 | std::string const &initial_path, 10 | std::vector filters = { "All Files", "*" }, 11 | pfd::opt option = pfd::opt::none); 12 | ``` 13 | 14 | The `option` parameter can be `pfd::opt::multiselect` to allow selecting multiple files. 15 | 16 | The selected files are queried using `pfd::open_file::result()`. If the user canceled the 17 | operation, the returned list is empty: 18 | 19 | ```cpp 20 | std::vector pfd::open_file::result(); 21 | ``` 22 | 23 | It is possible to ask the file open dialog whether the user took action using the 24 | `pfd::message::ready()` method, with an optional `timeout` argument. If the user did not validate 25 | the dialog within `timeout` milliseconds, the function will return `false`: 26 | 27 | ```cpp 28 | bool pfd::open_file::ready(int timeout = pfd::default_wait_timeout); 29 | ``` 30 | 31 | ## Example 1: simple file selection 32 | 33 | Using `pfd::open_file::result()` will wait for user action before returning. This operation will 34 | block and return the user choice: 35 | 36 | ```cpp 37 | auto selection = pfd::open_file("Select a file").result(); 38 | if (!selection.empty()) 39 | std::cout << "User selected file " << selection[0] << "\n"; 40 | ``` 41 | 42 | ## Example 2: filters 43 | 44 | The filter list enumerates filter names and corresponded space-separated wildcard lists. It 45 | defaults to `{ "All Files", "*" }`, but here is how to use other options: 46 | 47 | ```cpp 48 | auto selection = pfd::open_file("Select a file", ".", 49 | { "Image Files", "*.png *.jpg *.jpeg *.bmp", 50 | "Audio Files", "*.wav *.mp3", 51 | "All Files", "*" }, 52 | pfd::opt::multiselect).result(); 53 | // Do something with selection 54 | for (auto const &filename : dialog.result()) 55 | std::cout << "Selected file: " << filename << "\n"; 56 | ``` 57 | 58 | ## Example 3: asynchronous file open 59 | 60 | Using `pfd::open_file::ready()` allows the application to perform other tasks while waiting for 61 | user input: 62 | 63 | ```cpp 64 | // File open dialog 65 | auto dialog = pfd::open_file("Select file to open"); 66 | 67 | // Do something while waiting for user input 68 | while (!dialog.ready(1000)) 69 | std::cout << "Waited 1 second for user input...\n"; 70 | 71 | // Act depending on the user choice 72 | std::cout << "Number of selected files: " << dialog.result().size() << "\n"; 73 | ``` 74 | 75 | ## Screenshots 76 | 77 | Windows 10: 78 | ![open-win32](https://user-images.githubusercontent.com/245089/47155865-0f8cd900-d2e6-11e8-8041-1e20b6f77dee.png) 79 | 80 | Mac OS X (dark theme): 81 | ![image](https://user-images.githubusercontent.com/245089/56053378-39363280-5d54-11e9-9583-9f1c978fa0db.png) 82 | 83 | Mac OS X (light theme): 84 | ![image](https://user-images.githubusercontent.com/245089/56053413-4fdc8980-5d54-11e9-85e3-e9e5d0e10772.png) 85 | 86 | Linux (GNOME desktop): 87 | ![open-gnome](https://user-images.githubusercontent.com/245089/47155867-0f8cd900-d2e6-11e8-93af-275636491ec4.png) 88 | 89 | Linux (KDE desktop): 90 | ![open-kde](https://user-images.githubusercontent.com/245089/47155866-0f8cd900-d2e6-11e8-8006-f14b948afc55.png) 91 | -------------------------------------------------------------------------------- /libdialog/doc/pfd.md: -------------------------------------------------------------------------------- 1 | ## Portable File Dialogs documentation 2 | 3 | The library can be used either as a [header-only library](https://en.wikipedia.org/wiki/Header-only), 4 | or as a [single file library](https://github.com/nothings/single_file_libs). 5 | 6 | ### Use as header-only library 7 | 8 | Just include the main header file wherever needed: 9 | 10 | ```cpp 11 | #include "portable-file-dialogs.h" 12 | 13 | /* ... */ 14 | 15 | pfd::message::message("Hello", "This is a test"); 16 | 17 | /* ... */ 18 | ``` 19 | 20 | ### Use as a single-file library 21 | 22 | Defining the `PFD_SKIP_IMPLEMENTATION` macro before including `portable-file-dialogs.h` will 23 | skip all the implementation code and reduce compilation times. You still need to include the 24 | header without the macro at least once, typically in a `pfd-impl.cpp` file. 25 | 26 | ```cpp 27 | // In pfd-impl.cpp 28 | #include "portable-file-dialogs.h" 29 | ``` 30 | 31 | ```cpp 32 | // In all other files 33 | #define PFD_SKIP_IMPLEMENTATION 1 34 | #include "portable-file-dialogs.h" 35 | ``` 36 | 37 | ### General concepts 38 | 39 | Dialogs inherit from `pfd::dialog` and are created by calling their class constructor. Their 40 | destructor will block until the window is closed by user interaction. So for instance this 41 | will block until the end of the line: 42 | 43 | ```cpp 44 | pfd::message::message("Hi", "there"); 45 | ``` 46 | 47 | Whereas this will only block until the end of the scope, allowing the program to perform 48 | additional operations while the dialog is open: 49 | 50 | ```cpp 51 | { 52 | auto m = pfd::message::message("Hi", "there"); 53 | 54 | // ... perform asynchronous operations here 55 | } 56 | ``` 57 | 58 | It is possible to call `bool pfd::dialog::ready(timeout)` on the dialog in order to query its 59 | status and perform asynchronous operations as long as the user has not interacted: 60 | 61 | ```cpp 62 | { 63 | auto m = pfd::message::message("Hi", "there"); 64 | 65 | while (!m.ready()) 66 | { 67 | // ... perform asynchronous operations here 68 | } 69 | } 70 | ``` 71 | 72 | If necessary, a dialog can be forcibly closed using `bool pfd::dialog::kill()`. Note that this 73 | may be confusing to the user and should only be used in very specific situations. It is also not 74 | possible to close a Windows message box that provides no _Cancel_ button. 75 | 76 | ```cpp 77 | { 78 | auto m = pfd::message::message("Hi", "there"); 79 | 80 | while (!m.ready()) 81 | { 82 | // ... perform asynchronous operations here 83 | 84 | if (too_much_time_has_passed()) 85 | m.kill(); 86 | } 87 | } 88 | ``` 89 | 90 | Finally, the user response can be retrieved using `pfd::dialog::result()`. The return value of 91 | this function depends on which dialog is being used. See their respective documentation for more 92 | information: 93 | 94 | * [`pfd::message`](message.md) (message box) 95 | * [`pfd::notify`](notify.md) (notification) 96 | * [`pfd::open_file`](open_file.md) (file open) 97 | * [`pfd::save_file`](save_file.md) (file save) 98 | * [`pfd::select_folder`](select_folder.md) (folder selection) 99 | 100 | ### Settings 101 | 102 | The library can be queried and configured through the `pfd::settings` class. 103 | 104 | ```cpp 105 | bool pfd::settings::available(); 106 | void pfd::settings::verbose(bool value); 107 | void pfd::settings::rescan(); 108 | ``` 109 | 110 | The return value of `pfd::settings::available()` indicates whether a suitable dialog backend (such 111 | as Zenity or KDialog on Linux) has been found. If not, the library will not work and all dialog 112 | invocations will be no-ops. The program will not crash but you should account for this situation 113 | and add a fallback mechanism or exit gracefully. 114 | 115 | Calling `pfd::settings::rescan()` will force a rescan of available backends. This may change the 116 | result of `pfd::settings::available()` if a backend was installed on the system in the meantime. 117 | This is probably only useful for debugging purposes. 118 | 119 | Calling `pfd::settings::verbose(true)` may help debug the library. It will output debug information 120 | to `std::cout` about some operations being performed. 121 | -------------------------------------------------------------------------------- /libdialog/doc/save_file.md: -------------------------------------------------------------------------------- 1 | ## File Open API 2 | 3 | The `pfd::save_file` class handles file saving dialogs. It can be provided a title, a starting 4 | directory and/or pre-selected file, an optional filter for recognised file types, and an optional 5 | flag to allow multiple selection: 6 | 7 | ```cpp 8 | pfd::save_file::save_file(std::string const &title, 9 | std::string const &initial_path, 10 | std::vector filters = { "All Files", "*" }, 11 | pfd::opt option = pfd::opt::none); 12 | ``` 13 | 14 | The `option` parameter can be `pfd::opt::force_overwrite` to disable a potential warning when 15 | saving to an existing file. 16 | 17 | The selected file is queried using `pfd::save_file::result()`. If the user canceled the 18 | operation, the returned file name is empty: 19 | 20 | ```cpp 21 | std::string pfd::save_file::result(); 22 | ``` 23 | 24 | It is possible to ask the file save dialog whether the user took action using the 25 | `pfd::message::ready()` method, with an optional `timeout` argument. If the user did not validate 26 | the dialog within `timeout` milliseconds, the function will return `false`: 27 | 28 | ```cpp 29 | bool pfd::save_file::ready(int timeout = pfd::default_wait_timeout); 30 | ``` 31 | 32 | ## Example 1: simple file selection 33 | 34 | Using `pfd::save_file::result()` will wait for user action before returning. This operation will 35 | block and return the user choice: 36 | 37 | ```cpp 38 | auto destination = pfd::save_file("Select a file").result(); 39 | if (!destination.empty()) 40 | std::cout << "User selected file " << destination << "\n"; 41 | ``` 42 | 43 | ## Example 2: filters 44 | 45 | The filter list enumerates filter names and corresponded space-separated wildcard lists. It 46 | defaults to `{ "All Files", "*" }`, but here is how to use other options: 47 | 48 | ```cpp 49 | auto destination = pfd::save_file("Select a file", ".", 50 | { "Image Files", "*.png *.jpg *.jpeg *.bmp", 51 | "Audio Files", "*.wav *.mp3", 52 | "All Files", "*" }, 53 | pfd::opt::force_overwrite).result(); 54 | // Do something with destination 55 | std::cout << "Selected file: " << destination << "\n"; 56 | ``` 57 | 58 | ## Example 3: asynchronous file save 59 | 60 | Using `pfd::save_file::ready()` allows the application to perform other tasks while waiting for 61 | user input: 62 | 63 | ```cpp 64 | // File save dialog 65 | auto dialog = pfd::save_file("Select file to save"); 66 | 67 | // Do something while waiting for user input 68 | while (!dialog.ready(1000)) 69 | std::cout << "Waited 1 second for user input...\n"; 70 | 71 | // Act depending on the user choice 72 | std::cout << "User selected file: " << dialog.result() << "\n"; 73 | ``` 74 | -------------------------------------------------------------------------------- /libdialog/doc/select_folder.md: -------------------------------------------------------------------------------- 1 | ## Folder Selection API 2 | 3 | The `pfd::select_folder` class handles folder opening dialogs. It can be provided a title, and an 4 | optional starting directory: 5 | 6 | ```cpp 7 | pfd::select_folder::select_folder(std::string const &title, 8 | std::string const &default_path = "", 9 | pfd::opt option = pfd::opt::none); 10 | ``` 11 | 12 | The `option` parameter can be `pfd::opt::force_path` to force the operating system to use the 13 | provided path. Some systems default to the most recently used path, if applicable. 14 | 15 | The selected folder is queried using `pfd::select_folder::result()`. If the user canceled the 16 | operation, the returned string is empty: 17 | 18 | ```cpp 19 | std::string pfd::select_folder::result(); 20 | ``` 21 | 22 | It is possible to ask the folder selection dialog whether the user took action using the 23 | `pfd::message::ready()` method, with an optional `timeout` argument. If the user did not validate 24 | the dialog within `timeout` milliseconds, the function will return `false`: 25 | 26 | ```cpp 27 | bool pfd::select_folder::ready(int timeout = pfd::default_wait_timeout); 28 | ``` 29 | 30 | ## Example 1: simple folder selection 31 | 32 | Using `pfd::select_folder::result()` will wait for user action before returning. This operation 33 | will block and return the user choice: 34 | 35 | ```cpp 36 | auto selection = pfd::select_folder("Select a folder").result(); 37 | if (!selection.empty()) 38 | std::cout << "User selected folder " << selection << "\n"; 39 | ``` 40 | 41 | ## Example 2: asynchronous folder open 42 | 43 | Using `pfd::select_folder::ready()` allows the application to perform other tasks while waiting for user input: 44 | 45 | ```cpp 46 | // Folder selection dialog 47 | auto dialog = pfd::select_folder("Select folder to open"); 48 | 49 | // Do something while waiting for user input 50 | while (!dialog.ready(1000)) 51 | std::cout << "Waited 1 second for user input...\n"; 52 | 53 | // Act depending on the user choice 54 | std::cout << "Selected folder: " << dialog.result() << "\n"; 55 | ``` 56 | -------------------------------------------------------------------------------- /libdialog/examples/Makefile: -------------------------------------------------------------------------------- 1 | 2 | BINARIES = example kill 3 | 4 | CXXFLAGS = -I.. -std=c++11 -g -ggdb -Wall -Wextra 5 | 6 | all: $(BINARIES) 7 | 8 | example: example.cpp ../portable-file-dialogs.h 9 | $(CXX) $(CXXFLAGS) $(filter %.cpp, $^) -o $@ 10 | 11 | kill: kill.cpp ../portable-file-dialogs.h 12 | $(CXX) $(CXXFLAGS) $(filter %.cpp, $^) -o $@ 13 | 14 | clean: 15 | rm -f $(BINARIES) 16 | 17 | -------------------------------------------------------------------------------- /libdialog/examples/example.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Portable File Dialogs 3 | // 4 | // Copyright © 2018—2020 Sam Hocevar 5 | // 6 | // This program is free software. It comes without any warranty, to 7 | // the extent permitted by applicable law. You can redistribute it 8 | // and/or modify it under the terms of the Do What the Fuck You Want 9 | // to Public License, Version 2, as published by the WTFPL Task Force. 10 | // See http://www.wtfpl.net/ for more details. 11 | // 12 | 13 | #include "portable-file-dialogs.h" 14 | 15 | #include 16 | 17 | #if _WIN32 18 | #define DEFAULT_PATH "C:\\" 19 | #else 20 | #define DEFAULT_PATH "/tmp" 21 | #endif 22 | 23 | int main() 24 | { 25 | // Check that a backend is available 26 | if (!pfd::settings::available()) 27 | { 28 | std::cout << "Portable File Dialogs are not available on this platform.\n"; 29 | return 1; 30 | } 31 | 32 | // Set verbosity to true 33 | pfd::settings::verbose(true); 34 | 35 | // Notification 36 | pfd::notify("Important Notification", 37 | "This is ' a message, pay \" attention \\ to it!", 38 | pfd::icon::info); 39 | 40 | // Message box with nice message 41 | auto m = pfd::message("Personal Message", 42 | "You are an amazing person, don’t let anyone make you think otherwise.", 43 | pfd::choice::yes_no_cancel, 44 | pfd::icon::warning); 45 | 46 | // Optional: do something while waiting for user action 47 | for (int i = 0; i < 10 && !m.ready(1000); ++i) 48 | std::cout << "Waited 1 second for user input...\n"; 49 | 50 | // Do something according to the selected button 51 | switch (m.result()) 52 | { 53 | case pfd::button::yes: std::cout << "User agreed.\n"; break; 54 | case pfd::button::no: std::cout << "User disagreed.\n"; break; 55 | case pfd::button::cancel: std::cout << "User freaked out.\n"; break; 56 | default: break; // Should not happen 57 | } 58 | 59 | // Directory selection 60 | auto dir = pfd::select_folder("Select any directory", DEFAULT_PATH).result(); 61 | std::cout << "Selected dir: " << dir << "\n"; 62 | 63 | // File open 64 | auto f = pfd::open_file("Choose files to read", DEFAULT_PATH, 65 | { "Text Files (.txt .text)", "*.txt *.text", 66 | "All Files", "*" }, 67 | pfd::opt::multiselect); 68 | std::cout << "Selected files:"; 69 | for (auto const &name : f.result()) 70 | std::cout << " " + name; 71 | std::cout << "\n"; 72 | } 73 | 74 | // Unused function that just tests the whole API 75 | void api() 76 | { 77 | // pfd::settings 78 | pfd::settings::verbose(true); 79 | pfd::settings::rescan(); 80 | 81 | // pfd::notify 82 | pfd::notify("", ""); 83 | pfd::notify("", "", pfd::icon::info); 84 | pfd::notify("", "", pfd::icon::warning); 85 | pfd::notify("", "", pfd::icon::error); 86 | pfd::notify("", "", pfd::icon::question); 87 | 88 | pfd::notify a("", ""); 89 | (void)a.ready(); 90 | (void)a.ready(42); 91 | 92 | // pfd::message 93 | pfd::message("", ""); 94 | pfd::message("", "", pfd::choice::ok); 95 | pfd::message("", "", pfd::choice::ok_cancel); 96 | pfd::message("", "", pfd::choice::yes_no); 97 | pfd::message("", "", pfd::choice::yes_no_cancel); 98 | pfd::message("", "", pfd::choice::retry_cancel); 99 | pfd::message("", "", pfd::choice::abort_retry_ignore); 100 | pfd::message("", "", pfd::choice::ok, pfd::icon::info); 101 | pfd::message("", "", pfd::choice::ok, pfd::icon::warning); 102 | pfd::message("", "", pfd::choice::ok, pfd::icon::error); 103 | pfd::message("", "", pfd::choice::ok, pfd::icon::question); 104 | 105 | pfd::message b("", ""); 106 | (void)b.ready(); 107 | (void)b.ready(42); 108 | (void)b.result(); 109 | } 110 | 111 | -------------------------------------------------------------------------------- /libdialog/examples/example.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 15.0 29 | {10F4364D-27C4-4C74-8079-7C42971E81E7} 30 | Win32Proj 31 | example 32 | 10.0 33 | 34 | 35 | 36 | Application 37 | v142 38 | Unicode 39 | 40 | 41 | true 42 | 43 | 44 | false 45 | true 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | true 58 | 59 | 60 | false 61 | 62 | 63 | 64 | .. 65 | NotUsing 66 | Level3 67 | true 68 | true 69 | 70 | 71 | Console 72 | true 73 | 74 | 75 | 76 | 77 | Disabled 78 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 79 | 80 | 81 | 82 | 83 | MaxSpeed 84 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 85 | true 86 | true 87 | 88 | 89 | true 90 | true 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /libdialog/examples/kill.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Portable File Dialogs 3 | // 4 | // Copyright © 2018—2020 Sam Hocevar 5 | // 6 | // This program is free software. It comes without any warranty, to 7 | // the extent permitted by applicable law. You can redistribute it 8 | // and/or modify it under the terms of the Do What the Fuck You Want 9 | // to Public License, Version 2, as published by the WTFPL Task Force. 10 | // See http://www.wtfpl.net/ for more details. 11 | // 12 | 13 | #include "portable-file-dialogs.h" 14 | 15 | #include 16 | 17 | int main() 18 | { 19 | // Set verbosity to true 20 | pfd::settings::verbose(true); 21 | 22 | // Message box with nice message 23 | auto m = pfd::message("Upgrade software?", 24 | "Press OK to upgrade this software.\n" 25 | "\n" 26 | "By default, the software will update itself\n" 27 | "automatically in 10 seconds.", 28 | pfd::choice::ok_cancel, 29 | pfd::icon::warning); 30 | 31 | // Wait for an answer for up to 10 seconds 32 | for (int i = 0; i < 10 && !m.ready(1000); ++i) 33 | ; 34 | 35 | // Upgrade software if user clicked OK, or if user didn’t interact 36 | bool upgrade = m.ready() ? m.result() == pfd::button::ok : m.kill(); 37 | if (upgrade) 38 | std::cout << "Upgrading software!\n"; 39 | else 40 | std::cout << "Not upgrading software.\n"; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /libdialog/examples/kill.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 15.0 29 | {B94D26B1-7EF7-43A2-A973-9A96A08E2E17} 30 | Win32Proj 31 | kill 32 | 10.0 33 | 34 | 35 | 36 | Application 37 | v142 38 | Unicode 39 | 40 | 41 | true 42 | 43 | 44 | false 45 | true 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | true 58 | 59 | 60 | false 61 | 62 | 63 | 64 | .. 65 | NotUsing 66 | Level3 67 | true 68 | true 69 | 70 | 71 | Console 72 | true 73 | 74 | 75 | 76 | 77 | Disabled 78 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 79 | 80 | 81 | 82 | 83 | MaxSpeed 84 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 85 | true 86 | true 87 | 88 | 89 | true 90 | true 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /libdxfrw/Makefile.am: -------------------------------------------------------------------------------- 1 | # -*- Makefile -*- 2 | 3 | AM_CPPFLAGS = ${my_CPPFLAGS} -Wall -Woverloaded-virtual 4 | ACLOCAL_AMFLAGS = -I m4 5 | 6 | library_includedir=$(includedir)/libdxfrw$(LIBRARY_AGE) 7 | library_include_HEADERS = drw_base.h drw_entities.h drw_interface.h \ 8 | drw_objects.h drw_header.h drw_classes.h libdxfrw.h libdwgr.h 9 | dist_noinst_HEADERS = intern/dxfreader.h intern/dxfwriter.h intern/drw_dbg.h \ 10 | intern/dwgutil.h intern/dwgreader.h intern/dwgreader15.h \ 11 | intern/dwgreader18.h intern/dwgreader21.h intern/dwgreader24.h \ 12 | intern/dwgreader27.h intern/dwgbuffer.h intern/drw_cptable932.h \ 13 | intern/drw_cptable936.h intern/drw_cptable949.h intern/drw_cptable950.h \ 14 | intern/drw_cptables.h intern/drw_textcodec.h intern/rscodec.h 15 | 16 | lib_LTLIBRARIES = libdxfrw.la 17 | 18 | libdxfrw_la_SOURCES = drw_entities.cpp drw_objects.cpp drw_header.cpp intern/drw_dbg.cpp \ 19 | drw_classes.cpp libdwgr.cpp libdxfrw.cpp intern/dwgutil.cpp \ 20 | intern/dxfreader.cpp intern/dwgreader15.cpp intern/dwgreader18.cpp intern/dwgreader21.cpp \ 21 | intern/dwgreader24.cpp intern/dwgreader27.cpp intern/dxfwriter.cpp intern/dwgreader.cpp \ 22 | intern/dwgbuffer.cpp intern/drw_textcodec.cpp intern/rscodec.cpp 23 | 24 | libdxfrw_la_LDFLAGS = -no-undefined -version-number $(LIBRARY_AGE):$(LIBRARY_CURRENT):$(LIBRARY_REVISION) 25 | 26 | libdxfrw_la_LIBADD = 27 | 28 | pkgconfigdir = ${libdir}/pkgconfig 29 | pkgconfig_DATA = ${top_builddir}/libdxfrw$(LIBRARY_AGE).pc 30 | 31 | EXTRA_DIST = ${top_builddir}/autogen.sh ${top_builddir}/makefile.mingw ${top_builddir}/vs2013/* 32 | 33 | libdxfrw.pc: ${top_builddir}/config.status 34 | -------------------------------------------------------------------------------- /libdxfrw/drw_classes.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #include "drw_classes.h" 14 | #include "intern/dxfreader.h" 15 | #include "intern/dxfwriter.h" 16 | #include "intern/dwgbuffer.h" 17 | #include "intern/drw_dbg.h" 18 | 19 | void DRW_Class::parseCode(int code, dxfReader *reader){ 20 | switch (code) { 21 | case 1: 22 | recName = reader->getUtf8String(); 23 | break; 24 | case 2: 25 | className = reader->getUtf8String(); 26 | break; 27 | case 3: 28 | appName = reader->getUtf8String(); 29 | break; 30 | case 90: 31 | proxyFlag = reader->getInt32(); 32 | break; 33 | case 91: 34 | instanceCount = reader->getInt32(); 35 | break; 36 | case 280: 37 | wasaProxyFlag = reader->getInt32(); 38 | break; 39 | case 281: 40 | entityFlag = reader->getInt32(); 41 | break; 42 | default: 43 | break; 44 | } 45 | } 46 | 47 | bool DRW_Class::parseDwg(DRW::Version version, dwgBuffer *buf, dwgBuffer *strBuf){ 48 | DRW_DBG("\n***************************** parsing Class *********************************************\n"); 49 | 50 | classNum = buf->getBitShort(); 51 | DRW_DBG("Class number: "); DRW_DBG(classNum); 52 | proxyFlag = buf->getBitShort(); //in dwg specs says "version" 53 | 54 | appName = strBuf->getVariableText(version, false); 55 | className = strBuf->getVariableText(version, false); 56 | recName = strBuf->getVariableText(version, false); 57 | 58 | DRW_DBG("\napp name: "); DRW_DBG(appName.c_str()); 59 | DRW_DBG("\nclass name: "); DRW_DBG(className.c_str()); 60 | DRW_DBG("\ndxf rec name: "); DRW_DBG(recName.c_str()); 61 | wasaProxyFlag = buf->getBit(); //in dwg says wasazombie 62 | entityFlag = buf->getBitShort(); 63 | entityFlag = entityFlag == 0x1F2 ? 1: 0; 64 | 65 | DRW_DBG("\nProxy capabilities flag: "); DRW_DBG(proxyFlag); 66 | DRW_DBG(", proxy flag (280): "); DRW_DBG(wasaProxyFlag); 67 | DRW_DBG(", entity flag: "); DRW_DBGH(entityFlag); 68 | 69 | if (version > DRW::AC1015) {//2004+ 70 | instanceCount = buf->getBitLong(); 71 | DRW_DBG("\nInstance Count: "); DRW_DBG(instanceCount); 72 | duint32 dwgVersion = buf->getBitLong(); 73 | DRW_DBG("\nDWG version: "); DRW_DBG(dwgVersion); 74 | DRW_DBG("\nmaintenance version: "); DRW_DBG(buf->getBitLong()); 75 | DRW_DBG("\nunknown 1: "); DRW_DBG(buf->getBitLong()); 76 | DRW_DBG("\nunknown 2: "); DRW_DBG(buf->getBitLong()); 77 | } 78 | DRW_DBG("\n"); 79 | toDwgType(); 80 | return buf->isGood(); 81 | } 82 | 83 | void DRW_Class::write(dxfWriter *writer, DRW::Version ver){ 84 | if (ver > DRW::AC1009) { 85 | writer->writeString(0, "CLASS"); 86 | writer->writeString(1, recName); 87 | writer->writeString(2, className); 88 | writer->writeString(3, appName); 89 | writer->writeInt32(90, proxyFlag); 90 | if (ver > DRW::AC1015) { //2004+ 91 | writer->writeInt32(91, instanceCount); 92 | } 93 | writer->writeInt16(280, wasaProxyFlag); 94 | writer->writeInt16(281, entityFlag); 95 | } 96 | } 97 | 98 | void DRW_Class::toDwgType(){ 99 | if (recName == "LWPOLYLINE") 100 | dwgType = 77; 101 | else if (recName == "HATCH") 102 | dwgType = 78; 103 | else if (recName == "GROUP") 104 | dwgType = 72; 105 | /* else if (recName == "GROUP") 106 | dwgType = 72;*/ 107 | else if (recName == "LAYOUT") 108 | dwgType = 82; 109 | else if (recName == "IMAGE") 110 | dwgType = 101; 111 | else if (recName == "IMAGEDEF") 112 | dwgType = 102; 113 | else 114 | dwgType =0; 115 | } 116 | -------------------------------------------------------------------------------- /libdxfrw/drw_classes.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef DRW_CLASSES_H 14 | #define DRW_CLASSES_H 15 | 16 | 17 | #include "drw_base.h" 18 | //#include "libdwgr.h" 19 | 20 | class dxfReader; 21 | class dxfWriter; 22 | class dwgBuffer; 23 | 24 | //! Class to handle classes entries 25 | /*! 26 | * Class to handle classes table entries 27 | * TODO: verify the dxf read/write part 28 | * @author Rallaz 29 | */ 30 | class DRW_Class { 31 | public: 32 | DRW_Class() { 33 | } 34 | ~DRW_Class() { 35 | } 36 | 37 | void parseCode(int code, dxfReader *reader); 38 | void write(dxfWriter *writer, DRW::Version ver); 39 | bool parseDwg(DRW::Version version, dwgBuffer *buf, dwgBuffer *strBuf); 40 | 41 | private: 42 | void toDwgType(); 43 | public: 44 | UTF8STRING recName; /*!< record name, code 1 */ 45 | UTF8STRING className; /*!< C++ class name, code 2 */ 46 | UTF8STRING appName; /*!< app name, code 3 */ 47 | int proxyFlag; /*!< Proxy capabilities flag, code 90 */ 48 | int instanceCount; /*!< number of instances for a custom class, code 91*/ 49 | int wasaProxyFlag; /*!< proxy flag (app loaded on save), code 280 */ 50 | int entityFlag; /*!< entity flag, code 281 (0 object, 1 entity)*/ 51 | public: //only for read dwg 52 | duint16 classNum; 53 | int dwgType; 54 | }; 55 | 56 | #endif 57 | 58 | // EOF 59 | 60 | -------------------------------------------------------------------------------- /libdxfrw/drw_header.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef DRW_HEADER_H 14 | #define DRW_HEADER_H 15 | 16 | 17 | #include 18 | #include "drw_base.h" 19 | 20 | class dxfReader; 21 | class dxfWriter; 22 | class dwgBuffer; 23 | 24 | #define SETHDRFRIENDS friend class dxfRW; \ 25 | friend class dwgReader; 26 | 27 | //! Class to handle header entries 28 | /*! 29 | * Class to handle header vars, to read iterate over "std::map vars" 30 | * to write add a DRW_Variant* into "std::map vars" (do not delete it, are cleared in dtor) 31 | * or use add* helper functions. 32 | * @author Rallaz 33 | */ 34 | class DRW_Header { 35 | SETHDRFRIENDS 36 | public: 37 | DRW_Header(); 38 | ~DRW_Header() { 39 | clearVars(); 40 | } 41 | 42 | DRW_Header(const DRW_Header& h){ 43 | this->version = h.version; 44 | this->comments = h.comments; 45 | for (std::map::const_iterator it=h.vars.begin(); it!=h.vars.end(); ++it){ 46 | this->vars[it->first] = new DRW_Variant( *(it->second) ); 47 | } 48 | this->curr = NULL; 49 | } 50 | DRW_Header& operator=(const DRW_Header &h) { 51 | if(this != &h) { 52 | clearVars(); 53 | this->version = h.version; 54 | this->comments = h.comments; 55 | for (std::map::const_iterator it=h.vars.begin(); it!=h.vars.end(); ++it){ 56 | this->vars[it->first] = new DRW_Variant( *(it->second) ); 57 | } 58 | } 59 | return *this; 60 | } 61 | 62 | void addDouble(std::string key, double value, int code); 63 | void addInt(std::string key, int value, int code); 64 | void addStr(std::string key, std::string value, int code); 65 | void addCoord(std::string key, DRW_Coord value, int code); 66 | std::string getComments() const {return comments;} 67 | void write(dxfWriter *writer, DRW::Version ver); 68 | void addComment(std::string c); 69 | 70 | protected: 71 | void parseCode(int code, dxfReader *reader); 72 | bool parseDwg(DRW::Version version, dwgBuffer *buf, dwgBuffer *hBbuf, duint8 mv=0); 73 | private: 74 | bool getDouble(std::string key, double *varDouble); 75 | bool getInt(std::string key, int *varInt); 76 | bool getStr(std::string key, std::string *varStr); 77 | bool getCoord(std::string key, DRW_Coord *varStr); 78 | void clearVars(){ 79 | for (std::map::iterator it=vars.begin(); it!=vars.end(); ++it) 80 | delete it->second; 81 | 82 | vars.clear(); 83 | } 84 | 85 | public: 86 | std::map vars; 87 | private: 88 | std::string comments; 89 | std::string name; 90 | DRW_Variant* curr; 91 | int version; //to use on read 92 | 93 | duint32 linetypeCtrl; 94 | duint32 layerCtrl; 95 | duint32 styleCtrl; 96 | duint32 dimstyleCtrl; 97 | duint32 appidCtrl; 98 | duint32 blockCtrl; 99 | duint32 viewCtrl; 100 | duint32 ucsCtrl; 101 | duint32 vportCtrl; 102 | duint32 vpEntHeaderCtrl; 103 | }; 104 | 105 | #endif 106 | 107 | // EOF 108 | 109 | -------------------------------------------------------------------------------- /libdxfrw/dx_data.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** dwg2dxf - Program to convert dwg/dxf to dxf(ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef DX_DATA_H 14 | #define DX_DATA_H 15 | #include "libdxfrw.h" 16 | 17 | //class to store image data and path from DRW_ImageDef 18 | class dx_ifaceImg : public DRW_Image { 19 | public: 20 | dx_ifaceImg(){} 21 | dx_ifaceImg(const DRW_Image& p):DRW_Image(p){} 22 | ~dx_ifaceImg(){} 23 | std::string path; //stores the image path 24 | }; 25 | 26 | //container class to store entites. 27 | class dx_ifaceBlock : public DRW_Block { 28 | public: 29 | dx_ifaceBlock(){} 30 | dx_ifaceBlock(const DRW_Block& p):DRW_Block(p){} 31 | ~dx_ifaceBlock(){ 32 | for (std::list::const_iterator it=ent.begin(); it!=ent.end(); ++it) 33 | delete *it; 34 | } 35 | std::listent; //stores the entities list 36 | }; 37 | 38 | 39 | //container class to store full dwg/dxf data. 40 | class dx_data { 41 | public: 42 | dx_data(){ 43 | mBlock = new dx_ifaceBlock(); 44 | } 45 | ~dx_data(){ 46 | //cleanup, 47 | for (std::list::const_iterator it=blocks.begin(); it!=blocks.end(); ++it) 48 | delete *it; 49 | delete mBlock; 50 | } 51 | 52 | DRW_Header headerC; //stores a copy of the header vars 53 | std::listlineTypes; //stores a copy of all line types 54 | std::listlayers; //stores a copy of all layers 55 | std::listdimStyles; //stores a copy of all dimension styles 56 | std::listVPorts; //stores a copy of all vports 57 | std::listtextStyles; //stores a copy of all text styles 58 | std::listappIds; //stores a copy of all line types 59 | std::listblocks; //stores a copy of all blocks and the entities in it 60 | std::listimages; //temporary list to find images for link with DRW_ImageDef. Do not delete it!! 61 | 62 | dx_ifaceBlock* mBlock; //container to store model entities 63 | 64 | 65 | }; 66 | 67 | #endif // DX_DATA_H 68 | -------------------------------------------------------------------------------- /libdxfrw/dx_iface.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** dwg2dxf - Program to convert dwg/dxf to dxf(ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #include 14 | #include 15 | #include "dx_iface.h" 16 | #include "libdwgr.h" 17 | #include "libdxfrw.h" 18 | 19 | 20 | bool dx_iface::fileImport(const std::string& fileI, dx_data *fData){ 21 | unsigned int found = fileI.find_last_of("."); 22 | std::string fileExt = fileI.substr(found+1); 23 | std::transform(fileExt.begin(), fileExt.end(),fileExt.begin(), ::toupper); 24 | cData = fData; 25 | currentBlock = cData->mBlock; 26 | 27 | if (fileExt == "DXF"){ 28 | //loads dxf 29 | dxfRW* dxf = new dxfRW(fileI.c_str()); 30 | bool success = dxf->read(this, false); 31 | delete dxf; 32 | return success; 33 | } else if (fileExt == "DWG"){ 34 | //loads dwg 35 | dwgR* dwg = new dwgR(fileI.c_str()); 36 | bool success = dwg->read(this, false); 37 | delete dwg; 38 | return success; 39 | } 40 | std::cout << "file extension can be dxf or dwg" << std::endl; 41 | return false; 42 | } 43 | 44 | bool dx_iface::fileExport(const std::string& file, DRW::Version v, bool binary, dx_data *fData){ 45 | cData = fData; 46 | dxfW = new dxfRW(file.c_str()); 47 | bool success = dxfW->write(this, v, binary); 48 | delete dxfW; 49 | return success; 50 | 51 | } 52 | 53 | void dx_iface::clear(dx_data *fData){ 54 | fData->VPorts.clear(); 55 | fData->appIds.clear(); 56 | fData->blocks.clear(); 57 | fData->dimStyles.clear(); 58 | fData->headerC.vars.clear(); 59 | fData->images.clear(); 60 | fData->layers.clear(); 61 | fData->lineTypes.clear(); 62 | fData->mBlock->ent.clear(); 63 | fData->textStyles.clear(); 64 | } 65 | 66 | void dx_iface::writeEntity(DRW_Entity* e){ 67 | switch (e->eType) { 68 | case DRW::POINT: 69 | dxfW->writePoint(static_cast(e)); 70 | break; 71 | case DRW::LINE: 72 | dxfW->writeLine(static_cast(e)); 73 | break; 74 | case DRW::CIRCLE: 75 | dxfW->writeCircle(static_cast(e)); 76 | break; 77 | case DRW::ARC: 78 | dxfW->writeArc(static_cast(e)); 79 | break; 80 | case DRW::SOLID: 81 | dxfW->writeSolid(static_cast(e)); 82 | break; 83 | case DRW::ELLIPSE: 84 | dxfW->writeEllipse(static_cast(e)); 85 | break; 86 | case DRW::LWPOLYLINE: 87 | dxfW->writeLWPolyline(static_cast(e)); 88 | break; 89 | case DRW::POLYLINE: 90 | dxfW->writePolyline(static_cast(e)); 91 | break; 92 | case DRW::SPLINE: 93 | dxfW->writeSpline(static_cast(e)); 94 | break; 95 | // case RS2::EntitySplinePoints: 96 | // writeSplinePoints(static_cast(e)); 97 | // break; 98 | // case RS2::EntityVertex: 99 | // break; 100 | case DRW::INSERT: 101 | dxfW->writeInsert(static_cast(e)); 102 | break; 103 | case DRW::MTEXT: 104 | dxfW->writeMText(static_cast(e)); 105 | break; 106 | case DRW::TEXT: 107 | dxfW->writeText(static_cast(e)); 108 | break; 109 | case DRW::DIMLINEAR: 110 | case DRW::DIMALIGNED: 111 | case DRW::DIMANGULAR: 112 | case DRW::DIMANGULAR3P: 113 | case DRW::DIMRADIAL: 114 | case DRW::DIMDIAMETRIC: 115 | case DRW::DIMORDINATE: 116 | dxfW->writeDimension(static_cast(e)); 117 | break; 118 | case DRW::LEADER: 119 | dxfW->writeLeader(static_cast(e)); 120 | break; 121 | case DRW::HATCH: 122 | dxfW->writeHatch(static_cast(e)); 123 | break; 124 | case DRW::IMAGE: 125 | dxfW->writeImage(static_cast(e), static_cast(e)->path); 126 | break; 127 | default: 128 | break; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /libdxfrw/intern/drw_dbg.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #include 14 | #include 15 | #include "drw_dbg.h" 16 | 17 | DRW_dbg *DRW_dbg::instance= NULL; 18 | 19 | /*********private clases*************/ 20 | class print_none { 21 | public: 22 | virtual void printS(std::string s){(void)s;} 23 | virtual void printI(long long int i){(void)i;} 24 | virtual void printUI(long long unsigned int i){(void)i;} 25 | virtual void printD(double d){(void)d;} 26 | virtual void printH(long long int i){(void)i;} 27 | virtual void printB(int i){(void)i;} 28 | virtual void printHL(int c, int s, int h){(void)c;(void)s;(void)h;} 29 | virtual void printPT(double x, double y, double z){(void)x;(void)y;(void)z;} 30 | print_none(){} 31 | virtual ~print_none(){} 32 | }; 33 | 34 | class print_debug : public print_none { 35 | public: 36 | virtual void printS(std::string s); 37 | virtual void printI(long long int i); 38 | virtual void printUI(long long unsigned int i); 39 | virtual void printD(double d); 40 | virtual void printH(long long int i); 41 | virtual void printB(int i); 42 | virtual void printHL(int c, int s, int h); 43 | virtual void printPT(double x, double y, double z); 44 | print_debug(); 45 | virtual ~print_debug(){} 46 | private: 47 | std::ios_base::fmtflags flags; 48 | }; 49 | 50 | /********* debug class *************/ 51 | DRW_dbg *DRW_dbg::getInstance(){ 52 | if (instance == NULL){ 53 | instance = new DRW_dbg; 54 | } 55 | return instance; 56 | } 57 | 58 | DRW_dbg::DRW_dbg(){ 59 | level = NONE; 60 | prClass = new print_none; 61 | flags = std::cerr.flags(); 62 | } 63 | 64 | void DRW_dbg::setLevel(LEVEL lvl){ 65 | level = lvl; 66 | delete prClass; 67 | switch (level){ 68 | case DEBUG: 69 | prClass = new print_debug; 70 | break; 71 | default: 72 | prClass = new print_none; 73 | } 74 | } 75 | 76 | DRW_dbg::LEVEL DRW_dbg::getLevel(){ 77 | return level; 78 | } 79 | 80 | void DRW_dbg::print(std::string s){ 81 | prClass->printS(s); 82 | } 83 | 84 | void DRW_dbg::print(int i){ 85 | prClass->printI(i); 86 | } 87 | 88 | void DRW_dbg::print(unsigned int i){ 89 | prClass->printUI(i); 90 | } 91 | 92 | void DRW_dbg::print(long long int i){ 93 | prClass->printI(i); 94 | } 95 | 96 | void DRW_dbg::print(long unsigned int i){ 97 | prClass->printUI(i); 98 | } 99 | 100 | void DRW_dbg::print(long long unsigned int i){ 101 | prClass->printUI(i); 102 | } 103 | 104 | void DRW_dbg::print(double d){ 105 | prClass->printD(d); 106 | } 107 | 108 | void DRW_dbg::printH(long long int i){ 109 | prClass->printH(i); 110 | } 111 | 112 | void DRW_dbg::printB(int i){ 113 | prClass->printB(i); 114 | } 115 | void DRW_dbg::printHL(int c, int s, int h){ 116 | prClass->printHL(c, s, h); 117 | } 118 | 119 | void DRW_dbg::printPT(double x, double y, double z){ 120 | prClass->printPT(x, y, z); 121 | } 122 | 123 | print_debug::print_debug(){ 124 | flags = std::cerr.flags(); 125 | } 126 | 127 | void print_debug::printS(std::string s){ 128 | std::cerr << s; 129 | } 130 | 131 | void print_debug::printI(long long int i){ 132 | std::cerr << i; 133 | } 134 | 135 | void print_debug::printUI(long long unsigned int i){ 136 | std::cerr << i; 137 | } 138 | 139 | void print_debug::printD(double d){ 140 | std::cerr << std::fixed << d; 141 | } 142 | 143 | void print_debug::printH(long long i){ 144 | std::cerr << "0x" << std::setw(2) << std::setfill('0'); 145 | std::cerr << std::hex << i; 146 | std::cerr.flags(flags); 147 | } 148 | 149 | void print_debug::printB(int i){ 150 | std::cerr << std::setw(8) << std::setfill('0'); 151 | std::cerr << std::setbase(2) << i; 152 | std::cerr.flags(flags); 153 | } 154 | 155 | void print_debug::printHL(int c, int s, int h){ 156 | std::cerr << c << '.' << s << '.'; 157 | std::cerr << "0x" << std::setw(2) << std::setfill('0'); 158 | std::cerr << std::hex << h; 159 | std::cerr.flags(flags); 160 | } 161 | 162 | void print_debug::printPT(double x, double y, double z){ 163 | std::cerr << std::fixed << "x: " << x << ", y: " << y << ", z: "<< z; 164 | } 165 | -------------------------------------------------------------------------------- /libdxfrw/intern/drw_dbg.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef DRW_DBG_H 14 | #define DRW_DBG_H 15 | 16 | #include 17 | #include 18 | //#include 19 | 20 | #define DRW_DBGSL(a) DRW_dbg::getInstance()->setLevel(a) 21 | #define DRW_DBGGL DRW_dbg::getInstance()->getLevel() 22 | #define DRW_DBG(a) DRW_dbg::getInstance()->print(a) 23 | #define DRW_DBGH(a) DRW_dbg::getInstance()->printH(a) 24 | #define DRW_DBGB(a) DRW_dbg::getInstance()->printB(a) 25 | #define DRW_DBGHL(a, b, c) DRW_dbg::getInstance()->printHL(a, b ,c) 26 | #define DRW_DBGPT(a, b, c) DRW_dbg::getInstance()->printPT(a, b, c) 27 | 28 | 29 | class print_none; 30 | 31 | class DRW_dbg { 32 | public: 33 | enum LEVEL { 34 | NONE, 35 | DEBUG 36 | }; 37 | void setLevel(LEVEL lvl); 38 | LEVEL getLevel(); 39 | static DRW_dbg *getInstance(); 40 | void print(std::string s); 41 | void print(int i); 42 | void print(unsigned int i); 43 | void print(long long int i); 44 | void print(long unsigned int i); 45 | void print(long long unsigned int i); 46 | void print(double d); 47 | void printH(long long int i); 48 | void printB(int i); 49 | void printHL(int c, int s, int h); 50 | void printPT(double x, double y, double z); 51 | 52 | private: 53 | DRW_dbg(); 54 | static DRW_dbg *instance; 55 | LEVEL level; 56 | std::ios_base::fmtflags flags; 57 | print_none* prClass; 58 | }; 59 | 60 | 61 | #endif // DRW_DBG_H 62 | -------------------------------------------------------------------------------- /libdxfrw/intern/drw_textcodec.h: -------------------------------------------------------------------------------- 1 | #ifndef DRW_TEXTCODEC_H 2 | #define DRW_TEXTCODEC_H 3 | 4 | #include 5 | 6 | class DRW_Converter; 7 | 8 | class DRW_TextCodec 9 | { 10 | public: 11 | DRW_TextCodec(); 12 | ~DRW_TextCodec(); 13 | std::string fromUtf8(std::string s); 14 | std::string toUtf8(std::string s); 15 | int getVersion(){return version;} 16 | void setVersion(std::string *v, bool dxfFormat); 17 | void setVersion(int v, bool dxfFormat); 18 | void setCodePage(std::string *c, bool dxfFormat); 19 | void setCodePage(std::string c, bool dxfFormat){setCodePage(&c, dxfFormat);} 20 | std::string getCodePage(){return cp;} 21 | 22 | private: 23 | std::string correctCodePage(const std::string& s); 24 | 25 | private: 26 | int version; 27 | std::string cp; 28 | DRW_Converter *conv; 29 | }; 30 | 31 | class DRW_Converter 32 | { 33 | public: 34 | DRW_Converter(const int *t, int l){table = t; 35 | cpLenght = l;} 36 | virtual ~DRW_Converter(){} 37 | virtual std::string fromUtf8(std::string *s) {return *s;} 38 | virtual std::string toUtf8(std::string *s); 39 | std::string encodeText(std::string stmp); 40 | std::string decodeText(int c); 41 | std::string encodeNum(int c); 42 | int decodeNum(std::string s, int *b); 43 | const int *table; 44 | int cpLenght; 45 | }; 46 | 47 | class DRW_ConvUTF16 : public DRW_Converter { 48 | public: 49 | DRW_ConvUTF16():DRW_Converter(NULL, 0) {} 50 | virtual std::string fromUtf8(std::string *s); 51 | virtual std::string toUtf8(std::string *s); 52 | }; 53 | 54 | class DRW_ConvTable : public DRW_Converter { 55 | public: 56 | DRW_ConvTable(const int *t, int l):DRW_Converter(t, l) {} 57 | virtual std::string fromUtf8(std::string *s); 58 | virtual std::string toUtf8(std::string *s); 59 | }; 60 | 61 | class DRW_ConvDBCSTable : public DRW_Converter { 62 | public: 63 | DRW_ConvDBCSTable(const int *t, const int *lt, const int dt[][2], int l):DRW_Converter(t, l) { 64 | leadTable = lt; 65 | doubleTable = dt; 66 | } 67 | 68 | virtual std::string fromUtf8(std::string *s); 69 | virtual std::string toUtf8(std::string *s); 70 | private: 71 | const int *leadTable; 72 | const int (*doubleTable)[2]; 73 | 74 | }; 75 | 76 | class DRW_Conv932Table : public DRW_Converter { 77 | public: 78 | DRW_Conv932Table(const int *t, const int *lt, const int dt[][2], int l):DRW_Converter(t, l) { 79 | leadTable = lt; 80 | doubleTable = dt; 81 | } 82 | 83 | virtual std::string fromUtf8(std::string *s); 84 | virtual std::string toUtf8(std::string *s); 85 | private: 86 | const int *leadTable; 87 | const int (*doubleTable)[2]; 88 | 89 | }; 90 | 91 | class DRW_ExtConverter : public DRW_Converter { 92 | public: 93 | DRW_ExtConverter(const char *enc):DRW_Converter(NULL, 0) { 94 | encoding = enc; 95 | } 96 | virtual std::string fromUtf8(std::string *s); 97 | virtual std::string toUtf8(std::string *s); 98 | private: 99 | const char *encoding; 100 | std::string convertByiconv(const char *in_encode, 101 | const char *out_encode, 102 | const std::string *s); 103 | }; 104 | 105 | #endif // DRW_TEXTCODEC_H 106 | -------------------------------------------------------------------------------- /libdxfrw/intern/dwgbuffer.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef DWGBUFFER_H 14 | #define DWGBUFFER_H 15 | 16 | #include 17 | #include 18 | #include "../drw_base.h" 19 | 20 | class DRW_Coord; 21 | class DRW_TextCodec; 22 | 23 | class dwgBasicStream{ 24 | protected: 25 | dwgBasicStream(){} 26 | public: 27 | virtual ~dwgBasicStream(){} 28 | virtual bool read(duint8* s, duint64 n) = 0; 29 | virtual duint64 size() = 0; 30 | virtual duint64 getPos() = 0; 31 | virtual bool setPos(duint64 p) = 0; 32 | virtual bool good() = 0; 33 | virtual dwgBasicStream* clone() = 0; 34 | }; 35 | 36 | class dwgFileStream: public dwgBasicStream{ 37 | public: 38 | dwgFileStream(std::ifstream *s){ 39 | stream =s; 40 | stream->seekg (0, std::ios::end); 41 | sz = stream->tellg(); 42 | stream->seekg(0, std::ios_base::beg); 43 | } 44 | virtual ~dwgFileStream(){} 45 | virtual bool read(duint8* s, duint64 n); 46 | virtual duint64 size(){return sz;} 47 | virtual duint64 getPos(){return stream->tellg();} 48 | virtual bool setPos(duint64 p); 49 | virtual bool good(){return stream->good();} 50 | virtual dwgBasicStream* clone(){return new dwgFileStream(stream);} 51 | private: 52 | std::ifstream *stream; 53 | duint64 sz; 54 | }; 55 | 56 | class dwgCharStream: public dwgBasicStream{ 57 | public: 58 | dwgCharStream(duint8 *buf, int s){ 59 | stream =buf; 60 | sz = s; 61 | pos = 0; 62 | isOk = true; 63 | } 64 | virtual ~dwgCharStream(){} 65 | virtual bool read(duint8* s, duint64 n); 66 | virtual duint64 size(){return sz;} 67 | virtual duint64 getPos(){return pos;} 68 | virtual bool setPos(duint64 p); 69 | virtual bool good(){return isOk;} 70 | virtual dwgBasicStream* clone(){return new dwgCharStream(stream, sz);} 71 | private: 72 | duint8 *stream; 73 | duint64 sz; 74 | duint64 pos; 75 | bool isOk; 76 | }; 77 | 78 | class dwgBuffer { 79 | public: 80 | dwgBuffer(std::ifstream *stream, DRW_TextCodec *decoder = NULL); 81 | dwgBuffer(duint8 *buf, int size, DRW_TextCodec *decoder= NULL); 82 | dwgBuffer( const dwgBuffer& org ); 83 | dwgBuffer& operator=( const dwgBuffer& org ); 84 | ~dwgBuffer(); 85 | duint64 size(){return filestr->size();} 86 | bool setPosition(duint64 pos); 87 | duint64 getPosition(); 88 | void resetPosition(){setPosition(0); setBitPos(0);} 89 | void setBitPos(duint8 pos); 90 | duint8 getBitPos(){return bitPos;} 91 | bool moveBitPos(dint32 size); 92 | 93 | duint8 getBit(); //B 94 | bool getBoolBit(); //B as bool 95 | duint8 get2Bits(); //BB 96 | duint8 get3Bits(); //3B 97 | duint16 getBitShort(); //BS 98 | dint16 getSBitShort(); //BS 99 | dint32 getBitLong(); //BL 100 | duint64 getBitLongLong(); //BLL (R24) 101 | double getBitDouble(); //BD 102 | //2BD => call BD 2 times 103 | DRW_Coord get3BitDouble(); //3BD 104 | duint8 getRawChar8(); //RC 105 | duint16 getRawShort16(); //RS 106 | double getRawDouble(); //RD 107 | duint32 getRawLong32(); //RL 108 | duint64 getRawLong64(); //RLL 109 | DRW_Coord get2RawDouble(); //2RD 110 | //3RD => call RD 3 times 111 | duint32 getUModularChar(); //UMC, unsigned for offsets in 1015 112 | dint32 getModularChar(); //MC 113 | dint32 getModularShort(); //MS 114 | dwgHandle getHandle(); //H 115 | dwgHandle getOffsetHandle(duint32 href); //H converted to hard 116 | UTF8STRING getVariableText(DRW::Version v, bool nullTerm = true); //TV => call TU for 2007+ or T for previous versions 117 | UTF8STRING getCP8Text(); //T 8 bit text converted from codepage to utf8 118 | UTF8STRING getUCSText(bool nullTerm = true); //TU unicode 16 bit (UCS) text converted to utf8 119 | UTF8STRING getUCSStr(duint16 ts); 120 | 121 | duint16 getObjType(DRW::Version v); //OT 122 | 123 | //X, U, SN, 124 | 125 | DRW_Coord getExtrusion(bool b_R2000_style); //BE 126 | double getDefaultDouble(double d); //DD 127 | double getThickness(bool b_R2000_style);//BT 128 | //3DD 129 | duint32 getCmColor(DRW::Version v); //CMC 130 | duint32 getEnColor(DRW::Version v); //ENC 131 | //TC 132 | 133 | duint16 getBERawShort16(); //RS big-endian order 134 | 135 | bool isGood(){return filestr->good();} 136 | bool getBytes(duint8 *buf, int size); 137 | int numRemainingBytes(){return (maxSize- filestr->getPos());} 138 | 139 | duint16 crc8(duint16 dx,dint32 start,dint32 end); 140 | duint32 crc32(duint32 seed,dint32 start,dint32 end); 141 | 142 | // duint8 getCurrByte(){return currByte;} 143 | DRW_TextCodec *decoder; 144 | 145 | private: 146 | dwgBasicStream *filestr; 147 | int maxSize; 148 | duint8 currByte; 149 | duint8 bitPos; 150 | 151 | UTF8STRING get8bitStr(); 152 | UTF8STRING get16bitStr(duint16 textSize, bool nullTerm = true); 153 | }; 154 | 155 | #endif // DWGBUFFER_H 156 | -------------------------------------------------------------------------------- /libdxfrw/intern/dwgreader15.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef DWGREADER15_H 14 | #define DWGREADER15_H 15 | 16 | #include 17 | #include 18 | #include "drw_textcodec.h" 19 | #include "dwgbuffer.h" 20 | #include "dwgreader.h" 21 | 22 | class dwgReader15 : public dwgReader { 23 | public: 24 | dwgReader15(std::ifstream *stream, dwgR *p):dwgReader(stream, p){ } 25 | virtual ~dwgReader15() {} 26 | bool readMetaData(); 27 | bool readFileHeader(); 28 | bool readDwgHeader(DRW_Header& hdr); 29 | bool readDwgClasses(); 30 | bool readDwgHandles(); 31 | bool readDwgTables(DRW_Header& hdr); 32 | bool readDwgBlocks(DRW_Interface& intfa); 33 | bool readDwgEntities(DRW_Interface& intfa){ 34 | bool ret = true; 35 | ret = dwgReader::readDwgEntities(intfa, fileBuf); 36 | return ret; 37 | } 38 | bool readDwgObjects(DRW_Interface& intfa){ 39 | bool ret = true; 40 | ret = dwgReader::readDwgObjects(intfa, fileBuf); 41 | return ret; 42 | } 43 | // bool readDwgEntity(objHandle& obj, DRW_Interface& intfa); 44 | }; 45 | 46 | 47 | #endif // DWGREADER15_H 48 | -------------------------------------------------------------------------------- /libdxfrw/intern/dwgreader18.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef DWGREADER18_H 14 | #define DWGREADER18_H 15 | 16 | #include 17 | #include 18 | #include "dwgreader.h" 19 | //#include "../drw_textcodec.h" 20 | #include "dwgbuffer.h" 21 | 22 | static const int DRW_magicNum18[] = { 23 | 0x29, 0x23, 0xbe, 0x84, 0xe1, 0x6c, 0xd6, 0xae, 24 | 0x52, 0x90, 0x49, 0xf1, 0xf1, 0xbb, 0xe9, 0xeb, 25 | 0xb3, 0xa6, 0xdb, 0x3c, 0x87, 0x0c, 0x3e, 0x99, 26 | 0x24, 0x5e, 0x0d, 0x1c, 0x06, 0xb7, 0x47, 0xde, 27 | 0xb3, 0x12, 0x4d, 0xc8, 0x43, 0xbb, 0x8b, 0xa6, 28 | 0x1f, 0x03, 0x5a, 0x7d, 0x09, 0x38, 0x25, 0x1f, 29 | 0x5d, 0xd4, 0xcb, 0xfc, 0x96, 0xf5, 0x45, 0x3b, 30 | 0x13, 0x0d, 0x89, 0x0a, 0x1c, 0xdb, 0xae, 0x32, 31 | 0x20, 0x9a, 0x50, 0xee, 0x40, 0x78, 0x36, 0xfd, 32 | 0x12, 0x49, 0x32, 0xf6, 0x9e, 0x7d, 0x49, 0xdc, 33 | 0xad, 0x4f, 0x14, 0xf2, 0x44, 0x40, 0x66, 0xd0, 34 | 0x6b, 0xc4, 0x30, 0xb7, 0x32, 0x3b, 0xa1, 0x22, 35 | 0xf6, 0x22, 0x91, 0x9d, 0xe1, 0x8b, 0x1f, 0xda, 36 | 0xb0, 0xca, 0x99, 0x02 37 | }; 38 | 39 | static const int DRW_magicNumEnd18[] = { 40 | 0xf8, 0x46, 0x6a, 0x04, 0x96, 0x73, 0x0e, 0xd9, 41 | 0x16, 0x2f, 0x67, 0x68, 0xd4, 0xf7, 0x4a, 0x4a, 42 | 0xd0, 0x57, 0x68, 0x76}; 43 | 44 | class dwgReader18 : public dwgReader { 45 | public: 46 | dwgReader18(std::ifstream *stream, dwgR *p):dwgReader(stream, p){ 47 | objData = NULL; 48 | } 49 | virtual ~dwgReader18(){ 50 | if (objData != NULL) 51 | delete[] objData; 52 | } 53 | bool readMetaData(); 54 | bool readFileHeader(); 55 | bool readDwgHeader(DRW_Header& hdr); 56 | bool readDwgClasses(); 57 | bool readDwgHandles(); 58 | bool readDwgTables(DRW_Header& hdr); 59 | bool readDwgBlocks(DRW_Interface& intfa){ 60 | bool ret = true; 61 | dwgBuffer dataBuf(objData, uncompSize, &decoder); 62 | ret = dwgReader::readDwgBlocks(intfa, &dataBuf); 63 | return ret; 64 | } 65 | 66 | virtual bool readDwgEntities(DRW_Interface& intfa){ 67 | bool ret = true; 68 | dwgBuffer dataBuf(objData, uncompSize, &decoder); 69 | ret = dwgReader::readDwgEntities(intfa, &dataBuf); 70 | return ret; 71 | } 72 | virtual bool readDwgObjects(DRW_Interface& intfa){ 73 | bool ret = true; 74 | dwgBuffer dataBuf(objData, uncompSize, &decoder); 75 | ret = dwgReader::readDwgObjects(intfa, &dataBuf); 76 | return ret; 77 | } 78 | 79 | // bool readDwgEntity(objHandle& obj, DRW_Interface& intfa){ 80 | // bool ret = true; 81 | // return ret; 82 | // } 83 | 84 | protected: 85 | duint8 *objData; 86 | duint64 uncompSize; 87 | 88 | private: 89 | void genMagicNumber(); 90 | // dwgBuffer* bufObj; 91 | void parseSysPage(duint8 *decompSec, duint32 decompSize); //called: Section page map: 0x41630e3b 92 | bool parseDataPage(dwgSectionInfo si/*, duint8 *dData*/); //called ???: Section map: 0x4163003b 93 | duint32 checksum(duint32 seed, duint8* data, duint32 sz); 94 | 95 | private: 96 | duint32 securityFlags; 97 | }; 98 | 99 | #endif // DWGREADER18_H 100 | -------------------------------------------------------------------------------- /libdxfrw/intern/dwgreader21.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef DWGREADER21_H 14 | #define DWGREADER21_H 15 | 16 | #include 17 | #include 18 | #include "drw_textcodec.h" 19 | #include "dwgbuffer.h" 20 | #include "dwgreader.h" 21 | 22 | //reader for AC1021 aka v2007, chapter 5 23 | class dwgReader21 : public dwgReader { 24 | public: 25 | dwgReader21(std::ifstream *stream, dwgR *p):dwgReader(stream, p){ 26 | objData = NULL; 27 | dataSize = 0; 28 | } 29 | virtual ~dwgReader21(){ 30 | if (objData != NULL) 31 | delete[] objData; 32 | } 33 | bool readMetaData(); 34 | bool readFileHeader(); 35 | bool readDwgHeader(DRW_Header& hdr); 36 | bool readDwgClasses(); 37 | bool readDwgHandles(); 38 | bool readDwgTables(DRW_Header& hdr); 39 | bool readDwgBlocks(DRW_Interface& intfa); 40 | virtual bool readDwgEntities(DRW_Interface& intfa){ 41 | bool ret = true; 42 | dwgBuffer dataBuf(objData, dataSize, &decoder); 43 | ret = dwgReader::readDwgEntities(intfa, &dataBuf); 44 | return ret; 45 | } 46 | virtual bool readDwgObjects(DRW_Interface& intfa){ 47 | bool ret = true; 48 | dwgBuffer dataBuf(objData, dataSize, &decoder); 49 | ret = dwgReader::readDwgObjects(intfa, &dataBuf); 50 | return ret; 51 | } 52 | //bool readDwgEntity(objHandle& obj, DRW_Interface& intfa){ 53 | // return false; 54 | //} 55 | 56 | private: 57 | bool parseSysPage(duint64 sizeCompressed, duint64 sizeUncompressed, duint64 correctionFactor, duint64 offset, duint8 *decompData); 58 | bool parseDataPage(dwgSectionInfo si, duint8 *dData); 59 | 60 | duint8 *objData; 61 | duint64 dataSize; 62 | 63 | }; 64 | 65 | #endif // DWGREADER21_H 66 | -------------------------------------------------------------------------------- /libdxfrw/intern/dwgreader24.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "drw_dbg.h" 19 | #include "dwgreader24.h" 20 | #include "drw_textcodec.h" 21 | #include "../libdwgr.h" 22 | 23 | 24 | bool dwgReader24::readFileHeader() { 25 | DRW_DBG("dwgReader24::readFileHeader\n"); 26 | bool ret = dwgReader18::readFileHeader(); 27 | DRW_DBG("dwgReader24::readFileHeader END\n"); 28 | return ret; 29 | } 30 | 31 | bool dwgReader24::readDwgHeader(DRW_Header& hdr){ 32 | DRW_DBG("dwgReader24::readDwgHeader\n"); 33 | bool ret = dwgReader18::readDwgHeader(hdr); 34 | DRW_DBG("dwgReader24::readDwgHeader END\n"); 35 | return ret; 36 | } 37 | 38 | bool dwgReader24::readDwgClasses(){ 39 | DRW_DBG("\ndwgReader24::readDwgClasses"); 40 | bool ret = dwgReader18::readDwgClasses(); 41 | DRW_DBG("\ndwgReader24::readDwgClasses END\n"); 42 | return ret; 43 | } 44 | -------------------------------------------------------------------------------- /libdxfrw/intern/dwgreader24.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef DWGREADER24_H 14 | #define DWGREADER24_H 15 | 16 | #include 17 | #include 18 | #include "drw_textcodec.h" 19 | #include "dwgbuffer.h" 20 | #include "dwgreader18.h" 21 | 22 | class dwgReader24 : public dwgReader18 { 23 | public: 24 | dwgReader24(std::ifstream *stream, dwgR *p):dwgReader18(stream, p){ } 25 | virtual ~dwgReader24(){} 26 | bool readFileHeader(); 27 | bool readDwgHeader(DRW_Header& hdr); 28 | bool readDwgClasses(); 29 | // bool readDwgHandles(){return false;} 30 | // bool readDwgTables(){return false;} 31 | bool readDwgBlocks(DRW_Interface& intfa){ 32 | bool ret = true; 33 | dwgBuffer dataBuf(objData, uncompSize, &decoder); 34 | ret = dwgReader::readDwgBlocks(intfa, &dataBuf); 35 | return ret; 36 | } 37 | virtual bool readDwgEntities(DRW_Interface& intfa){ 38 | bool ret = true; 39 | dwgBuffer dataBuf(objData, uncompSize, &decoder); 40 | ret = dwgReader::readDwgEntities(intfa, &dataBuf); 41 | return ret; 42 | } 43 | virtual bool readDwgObjects(DRW_Interface& intfa){ 44 | bool ret = true; 45 | dwgBuffer dataBuf(objData, uncompSize, &decoder); 46 | ret = dwgReader::readDwgObjects(intfa, &dataBuf); 47 | return ret; 48 | } 49 | 50 | // bool readDwgEntity(objHandle& obj, DRW_Interface& intfa){ 51 | // DRW_UNUSED(obj); 52 | // DRW_UNUSED(intfa); 53 | // return false;} 54 | }; 55 | 56 | #endif // DWGREADER24_H 57 | -------------------------------------------------------------------------------- /libdxfrw/intern/dwgreader27.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "drw_dbg.h" 19 | #include "dwgreader27.h" 20 | #include "drw_textcodec.h" 21 | #include "../libdwgr.h" 22 | 23 | 24 | bool dwgReader27::readFileHeader() { 25 | DRW_DBG("dwgReader27::readFileHeader\n"); 26 | bool ret = dwgReader18::readFileHeader(); 27 | DRW_DBG("dwgReader27::readFileHeader END\n"); 28 | return ret; 29 | } 30 | 31 | bool dwgReader27::readDwgHeader(DRW_Header& hdr){ 32 | DRW_DBG("dwgReader27::readDwgHeader\n"); 33 | bool ret = dwgReader18::readDwgHeader(hdr); 34 | DRW_DBG("dwgReader27::readDwgHeader END\n"); 35 | return ret; 36 | } 37 | 38 | bool dwgReader27::readDwgClasses(){ 39 | DRW_DBG("dwgReader27::readDwgClasses"); 40 | bool ret = dwgReader18::readDwgClasses(); 41 | DRW_DBG("\ndwgReader27::readDwgClasses END\n"); 42 | return ret; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /libdxfrw/intern/dwgreader27.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef DWGREADER27_H 14 | #define DWGREADER27_H 15 | 16 | #include 17 | #include 18 | #include "drw_textcodec.h" 19 | #include "dwgbuffer.h" 20 | #include "dwgreader18.h" 21 | 22 | class dwgReader27 : public dwgReader18 { 23 | public: 24 | dwgReader27(std::ifstream *stream, dwgR *p):dwgReader18(stream, p){ } 25 | virtual ~dwgReader27(){} 26 | bool readFileHeader(); 27 | bool readDwgHeader(DRW_Header& hdr); 28 | bool readDwgClasses(); 29 | // bool readDwgHandles(){return false;} 30 | // bool readDwgTables(){return false;} 31 | bool readDwgBlocks(DRW_Interface& intfa){ 32 | bool ret = true; 33 | dwgBuffer dataBuf(objData, uncompSize, &decoder); 34 | ret = dwgReader::readDwgBlocks(intfa, &dataBuf); 35 | return ret; 36 | } 37 | virtual bool readDwgEntities(DRW_Interface& intfa){ 38 | bool ret = true; 39 | dwgBuffer dataBuf(objData, uncompSize, &decoder); 40 | ret = dwgReader::readDwgEntities(intfa, &dataBuf); 41 | return ret; 42 | } 43 | virtual bool readDwgObjects(DRW_Interface& intfa){ 44 | bool ret = true; 45 | dwgBuffer dataBuf(objData, uncompSize, &decoder); 46 | ret = dwgReader::readDwgObjects(intfa, &dataBuf); 47 | return ret; 48 | } 49 | // bool readDwgEntity(objHandle& obj, DRW_Interface& intfa){ 50 | // DRW_UNUSED(obj); 51 | // DRW_UNUSED(intfa); 52 | // return false;} 53 | }; 54 | 55 | #endif // DWGREADER21_H 56 | -------------------------------------------------------------------------------- /libdxfrw/intern/dwgutil.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef DWGUTIL_H 14 | #define DWGUTIL_H 15 | 16 | #include "../drw_base.h" 17 | 18 | namespace DRW { 19 | std::string toHexStr(int n); 20 | } 21 | 22 | class dwgRSCodec { 23 | public: 24 | dwgRSCodec(){} 25 | ~dwgRSCodec(){} 26 | static void decode239I(duint8 *in, duint8 *out, duint32 blk); 27 | static void decode251I(duint8 *in, duint8 *out, duint32 blk); 28 | }; 29 | 30 | class dwgCompressor { 31 | public: 32 | dwgCompressor(){} 33 | ~dwgCompressor(){} 34 | 35 | void decompress18(duint8 *cbuf, duint8 *dbuf, duint32 csize, duint32 dsize); 36 | static void decrypt18Hdr(duint8 *buf, duint32 size, duint32 offset); 37 | // static void decrypt18Data(duint8 *buf, duint32 size, duint32 offset); 38 | static void decompress21(duint8 *cbuf, duint8 *dbuf, duint32 csize, duint32 dsize); 39 | 40 | private: 41 | duint32 litLength18(); 42 | static duint32 litLength21(duint8 *cbuf, duint8 oc, duint32 *si); 43 | static void copyCompBytes21(duint8 *cbuf, duint8 *dbuf, duint32 l, duint32 si, duint32 di); 44 | static void readInstructions21(duint8 *cbuf, duint32 *si, duint8 *oc, duint32 *so, duint32 *l); 45 | 46 | duint32 longCompressionOffset(); 47 | duint32 long20CompressionOffset(); 48 | duint32 twoByteOffset(duint32 *ll); 49 | 50 | duint8 *bufC; 51 | duint8 *bufD; 52 | duint32 sizeC; 53 | duint32 sizeD; 54 | duint32 pos; 55 | duint32 rpos; 56 | 57 | }; 58 | 59 | class secEnum { 60 | public: 61 | enum DWGSection { 62 | UNKNOWNS, /*!< UNKNOWN section. */ 63 | FILEHEADER, /*!< File Header (in R3-R15*/ 64 | HEADER, /*!< AcDb:Header */ 65 | CLASSES, /*!< AcDb:Classes */ 66 | SUMARYINFO, /*!< AcDb:SummaryInfo */ 67 | PREVIEW, /*!< AcDb:Preview */ 68 | VBAPROY, /*!< AcDb:VBAProject */ 69 | APPINFO, /*!< AcDb:AppInfo */ 70 | FILEDEP, /*!< AcDb:FileDepList */ 71 | REVHISTORY, /*!< AcDb:RevHistory */ 72 | SECURITY, /*!< AcDb:Security */ 73 | OBJECTS, /*!< AcDb:AcDbObjects */ 74 | OBJFREESPACE, /*!< AcDb:ObjFreeSpace */ 75 | TEMPLATE, /*!< AcDb:Template */ 76 | HANDLES, /*!< AcDb:Handles */ 77 | PROTOTYPE, /*!< AcDb:AcDsPrototype_1b */ 78 | AUXHEADER, /*!< AcDb:AuxHeader, in (R13-R15) second file header */ 79 | SIGNATURE, /*!< AcDb:Signature */ 80 | APPINFOHISTORY, /*!< AcDb:AppInfoHistory (in ac1021 may be a renamed section?*/ 81 | EXTEDATA, /*!< Extended Entity Data */ 82 | PROXYGRAPHICS /*!< PROXY ENTITY GRAPHICS */ 83 | }; 84 | 85 | secEnum(){} 86 | ~secEnum(){} 87 | 88 | static DWGSection getEnum(std::string nameSec); 89 | }; 90 | 91 | #endif // DWGUTIL_H 92 | -------------------------------------------------------------------------------- /libdxfrw/intern/dxfreader.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef DXFREADER_H 14 | #define DXFREADER_H 15 | 16 | #include "drw_textcodec.h" 17 | 18 | class dxfReader { 19 | public: 20 | enum TYPE { 21 | STRING, 22 | INT32, 23 | INT64, 24 | DOUBLE, 25 | BOOL, 26 | INVALID 27 | }; 28 | enum TYPE type; 29 | public: 30 | dxfReader(std::ifstream *stream){ 31 | filestr = stream; 32 | type = INVALID; 33 | } 34 | virtual ~dxfReader(){} 35 | bool readRec(int *code); 36 | 37 | std::string getString() {return strData;} 38 | int getHandleString();//Convert hex string to int 39 | std::string toUtf8String(std::string t) {return decoder.toUtf8(t);} 40 | std::string getUtf8String() {return decoder.toUtf8(strData);} 41 | double getDouble() {return doubleData;} 42 | int getInt32() {return intData;} 43 | unsigned long long int getInt64() {return int64;} 44 | bool getBool() { return (intData==0) ? false : true;} 45 | int getVersion(){return decoder.getVersion();} 46 | void setVersion(std::string *v, bool dxfFormat){decoder.setVersion(v, dxfFormat);} 47 | void setCodePage(std::string *c){decoder.setCodePage(c, true);} 48 | std::string getCodePage(){ return decoder.getCodePage();} 49 | 50 | protected: 51 | virtual bool readCode(int *code) = 0; //return true if sucesful (not EOF) 52 | virtual bool readString(std::string *text) = 0; 53 | virtual bool readString() = 0; 54 | virtual bool readInt16() = 0; 55 | virtual bool readInt32() = 0; 56 | virtual bool readInt64() = 0; 57 | virtual bool readDouble() = 0; 58 | virtual bool readBool() = 0; 59 | 60 | protected: 61 | std::ifstream *filestr; 62 | std::string strData; 63 | double doubleData; 64 | signed int intData; //32 bits integer 65 | unsigned long long int int64; //64 bits integer 66 | bool skip; //set to true for ascii dxf, false for binary 67 | private: 68 | DRW_TextCodec decoder; 69 | }; 70 | 71 | class dxfReaderBinary : public dxfReader { 72 | public: 73 | dxfReaderBinary(std::ifstream *stream):dxfReader(stream){skip = false; } 74 | virtual ~dxfReaderBinary() {} 75 | virtual bool readCode(int *code); 76 | virtual bool readString(std::string *text); 77 | virtual bool readString(); 78 | virtual bool readInt16(); 79 | virtual bool readInt32(); 80 | virtual bool readInt64(); 81 | virtual bool readDouble(); 82 | virtual bool readBool(); 83 | }; 84 | 85 | class dxfReaderAscii : public dxfReader { 86 | public: 87 | dxfReaderAscii(std::ifstream *stream):dxfReader(stream){skip = true; } 88 | virtual ~dxfReaderAscii(){} 89 | virtual bool readCode(int *code); 90 | virtual bool readString(std::string *text); 91 | virtual bool readString(); 92 | virtual bool readInt16(); 93 | virtual bool readDouble(); 94 | virtual bool readInt32(); 95 | virtual bool readInt64(); 96 | virtual bool readBool(); 97 | }; 98 | 99 | #endif // DXFREADER_H 100 | -------------------------------------------------------------------------------- /libdxfrw/intern/dxfwriter.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef DXFWRITER_H 14 | #define DXFWRITER_H 15 | 16 | #include "drw_textcodec.h" 17 | 18 | class dxfWriter { 19 | public: 20 | dxfWriter(std::ofstream *stream){filestr = stream; /*count =0;*/} 21 | virtual ~dxfWriter(){} 22 | virtual bool writeString(int code, std::string text) = 0; 23 | bool writeUtf8String(int code, std::string text); 24 | bool writeUtf8Caps(int code, std::string text); 25 | std::string fromUtf8String(std::string t) {return encoder.fromUtf8(t);} 26 | virtual bool writeInt16(int code, int data) = 0; 27 | virtual bool writeInt32(int code, int data) = 0; 28 | virtual bool writeInt64(int code, unsigned long long int data) = 0; 29 | virtual bool writeDouble(int code, double data) = 0; 30 | virtual bool writeBool(int code, bool data) = 0; 31 | void setVersion(std::string *v, bool dxfFormat){encoder.setVersion(v, dxfFormat);} 32 | void setCodePage(std::string *c){encoder.setCodePage(c, true);} 33 | std::string getCodePage(){return encoder.getCodePage();} 34 | protected: 35 | std::ofstream *filestr; 36 | private: 37 | DRW_TextCodec encoder; 38 | }; 39 | 40 | class dxfWriterBinary : public dxfWriter { 41 | public: 42 | dxfWriterBinary(std::ofstream *stream):dxfWriter(stream){} 43 | virtual ~dxfWriterBinary() {} 44 | virtual bool writeString(int code, std::string text); 45 | virtual bool writeInt16(int code, int data); 46 | virtual bool writeInt32(int code, int data); 47 | virtual bool writeInt64(int code, unsigned long long int data); 48 | virtual bool writeDouble(int code, double data); 49 | virtual bool writeBool(int code, bool data); 50 | }; 51 | 52 | class dxfWriterAscii : public dxfWriter { 53 | public: 54 | dxfWriterAscii(std::ofstream *stream); 55 | virtual ~dxfWriterAscii(){} 56 | virtual bool writeString(int code, std::string text); 57 | virtual bool writeInt16(int code, int data); 58 | virtual bool writeInt32(int code, int data); 59 | virtual bool writeInt64(int code, unsigned long long int data); 60 | virtual bool writeDouble(int code, double data); 61 | virtual bool writeBool(int code, bool data); 62 | }; 63 | 64 | #endif // DXFWRITER_H 65 | -------------------------------------------------------------------------------- /libdxfrw/intern/rscodec.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2014 J.F. Soriano (Rallaz), rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | /** 14 | * Reed-Solomon codec 15 | * Reed Solomon code lifted from encoder/decoder for Reed-Solomon written by Simon Rockliff 16 | * 17 | * Original code: 18 | * This program may be freely modified and/or given to whoever wants it. 19 | * A condition of such distribution is that the author's contribution be 20 | * acknowledged by his name being left in the comments heading the program, 21 | * however no responsibility is accepted for any financial or other loss which 22 | * may result from some unforseen errors or malfunctioning of the program 23 | * during use. 24 | * Simon Rockliff, 26th June 1991 25 | */ 26 | 27 | 28 | 29 | #ifndef RSCODEC_H 30 | #define RSCODEC_H 31 | /** 32 | mm: RS code over GF(2^4) 33 | nn: nn= (2^mm) - 1 length of codeword 34 | tt: number of errors that can be corrected 35 | kk: kk = nn-2*tt 36 | pp: irreducible polynomial coeffts, pp [mm] send as int 37 | */ 38 | class RScodec { 39 | public: 40 | RScodec(unsigned int pp, int mm, int tt); 41 | 42 | ~RScodec(); 43 | // bool encode(int *data, int *parity); 44 | // int decode(int *recd); 45 | bool encode(unsigned char *data, unsigned char *parity); 46 | int decode(unsigned char *data); 47 | bool isOkey(){return isOk;} 48 | const unsigned int* indexOf() {return index_of;} 49 | const int* alphaTo() {return alpha_to;} 50 | 51 | private: 52 | void RSgenerate_gf(unsigned int pp); 53 | void RSgen_poly(); 54 | int calcDecode(unsigned char* data, int* recd, int** elp, int* d, int* l, int* u_lu, int* s, int* root, int* loc, int* z, int* err, int* reg, int bb); 55 | 56 | 57 | private: 58 | int mm; //RS code over GF(2^4) 59 | int tt; //number of errors that can be corrected 60 | int nn; //(2^mm) - 1 length of codeword 61 | int kk; //nn-2*tt length of original data 62 | 63 | int *gg; 64 | bool isOk; 65 | unsigned int *index_of; 66 | int *alpha_to; 67 | }; 68 | 69 | #endif // RSCODEC_H 70 | -------------------------------------------------------------------------------- /libdxfrw/libdwgr.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef LIBDWGR_H 14 | #define LIBDWGR_H 15 | 16 | #include 17 | //#include 18 | #include "drw_entities.h" 19 | #include "drw_objects.h" 20 | #include "drw_classes.h" 21 | #include "drw_interface.h" 22 | 23 | class dwgReader; 24 | 25 | class dwgR { 26 | public: 27 | dwgR(const char* name); 28 | ~dwgR(); 29 | //read: return true if all ok 30 | bool read(DRW_Interface *interface_, bool ext); 31 | bool getPreview(); 32 | DRW::Version getVersion(){return version;} 33 | DRW::error getError(){return error;} 34 | bool testReader(); 35 | void setDebug(DRW::DBG_LEVEL lvl); 36 | 37 | private: 38 | bool openFile(std::ifstream *filestr); 39 | bool processDwg(); 40 | private: 41 | DRW::Version version; 42 | DRW::error error; 43 | std::string fileName; 44 | bool applyExt; /*apply extrusion in entities to conv in 2D?*/ 45 | std::string codePage; 46 | DRW_Interface *iface; 47 | dwgReader *reader; 48 | 49 | }; 50 | 51 | #endif // LIBDWGR_H 52 | -------------------------------------------------------------------------------- /libdxfrw/libdxfrw.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | ** libDXFrw - Library to read/write DXF files (ascii & binary) ** 3 | ** ** 4 | ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** 5 | ** ** 6 | ** This library is free software, licensed under the terms of the GNU ** 7 | ** General Public License as published by the Free Software Foundation, ** 8 | ** either version 2 of the License, or (at your option) any later version. ** 9 | ** You should have received a copy of the GNU General Public License ** 10 | ** along with this program. If not, see . ** 11 | ******************************************************************************/ 12 | 13 | #ifndef LIBDXFRW_H 14 | #define LIBDXFRW_H 15 | 16 | #include 17 | #include "drw_entities.h" 18 | #include "drw_objects.h" 19 | #include "drw_header.h" 20 | #include "drw_interface.h" 21 | 22 | 23 | class dxfReader; 24 | class dxfWriter; 25 | 26 | class dxfRW { 27 | public: 28 | dxfRW(const char* name); 29 | ~dxfRW(); 30 | void setDebug(DRW::DBG_LEVEL lvl); 31 | /// reads the file specified in constructor 32 | /*! 33 | * An interface must be provided. It is used by the class to signal various 34 | * components being added. 35 | * @param interface_ the interface to use 36 | * @param ext should the extrusion be applied to convert in 2D? 37 | * @return true for success 38 | */ 39 | bool read(DRW_Interface *interface_, bool ext); 40 | void setBinary(bool b) {binFile = b;} 41 | 42 | bool write(DRW_Interface *interface_, DRW::Version ver, bool bin); 43 | bool writeLineType(DRW_LType *ent); 44 | bool writeLayer(DRW_Layer *ent); 45 | bool writeDimstyle(DRW_Dimstyle *ent); 46 | bool writeTextstyle(DRW_Textstyle *ent); 47 | bool writeVport(DRW_Vport *ent); 48 | bool writeAppId(DRW_AppId *ent); 49 | bool writePoint(DRW_Point *ent); 50 | bool writeLine(DRW_Line *ent); 51 | bool writeRay(DRW_Ray *ent); 52 | bool writeXline(DRW_Xline *ent); 53 | bool writeCircle(DRW_Circle *ent); 54 | bool writeArc(DRW_Arc *ent); 55 | bool writeEllipse(DRW_Ellipse *ent); 56 | bool writeTrace(DRW_Trace *ent); 57 | bool writeSolid(DRW_Solid *ent); 58 | bool write3dface(DRW_3Dface *ent); 59 | bool writeLWPolyline(DRW_LWPolyline *ent); 60 | bool writePolyline(DRW_Polyline *ent); 61 | bool writeSpline(DRW_Spline *ent); 62 | bool writeBlockRecord(std::string name); 63 | bool writeBlock(DRW_Block *ent); 64 | bool writeInsert(DRW_Insert *ent); 65 | bool writeMText(DRW_MText *ent); 66 | bool writeText(DRW_Text *ent); 67 | bool writeHatch(DRW_Hatch *ent); 68 | bool writeViewport(DRW_Viewport *ent); 69 | DRW_ImageDef *writeImage(DRW_Image *ent, std::string name); 70 | bool writeLeader(DRW_Leader *ent); 71 | bool writeDimension(DRW_Dimension *ent); 72 | void setEllipseParts(int parts){elParts = parts;} /*!< set parts munber when convert ellipse to polyline */ 73 | 74 | private: 75 | /// used by read() to parse the content of the file 76 | bool processDxf(); 77 | bool processHeader(); 78 | bool processTables(); 79 | bool processBlocks(); 80 | bool processBlock(); 81 | bool processEntities(bool isblock); 82 | bool processObjects(); 83 | 84 | bool processLType(); 85 | bool processLayer(); 86 | bool processDimStyle(); 87 | bool processTextStyle(); 88 | bool processVports(); 89 | bool processAppId(); 90 | 91 | bool processPoint(); 92 | bool processLine(); 93 | bool processRay(); 94 | bool processXline(); 95 | bool processCircle(); 96 | bool processArc(); 97 | bool processEllipse(); 98 | bool processTrace(); 99 | bool processSolid(); 100 | bool processInsert(); 101 | bool processLWPolyline(); 102 | bool processPolyline(); 103 | bool processVertex(DRW_Polyline* pl); 104 | bool processText(); 105 | bool processMText(); 106 | bool processHatch(); 107 | bool processSpline(); 108 | bool process3dface(); 109 | bool processViewport(); 110 | bool processImage(); 111 | bool processImageDef(); 112 | bool processDimension(); 113 | bool processLeader(); 114 | 115 | // bool writeHeader(); 116 | bool writeEntity(DRW_Entity *ent); 117 | bool writeTables(); 118 | bool writeBlocks(); 119 | bool writeObjects(); 120 | bool writeExtData(const std::vector &ed); 121 | /*use version from dwgutil.h*/ 122 | std::string toHexStr(int n);//RLZ removeme 123 | 124 | private: 125 | DRW::Version version; 126 | std::string fileName; 127 | std::string codePage; 128 | bool binFile; 129 | dxfReader *reader; 130 | dxfWriter *writer; 131 | DRW_Interface *iface; 132 | DRW_Header header; 133 | // int section; 134 | std::string nextentity; 135 | int entCount; 136 | bool wlayer0; 137 | bool dimstyleStd; 138 | bool applyExt; 139 | bool writingBlock; 140 | int elParts; /*!< parts munber when convert ellipse to polyline */ 141 | std::map blockMap; 142 | std::vector imageDef; /*!< imageDef list */ 143 | 144 | int currHandle; 145 | 146 | }; 147 | 148 | #endif // LIBDXFRW_H 149 | -------------------------------------------------------------------------------- /libdxfrw/main_doc.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @mainpage 4 | * 5 | * This manual documents the use of libdxfrw. 6 | * 7 | * With libdxfrw you can read and write several parts of a dxf files.

8 | * Dxf files can be written in assci and binary form, both are supported.

9 | * Dwg support (only read) are work in progress.

10 | * 11 | * the complete documentation and examples are pending to free time, 12 | * but to start see DRW_Interface, dxfRW & dwgR, clases 13 | */ 14 | 15 | -------------------------------------------------------------------------------- /libgcode/gcode.h: -------------------------------------------------------------------------------- 1 | #ifndef GCODE_H 2 | #define GCODE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "opencascade.h" 10 | #include "draw_primitives.h" 11 | #include 12 | 13 | using namespace occ; 14 | 15 | class gcode 16 | { 17 | public: 18 | gcode(); 19 | void generate(); // Will produce a gcode file in the program build directory with a .ngc extension. 20 | void clear(); // Remove all content of gcode.ngc file. 21 | 22 | //! Helper functions: 23 | std::vector get_lead_in_points(unsigned int i /* contourvec[i]*/); 24 | std::vector get_lead_out_points(unsigned int i /* contourvec[i]*/); 25 | unsigned int increment_line_nr(); 26 | std::string new_line_nr(bool print); // If print=0 there are no line numbers printed in gcode output file. 27 | 28 | private: 29 | std::string linenumber_format={}; 30 | }; 31 | 32 | #endif // GCODE_H 33 | -------------------------------------------------------------------------------- /libocc/opencascade.h: -------------------------------------------------------------------------------- 1 | #ifndef OPENCASCADE_H 2 | #define OPENCASCADE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #ifdef _WIN32 19 | #include 20 | #else 21 | #undef None 22 | #include 23 | #endif 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | //show xyz axis 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | 39 | #define gp_Euler gp_Pnt // Used as universal toolset. 40 | 41 | struct SEGMENT{ 42 | std::vector Ais_ShapeVec={}; ///each stepfile can contain multiple shapes, we need the vector. 43 | gp_Trsf MyTrsf={}; 44 | }; 45 | extern SEGMENT Segment; 46 | extern std::vector SegmentVec; 47 | 48 | extern gp_Trsf level0x1x2x3x4x5x6; 49 | 50 | namespace occ { 51 | class Opencascade: public QGLWidget 52 | { 53 | Q_OBJECT 54 | public: 55 | explicit Opencascade(QWidget *parent = nullptr); 56 | 57 | bool Readstepfile(const std::string& theStepName); 58 | void Visit(const TDF_Label& theLabel); 59 | void Init_robot(); 60 | void setup_tcp_origin(); 61 | void show_3d_interactive_box(); 62 | 63 | void show_shape(Handle(AIS_Shape) ashape); 64 | void set_shape_selected(Handle(AIS_Shape) ashape); 65 | void clear_selection(); 66 | void Redraw(); 67 | void update_jointpos(double j0, double j1, double j2, double j3, double j4, double j5); 68 | 69 | // View 70 | void set_orthographic(); 71 | void set_perspective(); 72 | void set_view_front(); 73 | void set_view_back(); 74 | void set_view_left(); 75 | void set_view_right(); 76 | void set_view_top(); 77 | void set_view_bottom(); 78 | 79 | // Zoom 80 | void zoom_all(); 81 | 82 | // Selection 83 | void get_selections(); 84 | void delete_selections(); 85 | 86 | // Erase 87 | void erase_all(); 88 | 89 | private: 90 | void m_initialize_context(); 91 | Handle(AIS_InteractiveContext) m_context; 92 | Handle(V3d_Viewer) m_viewer; 93 | Handle(V3d_View) m_view; 94 | Handle(Graphic3d_GraphicDriver) m_graphic_driver; 95 | Handle(AIS_InteractiveObject) m_aisViewCube; 96 | 97 | // Xyz axis sign. 98 | Handle(Geom_Axis2Placement) axis; 99 | Handle(AIS_Trihedron) aisTrihedron; 100 | std::vector aisTrihedrons; 101 | 102 | protected: 103 | void paintEvent(QPaintEvent *); 104 | void resizeEvent(QResizeEvent *); 105 | void mousePressEvent(QMouseEvent *event); 106 | void mouseReleaseEvent(QMouseEvent *event); 107 | void mouseMoveEvent(QMouseEvent *event); 108 | void wheelEvent(QWheelEvent *event); 109 | 110 | protected: 111 | enum CurrentAction3d 112 | { 113 | CurAction3d_Nothing, 114 | CurAction3d_DynamicPanning, 115 | CurAction3d_DynamicZooming, 116 | CurAction3d_DynamicRotation 117 | }; 118 | 119 | private: 120 | Standard_Integer m_x_max; 121 | Standard_Integer m_y_max; 122 | CurrentAction3d m_current_mode; 123 | //gp_Trsf current_tcp; 124 | 125 | Handle(AIS_Shape) aisBody_tcp_xaxis, aisBody_tcp_yaxis, aisBody_tcp_zaxis; 126 | 127 | public: 128 | unsigned int selected_contour=0; 129 | 130 | signals: 131 | 132 | public slots: 133 | }; 134 | } 135 | 136 | #endif // OPENCASCADE_H 137 | 138 | 139 | -------------------------------------------------------------------------------- /libspline/bezier_spline.h: -------------------------------------------------------------------------------- 1 | #include "spline.h" 2 | 3 | /* Cubic Bezier Spline (B-Spline) Implementation 4 | * Based on this article: 5 | * http://www.particleincell.com/blog/2012/bezier-splines/ 6 | */ 7 | class BezierSpline : public SplineCurve 8 | { 9 | private: 10 | std::vector p1_points_; // First Control Points for a curve 11 | std::vector p2_points_; // Control Points for the curve 12 | 13 | public: 14 | BezierSpline() 15 | { 16 | p1_points_.reserve(NOM_SIZE); 17 | p2_points_.reserve(NOM_SIZE); 18 | } 19 | 20 | // Inherited Functions // 21 | std::tuple Evaluate(int seg, double t) ; 22 | void ResetDerived() override; 23 | bool ComputeSpline() override; 24 | void PrintDerivedData() override; 25 | bool BuildSpline(std::vector path, int divisions); 26 | }; 27 | -------------------------------------------------------------------------------- /libspline/cubic_spline.h: -------------------------------------------------------------------------------- 1 | #ifndef CUBIC_SPLINE_H 2 | #define CUBIC_SPLINE_H 3 | #include "spline.h" 4 | 5 | using namespace Eigen; 6 | 7 | /** Cubic Spline 8 | * Works best with tightly packed waypoint list 9 | * */ 10 | class CubicSpline : public SplineCurve 11 | { 12 | private: 13 | /* The system of linear equations found by solving 14 | * for the 3 order spline polynomial is given by: 15 | * A*x = b. The "x" is represented by x_col_ and the 16 | * "b" is represented by waypoints in the code. 17 | * 18 | * The "A" is formulated with diagonal elements and 19 | * symmetric off-diagonal elements. The 20 | * general structure (for six waypoints) looks like: 21 | * 22 | * 23 | * | d1 u1 0 0 0 | | x1 | | b1 | 24 | * | u1 d2 u2 0 0 | | x2 | | b2 | 25 | * | 0 u2 d3 u3 0 | * | x3 | = | b3 | 26 | * | 0 0 u3 d4 u4 | | x4 | | b4 | 27 | * | 0 0 0 u4 d5 | | x5 | | b5 | 28 | * 29 | * 30 | * The general derivation for this can be found 31 | * in Robert Sedgewick's "Algorithms in C++". 32 | * 33 | */ 34 | Vector3d x_col_[NOM_SIZE][4]; // column full of constants to solve for trinomial 35 | 36 | public: 37 | /** Overall arc length integrand of the curve */ 38 | double ArcLengthIntegrand(double t); 39 | 40 | /** Arc length integrand of a spline segment and point in time */ 41 | double SplineArcLengthIntegrand(int spline, double t); 42 | 43 | /** Integrates for the area under a spline numerically */ 44 | double IntegrateSpline(int spline, double t); 45 | 46 | /** Integrates for the area under the entire curve by summing the 47 | * integrations of all the independent splines. 48 | */ 49 | double IntegrateCurve(float t0, float t1); 50 | 51 | /** Determines what spline is being used at a specific parametric time 52 | * along the curve. Use this to convert from global time to spline time. 53 | */ 54 | Vector3d SplineAtTime(double t); 55 | 56 | /** Determines the constant velocity along a spline segment. 57 | * Use this to determine the velocity from a global time perspective 58 | * rather than a segmented time perspective. 59 | */ 60 | Vector3d ConstVelocitySplineAtTime(double t, double speed); 61 | 62 | /** Determine the length of the entire trajectory curve */ 63 | double EvaluateCurveLength(); 64 | 65 | CubicSpline(); 66 | CubicSpline(std::vector points); 67 | CubicSpline(std::vector points, int segments_per_pt); 68 | ~CubicSpline(){} 69 | 70 | /** 71 | * Evaluate spline for the ith segment for x,y,z params. 72 | * The value of param t must be (0<=t<=1) 73 | */ 74 | std::tuple EvaluateSplineAtTime(double t) override; 75 | 76 | // Inherited Functions from spline.h // 77 | /* Clear out all the data.*/ 78 | void ResetDerived() override; 79 | bool ComputeSpline() override; 80 | void PrintDerivedData() override; 81 | bool BuildSpline() override; 82 | bool BuildSpline(std::vector points) override; 83 | 84 | }; 85 | 86 | #endif -------------------------------------------------------------------------------- /libspline/spline.cpp: -------------------------------------------------------------------------------- 1 | #include "spline.h" 2 | 3 | /* Clear out data */ 4 | void SplineCurve::Reset() 5 | { 6 | points_.clear(); 7 | pos_profile_.clear(); 8 | vel_profile_.clear(); 9 | accel_profile_.clear(); 10 | curvature_profile_.clear(); 11 | spline_lengths_.clear(); 12 | // ResetDerived(); 13 | } 14 | 15 | void SplineCurve::AddPoint(const Vector3d& pt) 16 | { 17 | // if new point is colinear with previous pts remove the last pt 18 | // and replace it with this one 19 | if(elim_colinear_pts_ && points_.size()>2) 20 | { 21 | int n = points_.size()-1; 22 | Vector3d p0 = points_[n-1]-points_[n-2]; 23 | Vector3d p1 = points_[n]-points_[n-1]; 24 | Vector3d p2 = pt-points_[n]; 25 | // test for colinearity by comparing slopes 26 | // of two lines. If slopes are equivalent assume colinearity 27 | double delta = (p2.y()-p1.y())*(p1.x()-p0.x())-(p1.y()-p0.y())*(p2.x()-p1.x()); 28 | if(std::abs(delta) < 0.001) 29 | { 30 | std::cout<< "Point " << points_[n] << "was removed with delta:" << delta << std::endl; 31 | points_.pop_back(); 32 | } 33 | } 34 | points_.push_back(pt); 35 | 36 | } 37 | 38 | void SplineCurve::PrintData(int segments=5) 39 | { 40 | assert(segments>1); 41 | std::cout << "Original Points (" << points_.size() << ")" << std::endl; 42 | std::cout << "-----------------------------" << std::endl; 43 | for(int idx = 0; idx < points_.size(); ++idx) 44 | { 45 | std::cout << "[" << idx << "]" << " " << points_[idx] << std::endl; 46 | } 47 | 48 | std::cout << "-----------------------------" << std::endl; 49 | PrintDerivedData(); 50 | 51 | std::cout << "-----------------------------" << std::endl; 52 | std::cout << "Evaluating Spline at " << segments << " points." << std::endl; 53 | for(int idx = 0; idx < points_.size(); idx++) 54 | { 55 | std::cout << "---------- " << "From " << points_[idx] << " to " << points_[idx+1] << "." << std::endl; 56 | for(int tIdx = 0; tIdx < segments+1; ++tIdx) 57 | { 58 | double t = tIdx*1.0/segments; 59 | std::tuple state_info = EvaluateSplineAtTime(t); 60 | std::cout << "[" << tIdx << "]" << " "; 61 | std::cout << "[" << t*100 << "%]" << " "; 62 | std::cout << " --> " << std::get<0>(state_info); 63 | std::cout << std::endl; 64 | } 65 | } 66 | } 67 | 68 | 69 | -------------------------------------------------------------------------------- /libspline/spline.h: -------------------------------------------------------------------------------- 1 | #ifndef SPLINE_H 2 | #define SPLINE_H 3 | 4 | //internals 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | // externals 12 | #include 13 | 14 | using namespace Eigen; 15 | class SplineCurve 16 | { 17 | private: 18 | std::vector points_; // array of primary setpoints added to plot 19 | bool elim_colinear_pts_; // removes colinear points if enabled 20 | 21 | protected: 22 | int segments_per_pt_; 23 | 24 | std::vector pos_profile_; // Curve of all positions 25 | std::vector vel_profile_; // Curve velocity profile 26 | std::vector accel_profile_; // Curve acceleration profile 27 | std::vector curvature_profile_; // Curvature (k) of spline between knots. 28 | // Each curvature index represents a segment 29 | std::vector spline_lengths_; // lengths of all the spline segments in an array. 30 | 31 | /* Override */ 32 | virtual void ResetDerived() = 0; 33 | enum 34 | { 35 | NOM_SIZE = 32 // Max size of the waypoint list 36 | }; 37 | 38 | public: 39 | 40 | 41 | SplineCurve() 42 | { 43 | segments_per_pt_ = 50; 44 | points_.reserve(NOM_SIZE); 45 | elim_colinear_pts_ = false ; 46 | } 47 | SplineCurve(std::vector points) 48 | { 49 | segments_per_pt_ = 50; 50 | points_.reserve(points.size()); 51 | for(int i = 0; i points, int segments_per_pt) 58 | { 59 | segments_per_pt_ = segments_per_pt; 60 | points_.reserve(points.size()); 61 | for(int i = 0; i& GetPoints() { return points_; } 71 | const std::vector& GetPositionProfile() { return pos_profile_; } 72 | const std::vector& GetVelocityProfile() { return vel_profile_; } 73 | const std::vector& GetAccelerationProfile() { return accel_profile_; } 74 | const std::vector& GetCurvatureProfile() { return curvature_profile_; } 75 | const std::vector& GetSplineLengths(){return spline_lengths_;} 76 | 77 | bool GetElimColinearPoints() { return elim_colinear_pts_; } 78 | void SetelimColinearPoints(bool elim) { elim_colinear_pts_ = true;} 79 | 80 | /* Virtual Spline Properties */ 81 | /** Determine the cubic function for a spline segmenet between two setpoints 82 | * Evaluate will automatically be run from BuildSpline() to determine the cubic functions. 83 | * 84 | * This function returns the state information regarding a specific spline segmeent 85 | * and save the state information to create a motion profile for 86 | * position, velocity, acceleration, and curvature for all t in the list. 87 | * Evaluate the spline for the ith segment for parameter. 88 | * The value of parameter t must be between 0 and 1. 89 | * 90 | */ 91 | virtual std::tuple EvaluateSplineAtTime(double t) = 0; 92 | 93 | /**This function will create your entire spline from an array of waypoints 94 | * based on the number of steps(divisons) desired for the splines. 95 | * 96 | * The maximum allowable size for a waypoint list is 32. Realistically it 97 | * shouldn't need to go past that. But if necessary change NOM_SIZE. 98 | */ 99 | virtual bool BuildSpline(std::vector setpoints)=0; 100 | virtual bool BuildSpline()=0; 101 | 102 | /**Triangulizes the "A" matrix of a cubic function*/ 103 | virtual bool ComputeSpline() = 0; 104 | 105 | // virtual double ArcLengthIntegrand(int spline, double t) = 0; 106 | // virtual double Integrate(int spline, double t) = 0; 107 | // virtual Vector3d ConstVelocitySplineAtTime(double t) = 0; 108 | 109 | /** Prints out data pertaining to a specific spline type. */ 110 | virtual void PrintDerivedData() {} 111 | 112 | /** Erase the current waypoint list and state information */ 113 | void Reset(); 114 | 115 | /** Adds a waypoint to the end of the spline list 116 | * Make sure you run BuildSpline() again after you use this 117 | * to update the relevant state information. 118 | */ 119 | void AddPoint(const Vector3d& pt); 120 | 121 | /**Prints the data relating to a specific spline segment */ 122 | void PrintData(int segments); 123 | 124 | }; 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | 3 | #include 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | QApplication a(argc, argv); 8 | MainWindow w; 9 | w.show(); 10 | return a.exec(); 11 | } 12 | -------------------------------------------------------------------------------- /mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | using namespace Eigen; 16 | 17 | #include "opencascade.h" 18 | #include "draw_primitives.h" 19 | using namespace occ; 20 | 21 | #include "contours.h" 22 | #include "offsets.h" 23 | #include "gcode.h" 24 | 25 | #include 26 | #include 27 | 28 | // File read operations. 29 | #include 30 | #include 31 | #include 32 | 33 | // Dialog file open library, https://github.com/samhocevar/portable-file-dialogs/blob/master/examples/example.cpp 34 | #include 35 | #if _WIN32 36 | #define DEFAULT_PATH "C:\\" 37 | #else 38 | #define DEFAULT_PATH "/tmp" 39 | #endif 40 | 41 | QT_BEGIN_NAMESPACE 42 | namespace Ui { class MainWindow; } 43 | QT_END_NAMESPACE 44 | 45 | class MainWindow : public QMainWindow 46 | { 47 | Q_OBJECT 48 | 49 | public: 50 | MainWindow(QWidget *parent = nullptr); 51 | ~MainWindow(); 52 | 53 | bool open_dxf_file(std::string filename); 54 | bool save_dxf_file(std::string filename); 55 | bool write_entity(); 56 | 57 | void Update_Opencascade(); 58 | void load_opencascade_primitives(); 59 | 60 | void gcode_preview(); 61 | void gcode_get_user_settings(); 62 | 63 | void generate_contours(); 64 | void generate_pockets(); 65 | 66 | private slots: 67 | void process(); 68 | 69 | void rotate_lead_in_out(); 70 | 71 | void add_operation(); 72 | 73 | void clear_operations(); 74 | 75 | void process_operations(); 76 | 77 | void on_toolButton_open_dxf_pressed(); 78 | 79 | private: 80 | Ui::MainWindow *ui; 81 | 82 | // Dxf data 83 | dx_data fData; 84 | dx_data fCleanData; // To clean the fData. 85 | dx_iface *iface = new dx_iface; 86 | Opencascade* OpencascadeWidget; 87 | }; 88 | #endif // MAINWINDOW_H 89 | -------------------------------------------------------------------------------- /qt-dxf.pro: -------------------------------------------------------------------------------- 1 | QT += core gui opengl 2 | 3 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 4 | 5 | CONFIG += c++20 6 | TARGET = cam 7 | 8 | # This code depends on zenity. 9 | # sudo apt-get install zenity 10 | 11 | # You can make your code fail to compile if it uses deprecated APIs. 12 | # In order to do so, uncomment the following line. 13 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 14 | 15 | SOURCES += \ 16 | libcavalier/offsets.cpp \ 17 | libcontour/contours.cpp \ 18 | libdata/variable.cpp \ 19 | libdxfrw/drw_classes.cpp \ 20 | libdxfrw/drw_entities.cpp \ 21 | libdxfrw/drw_header.cpp \ 22 | libdxfrw/drw_objects.cpp \ 23 | libdxfrw/dx_iface.cpp \ 24 | libdxfrw/intern/drw_dbg.cpp \ 25 | libdxfrw/intern/drw_textcodec.cpp \ 26 | libdxfrw/intern/dwgbuffer.cpp \ 27 | libdxfrw/intern/dwgreader.cpp \ 28 | libdxfrw/intern/dwgreader15.cpp \ 29 | libdxfrw/intern/dwgreader18.cpp \ 30 | libdxfrw/intern/dwgreader21.cpp \ 31 | libdxfrw/intern/dwgreader24.cpp \ 32 | libdxfrw/intern/dwgreader27.cpp \ 33 | libdxfrw/intern/dwgutil.cpp \ 34 | libdxfrw/intern/dxfreader.cpp \ 35 | libdxfrw/intern/dxfwriter.cpp \ 36 | libdxfrw/intern/rscodec.cpp \ 37 | libdxfrw/libdwgr.cpp \ 38 | libdxfrw/libdxfrw.cpp \ 39 | libgcode/gcode.cpp \ 40 | libocc/draw_primitives.cpp \ 41 | libspline/bezier_spline.cpp \ 42 | libspline/cubic_spline.cpp \ 43 | libspline/spline.cpp \ 44 | main.cpp \ 45 | mainwindow.cpp \ 46 | libocc/opencascade.cpp 47 | HEADERS += \ 48 | libcavalier/offsets.h \ 49 | libcontour/contours.h \ 50 | libdata/variable.h \ 51 | libdialog/portable-file-dialogs.h \ 52 | libdxfrw/drw_base.h \ 53 | libdxfrw/drw_classes.h \ 54 | libdxfrw/drw_entities.h \ 55 | libdxfrw/drw_header.h \ 56 | libdxfrw/drw_interface.h \ 57 | libdxfrw/drw_objects.h \ 58 | libdxfrw/dx_data.h \ 59 | libdxfrw/dx_iface.h \ 60 | libdxfrw/intern/drw_cptable932.h \ 61 | libdxfrw/intern/drw_cptable936.h \ 62 | libdxfrw/intern/drw_cptable949.h \ 63 | libdxfrw/intern/drw_cptable950.h \ 64 | libdxfrw/intern/drw_cptables.h \ 65 | libdxfrw/intern/drw_dbg.h \ 66 | libdxfrw/intern/drw_textcodec.h \ 67 | libdxfrw/intern/dwgbuffer.h \ 68 | libdxfrw/intern/dwgreader.h \ 69 | libdxfrw/intern/dwgreader15.h \ 70 | libdxfrw/intern/dwgreader18.h \ 71 | libdxfrw/intern/dwgreader21.h \ 72 | libdxfrw/intern/dwgreader24.h \ 73 | libdxfrw/intern/dwgreader27.h \ 74 | libdxfrw/intern/dwgutil.h \ 75 | libdxfrw/intern/dxfreader.h \ 76 | libdxfrw/intern/dxfwriter.h \ 77 | libdxfrw/intern/rscodec.h \ 78 | libdxfrw/libdwgr.h \ 79 | libdxfrw/libdxfrw.h \ 80 | libdxfrw/main_doc.h \ 81 | libgcode/gcode.h \ 82 | libocc/draw_primitives.h \ 83 | libspline/bezier_spline.h \ 84 | libspline/cubic_spline.h \ 85 | libspline/spline.h \ 86 | mainwindow.h \ 87 | libocc/opencascade.h 88 | 89 | FORMS += \ 90 | mainwindow.ui 91 | 92 | # Local include paths. 93 | INCLUDEPATH+= libdxfrw/ \ 94 | libocc/ \ 95 | libspline/ \ 96 | libcavalier/ \ 97 | libcavalier/include/cavc/ \ 98 | libcontour/ \ 99 | libdata/ \ 100 | libgcode/ \ 101 | libdialog/ \ 102 | 103 | # Default rules for deployment. 104 | qnx: target.path = /tmp/$${TARGET}/bin 105 | else: unix:!android: target.path = /opt/$${TARGET}/bin 106 | !isEmpty(target.path): INSTALLS += target 107 | 108 | DISTFILES += \ 109 | 110 | # this copies the configuration files etc to the build direcory. So user has only to edit the source directory. 111 | # copydata.commands = $(COPY_DIR) $$PWD/* $$OUT_PWD 112 | # first.depends = $(first) copydata 113 | # export(first.depends) 114 | # export(copydata.commands) 115 | # QMAKE_EXTRA_TARGETS += first copydata 116 | 117 | # Opencascade 118 | LIBS+= -L/usr/local/lib/ \ 119 | 120 | INCLUDEPATH += /usr/local/include/kdl/ \ 121 | /usr/local/include/opencascade/ \ 122 | /usr/include/eigen3/ \ 123 | /usr/include/ \ 124 | /usr/local/lib/ \ 125 | 126 | # compiled libs .so files: 127 | # LIBS += -lorocos-kdl 128 | 129 | # compiled libs .so files: 130 | LIBS += -lTKPrim 131 | LIBS += -lTKernel 132 | LIBS += -lTKMath -lTKTopAlgo -lTKService 133 | LIBS += -lTKG2d -lTKG3d -lTKV3d -lTKOpenGl 134 | LIBS += -lTKBRep -lTKXSBase -lTKGeomBase 135 | LIBS += -lTKMeshVS -lTKXSDRAW 136 | LIBS += -lTKLCAF -lTKXCAF -lTKCAF 137 | LIBS += -lTKCDF -lTKBin -lTKBinL -lTKBinXCAF -lTKXml -lTKXmlL -lTKXmlXCAF 138 | # -- IGES support 139 | LIBS += -lTKIGES 140 | # -- STEP support 141 | LIBS += -lTKSTEP -lTKXDESTEP -lTKXDEIGES 142 | # -- STL support 143 | LIBS += -lTKSTL 144 | # -- OBJ/glTF support 145 | LIBS += -lTKRWMesh 146 | # -- VRML support 147 | LIBS += -lTKVRML 148 | 149 | RESOURCES += \ 150 | icons.qrc 151 | 152 | --------------------------------------------------------------------------------