--- a/src/document.cpp Tue Jun 14 22:31:39 2022 +0300 +++ b/src/document.cpp Tue Jun 14 23:04:49 2022 +0300 @@ -70,8 +70,8 @@ // And finally transform it back to grid coordinates by transforming it with the // grid matrix. this->worldPosition = this->gridMatrix * glm::vec4{*this->worldPosition, 1}; + this->polygon.back() = *this->worldPosition; } - this->updatePreviewPolygon(); } static QVector<QPointF> convertWorldPointsToScreenPoints( @@ -119,6 +119,24 @@ painter->drawPolygon(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)}); } +static opt<std::vector<glm::vec3>> modelActionPoints(const ModelAction& action) +{ + opt<std::vector<glm::vec3>> result; + if (const AppendToModel* append = std::get_if<AppendToModel>(&action)) { + const ModelElement& newElement = append->newElement; + if (const LineSegment* seg = std::get_if<Colored<LineSegment>>(&newElement)) { + result = {seg->p1, seg->p2}; + } + else if (const Triangle* tri = std::get_if<Colored<Triangle>>(&newElement)) { + result = {tri->p1, tri->p2, tri->p3}; + } + else if (const Quadrilateral* quad = std::get_if<Colored<Quadrilateral>>(&newElement)) { + result = {quad->p1, quad->p2, quad->p3, quad->p4}; + } + } + return result; +} + void EditTools::overpaint(QPainter* painter) { struct Pens @@ -151,26 +169,24 @@ case SelectMode: break; case DrawMode: - { - painter->setPen(this->isconcave ? pens.badPolygonPen : pens.polygonPen); - if (this->previewPolygon.size() > 2 and not this->isconcave) - { - if (worldPolygonWinding(this->previewPolygon, this->renderer) == Winding::Clockwise) { + painter->setPen(this->isconcave ? pens.badPolygonPen : pens.polygonPen); + for (const ModelAction& action : this->actions()) { + const opt<std::vector<glm::vec3>> points = modelActionPoints(action); + if (points.has_value()) { + if (worldPolygonWinding(*points, this->renderer) == Winding::Clockwise) { painter->setBrush(pens.greenPolygonBrush); } else { painter->setBrush(pens.redPolygonBrush); } - drawWorldPolygon(painter, this->previewPolygon, this->renderer); - } - else { - drawWorldPolyline(painter, this->previewPolygon, this->renderer); + drawWorldPolygon(painter, *points, this->renderer); } - painter->setBrush(pens.pointBrush); - painter->setPen(pens.pointPen); - for (const glm::vec3& point : this->polygon) { - drawWorldPoint(painter, point, this->renderer); - } + } + //drawWorldPolyline(painter, this->previewPolygon, this->renderer); + painter->setBrush(pens.pointBrush); + painter->setPen(pens.pointPen); + for (const glm::vec3& point : this->polygon) { + drawWorldPoint(painter, point, this->renderer); } break; } @@ -187,29 +203,24 @@ void EditTools::updatePreviewPolygon() { - this->previewPolygon = this->polygon; - if (this->worldPosition.has_value()) { - this->previewPolygon.resize(this->polygon.size() + 1); - this->previewPolygon.back() = *this->worldPosition; - } - if (this->previewPolygon.size() > 2) - { - this->isconcave = not isConvex(this->previewPolygon); + if (this->polygon.size() > 2) { + this->isconcave = not isConvex(this->polygon); } } void EditTools::removeLastPoint() { - if (this->polygon.size() > 0) - { + if (this->polygon.size() > 1) { this->polygon.erase(this->polygon.end() - 1); - this->updatePreviewPolygon(); } } -bool isCloseToExistingPoints(const std::vector<glm::vec3>& points, const glm::vec3 &pos) +template<typename T> +bool isCloseToExistingPoints(T begin, T end, const glm::vec3 &pos) { - return any(points, std::bind(isclose, std::placeholders::_1, pos)); + return std::any_of(begin, end, [&pos](const glm::vec3& p){ + return isclose(pos, p); + }); } EditingMode EditTools::currentEditingMode() const @@ -228,7 +239,7 @@ break; case DrawMode: if (event->button() == Qt::LeftButton and this->worldPosition.has_value()) { - if (isCloseToExistingPoints(this->polygon, *this->worldPosition)) { + if (isCloseToExistingPoints(this->polygon.begin(), this->polygon.end() - 1, *this->worldPosition)) { this->closeShape(); } else { @@ -238,21 +249,22 @@ } else if (true and event->button() == Qt::RightButton - and this->polygon.size() > 0 + and this->polygon.size() > 1 ) { - this->polygon.erase(this->polygon.end() - 1); + this->removeLastPoint(); updatePreviewPolygon(); } break; } } -void EditTools::closeShape() +const std::vector<ModelAction> EditTools::actions() const { + std::vector<ModelAction> result; if (this->polygon.size() >= 2 and this->polygon.size() <= 4) { switch (this->polygon.size()) { case 2: - Q_EMIT this->modelAction(AppendToModel{ + result.push_back(AppendToModel{ .newElement = Colored<LineSegment>{ LineSegment{ .p1 = this->polygon[0], @@ -263,7 +275,7 @@ }); break; case 3: - Q_EMIT this->modelAction(AppendToModel{ + result.push_back(AppendToModel{ .newElement = Colored<Triangle>{ Triangle{ .p1 = this->polygon[0], @@ -275,7 +287,7 @@ }); break; case 4: - Q_EMIT this->modelAction(AppendToModel{ + result.push_back(AppendToModel{ .newElement = Colored<Quadrilateral>{ Quadrilateral{ .p1 = this->polygon[0], @@ -289,6 +301,14 @@ break; } } + return result; +} + +void EditTools::closeShape() +{ + for (const ModelAction& action : this->actions()) { + Q_EMIT this->modelAction(action); + } this->polygon.clear(); this->updatePreviewPolygon(); }