图形学与计算机辅助设计-大作业例子整理-夹点移动方式修改线

21 篇文章 0 订阅
19 篇文章 0 订阅

整理下大作业例子,这个是按照AutoCAD的操作模式写的,单击线和圆弧将显示夹点,点击夹点将修改实体,
图形学课程的算法都是讲怎么生成像素,像DDA或者光栅化的讲OpenGL内部怎么实现的,所以一般不是讲怎么用OpenGL。

实现是在QPainter上绘制。程序是在VC2019,Qt5.14.2-msvc2017-64预编译库, Eigen3是eigen-3.4.0。蓝奏云上压缩包是编译好的exe,
地址 QtWidgets00

下面的代码实现在QXViewWgt.h 和QXViewWgt.cpp 这个自定义的QWidget中。

截图
在这里插入图片描述

QXViewWgt.h

#pragma once

#include <QWidget>
#include "ui_QXViewWgt.h"

class QXViewWgt : public QWidget
{
	Q_OBJECT

public:
	QXViewWgt(QWidget* parent = Q_NULLPTR);
	~QXViewWgt();

	void paintEvent(QPaintEvent* event);
	void mouseMoveEvent(QMouseEvent* event);
	void mousePressEvent(QMouseEvent* event);
	void mouseReleaseEvent(QMouseEvent* event);

private:
	Ui::QXViewWgt ui;
};

QXViewWgt.cpp

