diff --git a/lcUI/lcadpaperviewer.cpp b/lcUI/lcadpaperviewer.cpp index 9e12475ae..7890e3b3d 100644 --- a/lcUI/lcadpaperviewer.cpp +++ b/lcUI/lcadpaperviewer.cpp @@ -5,7 +5,7 @@ using namespace lc::ui; using namespace lc::viewer; #define PAPER_WIDTH 300 -#define PAPER_HEIGHT 200 +#define PAPER_HEIGHT -200 LCADPaperViewer::LCADPaperViewer(QWidget* parent,int id = 0):LCADViewer(parent),_id(id){ _gradientBackground = std::make_shared(PAPER_WIDTH, PAPER_HEIGHT); @@ -47,4 +47,4 @@ void LCADPaperViewer::setDocument(std::shared_ptr documen void LCADPaperViewer::onMouseMoveEvent(){ emit setActive(_id); -}; \ No newline at end of file +}; diff --git a/lcUI/lcadviewerproxy.cpp b/lcUI/lcadviewerproxy.cpp index f5a400415..2cac4ae0c 100644 --- a/lcUI/lcadviewerproxy.cpp +++ b/lcUI/lcadviewerproxy.cpp @@ -25,6 +25,9 @@ LCADViewerProxy::LCADViewerProxy(QWidget* parent=0){ gridLayout->addWidget(_tabWidget, 0, 0, 1, 1); _tabWidget->addTab(_modelViewerImpl, tr("Model")); + _tabWidget->addTab(_modelViewerImpl, tr("Paper 1"));//Just for init, removed later + _tabWidget->addTab(_modelViewerImpl, tr("Paper 2")); + _paperViewers = new LCADPaperViewerImpl(this); //Connections to receive active View @@ -44,16 +47,19 @@ void LCADViewerProxy::setDocument(std::shared_ptr documen _modelViewerImpl->setDocument(document); _paperViewers->setDocument(document); + _tabWidget->removeTab(1); + _tabWidget->removeTab(1); + //For each block create viewport auto view = document->blockByName("*Paper_Space"); auto x = _paperViewers->getViewer(); x->setDocument(document,view); - _tabWidget->addTab(x,"Paper 1"); + _tabWidget->addTab(x,tr("Paper 1")); view = document->blockByName("*Paper_Space0"); x = _paperViewers->getViewer(); x->setDocument(document,view); - _tabWidget->addTab(x,"Paper 2"); + _tabWidget->addTab(x,tr("Paper 2")); } void LCADViewerProxy::setActive(LCADViewer* view,bool isModel){ @@ -70,4 +76,4 @@ void LCADViewerProxy::setActive(LCADViewer* view,bool isModel){ connect(_activeView, SIGNAL(mouseReleaseEvent()), this, SIGNAL(mouseReleaseEvent())); connect(_activeView, SIGNAL(keyPressEvent(int)), this, SIGNAL(keyPressEvent(int))); } -} \ No newline at end of file +} diff --git a/lcUI/mainwindow.cpp b/lcUI/mainwindow.cpp index eef2b2553..f1819078c 100644 --- a/lcUI/mainwindow.cpp +++ b/lcUI/mainwindow.cpp @@ -170,6 +170,7 @@ void MainWindow::ConnectInputEvents() QObject::connect(findMenuItemByObjectName("actionSelect_All"), &QAction::triggered, this, &MainWindow::selectAll); QObject::connect(findMenuItemByObjectName("actionSelect_None"), &QAction::triggered, this, &MainWindow::selectNone); QObject::connect(findMenuItemByObjectName("actionInvert_Selection"), &QAction::triggered, this, &MainWindow::invertSelection); + QObject::connect(findMenuItemByObjectName("actionClear_Undoable_Stack"), &QAction::triggered, this, &MainWindow::clearUndoableStack); } /* Menu functions */ @@ -541,26 +542,36 @@ void MainWindow::openFile() void MainWindow::undo() { _cadMdiChild.undoManager()->undo(); + _cadMdiChild.viewer()->update(); +} + +void MainWindow::clearUndoableStack() +{ + _cadMdiChild.undoManager()->removeUndoables(); } void MainWindow::redo() { _cadMdiChild.undoManager()->redo(); + _cadMdiChild.viewer()->update(); } void MainWindow::selectAll() { _cadMdiChild.viewer()->docCanvas()->selectAll(); + _cadMdiChild.viewer()->update(); } void MainWindow::selectNone() { _cadMdiChild.viewer()->docCanvas()->removeSelection(); + _cadMdiChild.viewer()->update(); } void MainWindow::invertSelection() { _cadMdiChild.viewer()->docCanvas()->inverseSelection(); + _cadMdiChild.viewer()->update(); } void MainWindow::runCustomizeToolbar() { diff --git a/lcUI/mainwindow.h b/lcUI/mainwindow.h index 4651d8bc5..ecc9eb65e 100644 --- a/lcUI/mainwindow.h +++ b/lcUI/mainwindow.h @@ -181,6 +181,7 @@ namespace lc void selectAll(); void selectNone(); void invertSelection(); + void clearUndoableStack(); // Customize toolbar slots void runCustomizeToolbar(); diff --git a/lcUI/mainwindow.ui b/lcUI/mainwindow.ui index e29f3ebb9..c9afa4a87 100644 --- a/lcUI/mainwindow.ui +++ b/lcUI/mainwindow.ui @@ -157,6 +157,7 @@ + @@ -289,6 +290,11 @@ &Polyline + + + P&oint + + &Spline diff --git a/lcUI/ui/icons/divide.svg b/lcUI/ui/icons/divide.svg new file mode 100644 index 000000000..289d98845 --- /dev/null +++ b/lcUI/ui/icons/divide.svg @@ -0,0 +1,116 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/lcUI/ui/icons/point.svg b/lcUI/ui/icons/point.svg new file mode 100644 index 000000000..6d2374830 --- /dev/null +++ b/lcUI/ui/icons/point.svg @@ -0,0 +1,76 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/lcUI/ui/mainwindow.ui b/lcUI/ui/mainwindow.ui index 33a3bff43..a631c278d 100644 --- a/lcUI/ui/mainwindow.ui +++ b/lcUI/ui/mainwindow.ui @@ -159,6 +159,7 @@ + @@ -294,6 +295,11 @@ &Polyline + + + P&oint + + &Spline diff --git a/lcUI/ui/resource.qrc b/lcUI/ui/resource.qrc index f2c908f69..75a1c74c7 100644 --- a/lcUI/ui/resource.qrc +++ b/lcUI/ui/resource.qrc @@ -31,5 +31,7 @@ icons/snap_grid.svg icons/snap_intersection.svg icons/snap_middle.svg + icons/point.svg + icons/divide.svg diff --git a/lcUILua/actions/copyoperation.lua b/lcUILua/actions/copyoperation.lua index 197d242da..05bd26891 100644 --- a/lcUILua/actions/copyoperation.lua +++ b/lcUILua/actions/copyoperation.lua @@ -100,6 +100,6 @@ function CopyOperation:close() luaInterface:deleteEvent('mouseMove', self) luaInterface:deleteEvent('point', self) - luaInterface:triggerEvent('operationFinished') + luaInterface:triggerEvent('operationFinished', self.widget) end end diff --git a/lcUILua/actions/splitoperation.lua b/lcUILua/actions/splitoperation.lua new file mode 100644 index 000000000..08580c45d --- /dev/null +++ b/lcUILua/actions/splitoperation.lua @@ -0,0 +1,68 @@ +SplitOperation = { + command_line = "SPLIT", + icon = "divide.svg" +} +SplitOperation.__index = SplitOperation + +setmetatable(SplitOperation, { + __index = Operations, + __call = function (o, ...) + local self = setmetatable({}, o) + self:_init(...) + return self + end, +}) + +function SplitOperation:_init(id) + Operations._init(self) + + self.selection = mainWindow:cadMdiChild():selection() + + message(tostring(#self.selection) .. " items selected") + + if(#self.selection == 1) then + self.entity = self.selection[1] + luaInterface:registerEvent('point', self) + message("Give split point") + else + self.finished = true + message('select only one item') + luaInterface:triggerEvent('operationFinished') + end +end + +function SplitOperation:onEvent(eventName, event) + if(eventName == "point" or eventName == "number") then + self:newData(event["position"]) + end +end + +function SplitOperation:newData(point) + local entities = lc.entity.Splitable.splitHelper(self.entity, point) + if(#entities == 0) then + self:close() + return + end + message('sucess') + local b = lc.operation.EntityBuilder(mainWindow:cadMdiChild():document()) + + b:appendEntity(self.entity) + b:appendOperation(lc.operation.Push()) + b:appendOperation(lc.operation.Remove()) + + b:processStack() + for k, entity in pairs(entities) do + b:appendEntity(entity) + end + b:execute() + + self:close() +end + +function SplitOperation:close() + if(not self.finished) then + self.finished = true + luaInterface:deleteEvent('point', self) + luaInterface:triggerEvent('operationFinished') + end +end diff --git a/lcUILua/createActions/createOperations.lua b/lcUILua/createActions/createOperations.lua index dd351b840..c2a49ab37 100644 --- a/lcUILua/createActions/createOperations.lua +++ b/lcUILua/createActions/createOperations.lua @@ -9,7 +9,7 @@ function CreateOperations:_init(builder, step) self.prevEntity = nil if(builder ~= nil) then - self.builder = builder() -- is it working? + self.builder = builder() end self.step = step diff --git a/lcUILua/createActions/pointoperations.lua b/lcUILua/createActions/pointoperations.lua new file mode 100644 index 000000000..63e161496 --- /dev/null +++ b/lcUILua/createActions/pointoperations.lua @@ -0,0 +1,39 @@ +PointOperations = { + command_line = "POINT", + icon = "point.svg", + descreption = "Point", + menu_actions = { + default = "actionPoint" + } +} +PointOperations.__index = PointOperations + +setmetatable(PointOperations, { + __index = CreateOperations, + __call = function (o, ...) + local self = setmetatable({}, o) + self:_init(...) + return self + end, +}) + +function PointOperations:_init() + CreateOperations._init(self, lc.builder.PointBuilder, "enterPoint") + mainWindow:cliCommand():commandActive(true) + message("Add a new point") +end + +--function PointOperations:_init_default() +-- message("POINT") +-- message("Provide Point") +-- self.step = "enterPoint" +--end + +function PointOperations:enterPoint(eventName, data) + if(eventName == "mouseMove") then + self.builder:setCoordinate(data["position"]) + elseif (eventName == "point") then + self.builder:setCoordinate(data["position"]) + self:createEntity() + end +end diff --git a/lcadluascript/bridge/lc_entity.cpp b/lcadluascript/bridge/lc_entity.cpp index 8f26ccc0e..02159b752 100644 --- a/lcadluascript/bridge/lc_entity.cpp +++ b/lcadluascript/bridge/lc_entity.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -22,6 +23,16 @@ #include #include "lc_entity.h" +//Do split if possible +std::vector splitHelper(lc::entity::CADEntity_CSPtr e, lc::geo::Coordinate& p){ + std::vector out; + auto splitable = std::dynamic_pointer_cast(e); + if (splitable){ + return splitable->splitEntity(p); + } + return out; +} + void import_lc_entity_namespace(kaguya::State& state) { state["lc"]["entity"] = kaguya::NewTable(); @@ -58,7 +69,12 @@ void import_lc_entity_namespace(kaguya::State& state) { .addFunction("setDragPoints", &lc::entity::Draggable::setDragPoints) ); - state["lc"]["entity"]["Arc"].setClass(kaguya::UserdataMetatable>() + state["lc"]["entity"]["Splitable"].setClass(kaguya::UserdataMetatable() + .addFunction("splitEntity", &lc::entity::Splitable::splitEntity) + .addStaticFunction("splitHelper", &splitHelper)//Does splitEntity if possible + ); + + state["lc"]["entity"]["Arc"].setClass(kaguya::UserdataMetatable>() .addFunction("accept", &lc::entity::Arc::accept) .addFunction("boundingBox", &lc::entity::Arc::boundingBox) .addFunction("copy", &lc::entity::Arc::copy) @@ -79,7 +95,7 @@ void import_lc_entity_namespace(kaguya::State& state) { .addFunction("lineTangentPointsOnEntity", &lc::entity::Tangentable::lineTangentPointsOnEntity) ); - state["lc"]["entity"]["Circle"].setClass(kaguya::UserdataMetatable>() + state["lc"]["entity"]["Circle"].setClass(kaguya::UserdataMetatable>() .addFunction("accept", &lc::entity::Circle::accept) .addFunction("boundingBox", &lc::entity::Circle::boundingBox) .addFunction("copy", &lc::entity::Circle::copy) @@ -199,7 +215,7 @@ void import_lc_entity_namespace(kaguya::State& state) { .addFunction("setDragPoints", &lc::entity::DimRadial::setDragPoints) ); - state["lc"]["entity"]["Ellipse"].setClass(kaguya::UserdataMetatable>() + state["lc"]["entity"]["Ellipse"].setClass(kaguya::UserdataMetatable>() .addFunction("accept", &lc::entity::Ellipse::accept) .addFunction("boundingBox", &lc::entity::Ellipse::boundingBox) .addFunction("copy", &lc::entity::Ellipse::copy) @@ -214,7 +230,7 @@ void import_lc_entity_namespace(kaguya::State& state) { .addFunction("snapPoints", &lc::entity::Ellipse::snapPoints) ); - state["lc"]["entity"]["Line"].setClass(kaguya::UserdataMetatable>() + state["lc"]["entity"]["Line"].setClass(kaguya::UserdataMetatable>() .addFunction("accept", &lc::entity::Line::accept) .addFunction("boundingBox", &lc::entity::Line::boundingBox) .addFunction("copy", &lc::entity::Line::copy) diff --git a/lckernel/CMakeLists.txt b/lckernel/CMakeLists.txt index 17471f8ce..7af06e122 100644 --- a/lckernel/CMakeLists.txt +++ b/lckernel/CMakeLists.txt @@ -141,6 +141,7 @@ cad/geometry/geobeziercubic.h cad/interface/entitydispatch.h cad/interface/metatype.h cad/interface/snapable.h +cad/interface/splitable.h cad/interface/snapconstrain.h cad/math/lcmath.h cad/math/equation.h diff --git a/lckernel/cad/builders/lwpolyline.cpp b/lckernel/cad/builders/lwpolyline.cpp index d777adc96..de18b4494 100644 --- a/lckernel/cad/builders/lwpolyline.cpp +++ b/lckernel/cad/builders/lwpolyline.cpp @@ -1,6 +1,7 @@ #include "lwpolyline.h" #include "cad/primitive/lwpolyline.h" #include "cad/interface/metatype.h" +#include "cad/math/lcmath.h" #include lc::builder::LWPolylineBuilder::LWPolylineBuilder() @@ -19,23 +20,41 @@ void lc::builder::LWPolylineBuilder::addLineVertex(const lc::geo::Coordinate& ve void lc::builder::LWPolylineBuilder::addArcVertex(const lc::geo::Coordinate& vert) { - _vertices.push_back(lc::builder::LWBuilderVertex(vert, _currentVertex_Bulge)); + int n = _vertices.size(); _currentVertex_Location = vert; + if(n<2){ + _vertices.push_back(lc::builder::LWBuilderVertex(vert, _currentVertex_Bulge)); + return; + } + auto vert1 = _vertices[n - 1]; + auto vert2 = _vertices[n - 2]; + double bulge,angle; + if(vert2.bulge==0){ + angle=-vert2.location.angleTo(vert1.location)+vert1.location.angleTo(vert); + }else{ + angle=-vert2.location.angleTo(vert1.location)+vert1.location.angleTo(vert); + } + //angle=lc::maths::Math::correctAngle(angle); + bulge=(1-cos(angle))/sin(angle); + _vertices[n - 1] = lc::builder::LWBuilderVertex(vert1.location, vert1.startWidth, vert1.endWidth, bulge); + _vertices.push_back(lc::builder::LWBuilderVertex(vert, _currentVertex_Bulge)); } void lc::builder::LWPolylineBuilder::modifyLastVertex(const geo::Coordinate& data) { int n = _vertices.size(); lc::builder::LWBuilderVertex& vert = _vertices[n - 1]; - _currentVertex_Bulge = tan(data.magnitude() / 4); - _vertices[n - 1] = lc::builder::LWBuilderVertex(vert.location, vert.startWidth, vert.endWidth, _currentVertex_Bulge); + //_currentVertex_Bulge = tan(data.magnitude() / 4); + _vertices[n - 1] = lc::builder::LWBuilderVertex(vert.location, vert.startWidth, vert.endWidth, vert.bulge); } void lc::builder::LWPolylineBuilder::modifyLastVertexArc() { int n = _vertices.size(); lc::builder::LWBuilderVertex& vert = _vertices[n - 1]; - _vertices[n - 1] = lc::builder::LWBuilderVertex(vert.location, vert.startWidth, vert.endWidth, _currentVertex_Bulge); + double bulge=vert.bulge; + if(bulge==0)bulge=_currentVertex_Bulge; + _vertices[n - 1] = lc::builder::LWBuilderVertex(vert.location, vert.startWidth, vert.endWidth, bulge); } void lc::builder::LWPolylineBuilder::modifyLastVertexLine() diff --git a/lckernel/cad/geometry/geoarc.cpp b/lckernel/cad/geometry/geoarc.cpp index 9964e20fc..74ef6ddfc 100644 --- a/lckernel/cad/geometry/geoarc.cpp +++ b/lckernel/cad/geometry/geoarc.cpp @@ -8,10 +8,9 @@ Arc::Arc(Coordinate center, double radius, double startAngle, double endAngle, b Base(), _center(std::move(center)), _radius(radius), - _startAngle(maths::Math::correctAngle(startAngle)), - _endAngle(maths::Math::correctAngle(endAngle)), + _startAngle(startAngle), + _endAngle(endAngle), _CCW(isCCW) { - if (radius <= 0.0) { throw std::runtime_error("Invalid radius"); } @@ -169,4 +168,4 @@ double Arc::bulge() const { } return bulge; -} \ No newline at end of file +} diff --git a/lckernel/cad/interface/splitable.h b/lckernel/cad/interface/splitable.h new file mode 100644 index 000000000..166c7d851 --- /dev/null +++ b/lckernel/cad/interface/splitable.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include "cad/geometry/geocoordinate.h" + +namespace lc { + namespace entity { + /** + * Any entity that we can be splitted into multiple entities + * + */ + class Splitable { + public: + virtual std::vector splitEntity(const geo::Coordinate& coord) const = 0; + //@TODO: add function two determine two points are in same side of entity for trim, or maybe lua operation auto removes selected entities + }; + + DECLARE_SHORT_SHARED_PTR(Splitable) + } +} + + diff --git a/lckernel/cad/primitive/arc.cpp b/lckernel/cad/primitive/arc.cpp index 20c8120d8..7324da207 100644 --- a/lckernel/cad/primitive/arc.cpp +++ b/lckernel/cad/primitive/arc.cpp @@ -90,6 +90,22 @@ geo::Coordinate Arc::nearestPointOnPath(const geo::Coordinate &coord) const { return pointOnPath; } +std::vector Arc::splitEntity(const geo::Coordinate& coord) const{ + std::vector out; + auto angle = (coord-center()).angle(); + // check if angle is between start and end + if (abs(coord.distanceTo(this->center())-this->radius()) < LCTOLERANCE) + if (isAngleBetween(angle)){ + auto newArc = std::make_shared(this->center(), this->radius(), this->startAngle(), angle, + this->CCW(), layer(), metaInfo(), block()); + out.push_back(newArc); + newArc = std::make_shared(this->center(), this->radius(), angle, this->endAngle(), + this->CCW(), layer(), metaInfo(), block()); + out.push_back(newArc); + } + return out; +} + CADEntity_CSPtr Arc::move(const geo::Coordinate &offset) const { auto newArc = std::make_shared(this->center() + offset, this->radius(), this->startAngle(), this->endAngle(), this->CCW(), layer(), metaInfo(), block()); @@ -157,7 +173,7 @@ std::map Arc::dragPoints() const { CADEntity_CSPtr Arc::setDragPoints(std::map dragPoints) const { try { - auto newEntity = std::make_shared(geo::Arc::createArcBulge(dragPoints.at(0), dragPoints.at(1), bulge()), layer(), metaInfo()); + auto newEntity = std::make_shared(geo::Arc::createArcBulge(dragPoints.at(0), dragPoints.at(1), CCW()), layer(), metaInfo()); newEntity->setID(id()); return newEntity; } diff --git a/lckernel/cad/primitive/arc.h b/lckernel/cad/primitive/arc.h index 6ee97c778..0d2cf3f53 100644 --- a/lckernel/cad/primitive/arc.h +++ b/lckernel/cad/primitive/arc.h @@ -4,6 +4,7 @@ #include "cad/const.h" #include "cad/interface/entitydispatch.h" #include "cad/interface/snapable.h" +#include "cad/interface/splitable.h" #include "cad/geometry/geocoordinate.h" #include "cad/geometry/geoarc.h" #include "cad/base/cadentity.h" @@ -16,7 +17,7 @@ namespace lc { namespace entity { - class Arc : public std::enable_shared_from_this, public CADEntity, public geo::Arc, public Snapable, public Draggable { + class Arc : public std::enable_shared_from_this, public CADEntity, public geo::Arc, public Snapable, public Draggable, public Splitable{ friend class builder::ArcBuilder; public: @@ -89,6 +90,7 @@ namespace lc { int maxNumberOfSnapPoints) const override; virtual geo::Coordinate nearestPointOnPath(const geo::Coordinate &coord) const override; + virtual std::vector splitEntity(const geo::Coordinate& coord) const; public: virtual void accept(GeoEntityVisitor &v) const override { v.visit(*this); } @@ -106,4 +108,4 @@ namespace lc { DECLARE_SHORT_SHARED_PTR(Arc) } -} \ No newline at end of file +} diff --git a/lckernel/cad/primitive/circle.cpp b/lckernel/cad/primitive/circle.cpp index c255c6726..1e44d0a8d 100644 --- a/lckernel/cad/primitive/circle.cpp +++ b/lckernel/cad/primitive/circle.cpp @@ -2,6 +2,7 @@ #include #include #include "cad/interface/metatype.h" +#include "arc.h" using namespace lc; using namespace entity; @@ -63,6 +64,17 @@ geo::Coordinate Circle::nearestPointOnPath(const geo::Coordinate &coord) const { return geo::Circle::nearestPointOnPath(coord); } +std::vector Circle::splitEntity(const geo::Coordinate& coord) const{ + std::vector out; + auto angle = (coord-center()).angle(); + if (abs(coord.distanceTo(this->center())-this->radius()) < LCTOLERANCE){ + auto newArc = std::make_shared(this->center(), this->radius(), angle+LCTOLERANCE, angle+2*M_PI-LCTOLERANCE, + true, layer(), metaInfo(), block()); + out.push_back(newArc); + } + return out; +} + CADEntity_CSPtr Circle::move(const geo::Coordinate &offset) const { auto newCircle = std::make_shared(this->center() + offset, this->radius(), layer(), metaInfo(), block()); newCircle->setID(this->id()); diff --git a/lckernel/cad/primitive/circle.h b/lckernel/cad/primitive/circle.h index a06da4253..fc48a3cff 100644 --- a/lckernel/cad/primitive/circle.h +++ b/lckernel/cad/primitive/circle.h @@ -9,6 +9,7 @@ #include "cad/base/cadentity.h" #include "cad/vo/entitycoordinate.h" #include "cad/interface/snapable.h" +#include "cad/interface/splitable.h" #include namespace lc { @@ -17,7 +18,8 @@ namespace lc { class Circle : public std::enable_shared_from_this, public CADEntity, public geo::Circle, - public Snapable { + public Snapable, + public Splitable { friend class builder::CircleBuilder; public: @@ -41,6 +43,7 @@ namespace lc { int maxNumberOfSnapPoints) const override; virtual geo::Coordinate nearestPointOnPath(const geo::Coordinate &coord) const override; + virtual std::vector splitEntity(const geo::Coordinate& coord) const; public: /** diff --git a/lckernel/cad/primitive/ellipse.cpp b/lckernel/cad/primitive/ellipse.cpp index ddf673a2c..fa083623b 100644 --- a/lckernel/cad/primitive/ellipse.cpp +++ b/lckernel/cad/primitive/ellipse.cpp @@ -311,5 +311,31 @@ geo::Coordinate Ellipse::nearestPointOnPath(const geo::Coordinate &coord) const return geo::Ellipse::nearestPointOnPath(coord); } - - +std::vector Ellipse::splitEntity(const geo::Coordinate& coord) const{ + std::vector out; + auto angle = (coord-center()).angle(); + auto nearestPoint = this->nearestPointOnPath(coord); + if(nearestPoint.distanceTo(coord)(this->center(), + this->majorP(), + this->minorRadius(), + this->startAngle(), angle, + isReversed(), + layer(), + metaInfo(), + block()); + out.push_back(newellipse); + newellipse = std::make_shared(this->center(), + this->majorP(), + this->minorRadius(), + angle, this->endAngle(), + isReversed(), + layer(), + metaInfo(), + block()); + + out.push_back(newellipse); + } + return out; +} diff --git a/lckernel/cad/primitive/ellipse.h b/lckernel/cad/primitive/ellipse.h index 54331b50b..706443603 100644 --- a/lckernel/cad/primitive/ellipse.h +++ b/lckernel/cad/primitive/ellipse.h @@ -3,6 +3,7 @@ #include "cad/const.h" #include "cad/interface/entitydispatch.h" #include +#include "cad/interface/splitable.h" #include "cad/geometry/geocoordinate.h" #include "cad/geometry/geoellipse.h" @@ -28,7 +29,8 @@ namespace lc { class Ellipse : public std::enable_shared_from_this, public CADEntity, public geo::Ellipse, - public Snapable { + public Snapable, + public Splitable { friend class builder::EllipseBuilder; public: /** @@ -120,6 +122,7 @@ namespace lc { int maxNumberOfSnapPoints) const override; virtual geo::Coordinate nearestPointOnPath(const geo::Coordinate &coord) const override; + virtual std::vector splitEntity(const geo::Coordinate& coord) const; public: virtual void accept(GeoEntityVisitor &v) const override { v.visit(*this); } diff --git a/lckernel/cad/primitive/hatch.cpp b/lckernel/cad/primitive/hatch.cpp index 589ff49a7..997e89182 100644 --- a/lckernel/cad/primitive/hatch.cpp +++ b/lckernel/cad/primitive/hatch.cpp @@ -19,42 +19,111 @@ Hatch::Hatch(const Hatch_CSPtr& other, bool sameID) : CADEntity(other, sameID){ CADEntity_CSPtr Hatch::move(const geo::Coordinate &offset) const { auto newHatch = std::make_shared(layer(), metaInfo(), block()); + + for(auto &x:_loopList){ + auto m = std::make_shared(); + for(auto &y:x->objList){ + m->objList.push_back(y->move(offset)); + } + newHatch->_loopList.push_back(m); + } + newHatch->calculateBoundingBox(); + newHatch->setID(this->id()); return newHatch; } CADEntity_CSPtr Hatch::copy(const geo::Coordinate &offset) const { auto newHatch = std::make_shared(layer(), metaInfo(), block()); + + for(auto &x:_loopList){ + auto m = std::make_shared(); + for(auto &y:x->objList){ + m->objList.push_back(y->copy(offset)); + } + newHatch->_loopList.push_back(m); + } + newHatch->calculateBoundingBox(); + return newHatch; } CADEntity_CSPtr Hatch::rotate(const geo::Coordinate &rotation_center, const double rotation_angle) const { auto newHatch = std::make_shared(layer(), metaInfo(), block()); + + for(auto &x:_loopList){ + auto m = std::make_shared(); + for(auto &y:x->objList){ + m->objList.push_back(y->rotate(rotation_center, rotation_angle)); + } + newHatch->_loopList.push_back(m); + } + newHatch->calculateBoundingBox(); + newHatch->setID(this->id()); return newHatch; } CADEntity_CSPtr Hatch::scale(const geo::Coordinate &scale_center, const geo::Coordinate &scale_factor) const { auto newHatch = std::make_shared(layer(), metaInfo(), block()); + + for(auto &x:_loopList){ + auto m = std::make_shared(); + for(auto &y:x->objList){ + m->objList.push_back(y->scale(scale_center,scale_factor)); + } + newHatch->_loopList.push_back(m); + } + newHatch->calculateBoundingBox(); + + newHatch->setID(this->id()); return newHatch; } CADEntity_CSPtr Hatch::mirror(const geo::Coordinate &axis1, const geo::Coordinate &axis2) const { auto newHatch = std::make_shared(layer(), metaInfo(), block()); + + for(auto &x:_loopList){ + auto m = std::make_shared(); + for(auto &y:x->objList){ + m->objList.push_back(y->mirror(axis1,axis2)); + } + newHatch->_loopList.push_back(m); + } + newHatch->calculateBoundingBox(); + + return newHatch; } const geo::Area Hatch::boundingBox() const { - return geo::Area(geo::Coordinate(),geo::Coordinate()); + return _boundingBox; } CADEntity_CSPtr Hatch::modify(meta::Layer_CSPtr layer, const meta::MetaInfo_CSPtr metaInfo, meta::Block_CSPtr block) const { auto newHatch = std::make_shared(layer, metaInfo,block); + + for(auto &x:_loopList){ + auto m = std::make_shared(); + for(auto &y:x->objList){ + m->objList.push_back(y); + } + newHatch->_loopList.push_back(m); + } + newHatch->calculateBoundingBox(); + + newHatch->setID(this->id()); return newHatch; } -void Hatch::addLoop(std::shared_ptr lp){ - _loopList.push_back(lp); +void Hatch::calculateBoundingBox(){ + _boundingBox = geo::Area(geo::Coordinate(),geo::Coordinate()); + //Merge box of each entities + for(auto &x:_loopList){ + for(auto &y:x->objList){ + _boundingBox = _boundingBox.merge(y->boundingBox()); + } + } } diff --git a/lckernel/cad/primitive/hatch.h b/lckernel/cad/primitive/hatch.h index 62cb1417f..754ce58d8 100644 --- a/lckernel/cad/primitive/hatch.h +++ b/lckernel/cad/primitive/hatch.h @@ -8,12 +8,17 @@ #include "cad/base/cadentity.h" #include "cad/vo/entitycoordinate.h" + + namespace lc { namespace entity { - struct HatchLoop - { - std::vector objList; - }; + struct HatchLoop{ + std::vector objList; + }; + + DECLARE_SHORT_SHARED_PTR(HatchLoop); + + class Hatch : public std::enable_shared_from_this, public CADEntity{ public: @@ -53,10 +58,9 @@ namespace lc { double _angle; /*!< hatch pattern angle, code 52 */ double _scale; /*!< hatch pattern scale, code 41 */ int _deflines; /*!< number of pattern definition lines, code 78 */ - - std::vector > _loopList; /*!< polyline list */ + geo::Area _boundingBox; //Bounding box for hatch public: - void addLoop(std::shared_ptr lp); + std::vector _loopList; /*!< polyline list */ void setPatternName(std::string name){_name = name;}; void setSolid(int solid){_solid = solid;}; // int _associative; /*!< associativity, code 71, associatve=1, non-assoc.=0 */ @@ -66,6 +70,7 @@ namespace lc { // int _loopsnum; /*!< namber of boundary paths (loops), code 91 */ void setAngle(double angle){_angle = angle;}; void setScale(double scale){_scale = scale;}; + void calculateBoundingBox(); }; DECLARE_SHORT_SHARED_PTR(Hatch) } diff --git a/lckernel/cad/primitive/line.cpp b/lckernel/cad/primitive/line.cpp index a2b64a418..0b4ad889e 100644 --- a/lckernel/cad/primitive/line.cpp +++ b/lckernel/cad/primitive/line.cpp @@ -66,6 +66,29 @@ geo::Coordinate Line::nearestPointOnPath(const geo::Coordinate& coord) const { return geo::Vector::nearestPointOnPath(coord); } +std::vector Line::splitEntity(const geo::Coordinate& coord) const{ + std::vector out; + auto nearestPoint = this->nearestPointOnPath(coord); + if(nearestPoint.distanceTo(coord)start() && nearestPoint!=this->end()){ + auto newLine = std::make_shared(this->start(), + nearestPoint, + layer(), + metaInfo(), + block() + ); + out.push_back(newLine); + newLine = std::make_shared(nearestPoint, + this->end(), + layer(), + metaInfo(), + block() + ); + out.push_back(newLine); + } + return out; +} + CADEntity_CSPtr Line::move(const geo::Coordinate& offset) const { auto newLine = std::make_shared(this->start() + offset, this->end() + offset, @@ -158,4 +181,4 @@ CADEntity_CSPtr Line::setDragPoints(std::map //A point was not in the map, don't change the entity return shared_from_this(); } -} \ No newline at end of file +} diff --git a/lckernel/cad/primitive/line.h b/lckernel/cad/primitive/line.h index cc0758be0..c44a4565d 100644 --- a/lckernel/cad/primitive/line.h +++ b/lckernel/cad/primitive/line.h @@ -9,6 +9,7 @@ #include "cad/geometry/geocoordinate.h" #include "cad/geometry/geovector.h" #include "cad/interface/snapable.h" +#include "cad/interface/splitable.h" #include "cad/interface/draggable.h" #include "cad/vo/entitycoordinate.h" #include "cad/meta/layer.h" @@ -29,7 +30,8 @@ namespace lc { public CADEntity, public geo::Vector, public Snapable, - public Draggable { + public Draggable, + public Splitable { friend class builder::LineBuilder; public: @@ -74,6 +76,7 @@ namespace lc { virtual std::map dragPoints() const override; virtual CADEntity_CSPtr setDragPoints(std::map dragPoints) const override; + virtual std::vector splitEntity(const geo::Coordinate& coord) const; /** * @brief move, moves by an offset @@ -130,4 +133,4 @@ namespace lc { DECLARE_SHORT_SHARED_PTR(Line) } -} \ No newline at end of file +} diff --git a/lckernel/cad/primitive/lwpolyline.h b/lckernel/cad/primitive/lwpolyline.h index e02f507c5..43bdf2610 100644 --- a/lckernel/cad/primitive/lwpolyline.h +++ b/lckernel/cad/primitive/lwpolyline.h @@ -243,4 +243,4 @@ namespace lc { DECLARE_SHORT_SHARED_PTR(LWPolyline) } -} \ No newline at end of file +} diff --git a/lckernel/cad/primitive/point.cpp b/lckernel/cad/primitive/point.cpp index bf7d6114e..69939c781 100644 --- a/lckernel/cad/primitive/point.cpp +++ b/lckernel/cad/primitive/point.cpp @@ -71,4 +71,47 @@ CADEntity_CSPtr Point::modify(meta::Layer_CSPtr layer, const meta::MetaInfo_CSPt return newEntity; } +// additional options +geo::Coordinate Point::nearestPointOnPath(const Coordinate& coord) const { + return geo::Coordinate(this->x(), this->y()); +} + +geo::Coordinate Point::nearestPointOnEntity(const Coordinate& coord) const { + return geo::Coordinate(this->x(), this->y()); +} + + +std::vector Point::snapPoints(const geo::Coordinate& coord, + const SimpleSnapConstrain & constrain, + double minDistanceToSnap, + int maxNumberOfSnapPoints) const { + std::vector points; + if ((bool) (constrain.constrain() & SimpleSnapConstrain::LOGICAL)) { + points.emplace_back(geo::Coordinate(this->x(), this->y()),0); + } + Snapable::snapPointsCleanup(points, coord, maxNumberOfSnapPoints, minDistanceToSnap); + return points; +} + +std::map Point::dragPoints() const { + std::map points; + points[0]=(geo::Coordinate(this->x(), this->y())); + return points; +} + +CADEntity_CSPtr Point::setDragPoints(std::map dragPoints) const { + try { + auto newEntity = std::make_shared(dragPoints.at(0), + layer(), + metaInfo(), + block() + ); + newEntity->setID(this->id()); + return newEntity; + } + catch(const std::out_of_range& e) { + //A point was not in the map, don't change the entity + return shared_from_this(); + } +} diff --git a/lckernel/cad/primitive/point.h b/lckernel/cad/primitive/point.h index cc49658ce..afa46c7aa 100644 --- a/lckernel/cad/primitive/point.h +++ b/lckernel/cad/primitive/point.h @@ -8,13 +8,16 @@ #include "cad/base/cadentity.h" #include "cad/vo/entitycoordinate.h" +#include "cad/interface/snapable.h" +#include "cad/interface/draggable.h" + #include #include namespace lc { namespace entity { - class Point : public std::enable_shared_from_this, public CADEntity, public geo::Coordinate, virtual public Visitable { + class Point : public std::enable_shared_from_this, public CADEntity, public geo::Coordinate, public Snapable, public Draggable, virtual public Visitable { friend class builder::PointBuilder; public: @@ -87,6 +90,15 @@ namespace lc { virtual CADEntity_CSPtr modify(meta::Layer_CSPtr layer, meta::MetaInfo_CSPtr metaInfo, meta::Block_CSPtr block) const override; + std::vector snapPoints(const geo::Coordinate &coord, + const SimpleSnapConstrain& constrain, + double minDistanceToSnap, + int maxNumberOfSnapPoints) const override; + std::map dragPoints() const override; + CADEntity_CSPtr setDragPoints(std::map dragPoints) const override; + geo::Coordinate nearestPointOnPath(const Coordinate& coord) const; + geo::Coordinate nearestPointOnEntity(const Coordinate& coord) const; + public: virtual void accept(GeoEntityVisitor &v) const override { v.visit(*this); } diff --git a/lckernel/cad/storage/documentimpl.cpp b/lckernel/cad/storage/documentimpl.cpp index 4a3ed5d8d..0095014d4 100644 --- a/lckernel/cad/storage/documentimpl.cpp +++ b/lckernel/cad/storage/documentimpl.cpp @@ -13,6 +13,9 @@ DocumentImpl::DocumentImpl(StorageManager_SPtr storageManager) : Document() , _storageManager(std::move(storageManager)) { _storageManager->addDocumentMetaType(std::make_shared("0", meta::MetaLineWidthByValue(1.0), Color(255, 255, 255))); + //Add papers too + _storageManager->addDocumentMetaType(std::make_shared("*Paper_Space", geo::Coordinate())); + _storageManager->addDocumentMetaType(std::make_shared("*Paper_Space0", geo::Coordinate())); } void DocumentImpl::execute(const operation::DocumentOperation_SPtr& operation) { @@ -160,11 +163,6 @@ std::map DocumentImpl::allLayers() const { lc::meta::Layer_CSPtr DocumentImpl::layerByName(const std::string& layerName) const { auto x = _storageManager->layerByName(layerName); - if (x==nullptr){ - //If layer not found create one - x=std::make_shared(layerName, meta::MetaLineWidthByValue(1.0), Color(255, 255, 255)); - _storageManager->addDocumentMetaType(x); - } return x; } @@ -173,11 +171,6 @@ lc::meta::Block_CSPtr DocumentImpl::blockByName(const std::string& blockName) co return nullptr; } auto x = _storageManager->blockByName(blockName); - if (x==nullptr){ - //If block not found create one - x=std::make_shared(blockName); - _storageManager->addDocumentMetaType(x); - } return x; } diff --git a/lckernel/tinyspline b/lckernel/tinyspline index 8b809ac02..f8b1ab7ec 160000 --- a/lckernel/tinyspline +++ b/lckernel/tinyspline @@ -1 +1 @@ -Subproject commit 8b809ac026d542933723221f6124d15f0d4a44f5 +Subproject commit f8b1ab7ec2a2bf43220044fe32c9869a5f6c3469 diff --git a/lcviewernoqt/documentcanvas.cpp b/lcviewernoqt/documentcanvas.cpp index 03edd5639..e23480789 100644 --- a/lcviewernoqt/documentcanvas.cpp +++ b/lcviewernoqt/documentcanvas.cpp @@ -220,7 +220,7 @@ void DocumentCanvas::render(LcPainter& painter, PainterType type) { } }); for(const auto& di: visibleDrawables) { - if(painter.isCachingEnabled() ) + if(painter.isCachingEnabled() && di->cacheable()) { if(painter.isEntityCached( (di->entity())->id() ) == true) { @@ -229,7 +229,7 @@ void DocumentCanvas::render(LcPainter& painter, PainterType type) { else { drawEntity(painter, di); - cacheEntity((di->entity())->id(), di); + cacheEntity((di->entity())->id(), di); } } else @@ -688,8 +688,11 @@ LCVDrawItem_SPtr DocumentCanvas::asDrawable(const lc::entity::CADEntity_CSPtr& e // Add 'Point' or 'Coordinate' auto coord = std::dynamic_pointer_cast(entity); + // Point cannot be cached since it change size(constant size) if (coord != nullptr) { - return std::make_shared(coord); + auto di = std::make_shared(coord); + di->cacheable(false); + return di; } // Add 'DimRadial' diff --git a/lcviewernoqt/drawitems/lclwpolyline.cpp b/lcviewernoqt/drawitems/lclwpolyline.cpp index 53f02c64d..da3ac8451 100644 --- a/lcviewernoqt/drawitems/lclwpolyline.cpp +++ b/lcviewernoqt/drawitems/lclwpolyline.cpp @@ -16,7 +16,9 @@ LCLWPolyline::LCLWPolyline(const lc::entity::LWPolyline_CSPtr& lwpolyline) : } void LCLWPolyline::draw(LcPainter &painter, const LcDrawOptions &options, const lc::geo::Area &rect) const { - for(const auto& drawItem : _drawItems) { + bool autoStroke = autostroke(); + for(auto drawItem : _drawItems) { + drawItem->autostroke(autoStroke); drawItem->draw(painter, options, rect); } } diff --git a/lcviewernoqt/drawitems/lclwpolyline.h b/lcviewernoqt/drawitems/lclwpolyline.h index 7936aaa6e..a88e29a2c 100644 --- a/lcviewernoqt/drawitems/lclwpolyline.h +++ b/lcviewernoqt/drawitems/lclwpolyline.h @@ -23,7 +23,7 @@ namespace lc { private: lc::entity::LWPolyline_CSPtr _polyLine; - std::vector _drawItems; + std::vector _drawItems; }; } } diff --git a/lcviewernoqt/drawitems/lcvarc.cpp b/lcviewernoqt/drawitems/lcvarc.cpp index 0edf27ccc..4678de044 100644 --- a/lcviewernoqt/drawitems/lcvarc.cpp +++ b/lcviewernoqt/drawitems/lcvarc.cpp @@ -16,7 +16,8 @@ void LCVArc::draw(LcPainter& painter, const LcDrawOptions &options, const lc::ge } else { painter.arc(_arc->center().x(), _arc->center().y(), _arc->radius(), _arc->startAngle(), _arc->endAngle()); } - painter.stroke(); + if(autostroke()) + painter.stroke(); } } diff --git a/lcviewernoqt/drawitems/lcvcircle.cpp b/lcviewernoqt/drawitems/lcvcircle.cpp index a3c90e44f..c3f25150f 100644 --- a/lcviewernoqt/drawitems/lcvcircle.cpp +++ b/lcviewernoqt/drawitems/lcvcircle.cpp @@ -12,7 +12,8 @@ LCVCircle::LCVCircle(const lc::entity::Circle_CSPtr& circle) : void LCVCircle::draw(LcPainter& painter, const LcDrawOptions &options, const lc::geo::Area& rect) const { if (_circle->radius() != 0) { painter.circle(_circle->center().x(), _circle->center().y(), _circle->radius()); - painter.stroke(); + if(autostroke()) + painter.stroke(); } } diff --git a/lcviewernoqt/drawitems/lcvdrawitem.cpp b/lcviewernoqt/drawitems/lcvdrawitem.cpp index 58c7115a5..d55c47840 100644 --- a/lcviewernoqt/drawitems/lcvdrawitem.cpp +++ b/lcviewernoqt/drawitems/lcvdrawitem.cpp @@ -4,8 +4,9 @@ using namespace lc::viewer; LCVDrawItem::LCVDrawItem(const lc::entity::CADEntity_CSPtr& entity, bool selectable) : _selectable(selectable), - _selected(false) { - + _selected(false), + _cacheable(true), + _autostroke(true) { } bool LCVDrawItem::selectable() const { @@ -19,3 +20,20 @@ bool LCVDrawItem::selected() const { void LCVDrawItem::selected(bool selected) { _selected = selected; } + +bool LCVDrawItem::cacheable() const { + return _cacheable; +} + +void LCVDrawItem::cacheable(bool cache) { + _cacheable = cache; +} + +bool LCVDrawItem::autostroke() const { + return _autostroke; +} + +void LCVDrawItem::autostroke(bool stroke) { + _autostroke = stroke; +} + diff --git a/lcviewernoqt/drawitems/lcvdrawitem.h b/lcviewernoqt/drawitems/lcvdrawitem.h index f41f7e9f7..4fac13494 100644 --- a/lcviewernoqt/drawitems/lcvdrawitem.h +++ b/lcviewernoqt/drawitems/lcvdrawitem.h @@ -37,6 +37,12 @@ namespace lc { virtual void selected(bool selected); + bool cacheable() const; + void cacheable(bool selected); + + bool autostroke() const; + void autostroke(bool stroke); + /** * @brief Return the entity which is drawn * @return Entity @@ -46,6 +52,8 @@ namespace lc { private: bool _selectable; bool _selected; + bool _cacheable; + bool _autostroke; }; DECLARE_SHORT_SHARED_PTR(LCVDrawItem) diff --git a/lcviewernoqt/drawitems/lcvellipse.cpp b/lcviewernoqt/drawitems/lcvellipse.cpp index 3a81794f9..3a55ab526 100644 --- a/lcviewernoqt/drawitems/lcvellipse.cpp +++ b/lcviewernoqt/drawitems/lcvellipse.cpp @@ -17,7 +17,8 @@ void LCVEllipse::draw(LcPainter& painter, const LcDrawOptions &options, const lc _ellipse->startAngle(), _ellipse->endAngle(), _ellipse->getAngle() ); - painter.stroke(); + if(autostroke()) + painter.stroke(); } } diff --git a/lcviewernoqt/drawitems/lcvhatch.cpp b/lcviewernoqt/drawitems/lcvhatch.cpp index c50ece67c..a0f7f7857 100644 --- a/lcviewernoqt/drawitems/lcvhatch.cpp +++ b/lcviewernoqt/drawitems/lcvhatch.cpp @@ -1,20 +1,40 @@ #include "lcvhatch.h" #include "../painters/lcpainter.h" #include "../lcdrawoptions.h" +#include "cad/primitive/arc.h" +#include "cad/primitive/line.h" +#include "cad/primitive/ellipse.h" +#include "cad/primitive/spline.h" +#include "cad/primitive/lwpolyline.h" +#include using namespace lc::viewer; LCVHatch::LCVHatch(const lc::entity::Hatch_CSPtr& hatch) : LCVDrawItem(hatch, true), _hatch(hatch) { + for(auto &x:_hatch->_loopList){ + for(auto &y:x->objList){ + auto di = DocumentCanvas::asDrawable(y); + di->autostroke(false); + _drawItems.push_back(di); + } + _drawItems.push_back(nullptr); + } } void LCVHatch::draw(LcPainter& painter, const LcDrawOptions &options, const lc::geo::Area& rect) const { - painter.circle(0, 0, 20); + for(const auto& drawItem : _drawItems) { + if(drawItem){ + drawItem->draw(painter, options, rect); + }else{ + painter.close_path(); + painter.fill(); + } + } painter.fill(); } lc::entity::CADEntity_CSPtr LCVHatch::entity() const { return _hatch; } - diff --git a/lcviewernoqt/drawitems/lcvhatch.h b/lcviewernoqt/drawitems/lcvhatch.h index a410fa45d..bf0cc78cd 100644 --- a/lcviewernoqt/drawitems/lcvhatch.h +++ b/lcviewernoqt/drawitems/lcvhatch.h @@ -26,6 +26,7 @@ namespace lc { private: lc::entity::Hatch_CSPtr _hatch; + std::vector _drawItems; }; } } diff --git a/lcviewernoqt/drawitems/lcvline.cpp b/lcviewernoqt/drawitems/lcvline.cpp index ea8c7c9c9..1f8587316 100644 --- a/lcviewernoqt/drawitems/lcvline.cpp +++ b/lcviewernoqt/drawitems/lcvline.cpp @@ -18,7 +18,8 @@ LCVLine::LCVLine(const lc::entity::Line_CSPtr& line) : void LCVLine::draw(LcPainter& painter, const LcDrawOptions &options, const lc::geo::Area& rect) const { painter.move_to(_line->start().x(), _line->start().y()); painter.line_to(_line->end().x(), _line->end().y()); - painter.stroke(); + if(autostroke()) + painter.stroke(); } lc::entity::CADEntity_CSPtr LCVLine::entity() const { diff --git a/lcviewernoqt/drawitems/lcvpoint.cpp b/lcviewernoqt/drawitems/lcvpoint.cpp index a8fcc19aa..07677b2b3 100644 --- a/lcviewernoqt/drawitems/lcvpoint.cpp +++ b/lcviewernoqt/drawitems/lcvpoint.cpp @@ -10,8 +10,8 @@ LCVPoint::LCVPoint(const lc::entity::Point_CSPtr& coordinate) : } void LCVPoint::draw(LcPainter& painter, const LcDrawOptions &options, const lc::geo::Area& rect) const { - painter.point(_point->x(), _point->y(), 3., true); - painter.stroke(); + painter.point(_point->x(), _point->y(), 3., true); //This actually strokes circle + painter.fill(); //fill method is not working in openGL painter } lc::entity::CADEntity_CSPtr LCVPoint::entity() const { diff --git a/lcviewernoqt/drawitems/lcvspline.cpp b/lcviewernoqt/drawitems/lcvspline.cpp index 8cb194ece..902494e6c 100644 --- a/lcviewernoqt/drawitems/lcvspline.cpp +++ b/lcviewernoqt/drawitems/lcvspline.cpp @@ -26,7 +26,8 @@ void LCVSpline::draw(LcPainter &painter, const LcDrawOptions &options, const lc: painter.line_to(bez[1].x(), bez[1].y()); } } - painter.stroke(); + if(autostroke()) + painter.stroke(); } lc::entity::CADEntity_CSPtr LCVSpline::entity() const { diff --git a/lcviewernoqt/painters/opengl/manager.h b/lcviewernoqt/painters/opengl/manager.h index 33588be17..f4d606fc3 100644 --- a/lcviewernoqt/painters/opengl/manager.h +++ b/lcviewernoqt/painters/opengl/manager.h @@ -85,8 +85,9 @@ namespace lc //----------------Functions adding data to entity-------------------------------- void setDefault(); void addDataToCurrentEntity(); + inline bool isNew(){return _current_vertices.size()==0;}; }; } } } -#endif // MANAGER_H \ No newline at end of file +#endif // MANAGER_H diff --git a/lcviewernoqt/painters/opengl/openglpainter.cpp b/lcviewernoqt/painters/opengl/openglpainter.cpp index d31de85fd..d85c19641 100644 --- a/lcviewernoqt/painters/opengl/openglpainter.cpp +++ b/lcviewernoqt/painters/opengl/openglpainter.cpp @@ -11,13 +11,28 @@ void OpenglPainter::set_manager(Manager* manager) void OpenglPainter::move_to(double x, double y) { + if(abs(_pen_x-x)>BBHEURISTIC2 || abs(_pen_y-y)>BBHEURISTIC2 || _manager->isNew()){ _manager->jump(); _manager->addVertex(x,y); _pen_x=x; _pen_y=y; + } } void OpenglPainter::point(double x, double y, double size, bool deviceCoords) { + if (deviceCoords){ + double x = size; + double y = size; + + double zeroCornerX = 0.; + double zeroCornerY = 0.; + + device_to_user(&zeroCornerX, &zeroCornerY); + device_to_user(&x, &y); + + size = (x - zeroCornerX); + } + circle(x,y,size); } void OpenglPainter::line_to(double x, double y) @@ -31,7 +46,7 @@ void OpenglPainter::arc(double x, double y, double r, double start, double end) if(startjump(); + //_manager->jump(); float delta=(std::abs(end-start)); float angle=0; @@ -41,7 +56,7 @@ void OpenglPainter::arc(double x, double y, double r, double start, double end) { angle=start - ( ((float)i)/points)*(delta) ; - _manager->addVertex( (x+r*cos(angle)) , (y+r*sin(angle)) ); + _manager->addVertex( (_pen_x=x+r*cos(angle)) , (_pen_y=y+r*sin(angle)) ); } } @@ -50,7 +65,7 @@ void OpenglPainter::arcNegative(double x, double y, double r, double start, doub if(start>end) end+=2*PI; - _manager->jump(); + //_manager->jump(); float delta=(std::abs(end-start)); float angle=0; @@ -59,7 +74,7 @@ void OpenglPainter::arcNegative(double x, double y, double r, double start, doub for(int i=0;iaddVertex( (x+r*cos(angle)) , (y+r*sin(angle)) ); + _manager->addVertex( (_pen_x=x+r*cos(angle)) , (_pen_y=y+r*sin(angle)) ); } } @@ -174,6 +189,7 @@ void OpenglPainter::close_path() void OpenglPainter::fill() { _manager->selectFill(); + stroke(); } void OpenglPainter::new_path() @@ -211,4 +227,4 @@ void OpenglPainter::set_dash(const double* dashes, const int num_dashes, double void OpenglPainter::dash_destroy() { _manager->selectDashes(NULL,0,0,false); -} \ No newline at end of file +} diff --git a/persistence/libdxfrw/dxfimpl.cpp b/persistence/libdxfrw/dxfimpl.cpp index 5dec07323..236cdda45 100644 --- a/persistence/libdxfrw/dxfimpl.cpp +++ b/persistence/libdxfrw/dxfimpl.cpp @@ -149,7 +149,7 @@ void DXFimpl::addBlock(const DRW_Block& data) { } _builder->append(std::make_shared(_document, _currentBlock)); - _blocks.insert(std::pair(data.name, _currentBlock)); + // May need to check if the block already exists: not sure _handleBlock.insert(std::pair(data.parentHandle, _currentBlock)); } @@ -164,7 +164,7 @@ void DXFimpl::addLine(const DRW_Line& data) { builder.setMetaInfo(getMetaInfo(data)); builder.setBlock(getBlock(data)); - builder.setLayer(_document->layerByName(data.layer)); + builder.setLayer(getLayer(data)); builder.setStart(coord(data.basePoint)); builder.setEnd(coord(data.secPoint)); @@ -177,7 +177,7 @@ void DXFimpl::addCircle(const DRW_Circle& data) { lc::builder::CircleBuilder builder; builder.setMetaInfo(getMetaInfo(data)); - builder.setLayer(_document->layerByName(data.layer)); + builder.setLayer(getLayer(data)); builder.setCenter(coord(data.basePoint)); builder.setRadius(data.radious); builder.setBlock(getBlock(data)); @@ -190,7 +190,7 @@ void DXFimpl::addArc(const DRW_Arc& data) { lc::builder::ArcBuilder builder; builder.setMetaInfo(getMetaInfo(data)); - builder.setLayer(_document->layerByName(data.layer)); + builder.setLayer(getLayer(data)); builder.setBlock(getBlock(data)); builder.setCenter(coord(data.basePoint)); builder.setRadius(data.radious); @@ -204,7 +204,7 @@ void DXFimpl::addArc(const DRW_Arc& data) { void DXFimpl::addEllipse(const DRW_Ellipse& data) { LOG_WARNING << "addEllipse"; std::shared_ptr mf = getMetaInfo(data); - auto layer = _document->layerByName(data.layer); + auto layer = getLayer(data); auto secPoint = coord(data.secPoint); auto lcEllipse = std::make_shared(coord(data.basePoint), @@ -245,13 +245,14 @@ void DXFimpl::addLayer(const DRW_Layer& data) { _builder->append(al); } else if (data.name.length() > 0 && (data.name.compare(0,1,"*") != 0)) { - std::make_shared(_document, layer)->execute(); + auto al = std::make_shared(_document, layer); + _builder->append(al); } } void DXFimpl::addSpline(const DRW_Spline* data) { LOG_WARNING << "addSpline"; - auto layer = _document->layerByName(data->layer); + auto layer = getLayer(*data); std::shared_ptr mf = getMetaInfo(*data); // http://discourse.mcneel.com/t/creating-on-nurbscurve-from-control-points-and-knot-vector/12928/3 @@ -280,7 +281,7 @@ void DXFimpl::addSpline(const DRW_Spline* data) { void DXFimpl::addText(const DRW_Text& data) { LOG_WARNING << "addText"; - auto layer = _document->layerByName(data.layer); + auto layer = getLayer(data); std::shared_ptr mf = getMetaInfo(data); auto lcText = std::make_shared(coord(data.basePoint), data.text, data.height, @@ -298,7 +299,7 @@ void DXFimpl::addText(const DRW_Text& data) { void DXFimpl::addPoint(const DRW_Point& data) { LOG_WARNING << "addPoint"; - auto layer = _document->layerByName(data.layer); + auto layer = getLayer(data); std::shared_ptr mf = getMetaInfo(data); auto lcPoint = std::make_shared(coord(data.basePoint), layer, @@ -311,7 +312,7 @@ void DXFimpl::addPoint(const DRW_Point& data) { void DXFimpl::addDimAlign(const DRW_DimAligned* data) { LOG_WARNING << "addDimAlign"; - auto layer = _document->layerByName(data->layer); + auto layer = getLayer(*data); std::shared_ptr mf = getMetaInfo(*data); auto lcDimAligned = std::make_shared( coord(data->getDefPoint()), @@ -333,7 +334,7 @@ void DXFimpl::addDimAlign(const DRW_DimAligned* data) { void DXFimpl::addDimLinear(const DRW_DimLinear* data) { LOG_WARNING << "addDimLinear"; - auto layer = _document->layerByName(data->layer); + auto layer = getLayer(*data); std::shared_ptr mf = getMetaInfo(*data); auto lcDimLinear = std::make_shared( coord(data->getDefPoint()), @@ -357,7 +358,7 @@ void DXFimpl::addDimLinear(const DRW_DimLinear* data) { void DXFimpl::addDimRadial(const DRW_DimRadial* data) { LOG_WARNING << "addDimRadial"; - auto layer = _document->layerByName(data->layer); + auto layer = getLayer(*data); std::shared_ptr mf = getMetaInfo(*data); auto lcDimRadial = std::make_shared( coord(data->getCenterPoint()), @@ -379,7 +380,7 @@ void DXFimpl::addDimRadial(const DRW_DimRadial* data) { void DXFimpl::addDimDiametric(const DRW_DimDiametric* data) { LOG_WARNING << "addDimDiametric"; - auto layer = _document->layerByName(data->layer); + auto layer = getLayer(*data); std::shared_ptr mf = getMetaInfo(*data); auto lcDimDiametric = std::make_shared( coord(data->getDiameter1Point()), @@ -401,7 +402,7 @@ void DXFimpl::addDimDiametric(const DRW_DimDiametric* data) { void DXFimpl::addDimAngular(const DRW_DimAngular* data) { LOG_WARNING << "addDimAngular"; - auto layer = _document->layerByName(data->layer); + auto layer = getLayer(*data); std::shared_ptr mf = getMetaInfo(*data); auto lcDimAngular = std::make_shared( coord(data->getDefPoint()), @@ -433,7 +434,7 @@ void DXFimpl::addDimOrdinate(const DRW_DimOrdinate* data) { void DXFimpl::addLWPolyline(const DRW_LWPolyline& data) { LOG_WARNING << "addLWPolyline"; - auto layer = _document->layerByName(data.layer); + auto layer = getLayer(data); std::shared_ptr mf = getMetaInfo(data); std::vector points; @@ -460,7 +461,7 @@ void DXFimpl::addLWPolyline(const DRW_LWPolyline& data) { //Handle polyline as lwpolyline void DXFimpl::addPolyline(const DRW_Polyline& data) { LOG_WARNING << "addPolyline"; - auto layer = _document->layerByName(data.layer); + auto layer = getLayer(data); std::shared_ptr mf = getMetaInfo(data); std::vector points; @@ -493,7 +494,7 @@ void DXFimpl::addHatch(const DRW_Hatch* data) { // Loop->objlist contains the 3 entities (copied) that define the hatch areas are the entities selected during hatch // loopList seems to contain the same entities, why?? LOG_WARNING << "addHatch "; - auto layer = _document->layerByName(data->layer); + auto layer = getLayer(*data); auto mf = getMetaInfo(*data); auto lcHatch = std::make_shared( layer, mf, @@ -512,7 +513,7 @@ void DXFimpl::addHatch(const DRW_Hatch* data) { for (auto x : data->looplist){ auto m = std::make_shared(); for(auto k : x->objlist){ - if(k->eType == DRW::ETYPE::LWPOLYLINE){ + if(k->eType == DRW::ETYPE::LWPOLYLINE){//done auto data = std::dynamic_pointer_cast(k); LOG_WARNING << "Polyline"; std::vector points; @@ -527,26 +528,30 @@ void DXFimpl::addHatch(const DRW_Hatch* data) { data->thickness, isCLosed, coord(data->extPoint), - nullptr + layer ); m->objList.push_back(lcLWPolyline); - }else if(k->eType == DRW::ETYPE::LINE){ + }else if(k->eType == DRW::ETYPE::LINE){//done auto data = std::dynamic_pointer_cast(k); + LOG_WARNING << "line"; lc::builder::LineBuilder builder; builder.setStart(coord(data->basePoint)); builder.setEnd(coord(data->secPoint)); + builder.setLayer(layer); m->objList.push_back(builder.build()); - }else if(k->eType == DRW::ETYPE::ARC){ + }else if(k->eType == DRW::ETYPE::ARC){//done auto data = std::dynamic_pointer_cast(k); lc::builder::ArcBuilder builder; - + LOG_WARNING << data->staangle <<','<< data->endangle; builder.setCenter(coord(data->basePoint)); builder.setRadius(data->radious); builder.setStartAngle(data->staangle); builder.setEndAngle(data->endangle); + builder.setIsCCW((bool) data->isccw); + builder.setLayer(layer); m->objList.push_back(builder.build()); - }else if(k->eType == DRW::ETYPE::ELLIPSE){ + }else if(k->eType == DRW::ETYPE::ELLIPSE){//done auto data = std::dynamic_pointer_cast(k); auto secPoint = coord(data->secPoint); auto lcEllipse = std::make_shared(coord(data->basePoint), @@ -555,7 +560,7 @@ void DXFimpl::addHatch(const DRW_Hatch* data) { data->staparam, data->endparam, data->isccw, - nullptr + layer ); m->objList.push_back(lcEllipse); }else if(k->eType == DRW::ETYPE::SPLINE){ @@ -582,8 +587,10 @@ void DXFimpl::addHatch(const DRW_Hatch* data) { m->objList.push_back(lcSpline); } } - lcHatch->addLoop(m); + lcHatch->_loopList.push_back(m); } + LOG_WARNING << "Hatch size: " << lcHatch->_loopList.size(); + lcHatch->calculateBoundingBox();//Not good api //@TODO: fix later _entityBuilder->appendEntity(lcHatch); } @@ -603,6 +610,22 @@ lc::meta::Block_CSPtr DXFimpl::getBlock(const DRW_Entity& data) const { return block; } +lc::meta::Layer_CSPtr DXFimpl::getLayer(const DRW_Entity& data) const { + lc::meta::Layer_CSPtr layer = _document->layerByName(data.layer); + + if (layer==nullptr){ + auto col = icol.intToColor(255); + auto lw = getLcLineWidth(DRW_LW_Conv::lineWidth::width00); + auto lp = _document->linePatternByName("CONTINUOUS"); + auto isFrozen = false; + // we need it anyway so, + layer = std::make_shared(data.layer, lw->width(), col->color(), lp, isFrozen); + auto al = std::make_shared(_document, layer); + _builder->append(al); + } + return layer; +} + lc::meta::MetaInfo_SPtr DXFimpl::getMetaInfo(const DRW_Entity& data) const { std::shared_ptr mf = nullptr; @@ -716,9 +739,22 @@ void DXFimpl::addInsert(const DRW_Insert& data) { lc::builder::InsertBuilder builder; builder.setMetaInfo(getMetaInfo(data)); builder.setBlock(getBlock(data)); - builder.setLayer(_document->layerByName(data.layer)); + auto layer = getLayer(data); + builder.setLayer(layer); builder.setCoordinate(coord(data.basePoint)); - builder.setDisplayBlock(_blocks[data.name]); + + auto block=_document->blockByName(data.name); + if (block==nullptr){ + // It requests block like V21_PAKNING , it is already defined or from other file?? + // These blocks were not declared in loading file + block = std::make_shared(data.name, geo::Coordinate()); + } + _builder->append(std::make_shared(_document, block)); + + // May need to check if the block already exists: not sure + _handleBlock.insert(std::pair(data.parentHandle, block)); + + builder.setDisplayBlock(block); builder.setDocument(_document); _entityBuilder->appendEntity(builder.build()); @@ -1289,12 +1325,6 @@ void DXFimpl::writeEntity(const lc::entity::CADEntity_CSPtr& entity) { writeInsert(insert); return; } - - auto spline = std::dynamic_pointer_cast(entity); - if (spline != nullptr) { - writeSpline(spline); - return; - } } void DXFimpl::writeBlockRecords() { diff --git a/persistence/libdxfrw/dxfimpl.h b/persistence/libdxfrw/dxfimpl.h index 81871f92b..6f6aacd64 100644 --- a/persistence/libdxfrw/dxfimpl.h +++ b/persistence/libdxfrw/dxfimpl.h @@ -230,6 +230,9 @@ namespace lc { lc::meta::Block_CSPtr getBlock(DRW_Entity const& data) const; + // this function adds layer too if not found: issue with some files + lc::meta::Layer_CSPtr getLayer(DRW_Entity const& data) const; + /** * Convert from a DRW_Coord to a geo::Coordinate */ @@ -241,11 +244,11 @@ namespace lc { lc::iColor icol; std::vector imageMapCache; - std::map _blocks; + //std::map _blocks; std::map _handleBlock; const static std::map _dxfToLCUnits; const static std::map _lcUnitsToDXF; }; } -} \ No newline at end of file +}