编写一款2D CAD/CAM软件(十六)交互绘制图形

发布于:2024-04-23 ⋅ 阅读:(21) ⋅ 点赞:(0)

绘制步骤

以交互绘制圆形为例:

  1. 点击鼠标左键,确定圆心位置;
  2. 抬起鼠标,移动鼠标,半径随鼠标位置变化;
  3. 点击左键确定半径,完成圆的绘制。

绘制结果

Code

/// j-operator-create-circle.h

#pragma once

#include "j-operator.h"
#include "j-geometry/j-geometry-circle.h"

namespace JNSOperator {

    enum class JCreateCircleStep {
        eCreateCircleStepInit = 0,
        eCreateCircleStepFirstDown,
        eCreateCircleStepFirstRelease,
        eCreateCircleStepSecondDown,
        eCreateCircleStepSecondRelease
    };

    class JOperatorCreateCircle : public JOperator {
    public:
        JOperatorCreateCircle(JOperatorManager *manager);
        virtual ~JOperatorCreateCircle();

        unsigned GetClassId() const override {
            return ID_OP_CREATE_CIRCLE;
        }

        bool IsOpDrawCircle() const override {
            return true;
        }

        void LButtonDown(const JNSGeometry::JGeoPoint &point) override;
        void LButtonUp(const JNSGeometry::JGeoPoint &point) override;
        void MouseMove(const JNSGeometry::JGeoPoint &point) override;
        void RButtonUp(const JNSGeometry::JGeoPoint &point) override;

        void BeforeOperate() override;
        void Reset() override;
        void EndOperate(JResult aResult) override;

        const JNSGeometry::JGeoCircle &GetAssistCircle();

        void SetCenterAndRadius(const JNSGeometry::JGeoPoint &center, double radius);

        JCreateCircleStep GetStatus();

    private:
        JNSGeometry::JGeoCircle assist_circle_;
        JCreateCircleStep step_ = JCreateCircleStep::eCreateCircleStepInit;
    };
}
/// j-operator-create-circle.cpp

#include "j-operator/j-operator-create-circle.h"
#include "j-operator/j-operator-manager.h"
#include "j-document/j-document.h"

namespace JNSOperator {
    JOperatorCreateCircle::JOperatorCreateCircle(JOperatorManager *manager)
            : JOperator(manager) {
        Reset();
    }

    JOperatorCreateCircle::~JOperatorCreateCircle() {}

    void JOperatorCreateCircle::LButtonDown(const JNSGeometry::JGeoPoint &point) {
        if (step_ == JCreateCircleStep::eCreateCircleStepInit) {
            assist_circle_.SetCenter(point);
            step_ = JCreateCircleStep::eCreateCircleStepFirstDown;
        } else if (step_ == JCreateCircleStep::eCreateCircleStepInit ||
                   step_ == JCreateCircleStep::eCreateCircleStepFirstDown ||
                   step_ == JCreateCircleStep::eCreateCircleStepFirstRelease) {
            double radius = point.DistanceTo(assist_circle_.GetCenter());
            assist_circle_.SetRadius(radius);

            step_ = JCreateCircleStep::eCreateCircleStepSecondDown;
        }
    }

    void JOperatorCreateCircle::LButtonUp(const JNSGeometry::JGeoPoint &point) {
        if (step_ == JCreateCircleStep::eCreateCircleStepFirstDown) {
            assist_circle_.SetCenter(point);
            step_ = JCreateCircleStep::eCreateCircleStepFirstRelease;
        } else if (step_ == JCreateCircleStep::eCreateCircleStepSecondDown) {
            double radius = point.DistanceTo(assist_circle_.GetCenter());
            assist_circle_.SetRadius(radius);
            step_ = JCreateCircleStep::eCreateCircleStepSecondRelease;
            EndOperate(JResult::eOk);
        }
    }

    void JOperatorCreateCircle::MouseMove(const JNSGeometry::JGeoPoint &point) {
        if (step_ == JCreateCircleStep::eCreateCircleStepInit ||
            step_ == JCreateCircleStep::eCreateCircleStepFirstDown) {
            assist_circle_.SetCenter(point);
        } else if (step_ == JCreateCircleStep::eCreateCircleStepFirstRelease ||
                   step_ == JCreateCircleStep::eCreateCircleStepSecondDown) {
            double radius = point.DistanceTo(assist_circle_.GetCenter());
            assist_circle_.SetRadius(radius);

        }
    }

    void JOperatorCreateCircle::RButtonUp(const JNSGeometry::JGeoPoint &point) {
    }

    void JOperatorCreateCircle::BeforeOperate() {
    }

    void JOperatorCreateCircle::Reset() {
        JNSGeometry::JGeoPoint center;
        center.InitInvalid();
        assist_circle_.SetCenter(center);
        assist_circle_.SetRadius(0.0);
        step_ = JCreateCircleStep::eCreateCircleStepInit;
    }

    void JOperatorCreateCircle::EndOperate(JResult aResult) {
        if (aResult == JResult::eOk) {
            if (!assist_circle_.GetCenter().IsValid()) {
                return;
            }

            auto circle = new JNSGeometry::JGeoCircle();
            circle->SetCenter(assist_circle_.GetCenter());
            circle->SetRadius(assist_circle_.GetRadius());
            op_manager_->GetDocument()->AddGeo(circle);
        } else {
        }

        Reset();

        op_manager_->BackToNormal();
    }

    const JNSGeometry::JGeoCircle &JOperatorCreateCircle::GetAssistCircle() {
        return assist_circle_;
    }

    void JOperatorCreateCircle::SetCenterAndRadius(const JNSGeometry::JGeoPoint &center, double radius) {
        assist_circle_.SetCenter(center);
        assist_circle_.SetRadius(radius);
    }

    JCreateCircleStep JOperatorCreateCircle::GetStatus() {
        return step_;
    }
}
/// j-view.cpp

    void JView::DrawOperator(JNSOperator::JOperatorCreateCircle *op) {
        auto circle = op->GetAssistCircle();
        auto center = circle.GetCenter();
        DrawPoint(static_cast<JNSGeometry::JGeoPoint *>(&center));
        DrawCircle(static_cast<JNSGeometry::JGeoCircle *>(&circle));
    }

以此为模板,可以将绘制其它基本图元的功能补齐。