/* -*-c++-*- vege module  - Copyright (C) 2008 yrcpp
 * 
 * This file is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

#include "QXViewWgt.h"
#include <QtGui/QPainter>
#include <QMouseEvent>
#include <Eigen/Eigen>
#include <vector>
#include <set>
#include <map>
#include <memory>

#define _USE_MATH_DEFINES
#include <math.h>

const double MIN_DIST = 1e-4;

namespace vege
{
	static QPainter* s_painter = nullptr;

	enum CurveState
	{
		CST_DEFAULT,
		CST_SNAPPED,
		CST_PICKED
	};

	class GripPoint
	{
	public:
		Eigen::Vector2d pt;
	};

	class Curve2d
	{
	protected:
		CurveState _state;
		std::map<int, GripPoint> _gripPoints;
		std::map<int, GripPoint> _preview_gripPoints;
		//bool _showGripPoint;
		bool _showModifyPreview;
	public:


		Curve2d() :_state(CST_DEFAULT),
			//_showGripPoint(false),
			_showModifyPreview(false)
		{}
		virtual ~Curve2d() {}
		virtual bool projectPoint(Eigen::Vector2d p, Eigen::Vector2d& q) = 0;
		virtual bool movePreviewGripPoint(int id, Eigen::Vector2d newPos) = 0;
		virtual bool updateGripPoint(int id, Eigen::Vector2d newPos) = 0;

		bool isGripPointShow() { return _state == CST_PICKED; }

		virtual void paint()
		{
			if (_state == CST_PICKED)
			{
				QPen pen0;
				pen0.setColor(QColor(101, 101, 101));
				pen0.setWidth(2);
				s_painter->setPen(pen0);
				double gripBoxW = 16.0;

				for (auto& g : _gripPoints)
				{
					s_painter->fillRect(g.second.pt.x() - gripBoxW * 0.5, g.second.pt.y() - gripBoxW * 0.5, gripBoxW, gripBoxW, QColor(0, 127, 255));
					s_painter->drawRect(g.second.pt.x() - gripBoxW*0.5, g.second.pt.y() - gripBoxW * 0.5, gripBoxW, gripBoxW);
				}
			}
		};
		virtual void setState(CurveState s)
		{
			if (_state == CST_PICKED && _state != s)
			{
				int k = 0;
			}
			_state = s;
		};

		virtual bool stateIs(CurveState s)
		{
			return _state == s;
		};

		int snapGripPoints(Eigen::Vector2d mos, double boxHalfSize, Eigen::Vector2d& gripPtPos)
		{
			for (auto& g : _gripPoints)
			{
				if (fabs(g.second.pt[0] - mos[0]) < boxHalfSize && 
					fabs(g.second.pt[1] - mos[1]) < boxHalfSize)
				{
					gripPtPos = g.second.pt;
					return g.first;
				}
			}

			return -1;
		}

		virtual void previewConfirm() {};
	};

	class Line2d : public Curve2d
	{
	public:
		Eigen::Vector2d _s;
		Eigen::Vector2d _e;

		Eigen::Vector2d _preview_s;
		Eigen::Vector2d _preview_e;

		Line2d(Eigen::Vector2d s, Eigen::Vector2d e) :_s(s), _e(e)
		{
			_gripPoints[0].pt = _s;
			_gripPoints[1].pt = (_s + _e) * 0.5;
			_gripPoints[2].pt = _e;

			_preview_gripPoints = _gripPoints;

			_preview_s = _s;
			_preview_e = _e;
		}

		virtual bool projectPoint(Eigen::Vector2d p, Eigen::Vector2d& q)
		{
			Eigen::Vector2d d = _e - _s;
			double v_se_length = d.norm();
			d.normalize();
			auto v_sp = p - _s;
			auto v_sq_length = (p - _s).dot(d);
			if (fabs(v_sq_length) < MIN_DIST)
			{
				q = _s;
				return true;
			}
			if (fabs(v_sq_length - v_se_length) < MIN_DIST)
			{
				q = _e;
				return true;
			}

			if (v_sq_length > 0.0 && v_sq_length < v_se_length)
			{
				q = _s + d * v_sq_length;
				return true;
			}

			q = { 0, 0 };
			return false;
		}

		void computeParametersByGripPointModify(std::map<int, GripPoint>& gripPoints,
			int id, Eigen::Vector2d newPos,
			Eigen::Vector2d& s, Eigen::Vector2d& e)
		{
			if (id == 0)
			{
				gripPoints[0].pt = newPos;
				gripPoints[1].pt = (gripPoints[0].pt + gripPoints[2].pt) * 0.5;
			}
			else if (id == 1)
			{
				Eigen::Vector2d v = newPos - gripPoints[1].pt;
				gripPoints[1].pt = newPos;
				gripPoints[0].pt = gripPoints[0].pt + v;
				gripPoints[2].pt = gripPoints[2].pt + v;
			}
			else if (id == 2)
			{
				gripPoints[2].pt = newPos;
				gripPoints[1].pt = (gripPoints[0].pt + gripPoints[2].pt) * 0.5;
			}

			s = gripPoints[0].pt;
			e = gripPoints[2].pt;
		}

		virtual bool movePreviewGripPoint(int id, Eigen::Vector2d newPos)
		{
			computeParametersByGripPointModify(_preview_gripPoints, id, newPos, _preview_s, _preview_e);

			_showModifyPreview = true;

			return true;
		}

		virtual void previewConfirm()
		{
			_gripPoints = _preview_gripPoints;
			_s = _gripPoints[0].pt;
			_e = _gripPoints[2].pt;
			_preview_s = _s;
			_preview_e = _e;

			_showModifyPreview = false;
		}

		virtual bool updateGripPoint(int id, Eigen::Vector2d newPos)
		{
			computeParametersByGripPointModify(_gripPoints, id, newPos, _s, _e);
			_preview_gripPoints = _gripPoints;
			_preview_s = _s;
			_preview_e = _e;

			_showModifyPreview = false;

			return true;
		}

		virtual void paint()
		{
			switch (_state)
			{
			case CST_DEFAULT:
			{
				QPen pen0;
				pen0.setColor(QColor(255, 255, 255));
				pen0.setWidth(1);
				s_painter->setPen(pen0);
				s_painter->drawLine(_s(0), _s(1), _e(0), _e(1));
			}
			break;
			case CST_SNAPPED:
			{
				QPen pen0;
				pen0.setColor(QColor(255, 255, 255));
				pen0.setWidth(3);

				s_painter->setPen(pen0);
				s_painter->drawLine(_s(0), _s(1), _e(0), _e(1));

				pen0.setColor(QColor(0, 0, 0));
				pen0.setWidth(1);
				pen0.setStyle(Qt::DotLine);
				s_painter->setPen(pen0);
				s_painter->drawLine(_s(0), _s(1), _e(0), _e(1));
			}
			break;
			case CST_PICKED:
			{
				QPen pen0;
				pen0.setColor(QColor(255, 255, 255));
				pen0.setWidth(1);
				pen0.setStyle(Qt::DashLine);

				s_painter->setPen(pen0);
				s_painter->drawLine(_s(0), _s(1), _e(0), _e(1));
			}
			break;
			default:
				break;
			}

			Curve2d::paint();

			if (_showModifyPreview)
			{
				QPen pen0;
				pen0.setColor(QColor(255, 255, 255));
				pen0.setWidth(1);
				s_painter->setPen(pen0);
				s_painter->drawLine(_preview_s(0), _preview_s(1), _preview_e(0), _preview_e(1));
			}
		}

	};

	struct Arc2dPara
	{
		Eigen::Vector2d _c;
		double _r;
		double _sang; //degree, [0.0,360)
		double _eang;
	};

	class Arc2d : public Curve2d
	{
	public:
		Eigen::Vector2d _c;
		double _r;
		double _sang; //degree, [0.0,360)
		double _eang;

		Arc2dPara _preview_para;

		std::vector<QPointF> _polyline;
		std::vector<QPointF> _preview_polyline;

		double _deg2rad(double degv)
		{
			return (M_PI * degv) / 180.0;
		}

		double _rad2deg(double radv)
		{
			return (180.0 * radv) / M_PI;
		}

		double _getMiddleAngle(double sang, double eang)
		{
			if (eang > sang)
			{
				return (sang + eang) * 0.5;
			}
			else
			{
				double m = 180.0 + (sang + eang) * 0.5;
				if (m > 360.0)
				{
					m -= 360.0;
				}
				return m;
			}
		}

		Eigen::Vector2d _getPoint(Eigen::Vector2d c,
			double r,
			double ang)
		{
			double x = r * cos(_deg2rad(ang));
			double y = r * sin(_deg2rad(ang));
			return c + Eigen::Vector2d(x, y);
		}

		double _getAngleByTwoPoints(Eigen::Vector2d c, Eigen::Vector2d pt)
		{
			Eigen::Vector2d v = pt - c;
			double x = v(0);
			double y = v(1);
			double s = sqrt(x * x + y * y);
			double ag = acos(x / s);
			double ag1 = _rad2deg(ag);
			if (y < 0.0)
			{
				ag1 = 360.0 - ag1;
			}

			return ag1;
		}

		double _angle(double sang, double eang)
		{
			if (eang > sang)
			{
				return eang - sang;
			}
			else
			{
				return 360.0 - sang + eang;
			}
		}

		bool isParallel(Eigen::Vector2d a, Eigen::Vector2d b, double tolr = 1e-3)
		{
			double v = a(0) * b(1) - a(1) * b(0);
			if (fabs(v) <= tolr)
			{
				return true;
			}

			return false;
		}

		bool _getCircleByThreePoints(Eigen::Vector2d v0, Eigen::Vector2d v1, Eigen::Vector2d v2,
			double& r, Eigen::Vector2d& c)
		{
			// two line cross at circle center
			// 
			// a s + m = b t + n
			//
			// |a0, -b0||s|= |n0-m0|
			// |a1, -b1||t|  |n1-m1|
			//
			// A  B  =  X
			// C  D     Y

			// s = 
			// [X B,
            //  Y D] /
			// [A B,
			//  C D]

			// t = 
			// [A X,
			//  C Y] /
			// [A B,
			//  C D]

			Eigen::Vector2d v01 = v1 - v0;
			Eigen::Vector2d a(-v01(1), v01(0));
			a.normalize();

			Eigen::Vector2d v12 = v2 - v1;
			Eigen::Vector2d b(-v12(1), v12(0));
			b.normalize();

			if (isParallel(a, b))
			{
				return false;
			}

			Eigen::Vector2d m = (v0 + v1) * 0.5;
			Eigen::Vector2d n = (v1 + v2) * 0.5;

			double A = a(0);
			double C = a(1);

			double B = -b(0);
			double D = -b(1);

			double X = n(0) - m(0);
			double Y = n(1) - m(1);

			double abcd = A * D - B * C;
			double sc = X * D - B * Y;
			double tc = A * Y - X * C;

			double s = sc / abcd;
			double t = tc / abcd;

			Eigen::Vector2d cs = a * s + m;
			Eigen::Vector2d ct = b * t + n;
			c = (cs + ct) * 0.5;

			double r0 = (c - v0).norm();
			double r1 = (c - v1).norm();
			double r2 = (c - v1).norm();

			r = (r0 + r1 + r2) / 3.0;

			return true;
		}

		void _getGripPointsByArc(Eigen::Vector2d c,
			double r,
			double sang,
			double eang, std::map<int, GripPoint>& gripPoints)
		{
			Eigen::Vector2d spt = _getPoint(_c, _r, _sang);
			Eigen::Vector2d ept = _getPoint(_c, _r, _eang);
			double mang = _getMiddleAngle(_sang, _eang);
			Eigen::Vector2d mpt = _getPoint(_c, _r, mang);

			_gripPoints[0].pt = spt;
			_gripPoints[1].pt = mpt;
			_gripPoints[2].pt = ept;
		}

		void arc2polyline(Eigen::Vector2d c,
			double r,
			double sang,
			double eang,
			std::vector<QPointF>& plpoints)
		{
			plpoints.clear();

			double angv = _angle(sang, eang);
			int segn = angv / 5.0 + 1;
			double da = angv / double(segn);
			plpoints.reserve(size_t(segn) + 1);

			double curang = sang;
			for (int i = 0; i < segn; i++)
			{
				Eigen::Vector2d pt = _getPoint(c, r, curang);
				plpoints.push_back(QPointF(pt(0), pt(1)));

				curang += da;
			}

			Eigen::Vector2d pt = _getPoint(c, r, eang);
			plpoints.push_back(QPointF(pt(0), pt(1)));
		}

		Arc2d(Eigen::Vector2d c, double r, double sang, double eang) :_c(c),
			_r(r),
			_sang(sang),
			_eang(eang)
		{
			//Eigen::Vector2d spt = _getPoint(_c, _r, _sang);
			//Eigen::Vector2d ept = _getPoint(_c, _r, _eang);
			//double mang = _getMiddleAngle(_sang, _eang);
			//Eigen::Vector2d mpt = _getPoint(_c, _r, mang);

			//_gripPoints[0].pt = spt;
			//_gripPoints[1].pt = mpt;
			//_gripPoints[2].pt = ept;

			_getGripPointsByArc(_c, _r, _sang, _eang, _gripPoints);

			arc2polyline(_c, _r, _sang, _eang, _polyline);

			_preview_polyline = _polyline;
			_preview_gripPoints = _gripPoints;

			_preview_para._c = _c;
			_preview_para._r = _r;
			_preview_para._sang = _sang;
			_preview_para._eang = _eang;
		}

		double degToRad(double degv)
		{
			return (degv * M_PI) / 180.0;
		}

		double radToDeg(double radv)
		{
			return (radv * 180.0) / M_PI;
		}

		Eigen::Vector2d startPoint()
		{
			return _c + Eigen::Vector2d(cos(degToRad(_sang)), sin(degToRad(_sang))) * _r;
		}

		Eigen::Vector2d endPoint()
		{
			return _c + Eigen::Vector2d(cos(degToRad(_eang)), sin(degToRad(_eang))) * _r;
		}

		double angle()
		{
			if (_eang > _sang)
			{
				return _eang - _sang;
			}
			else
			{
				return 360.0 - _sang + _eang;
			}
		}

		virtual bool projectPoint(Eigen::Vector2d p, Eigen::Vector2d& q)
		{
			Eigen::Vector2d d = p - _c;

			d.normalize();

			Eigen::Vector2d s = startPoint();
			if ((s - p).norm() < 1e-4)
			{
				q = s;
				return true;
			}

			Eigen::Vector2d e = endPoint();
			if ((e - p).norm() < 1e-4)
			{
				q = e;
				return true;
			}

			bool on_flag = false;
			double t = radToDeg(acos(d[0]));
			if (d[1] < 0.0)
			{
				t = 360.0 - t;
				if (t > 360.0)
				{
					t -= 360.0;
				}
			}

			if (_eang > _sang)
			{
				if (t > _sang && t < _eang)
				{
					on_flag = true;
				}
			}
			else
			{
				if ((t > _sang && t < 360.0) ||
					(t >= 0.0 && t < _eang)
					)
				{
					on_flag = true;
				}
			}

			if (on_flag)
			{
				q = _c + d * _r;
				return true;
			}

			q = { 0, 0 };
			return false;

		}

		virtual bool movePreviewGripPoint(int id, Eigen::Vector2d newPos)
		{
			_preview_gripPoints[id].pt = newPos;

			bool isOk =_getCircleByThreePoints(_preview_gripPoints[0].pt, _preview_gripPoints[1].pt, _preview_gripPoints[2].pt, _preview_para._r, _preview_para._c);
			if (!isOk)
			{

				copyParaToPreiviewParameters();
				return false;
			}

			_preview_para._sang = _getAngleByTwoPoints(_preview_para._c, _preview_gripPoints[0].pt);
			_preview_para._eang = _getAngleByTwoPoints(_preview_para._c, _preview_gripPoints[2].pt);

			arc2polyline(_preview_para._c, _preview_para._r, _preview_para._sang, _preview_para._eang, _preview_polyline);

			_showModifyPreview = true;

			return true;
		}

		virtual bool updateGripPoint(int id, Eigen::Vector2d newPos)
		{
			return false;
		}


		void copyParaToPreiviewParameters()
		{
			_preview_para._r = _r;
			_preview_para._c = _c;
			_preview_para._sang = _sang;
			_preview_para._eang = _eang;
		}

		void previewConfirmParameters()
		{
			_r = _preview_para._r;
			_c = _preview_para._c;
			_sang = _preview_para._sang;
			_eang = _preview_para._eang;
		}

		virtual void previewConfirm()
		{
			
			_getCircleByThreePoints(_preview_gripPoints[0].pt, _preview_gripPoints[1].pt, _preview_gripPoints[2].pt, _r, _c);

			_sang = _getAngleByTwoPoints(_c, _preview_gripPoints[0].pt);
			_eang = _getAngleByTwoPoints(_c, _preview_gripPoints[2].pt);

			_getGripPointsByArc(_c, _r, _sang, _eang, _gripPoints);

			previewConfirmParameters();
			_preview_gripPoints = _gripPoints;

			arc2polyline(_c, _r, _sang, _eang, _polyline);
			_preview_polyline = _polyline;
			

			_showModifyPreview = false;
		}

		virtual void paint()
		{
			switch (_state)
			{
			case CST_DEFAULT:
			{
				QPen pen0;
				pen0.setColor(QColor(255, 255, 255));
				pen0.setWidth(1);
				s_painter->setPen(pen0);
				//s_painter->drawArc(_c[0] - _r, _c[1] - _r, 2.0 * _r, 2.0 * _r, -_sang * 16, -angle() * 16);
				s_painter->drawPolyline(_polyline.data(), _polyline.size());
				
			}
			break;
			case CST_SNAPPED:
			{
				QPen pen0;
				pen0.setColor(QColor(255, 255, 255));
				pen0.setWidth(3);

				s_painter->setPen(pen0);
				//s_painter->drawArc(_c[0] - _r, _c[1] - _r, 2.0 * _r, 2.0 * _r, -_sang * 16, -angle() * 16);
				s_painter->drawPolyline(_polyline.data(), _polyline.size());

				pen0.setColor(QColor(0, 0, 0));
				pen0.setWidth(1);
				pen0.setStyle(Qt::DotLine);
				s_painter->setPen(pen0);
				//s_painter->drawArc(_c[0] - _r, _c[1] - _r, 2.0 * _r, 2.0 * _r, -_sang * 16, -angle() * 16);
				s_painter->drawPolyline(_polyline.data(), _polyline.size());
			}
			break;
			case CST_PICKED:
			{
				QPen pen0;
				pen0.setColor(QColor(255, 255, 255));
				pen0.setWidth(1);
				pen0.setStyle(Qt::DashLine);

				s_painter->setPen(pen0);
				//s_painter->drawArc(_c[0] - _r, _c[1] - _r, 2.0 * _r, 2.0 * _r, -_sang * 16, -angle() * 16);
				s_painter->drawPolyline(_polyline.data(), _polyline.size());
			}
			break;
			default:
				break;
			}

			Curve2d::paint();

			if (_showModifyPreview)
			{
				QPen pen0;
				pen0.setColor(QColor(255, 255, 255));
				pen0.setWidth(1);
				s_painter->setPen(pen0);
				s_painter->drawPolyline(_preview_polyline.data(), _preview_polyline.size());
			}
		}
	};

}// end of namespace vege

Eigen::Vector2d _mosPos(0.0, 0.0);
double _mosBoxHalfSize = 12;
double _mosBoxBaLength = 62;
double _snapSize = 1.414 * _mosBoxHalfSize;
std::vector<vege::Curve2d*> _curves;
vege::Curve2d* _snappedCurve = nullptr;
int _snappedCurveComponentId = -1;
// vege::Curve2d* _pickedCurve = nullptr;
std::set<vege::Curve2d*> _pickedCurves;
std::pair<vege::Curve2d*, int> _curPickedCurveGripPoint;

void _addPickedCurve(vege::Curve2d* c)
{
	if (c == nullptr)
	{
		return;
	}

	if (_pickedCurves.find(c) == _pickedCurves.end())
	{
		c->setState(vege::CST_PICKED);
		_pickedCurves.insert(c);
	}
}

void _removePickedCurve(vege::Curve2d* c)
{
	c->setState(vege::CST_DEFAULT);
	_pickedCurves.erase(c);
}

bool _isPickedCurve(vege::Curve2d* c)
{
	return _pickedCurves.find(c) != _pickedCurves.end();
}

void _clearPickedCurve()
{
	for (auto c: _pickedCurves)
	{
		c->setState(vege::CST_DEFAULT);
	}

	_pickedCurves.clear();
}

using namespace vege;

QXViewWgt::QXViewWgt(QWidget* parent)
	: QWidget(parent)
{
	ui.setupUi(this);

	_curves.push_back(new Line2d({ 50,50 }, { 450,50 }));
	_curves.push_back(new Line2d({ 50,50 }, { 50,350 }));
	_curves.push_back(new Line2d({ 450,50 }, { 450,350 }));

	_curves.push_back(new Arc2d({ 250,350 }, 200, 0, 180));
}

QXViewWgt::~QXViewWgt()
{
	for (auto& curv : _curves)
	{
		delete curv;
	}
}

void QXViewWgt::mouseReleaseEvent(QMouseEvent* event)
{
	if (_curPickedCurveGripPoint.first)
	{
		_curPickedCurveGripPoint.first->previewConfirm();



		_snappedCurve = nullptr;
		_snappedCurveComponentId = -1;
		_removePickedCurve(_curPickedCurveGripPoint.first);

		_curPickedCurveGripPoint.first = nullptr;
		_curPickedCurveGripPoint.second = -1;

		update();

		return;

	}

	if (_snappedCurve)
	{
		//if (_pickedCurve != _snappedCurve)
		//{
		//	if (_pickedCurve)
		//	{
		//		_pickedCurve->setState(CST_DEFAULT);
		//		_pickedCurve = nullptr;
		//	}

		//	_pickedCurve = _snappedCurve;
		//	_pickedCurve->setState(CST_PICKED);
		//}

		_addPickedCurve(_snappedCurve);

		if (_snappedCurveComponentId != -1)
		{
			_curPickedCurveGripPoint.first = _snappedCurve;
			_curPickedCurveGripPoint.second = _snappedCurveComponentId;
		}


	}
	else
	{
		//if (_pickedCurve)
		//{
		//	_pickedCurve->setState(CST_DEFAULT);
		//	_pickedCurve = nullptr;
		//}

		_clearPickedCurve();

	}

	update();
}

void QXViewWgt::mousePressEvent(QMouseEvent* event)
{
	QWidget::mousePressEvent(event);
}

void QXViewWgt::mouseMoveEvent(QMouseEvent* event)
{
	_mosPos(0) = event->pos().x();
	_mosPos(1) = (height()-1) - event->pos().y();

	// here we just try each curve, not use aabb
	Curve2d* curSnapped = nullptr;
	int curSnappedComId = -1;
	std::map<Curve2d*, std::pair<int, Eigen::Vector2d>  > _curSnappedCurveGripPts;
	std::map<Curve2d*, std::pair<int, Eigen::Vector2d>  > _curSnappedCurves;
	for (auto& curve : _curves)
	{

		QPen pen0;
		Eigen::Vector2d pt_q;
		int comId = -1;
		Eigen::Vector2d gripPtPos;
		comId = curve->snapGripPoints(_mosPos, _snapSize, gripPtPos);

		//if (comId != -1)
		//{
		//	curSnapped = curve;
		//	_mosPos = gripPtPos;
		//}
			

		//if (_isPickedCurve(curve))
		{
			if (comId >= 0)
			{
				curSnapped = curve;
				curSnappedComId = comId;
				_mosPos = gripPtPos;

				if (curve->isGripPointShow())
				{
					_curSnappedCurveGripPts[curSnapped] = std::make_pair(curSnappedComId, _mosPos);
				}
				else
				{
					_curSnappedCurves[curSnapped] = std::make_pair(curSnappedComId, _mosPos);
				}
				

				//break;
				continue;
			}
		}

		bool issucess = curve->projectPoint(_mosPos, pt_q);
		if (issucess)
		{
			double dist = (pt_q - _mosPos).norm();
			if (dist < _snapSize)
			{
				_mosPos = pt_q;
				curSnapped = curve;

				_curSnappedCurves[curSnapped] = std::make_pair(-1, _mosPos);
				//break;
				continue;
			}
		}
	}

	if (!_curSnappedCurveGripPts.empty())
	{
		curSnapped = _curSnappedCurveGripPts.begin()->first;
		curSnappedComId = _curSnappedCurveGripPts.begin()->second.first;
		_mosPos = _curSnappedCurveGripPts.begin()->second.second;
	}
	else if (!_curSnappedCurves.empty())
	{
		curSnapped = _curSnappedCurves.begin()->first;
		curSnappedComId = _curSnappedCurves.begin()->second.first;
		_mosPos = _curSnappedCurves.begin()->second.second;
	}
	else
	{
		curSnapped = nullptr;
		curSnappedComId = -1;
	}

	if (curSnapped == _curPickedCurveGripPoint.first)
	{
		curSnapped = nullptr;
	}

	// mov grip point and curve modify preview
	if (_curPickedCurveGripPoint.first)
	{
		_curPickedCurveGripPoint.first->movePreviewGripPoint(_curPickedCurveGripPoint.second, _mosPos);

		this->update();
		return;
	}

	if (curSnapped)
	{
		//if (/*_pickedCurve && _pickedCurve == curSnapped  */_isPickedCurve(curSnapped))
		//{
		//	_snappedCurve = curSnapped;
		//}
		//else
		{
			if (_snappedCurve)
			{
				if (_snappedCurve->stateIs(CST_SNAPPED))
				{
					_snappedCurve->setState(CST_DEFAULT);
				}
			}


			_snappedCurve = curSnapped;
			_snappedCurveComponentId = curSnappedComId;

			if (_snappedCurve->stateIs(CST_DEFAULT))
			{
				_snappedCurve->setState(CST_SNAPPED);
			}
		}
	}
	else
	{
		if (_snappedCurve)
		{
			if (_snappedCurve->stateIs(CST_SNAPPED))
			{
				_snappedCurve->setState(CST_DEFAULT);
			}

			_snappedCurve = nullptr;
			curSnappedComId = -1;
		}

	}



	this->update();
}

void QXViewWgt::paintEvent(QPaintEvent* event)
{
	QPainter painter(this);
	painter.translate(0, height());
	painter.scale(1, -1);

	vege::s_painter = &painter;

	painter.fillRect(0, 0, this->width(), this->height(),QColor(33,40,48));

	// draw curves
	for (auto& curve : _curves)
	{
		curve->paint();
	}

	// draw snap box
	QPen pen;
	pen.setColor(QColor(255, 255, 255));
	pen.setWidth(1);
	painter.setPen(pen);
	painter.drawLine(_mosPos(0) - _mosBoxBaLength, _mosPos(1), _mosPos(0) - _mosBoxHalfSize, _mosPos(1));
	painter.drawLine(_mosPos(0) + _mosBoxBaLength, _mosPos(1), _mosPos(0) + _mosBoxHalfSize, _mosPos(1));

	painter.drawLine(_mosPos(0), _mosPos(1) - _mosBoxBaLength, _mosPos(0), _mosPos(1) - _mosBoxHalfSize);
	painter.drawLine(_mosPos(0), _mosPos(1) + _mosBoxBaLength, _mosPos(0), _mosPos(1) + _mosBoxHalfSize);

	painter.drawRect(_mosPos(0) - _mosBoxHalfSize, _mosPos(1) - _mosBoxHalfSize, _mosBoxHalfSize * 2, _mosBoxHalfSize * 2);

	painter.end();
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值