Add tool spline

This commit is contained in:
dismine 2013-08-05 11:37:56 +03:00
parent 066432c980
commit 45856338f9
57 changed files with 4648 additions and 225 deletions

View File

@ -15,7 +15,6 @@ SOURCES += main.cpp\
mainwindow.cpp \
widgets/vmaingraphicsscene.cpp \
dialogs/dialogsinglepoint.cpp \
tools/vtoolsimplepoint.cpp \
widgets/vgraphicssimpletextitem.cpp \
xml/vdomdocument.cpp \
container/vpointf.cpp \
@ -43,13 +42,18 @@ SOURCES += main.cpp\
dialogs/dialogbisector.cpp \
tools/vtoollinepoint.cpp \
tools/vtoollineintersect.cpp \
dialogs/dialoglineintersect.cpp
dialogs/dialoglineintersect.cpp \
geometry/vspline.cpp \
tools/vtoolsinglepoint.cpp \
geometry/varc.cpp \
widgets/vcontrolpointspline.cpp \
tools/vtoolspline.cpp \
dialogs/dialogspline.cpp
HEADERS += mainwindow.h \
widgets/vmaingraphicsscene.h \
dialogs/dialogsinglepoint.h \
options.h \
tools/vtoolsimplepoint.h \
widgets/vgraphicssimpletextitem.h \
xml/vdomdocument.h \
container/vpointf.h \
@ -77,7 +81,13 @@ HEADERS += mainwindow.h \
dialogs/dialogbisector.h \
tools/vtoollinepoint.h \
tools/vtoollineintersect.h \
dialogs/dialoglineintersect.h
dialogs/dialoglineintersect.h \
geometry/vspline.h \
tools/vtoolsinglepoint.h \
geometry/varc.h \
widgets/vcontrolpointspline.h \
tools/vtoolspline.h \
dialogs/dialogspline.h
FORMS += mainwindow.ui \
dialogs/dialogsinglepoint.ui \
@ -88,7 +98,8 @@ FORMS += mainwindow.ui \
dialogs/dialogshoulderpoint.ui \
dialogs/dialognormal.ui \
dialogs/dialogbisector.ui \
dialogs/dialoglineintersect.ui
dialogs/dialoglineintersect.ui \
dialogs/dialogspline.ui
RESOURCES += \
icon.qrc \

View File

@ -73,6 +73,20 @@ void VContainer::UpdatePoint(qint64 id, const VPointF& point){
}
}
void VContainer::UpdateSpline(qint64 id, const VSpline &spl){
splines[id] = spl;
if(id > _id){
_id = id;
}
}
void VContainer::UpdateArc(qint64 id, const VArc &arc){
arcs[id] = arc;
if(id > _id){
_id = id;
}
}
void VContainer::UpdateStandartTableCell(const QString& name, const VStandartTableCell& cell){
standartTable[name] = cell;
}
@ -103,6 +117,9 @@ void VContainer::Clear(){
standartTable.clear();
incrementTable.clear();
lengthLines.clear();
splines.clear();
arcs.clear();
lengthArcs.clear();
}
void VContainer::ClearIncrementTable(){
@ -113,6 +130,14 @@ void VContainer::ClearLengthLines(){
lengthLines.clear();
}
void VContainer::ClearLengthSplines(){
lengthSplines.clear();
}
void VContainer::ClearLengthArcs(){
lengthArcs.clear();
}
void VContainer::SetSize(qint32 size){
base["Сг"] = size;
}
@ -159,6 +184,14 @@ const QMap<qint64, VPointF> *VContainer::DataPoints() const{
return &points;
}
const QMap<qint64, VSpline> *VContainer::DataSplines() const{
return &splines;
}
const QMap<qint64, VArc> *VContainer::DataArcs() const{
return &arcs;
}
const QMap<QString, qint32> *VContainer::DataBase() const{
return &base;
}
@ -175,11 +208,27 @@ const QMap<QString, qreal> *VContainer::DataLengthLines() const{
return &lengthLines;
}
const QMap<QString, qreal> *VContainer::DataLengthSplines() const{
return &lengthSplines;
}
void VContainer::AddLine(const qint64 &firstPointId, const qint64 &secondPointId){
QString nameLine = GetNameLine(firstPointId, secondPointId);
VPointF firstPoint = GetPoint(firstPointId);
VPointF secondPoint = GetPoint(secondPointId);
AddLine(nameLine, QLineF(firstPoint.toQPointF(), secondPoint.toQPointF()).length());
AddLengthLine(nameLine, QLineF(firstPoint.toQPointF(), secondPoint.toQPointF()).length());
}
qint64 VContainer::AddSpline(const VSpline &spl){
qint64 id = getNextId();
splines[id] = spl;
return id;
}
qint64 VContainer::AddArc(const VArc &arc){
qint64 id = getNextId();
arcs[id] = arc;
return id;
}
QString VContainer::GetNameLine(const qint64 &firstPoint, const qint64 &secondPoint) const{
@ -188,11 +237,50 @@ QString VContainer::GetNameLine(const qint64 &firstPoint, const qint64 &secondPo
return QString("Line_%1_%2").arg(first.name(), second.name());
}
void VContainer::AddLine(const QString &name, const qreal &value){
QString VContainer::GetNameSpline(const qint64 &firstPoint, const qint64 &secondPoint) const{
VPointF first = GetPoint(firstPoint);
VPointF second = GetPoint(secondPoint);
return QString("Spl_%1_%2").arg(first.name(), second.name());
}
QString VContainer::GetNameArc(const qint64 &firstPoint, const qint64 &centerPoint,
const qint64 &secondPoint) const{
VPointF first = GetPoint(firstPoint);
VPointF center = GetPoint(centerPoint);
VPointF second = GetPoint(secondPoint);
return QString("Arc_%1_%2_%3").arg(first.name(), center.name(), second.name());
}
void VContainer::AddLengthLine(const QString &name, const qreal &value){
Q_ASSERT(!name.isEmpty());
lengthLines[name] = value/PrintDPI*25.4;
}
void VContainer::AddLengthSpline(const qint64 &firstPointId, const qint64 &secondPointId){
QString nameLine = GetNameSpline(firstPointId, secondPointId);
VPointF firstPoint = GetPoint(firstPointId);
VPointF secondPoint = GetPoint(secondPointId);
AddLengthSpline(nameLine, QLineF(firstPoint.toQPointF(), secondPoint.toQPointF()).length());
}
void VContainer::AddLengthSpline(const QString &name, const qreal &value){
Q_ASSERT(!name.isEmpty());
lengthSplines[name] = value/PrintDPI*25.4;
}
void VContainer::AddLengthArc(const qint64 &firstPointId, const qint64 &centerPoint,
const qint64 &secondPointId){
QString nameLine = GetNameArc(firstPointId, centerPoint, secondPointId);
VPointF firstPoint = GetPoint(firstPointId);
VPointF secondPoint = GetPoint(secondPointId);
AddLengthArc(nameLine, QLineF(firstPoint.toQPointF(), secondPoint.toQPointF()).length());
}
void VContainer::AddLengthArc(const QString &name, const qreal &value){
Q_ASSERT(!name.isEmpty());
lengthArcs[name] = value/PrintDPI*25.4;
}
qreal VContainer::GetLine(const QString &name) const{
Q_ASSERT(!name.isEmpty());
if(lengthLines.contains(name)){
@ -203,3 +291,28 @@ qreal VContainer::GetLine(const QString &name) const{
}
return 0;
}
VSpline VContainer::GetSpline(qint64 id) const{
if(splines.contains(id)){
return splines.value(id);
} else {
qCritical()<<"Не можу знайти id = "<<id<<" в таблиці.";
throw"Не можу знайти сплайн за id.";
}
return VSpline();
}
VArc VContainer::GetArc(qint64 id) const{
if(arcs.contains(id)){
return arcs.value(id);
} else {
qCritical()<<"Не можу знайти id = "<<id<<" в таблиці.";
throw"Не можу знайти дугу за id.";
}
return VArc();
}
const QMap<QString, qreal> *VContainer::DataLengthArcs() const{
return &lengthArcs;
}

View File

@ -3,27 +3,52 @@
#include <QMap>
#include <QTableWidget>
#include "vpointf.h"
#include "vstandarttablecell.h"
#include "vincrementtablerow.h"
#include "../geometry/vspline.h"
#include "../geometry/varc.h"
/**
* @brief The VContainer class
*/
class VContainer
{
public:
/**
* @brief VContainer
*/
VContainer();
/**
* @brief GetPoint
* @param id
* @return
*/
VPointF GetPoint(qint64 id) const;
VStandartTableCell GetStandartTableCell(const QString& name) const;
VIncrementTableRow GetIncrementTableRow(const QString& name) const;
qreal GetLine(const QString &name) const;
VSpline GetSpline(qint64 id) const;
VArc GetArc(qint64 id) const;
qint64 getId();
qint64 AddPoint(const VPointF& point);
void AddStandartTableCell(const QString& name, const VStandartTableCell& cell);
void AddIncrementTableRow(const QString& name, const VIncrementTableRow &cell);
void AddLine(const QString &name, const qreal &value);
void AddLengthLine(const QString &name, const qreal &value);
void AddLengthSpline(const qint64 &firstPointId, const qint64 &secondPointId);
void AddLengthSpline(const QString &name, const qreal &value);
void AddLengthArc(const qint64 &firstPointId, const qint64 &centerPoint, const qint64 &secondPointId);
void AddLengthArc(const QString &name, const qreal &value);
void AddLine(const qint64 &firstPointId, const qint64 &secondPointId);
qint64 AddSpline(const VSpline& spl);
qint64 AddArc(const VArc& arc);
QString GetNameLine(const qint64 &firstPoint, const qint64 &secondPoint) const;
QString GetNameSpline(const qint64 &firstPoint, const qint64 &secondPoint) const;
QString GetNameArc(const qint64 &firstPoint, const qint64 &centerPoint,
const qint64 &secondPoint) const;
void UpdatePoint(qint64 id, const VPointF& point);
void UpdateSpline(qint64 id, const VSpline& spl);
void UpdateArc(qint64 id, const VArc& arc);
void UpdateStandartTableCell(const QString& name, const VStandartTableCell& cell);
void UpdateIncrementTableRow(const QString& name, const VIncrementTableRow& cell);
qreal GetValueStandartTableCell(const QString& name) const;
@ -31,6 +56,8 @@ public:
void Clear();
void ClearIncrementTable();
void ClearLengthLines();
void ClearLengthSplines();
void ClearLengthArcs();
void SetSize(qint32 size);
void SetGrowth(qint32 growth);
qint32 size() const;
@ -40,10 +67,14 @@ public:
qint64 getNextId();
void RemoveIncrementTableRow(const QString& name);
const QMap<qint64, VPointF> *DataPoints() const;
const QMap<qint64, VSpline> *DataSplines() const;
const QMap<qint64, VArc> *DataArcs() const;
const QMap<QString, qint32> *DataBase() const;
const QMap<QString, VStandartTableCell> *DataStandartTable() const;
const QMap<QString, VIncrementTableRow> *DataIncrementTable() const;
const QMap<QString, qreal> * DataLengthLines() const;
const QMap<QString, qreal> *DataLengthLines() const;
const QMap<QString, qreal> *DataLengthSplines() const;
const QMap<QString, qreal> *DataLengthArcs() const;
private:
qint64 _id;
QMap<QString, qint32> base;
@ -51,6 +82,10 @@ private:
QMap<QString, VStandartTableCell> standartTable;
QMap<QString, VIncrementTableRow> incrementTable;
QMap<QString, qreal> lengthLines;
QMap<qint64, VSpline> splines;
QMap<QString, qreal> lengthSplines;
QMap<qint64, VArc> arcs;
QMap<QString, qreal> lengthArcs;
};
#endif // VCONTAINER_H

View File

@ -8,5 +8,6 @@
<file>cursor/normal_cursor.png</file>
<file>cursor/bisector_cursor.png</file>
<file>cursor/intersect_cursor.png</file>
<file>cursor/spline_cursor.png</file>
</qresource>
</RCC>

BIN
cursor/spline_cursor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -44,7 +44,7 @@ DialogAlongLine::~DialogAlongLine()
delete ui;
}
void DialogAlongLine::ChoosedPoint(qint64 id, Scene::Type type){
void DialogAlongLine::ChoosedObject(qint64 id, Scene::Type type){
if(type == Scene::Point){
VPointF point = data->GetPoint(id);
if(number == 0){

View File

@ -27,7 +27,7 @@ public:
qint64 getSecondPointId() const;
void setSecondPointId(const qint64 &value);
public slots:
virtual void ChoosedPoint(qint64 id, Scene::Type type);
virtual void ChoosedObject(qint64 id, Scene::Type type);
virtual void DialogAccepted();
private:
Ui::DialogAlongLine *ui;

View File

@ -44,7 +44,7 @@ DialogBisector::~DialogBisector(){
delete ui;
}
void DialogBisector::ChoosedPoint(qint64 id, Scene::Type type){
void DialogBisector::ChoosedObject(qint64 id, Scene::Type type){
if(type == Scene::Point){
VPointF point = data->GetPoint(id);
if(number == 0){

View File

@ -34,7 +34,7 @@ public:
qint64 getThirdPointId() const;
void setThirdPointId(const qint64 &value);
public slots:
virtual void ChoosedPoint(qint64 id, Scene::Type type);
virtual void ChoosedObject(qint64 id, Scene::Type type);
virtual void DialogAccepted();
private:
Ui::DialogBisector *ui;

View File

@ -59,7 +59,7 @@ DialogEndLine::DialogEndLine(const VContainer *data, QWidget *parent) :
connect(ui->lineEditFormula, &QLineEdit::textChanged, this, &DialogEndLine::FormulaChanged);
}
void DialogEndLine::ChoosedPoint(qint64 id, Scene::Type type){
void DialogEndLine::ChoosedObject(qint64 id, Scene::Type type){
if(type == Scene::Point){
VPointF point = data->GetPoint(id);
ChangeCurrentText(ui->comboBoxBasePoint, point.name());

View File

@ -31,7 +31,7 @@ public:
qint64 getBasePointId() const;
void setBasePointId(const qint64 &value);
public slots:
virtual void ChoosedPoint(qint64 id, Scene::Type type);
virtual void ChoosedObject(qint64 id, Scene::Type type);
virtual void DialogAccepted();
private:
Ui::DialogEndLine *ui;

View File

@ -137,7 +137,49 @@ void DialogIncrements::FillLengthLines(){
item = new QTableWidgetItem(QString().setNum(length));
item->setTextAlignment(Qt::AlignHCenter);
ui->tableWidgetLines->setItem(currentRow, 1, item);
}
}
}
void DialogIncrements::FillLengthSplines(){
const QMap<QString, qreal> *splinesTable = data->DataLengthSplines();
qint32 currentRow = -1;
QMapIterator<QString, qreal> i(*splinesTable);
while (i.hasNext()) {
i.next();
qreal length = i.value();
currentRow++;
ui->tableWidgetSplines->setRowCount ( splinesTable->size() );
QTableWidgetItem *item = new QTableWidgetItem(QString(i.key()));
item->setTextAlignment(Qt::AlignHCenter);
item->setFont(QFont("Times", 12, QFont::Bold));
ui->tableWidgetSplines->setItem(currentRow, 0, item);
item = new QTableWidgetItem(QString().setNum(length));
item->setTextAlignment(Qt::AlignHCenter);
ui->tableWidgetSplines->setItem(currentRow, 1, item);
}
}
void DialogIncrements::FillLengthArcs(){
const QMap<QString, qreal> *arcsTable = data->DataLengthArcs();
qint32 currentRow = -1;
QMapIterator<QString, qreal> i(*arcsTable);
while (i.hasNext()) {
i.next();
qreal length = i.value();
currentRow++;
ui->tableWidgetArcs->setRowCount ( arcsTable->size() );
QTableWidgetItem *item = new QTableWidgetItem(QString(i.key()));
item->setTextAlignment(Qt::AlignHCenter);
item->setFont(QFont("Times", 12, QFont::Bold));
ui->tableWidgetArcs->setItem(currentRow, 0, item);
item = new QTableWidgetItem(QString().setNum(length));
item->setTextAlignment(Qt::AlignHCenter);
ui->tableWidgetArcs->setItem(currentRow, 1, item);
}
}
void DialogIncrements::FullUpdateFromFile(){
@ -156,6 +198,14 @@ void DialogIncrements::FullUpdateFromFile(){
InitialLinesTable();
FillLengthLines();
ui->tableWidgetSplines->clear();
InitialSplinesTable();
FillLengthSplines();
ui->tableWidgetArcs->clear();
InitialArcsTable();
FillLengthArcs();
connect(ui->tableWidgetIncrement, &QTableWidget::cellChanged, this,
&DialogIncrements::cellChanged);
}
@ -367,6 +417,22 @@ void DialogIncrements::InitialLinesTable(){
ui->tableWidgetLines->setHorizontalHeaderItem(1, new QTableWidgetItem("Довжина"));
}
void DialogIncrements::InitialSplinesTable(){
ui->tableWidgetSplines->resizeColumnsToContents();
ui->tableWidgetSplines->resizeRowsToContents();
ui->tableWidgetSplines->verticalHeader()->setDefaultSectionSize(20);
ui->tableWidgetSplines->setHorizontalHeaderItem(0, new QTableWidgetItem("Лінія"));
ui->tableWidgetSplines->setHorizontalHeaderItem(1, new QTableWidgetItem("Довжина"));
}
void DialogIncrements::InitialArcsTable(){
ui->tableWidgetArcs->resizeColumnsToContents();
ui->tableWidgetArcs->resizeRowsToContents();
ui->tableWidgetArcs->verticalHeader()->setDefaultSectionSize(20);
ui->tableWidgetArcs->setHorizontalHeaderItem(0, new QTableWidgetItem("Лінія"));
ui->tableWidgetArcs->setHorizontalHeaderItem(1, new QTableWidgetItem("Довжина"));
}
void DialogIncrements::DialogAccepted(){
emit DialogClosed(QDialog::Accepted);
}

View File

@ -33,9 +33,13 @@ private:
void InitialStandartTable();
void InitialIncrementTable();
void InitialLinesTable();
void InitialSplinesTable();
void InitialArcsTable();
void FillStandartTable();
void FillIncrementTable();
void FillLengthLines();
void FillLengthSplines();
void FillLengthArcs();
void AddIncrementToFile(quint64 id, QString name, qint32 base, qreal ksize, qreal kgrowth,
QString description);
};

View File

@ -20,7 +20,7 @@
<enum>QTabWidget::North</enum>
</property>
<property name="currentIndex">
<number>2</number>
<number>0</number>
</property>
<widget class="QWidget" name="tabStandart">
<attribute name="title">
@ -245,7 +245,7 @@
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QTableWidget" name="tableWidget_2">
<widget class="QTableWidget" name="tableWidgetSplines">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
@ -281,7 +281,7 @@
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QTableWidget" name="tableWidget_3">
<widget class="QTableWidget" name="tableWidgetArcs">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>

View File

@ -55,7 +55,7 @@ void DialogLine::DialogAccepted(){
DialogClosed(QDialog::Accepted);
}
void DialogLine::ChoosedPoint(qint64 id, Scene::Type type){
void DialogLine::ChoosedObject(qint64 id, Scene::Type type){
if(type == Scene::Point){
VPointF point = data->GetPoint(id);
if(number == 0){

View File

@ -21,7 +21,7 @@ public:
qint64 getSecondPoint() const;
void setSecondPoint(const qint64 &value);
public slots:
void ChoosedPoint(qint64 id, Scene::Type type);
void ChoosedObject(qint64 id, Scene::Type type);
virtual void DialogAccepted();
private:
Ui::DialogLine *ui;

View File

@ -25,7 +25,7 @@ DialogLineIntersect::~DialogLineIntersect()
delete ui;
}
void DialogLineIntersect::ChoosedPoint(qint64 id, Scene::Type type){
void DialogLineIntersect::ChoosedObject(qint64 id, Scene::Type type){
if(type == Scene::Point){
VPointF point = data->GetPoint(id);
if(number == 0){

View File

@ -24,7 +24,7 @@ public:
QString getPointName() const;
void setPointName(const QString &value);
public slots:
virtual void ChoosedPoint(qint64 id, Scene::Type type);
virtual void ChoosedObject(qint64 id, Scene::Type type);
virtual void DialogAccepted();
void P1Line1Changed( int index);
void P2Line1Changed( int index);

View File

@ -62,7 +62,7 @@ DialogNormal::~DialogNormal()
delete ui;
}
void DialogNormal::ChoosedPoint(qint64 id, Scene::Type type){
void DialogNormal::ChoosedObject(qint64 id, Scene::Type type){
if(type == Scene::Point){
VPointF point = data->GetPoint(id);
if(number == 0){

View File

@ -33,7 +33,7 @@ public:
qint64 getSecondPointId() const;
void setSecondPointId(const qint64 &value);
public slots:
virtual void ChoosedPoint(qint64 id, Scene::Type type);
virtual void ChoosedObject(qint64 id, Scene::Type type);
virtual void DialogAccepted();
private:
Ui::DialogNormal *ui;

View File

@ -45,7 +45,7 @@ DialogShoulderPoint::~DialogShoulderPoint()
delete ui;
}
void DialogShoulderPoint::ChoosedPoint(qint64 id, Scene::Type type){
void DialogShoulderPoint::ChoosedObject(qint64 id, Scene::Type type){
if(type == Scene::Point){
VPointF point = data->GetPoint(id);
if(number == 0){

View File

@ -29,7 +29,7 @@ public:
qint64 getPShoulder() const;
void setPShoulder(const qint64 &value);
public slots:
virtual void ChoosedPoint(qint64 id, Scene::Type type);
virtual void ChoosedObject(qint64 id, Scene::Type type);
virtual void DialogAccepted();
private:
Ui::DialogShoulderPoint *ui;

127
dialogs/dialogspline.cpp Normal file
View File

@ -0,0 +1,127 @@
#include "dialogspline.h"
#include "ui_dialogspline.h"
DialogSpline::DialogSpline(const VContainer *data, QWidget *parent) :
DialogTool(data, parent), ui(new Ui::DialogSpline)
{
ui->setupUi(this);
number = 0;
bOk = ui->buttonBox->button(QDialogButtonBox::Ok);
connect(bOk, &QPushButton::clicked, this, &DialogSpline::DialogAccepted);
QPushButton *bCansel = ui->buttonBox->button(QDialogButtonBox::Cancel);
connect(bCansel, &QPushButton::clicked, this, &DialogSpline::DialogRejected);
FillComboBoxPoints(ui->comboBoxP1);
FillComboBoxPoints(ui->comboBoxP4);
}
DialogSpline::~DialogSpline()
{
delete ui;
}
void DialogSpline::ChoosedObject(qint64 id, Scene::Type type){
if(type == Scene::Point){
VPointF point = data->GetPoint(id);
if(number == 0){
qint32 index = ui->comboBoxP1->findText(point.name());
if ( index != -1 ) { // -1 for not found
ui->comboBoxP1->setCurrentIndex(index);
number++;
return;
}
}
if(number == 1){
qint32 index = ui->comboBoxP4->findText(point.name());
if ( index != -1 ) { // -1 for not found
ui->comboBoxP4->setCurrentIndex(index);
number = 0;
index = ui->comboBoxP1->currentIndex();
qint64 p1Id = qvariant_cast<qint64>(ui->comboBoxP1->itemData(index));
QPointF p1 = data->GetPoint(p1Id);
QPointF p4 = data->GetPoint(id);
ui->spinBoxAngle1->setValue(QLineF(p1, p4).angle());
ui->spinBoxAngle2->setValue(QLineF(p4, p1).angle());
}
if(!isInitialized){
this->show();
}
}
}
}
void DialogSpline::DialogAccepted(){
qint32 index = ui->comboBoxP1->currentIndex();
p1 = qvariant_cast<qint64>(ui->comboBoxP1->itemData(index));
index = ui->comboBoxP4->currentIndex();
p4 = qvariant_cast<qint64>(ui->comboBoxP4->itemData(index));
angle1 = ui->spinBoxAngle1->value();
angle2 = ui->spinBoxAngle2->value();
kAsm1 = ui->doubleSpinBoxKasm1->value();
kAsm2 = ui->doubleSpinBoxKasm2->value();
kCurve = ui->doubleSpinBoxKcurve->value();
emit DialogClosed(QDialog::Accepted);
}
qreal DialogSpline::getKCurve() const{
return kCurve;
}
void DialogSpline::setKCurve(const qreal &value){
kCurve = value;
ui->doubleSpinBoxKcurve->setValue(value);
}
qreal DialogSpline::getKAsm2() const{
return kAsm2;
}
void DialogSpline::setKAsm2(const qreal &value){
kAsm2 = value;
ui->doubleSpinBoxKasm2->setValue(value);
}
qreal DialogSpline::getKAsm1() const{
return kAsm1;
}
void DialogSpline::setKAsm1(const qreal &value){
kAsm1 = value;
ui->doubleSpinBoxKasm1->setValue(value);
}
qreal DialogSpline::getAngle2() const{
return angle2;
}
void DialogSpline::setAngle2(const qreal &value){
angle2 = value;
ui->spinBoxAngle2->setValue(value);
}
qreal DialogSpline::getAngle1() const{
return angle1;
}
void DialogSpline::setAngle1(const qreal &value){
angle1 = value;
ui->spinBoxAngle1->setValue(value);
}
qint64 DialogSpline::getP4() const{
return p4;
}
void DialogSpline::setP4(const qint64 &value){
p4 = value;
ChangeCurrentData(ui->comboBoxP4, value);
}
qint64 DialogSpline::getP1() const{
return p1;
}
void DialogSpline::setP1(const qint64 &value){
p1 = value;
ChangeCurrentData(ui->comboBoxP1, value);
}

46
dialogs/dialogspline.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef DIALOGSPLINE_H
#define DIALOGSPLINE_H
#include "dialogtool.h"
#include "../container/vcontainer.h"
namespace Ui {
class DialogSpline;
}
class DialogSpline : public DialogTool
{
Q_OBJECT
public:
explicit DialogSpline(const VContainer *data, QWidget *parent = 0);
~DialogSpline();
qint64 getP1() const;
void setP1(const qint64 &value);
qint64 getP4() const;
void setP4(const qint64 &value);
qreal getAngle1() const;
void setAngle1(const qreal &value);
qreal getAngle2() const;
void setAngle2(const qreal &value);
qreal getKAsm1() const;
void setKAsm1(const qreal &value);
qreal getKAsm2() const;
void setKAsm2(const qreal &value);
qreal getKCurve() const;
void setKCurve(const qreal &value);
public slots:
virtual void ChoosedObject(qint64 id, Scene::Type type);
virtual void DialogAccepted();
private:
Ui::DialogSpline *ui;
qint32 number;
qint64 p1; // перша точка
qint64 p4; // четверта точка
qreal angle1; // кут нахилу дотичної в першій точці
qreal angle2; // кут нахилу дотичної в другій точці
qreal kAsm1;
qreal kAsm2;
qreal kCurve;
};
#endif // DIALOGSPLINE_H

230
dialogs/dialogspline.ui Normal file
View File

@ -0,0 +1,230 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogSpline</class>
<widget class="QDialog" name="DialogSpline">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>524</width>
<height>254</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Перша точка </string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxP1"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Коефіцієнт довжини першої контрольної точки</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBoxKasm1">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Кут першої контрольної точки</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxAngle1">
<property name="maximum">
<number>360</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Друга точка</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxP4"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Коефіцієнт довжини другої контрольної точки</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBoxKasm2">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Кут другої контрольної точки</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxAngle2">
<property name="maximum">
<number>360</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Коефіцієнт кривизни сплайну</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBoxKcurve">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>72</width>
<height>0</height>
</size>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogSpline</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogSpline</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -170,7 +170,7 @@ void DialogTool::CheckState(){
}
void DialogTool::ChoosedPoint(qint64 id, Scene::Type type){
void DialogTool::ChoosedObject(qint64 id, Scene::Type type){
Q_UNUSED(id);
Q_UNUSED(type);
}

View File

@ -22,7 +22,7 @@ public:
signals:
void DialogClosed(int result);
public slots:
virtual void ChoosedPoint(qint64 id, Scene::Type type);
virtual void ChoosedObject(qint64 id, Scene::Type type);
void NamePointChanged();
virtual void DialogAccepted();
virtual void DialogRejected();

1792
docs/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

294
geometry/varc.cpp Normal file
View File

@ -0,0 +1,294 @@
#define _USE_MATH_DEFINES
#include <cmath>
#include "varc.h"
#include <QDebug>
VArc::VArc (){
f1 = 0;
f2 = 0;
length = 0;
radius = 0;
center = 0;
p1 = QPointF( 0, 0 );
p2 = QPointF( 0, 0 );
points = 0;
}
VArc::VArc (const QMap<qint64, VPointF> *points, qint64 center, qreal radius, qreal f1, qreal f2 ){
this->points = points;
ModifiArc( center, radius, f1, f2 );
}
qreal VArc::GetF1 () const{
return f1;
}
qreal VArc::GetF2 () const{
return f2;
}
qreal VArc::GetLength () const{
return length;
}
qreal VArc::GetRadius () const{
return radius;
}
qint64 VArc::GetCenter() const{
return center;
}
QPointF VArc::GetCenterPoint() const{
if(points->contains(center)){
return points->value(center);
} else {
qCritical()<<"Не можу знайти id = "<<center<<" в таблиці.";
throw"Не можу знайти точку за id.";
}
return QPointF();
}
QPointF VArc::GetP1() const{
return p1;
}
QPointF VArc::GetP2 () const{
return p2;
}
const QMap<qint64, VPointF> *VArc::GetDataPoints() const{
return points;
}
void VArc::ModifiArc (qint64 center, qreal radius, qreal f1, qreal f2 ){
this->f1 = f1;
this->f2 = f2;
this->radius = radius;
this->center = center;
QPointF p1 ( GetCenterPoint().x () + radius, GetCenterPoint().y () );
QLineF centerP1(GetCenterPoint(), p1);
centerP1.setAngle(f1);
p1 = centerP1.p2();
QPointF p2 ( GetCenterPoint().x () + radius, GetCenterPoint().y () );
QLineF centerP2(GetCenterPoint(), p2);
centerP2.setAngle(f2);
p2 = centerP2.p2();
this->p1 = p1;
this->p2 = p2;
// визначимо довжину дуги за формулою.
// МОЖЛИВО НЕ ПРАВИЛЬНО. ПОТРІБНО ПЕРЕВІРИТИ ФОРМУЛУ, ОСКІЛЬКИ КУТ ПОВЕРТАЄТЬСЯ В ГРАДУСАХ!!!!!
//qreal ang = AngleArc ( f1, f2 ) ;
qreal ang = centerP1.angleTo(centerP2);
this->length = ang * radius * M_PI/180;
//qDebug()<<"ang = "<<ang<<"length ="<<length;
}
//void VArc::BiasArc ( qreal mx, qreal my ){
// this->center = QPointF( center.x()+mx, center.y()+my );
// this->p1 = QPointF( p1.x()+mx, p1.y()+my );
// this->p2 = QPointF( p2.x()+mx, p2.y()+my );
//}
//void VArc::RotationArc (QPointF pRotate, qreal angle ){
// QLineF pRotateCenter( pRotate, center );
// pRotateCenter.setAngle( angle );
// center = pRotateCenter.p2();
// QLineF pRotateP1( pRotate, p1 );
// pRotateP1.setAngle( angle );
// p1 = pRotateP1.p2();
// QLineF pRotateP2( pRotate, p2 );
// pRotateP2.setAngle( angle );
// p2 = pRotateP2.p2();
// QLineF centerP1 ( center, p1 );
// QLineF centerP2 ( center, p2 );
// f1 = centerP1.angle();
// f2 = centerP2.angle();
//}
VSpline VArc::SplOfArc ( qint32 number ) const{
qint32 n = NumberSplOfArc ();
if( number > n ){
throw "Дуга не складається з такої кількості сплайнів.";
}
qreal f1 = GetF1 ();
qreal f2 = GetF2 ();
qint32 i;
for ( i = 0; i < n; ++i ){
if ( i == n - 1 ){
f2 = GetF2 ();
} else {
if ( f1 + 90 > 360 ){
f2 = f1 + 90 - 360;
} else {
f2 = f1 + 90;
}
}
qreal anglF1, anglF2;
if ( f1 + 90 > 360 ){
anglF1 = f1 + 90 - 360 ;
} else {
anglF1 = f1 + 90 ;
}
if ( f2 - 90 < 0 ){
anglF2 = 360 + f2 - 90 ;
} else {
anglF2 = f2 - 90 ;
}
if ( i + 1 == number ){
// return VSpline (GetDataPoints(), GetP1 (), GetP2 (), anglF1, anglF2, 1., 1., 1. );
f1 = f2;
}
}
return VSpline();
}
//void VArc::CutArc ( qreal length, VArc &arcFir, VArc &arcSec ) const{
// if ( length > GetLength () ){
// qDebug()<<"Не правильна довжина дуги/n";
// exit(-1);
// }
// qreal angle;
// angle = GetF1 () + (length * 180) / (radius * M_PI);
// arcFir.ModifiArc ( GetCenter (), GetRadius (), GetF1 (), angle );
// arcSec.ModifiArc ( GetCenter (), GetRadius (), angle, GetF2 () );
//}
//void VArc::CutArc ( QPointF point, VArc &arcFir, VArc &arcSec ) const{
// VArc arc = VArc(center,radius, f1, QLineF(center, point).angle());
// if(this->length<arc.GetLength()){
// throw"Не можу розрізати дугу. Не правильна точка.";
// } else {
// CutArc ( arc.GetLength(), arcFir, arcSec );
// }
//}
QLineF::IntersectType VArc::CrossingArcLine ( const QLineF &line, QPointF *intersectionPoint ) const{
qint32 i, n;
QLineF::IntersectType type = QLineF::NoIntersection;
n = NumberSplOfArc ();
for ( i = 0; i < n; ++i ){
VSpline curve = SplOfArc ( i + 1 );
QPointF crosPoint;
type = curve.CrossingSplLine ( line, &crosPoint );
if ( type == QLineF::BoundedIntersection ){
*intersectionPoint = crosPoint;
return type;
} else{
if ( type == QLineF::NoIntersection || type == QLineF::UnboundedIntersection ){
throw "Не можу знайти точку перетину сплайну з лінією.";
}
}
}
}
qint32 VArc::NumberSplOfArc () const{
qint32 angArc = ( qint32 ) AngleArc ( GetF1 (), GetF2 () );
switch( angArc ){
case 0:
throw "Кут дуги не може бути 0 градусів.";
break;
case 90:
return 1;
case 180:
return 2;
case 270:
return 3;
case 360:
return 4;
default :
return ( qint32 ) AngleArc ( GetF1 (), GetF2 () ) / 90 + 1;
}
}
qreal VArc::AngleArc( qreal f1, qreal f2 ) const{
QLineF normal = QLineF( 0, 0, 100, 0 );
normal.setAngle(f1);
QLineF normal2 = QLineF( 0, 0, 100, 0 );
normal2.setAngle(f2);
return normal.angleTo(normal2);
}
QPainterPath VArc::GetPath() const{
QPainterPath Path;
qint32 numberSpl = NumberSplOfArc();
for(qint32 i = 1; i <= numberSpl; ++i){
VSpline spl = SplOfArc ( i );
Path.addPath( spl.GetPath() );
}
return Path;
}
QVector<QPointF> VArc::GetPoints () const{
QVector<QPointF> points;
qint32 numberSpl = NumberSplOfArc();
for(qint32 i = 1; i <= numberSpl; ++i){
VSpline spl = SplOfArc ( i );
points<<spl.GetPoints();
}
return points;
}
QPointF VArc::Tangent(const QPointF P, Tangent_e tan)const{
QLineF CP = QLineF(GetCenterPoint(),P);
CP.setLength(CP.length()/2);
QPointF O = CP.p2();
QLineF CO = QLineF(GetCenterPoint(),O);
qreal d = CO.length();
if ( d > GetRadius() + CO.length() ){
throw"Немає перетину кіл для знаходження дотичних.";
}
if ( d < qAbs(GetRadius() - CO.length()) ){
throw"Не можу знайти дотичну. Одне коло знаходиться в іншому.";
}
qreal a = (pow(GetRadius(),2) - pow(CO.length(),2) + pow(d,2) ) / (2*d);
qreal h = sqrt(pow(GetRadius(),2) - pow(a,2));
qreal x2 = GetCenterPoint().x() + a * (O.x() - GetCenterPoint().x())/d;
qreal y2 = GetCenterPoint().y() + a * (O.y() - GetCenterPoint().y())/d;
if(tan == VArc::FirstTangent){
qreal x3 = x2 - h * ( O.y() - GetCenterPoint().y() ) / d;
qreal y3 = y2 + h * ( O.x() - GetCenterPoint().x() ) / d;
return QPointF(x3,y3);
} else {
qreal x3 = x2 + h * ( O.y() - GetCenterPoint().y() ) / d;
qreal y3 = y2 - h * ( O.x() - GetCenterPoint().x() ) / d;
return QPointF(x3,y3);
}
}
bool VArc::Contains(const QPointF P)const{
QVector<QPointF> points = GetPoints ();
for(qint32 i=0; i< points.size();++i){
if((qint32)points[i].x()==(qint32)P.x() && (qint32)points[i].y()==(qint32)P.y()){
return true;
}
}
return false;
}
QPointF VArc::PutAlongArc(qreal length) const{
if(GetLength()<length){
throw"Довжина дуги менше заданої довжини";
} else {
qreal n = (length*180)/(M_PI*GetRadius());
QLineF CP1 = QLineF(GetCenterPoint(),GetP1());
CP1.setAngle(CP1.angle()+n);
return CP1.p2();
}
}
//void VArc::Mirror(const QPointF Pmirror){
// QPointF Center = center;
// Center = QPointF(Center.x() - Pmirror.x(), Center.y() - Pmirror.y());
// Center = QPointF(Center.x() * -1.0, Center.y() * 1.0);
// Center = QPointF(Center.x() + Pmirror.x(), Center.y() + Pmirror.y());
// QPointF P1 = p1;
// P1 = QPointF(P1.x() - Pmirror.x(), P1.y() - Pmirror.y());
// P1 = QPointF(P1.x() * -1.0, P1.y() * 1.0);
// P1 = QPointF(P1.x() + Pmirror.x(), P1.y() + Pmirror.y());
// QPointF P2 = p2;
// P2 = QPointF(P2.x() - Pmirror.x(), P2.y() - Pmirror.y());
// P2 = QPointF(P2.x() * -1.0, P2.y() * 1.0);
// P2 = QPointF(P2.x() + Pmirror.x(), P2.y() + Pmirror.y());
// this->ModifiArc ( Center, radius, QLineF(Center,P2).angle(), QLineF(Center,P1).angle() );
//}

192
geometry/varc.h Normal file
View File

@ -0,0 +1,192 @@
#ifndef VARC_H
#define VARC_H
#include "vspline.h"
#include <QPainterPath>
#include <QVector>
#include <QMap>
#include "container/vpointf.h"
/**
* @brief VArc клас, що реалізує дугу. Дуга розраховується за годиниковою стрілкою.
*/
class VArc{
public:
enum Tangent_e { FirstTangent, SecondTangent };
/**
* @brief VArc конструктор по замовчуванню.
*/
VArc ();
/**
* @brief VArc конструктор.
* @param center точка центру.
* @param radius радіус.
* @param f1 початковий кут в градусах.
* @param f2 кінцевий кут в градусах.
*/
VArc ( const QMap<qint64, VPointF> *points, qint64 center, qreal radius, qreal f1,
qreal f2 );
/**
* @brief GetF1 повертає початковий кут дуги.
* @return повертає кут в градусах.
*/
qreal GetF1 () const;
/**
* @brief GetF2 повертає кінцевий кут дуги.
* @return повертає кут в градусах.
*/
qreal GetF2 () const;
/**
* @brief GetLength повертає довжину дуги.
* @return повертає довжину дуги.
*/
qreal GetLength () const;
/**
* @brief GetRadius повертає радіус дуги.
* @return повертає радіус дуги.
*/
qreal GetRadius () const;
/**
* @brief GetCenter повертає точку центра дуги.
* @return повертає точку центра дуги.
*/
qint64 GetCenter () const;
QPointF GetCenterPoint() const;
/**
* @brief GetP1 повертає першу точку з якої починається дуга.
* @return точку початку дуги.
*/
QPointF GetP1 () const;
/**
* @brief GetP2 повертає другу точку в якій закінчується дуга.
* @return точку кінця дуги.
*/
QPointF GetP2 () const;
const QMap<qint64, VPointF> *GetDataPoints() const;
/**
* @brief ModifiArc змінює параметри дуги.
* @param center новий центр дуги.
* @param radius новий радіус дуги.
* @param f1 новий початковий кут в градусах.
* @param f2 новий кінцевий кут в градусах.
*/
void ModifiArc (qint64 center, qreal radius, qreal f1, qreal f2 );
/**
* @brief BiasArc зміщує дугу.
* @param mx зміщення по х координаті.
* @param my зміщення по у координаті.
*/
// void BiasArc ( qreal mx, qreal my );
/**
* @brief RotationArc повертає дугу на кут проти годиникової стрілки відносно точки.
* @param pRotate точка відносно якої повертається.
* @param angle кут в градусах на який повертається в градусах.
*/
// void RotationArc ( QPointF pRotate, qreal angle );
/**
* @brief SplOfArc повертає сплайн дуги за номером.
* @param number номер сплайна в дузі.
* @return сплайн.
*/
VSpline SplOfArc ( qint32 number ) const;
/**
* @brief CutArc розрізає дугу на дві дуги.
* @param length довжина першої дуги.
* @param arcFir перша дуга.
* @param arcSec друга дуга.
*/
// void CutArc ( qreal length, VArc &arcFir, VArc &arcSec ) const;
/**
* @brief CutArc розрізає дугу на дві дуги.
* @param point точка яка ділить дугу.
* @param arcFir перша дуга.
* @param arcSec друга дуга.
*/
// void CutArc ( QPointF point, VArc &arcFir, VArc &arcSec ) const;
/**
* @brief CrossingArcLine перевіряє перетин дуги і лінії.
* @param line лінія з якою шукаємо перетин.
* @param intersectionPoint точка перетину.
* @return результат перевірки на перетин.
*/
QLineF::IntersectType CrossingArcLine(const QLineF &line, QPointF *intersectionPoint) const;
/**
* @brief NumberSplOfArc метод шукає кілкість сплайнів які необхідні для відтворення такої дуги.
* @return кількість сплайнів.
*/
qint32 NumberSplOfArc () const;
/**
* @brief GetPath будує шлях по даній дузі.
* @return повертає шлях.
*/
QPainterPath GetPath() const;
/**
* @brief GetPoints повертає набір точок по яких можна побудувати дугу.
* @return набір точок дуги.
*/
QVector<QPointF>
GetPoints () const;
/**
* @brief Tangent розраховує дотичну до дуги.
* @param P точка через, що не належить дузі, через яку проходить дотична.
* @param tan перша чи друга дотична.
* @return точку дотичної на дузі.
*/
QPointF Tangent(const QPointF P,VArc::Tangent_e tan = VArc::FirstTangent)const;
/**
* @brief Contains перевіряє чи точка належить дузі.
* @param P точка що перевіряється.
* @return true - належить дузі, false - не належить дузі.
*/
bool Contains(const QPointF P)const;
/**
* @brief PutAlongArc розміщує точку на дузі.
* @param length довжина від початку дуги.
* @return точка що лежить на дузі.
*/
QPointF PutAlongArc(qreal length) const;
/**
* @brief Mirror дзеркальне відображення дуги.
* @param Pmirror точка відносно якої відбувається дзеркалення.
*/
// void Mirror(const QPointF Pmirror);
private:
/**
* @brief f1 початковий кут в градусах
*/
qreal f1; // початковий кут нахилу дуги (градуси)
/**
* @brief f2 кінцевий кут в градусах
*/
qreal f2; // кінцевий кут нахилу дуги (градуси)
/**
* @brief length довжина дуги.
*/
qreal length; // довжина дуги
/**
* @brief radius радіус дуги.
*/
qreal radius;
/**
* @brief center центральна точка дуги.
*/
qint64 center;
/**
* @brief p1 точка початку побудови дуги.
*/
QPointF p1;
/**
* @brief p2 кінцева точка побудови дуги.
*/
QPointF p2;
const QMap<qint64, VPointF> *points;
/**
* @brief AngleArc визначає кут дуги.
* @param f1 початковий кут дуги в градусах.
* @param f2 кінцевий кут в градусах.
* @return повертає кут в градусах.
*/
qreal AngleArc(qreal f1, qreal f2 ) const;
};
#endif // VARC_H

729
geometry/vspline.cpp Normal file
View File

@ -0,0 +1,729 @@
#define _USE_MATH_DEFINES
#include <cmath>
#include "vspline.h"
#include <QDebug>
VSpline::VSpline(){
p1 = 0;
p2 = QPointF();
p3 = QPointF();
p4 = 0;
angle1 = 0;
angle2 = 0;
points = 0;
kAsm1 = 1;
kAsm2 = 1;
kCurve = 1;
}
VSpline::VSpline ( const VSpline & spline ){
p1 = spline.GetP1 ();
p2 = spline.GetP2 ();
p3 = spline.GetP3 ();
p4 = spline.GetP4 ();
angle1 = spline.GetAngle1 ();
angle2 = spline.GetAngle2 ();
points = spline.GetDataPoints();
kAsm1 = spline.GetKasm1();
kAsm2 = spline.GetKasm2();
kCurve = spline.GetKcurve();
}
VSpline::VSpline (const QMap<qint64, VPointF> *points, qint64 p1, qint64 p4, qreal angle1, qreal angle2,
qreal kAsm1, qreal kAsm2 , qreal kCurve){
this->points = points;
ModifiSpl ( p1, p4, angle1, angle2, kAsm1, kAsm2, kCurve );
}
VSpline::VSpline (const QMap<qint64, VPointF> *points, qint64 p1, QPointF p2, QPointF p3, qint64 p4,
qreal kCurve){
this->points = points;
ModifiSpl ( p1, p2, p3, p4, kCurve);
}
void VSpline::ModifiSpl ( qint64 p1, qint64 p4, qreal angle1, qreal angle2,
qreal kAsm1, qreal kAsm2, qreal kCurve){
this->p1 = p1;
this->p4 = p4;
this->angle1 = angle1;
this->angle2 = angle2;
this->kAsm1 = kAsm1;
this->kAsm2 = kAsm2;
this->kCurve = kCurve;
QLineF p1pX(GetPointP1().x(), GetPointP1().y(), GetPointP1().x() + 100, GetPointP1().y());
p1pX.setAngle( angle1 );
qreal L = 0, radius = 0, angle = 90;
// angle = QLineF(GetPointP1(), p1pX.p2()).angleTo(QLineF(GetPointP1(), GetPointP4()));
// if ( angle > 180 ){
// angle = 360 - angle;
// }
QPointF point1 = GetPointP1();
QPointF point4 = GetPointP4();
radius = QLineF(QPointF(point1.x(), point4.y()),point4).length();
// radius = QLineF(GetPointP1(), GetPointP4()).length() / 2 / sin( angle * M_PI / 180.0 );
L = kCurve * radius * 4 / 3 * tan( angle * M_PI / 180.0 / 4 );
QLineF p1p2(GetPointP1().x(), GetPointP1().y(), GetPointP1().x() + L * kAsm1, GetPointP1().y());
p1p2.setAngle(angle1);
QLineF p4p3(GetPointP4().x(), GetPointP4().y(), GetPointP4().x() + L * kAsm2, GetPointP4().y());
p4p3.setAngle(angle2);
this->p2 = p1p2.p2();
this->p3 = p4p3.p2();
}
void VSpline::ModifiSpl (qint64 p1, QPointF p2, QPointF p3, qint64 p4, qreal kCurve){
this->p1 = p1;
this->p2 = p2;
this->p3 = p3;
this->p4 = p4;
this->angle1 = QLineF ( GetPointP1(), p2 ).angle();
this->angle2 = QLineF ( GetPointP4(), p3 ).angle();
QLineF p1pX(GetPointP1().x(), GetPointP1().y(), GetPointP1().x() + 100, GetPointP1().y());
p1pX.setAngle( angle1 );
qreal L = 0, radius = 0, angle = 90;
// angle = QLineF(GetPointP1(), p1pX.p2()).angleTo(QLineF(GetPointP1(), GetPointP4()));
// if ( angle >= 180 ){
// angle = 360 - angle;
// }
QPointF point1 = GetPointP1();
QPointF point4 = GetPointP4();
radius = QLineF(QPointF(point1.x(), point4.y()),point4).length();
// radius = QLineF(GetPointP1(), GetPointP4()).length() / 2 / sin( angle * M_PI / 180.0 );
L = kCurve * radius * 4 / 3 * tan( angle * M_PI / 180.0 / 4 );
this->kCurve = kCurve;
this->kAsm1 = QLineF ( GetPointP1(), p2 ).length()/L;
this->kAsm2 = QLineF ( GetPointP4(), p3 ).length()/L;
}
//void VSpline::RotationSpl (QPointF pRotate, qreal angle ){
// QLineF pRotateP1 (pRotate, p1);
// pRotateP1.setAngle(angle);
// p1 = pRotateP1.p2();
// QLineF pRotateP2 (pRotate, p2);
// pRotateP2.setAngle(angle);
// p2 = pRotateP2.p2();
// QLineF pRotateP3 (pRotate, p3);
// pRotateP3.setAngle(angle);
// p3 = pRotateP3.p2();
// QLineF pRotateP4 (pRotate, p4);
// pRotateP4.setAngle(angle);
// p4 = pRotateP4.p2();
// angle1 = QLineF(p1, p2).angle();
// angle2 = QLineF(p4, p2).angle();
//}
//void VSpline::BiasSpl ( qreal mx, qreal my ){
// p1 = QPointF(p1.x()+mx, p1.y()+my);
// p2 = QPointF(p2.x()+mx, p2.y()+my);
// p3 = QPointF(p3.x()+mx, p3.y()+my);
// p4 = QPointF(p4.x()+mx, p4.y()+my);
//}
qint64 VSpline::GetP1 () const{
return p1;
}
VPointF VSpline::GetPointP1() const{
if(points->contains(p1)){
return points->value(p1);
} else {
qCritical()<<"Не можу знайти id = "<<p1<<" в таблиці.";
throw"Не можу знайти точку за id.";
}
return VPointF();
}
QPointF VSpline::GetP2 () const{
return p2;
}
QPointF VSpline::GetP3 () const{
return p3;
}
qint64 VSpline::GetP4() const{
return p4;
}
VPointF VSpline::GetPointP4() const{
if(points->contains(p4)){
return points->value(p4);
} else {
qCritical()<<"Не можу знайти id = "<<p4<<" в таблиці.";
throw"Не можу знайти точку за id.";
}
return VPointF();
}
qreal VSpline::GetAngle1() const{
return angle1;
}
qreal VSpline::GetAngle2 () const{
return angle2;
}
qreal VSpline::GetLength () const{
return LengthBezier ( GetPointP1(), this->p2, this->p3, GetPointP4());
}
QString VSpline::GetName() const{
VPointF first = GetPointP1();
VPointF second = GetPointP4();
return QString("Spl_%1_%2").arg(first.name(), second.name());
}
qreal VSpline::GetKasm1() const{
return kAsm1;
}
qreal VSpline::GetKasm2() const{
return kAsm2;
}
qreal VSpline::GetKcurve() const{
return kCurve;
}
const QMap<qint64, VPointF> *VSpline::GetDataPoints() const{
return points;
}
QLineF::IntersectType VSpline::CrossingSplLine ( const QLineF &line, QPointF *intersectionPoint ) const{
QVector<qreal> px;
QVector<qreal> py;
px.append ( GetPointP1 ().x () );
py.append ( GetPointP1 ().y () );
QVector<qreal>& wpx = px;
QVector<qreal>& wpy = py;
PointBezier_r ( GetPointP1 ().x (), GetPointP1 ().y (), GetP2 ().x (), GetP2 ().y (),
GetP3 ().x (), GetP3 ().y (), GetPointP4 ().x (), GetPointP4 ().y (),
0, wpx, wpy);
px.append ( GetPointP4 ().x () );
py.append ( GetPointP4 ().y () );
qint32 i = 0;
QPointF crosPoint;
QLineF::IntersectType type = QLineF::NoIntersection;
for ( i = 0; i < px.count()-1; ++i ){
type = line.intersect(QLineF ( QPointF ( px[i], py[i] ),
QPointF ( px[i+1], py[i+1] )), &crosPoint);
if ( type == QLineF::BoundedIntersection ){
*intersectionPoint = crosPoint;
return type;
}
}
throw "Не можу знайти точку перетину сплайну з лінією.";
}
//void VSpline::CutSpline ( qreal length, VSpline* curFir, VSpline* curSec ) const{
// if ( length > GetLength()){
// throw"Не правильна довжина нового сплайну\n";
// }
// qreal parT = length / GetLength();
// QLineF seg1_2 ( GetPointP1 (), GetP2 () );
// seg1_2.setLength(seg1_2.length () * parT);
// QPointF p12 = seg1_2.p2();
// QLineF seg2_3 ( GetP2 (), GetP3 () );
// seg2_3.setLength(seg2_3.length () * parT);
// QPointF p23 = seg2_3.p2();
// QLineF seg12_23 ( p12, p23 );
// seg12_23.setLength(seg12_23.length () * parT);
// QPointF p123 = seg12_23.p2();
// QLineF seg3_4 ( GetP3 (), GetPointP4 () );
// seg3_4.setLength(seg3_4.length () * parT);
// QPointF p34 = seg3_4.p2();
// QLineF seg23_34 ( p23, p34 );
// seg23_34.setLength(seg23_34.length () * parT);
// QPointF p234 = seg23_34.p2();
// QLineF seg123_234 ( p123, p234 );
// seg123_234.setLength(seg123_234.length () * parT);
// QPointF p1234 = seg123_234.p2();
// curFir->ModifiSpl ( GetPointP1 (), p12, p123, p1234 );
// curSec->ModifiSpl ( p1234, p234, p34, GetPointP4 () );
//}
//void VSpline::CutSpline ( QPointF point, VSpline* curFir, VSpline* curSec ) const{
// qreal t = param_t (point);
// qreal length = t*this->GetLength();
// CutSpline ( length, curFir, curSec );
//}
void VSpline::PutAlongSpl (QPointF &moveP, qreal move ) const{
if ( GetLength () < move ){
qDebug()<<"Довжина більше довжини сплайну.";
qDebug()<<GetLength()<<"<"<<move;
throw "Довжина більше довжини сплайну.";
}
if ( move <= 0 ){
qDebug()<<"Довжина менше дорівнює нулю.";
throw "Довжина менше дорівнює нулю.";
}
qreal t = 0;
if ( move == 0 ){
t = 0;
} else {
t = move / GetLength ();
moveP.setX ( pow ( 1 - t, 3 ) * GetPointP1 ().x () + 3 * t * pow ( 1 - t, 2 ) *
GetP2 ().x () + 3 * t * t * ( 1 - t ) * GetP3 ().x () +
pow ( t, 3 ) * GetPointP4 ().x () );
moveP.setY ( pow ( 1 - t, 3 ) * GetPointP1 ().y () + 3 * t * pow ( 1 - t, 2 ) *
GetP2 ().y () + 3 * t * t * ( 1 - t ) * GetP3 ().y () +
pow ( t, 3 ) * GetPointP4 ().y () );
}
}
QVector<QPointF> VSpline::GetPoints () const{
return GetPoints(GetPointP1(), p2, p3, GetPointP4());
}
QVector<QPointF> VSpline::GetPoints (QPointF p1, QPointF p2, QPointF p3, QPointF p4) const{
QVector<QPointF> pvector;
QVector<qreal> x;
QVector<qreal> y;
QVector<qreal>& wx = x;
QVector<qreal>& wy = y;
x.append ( p1.x () );
y.append ( p1.y () );
PointBezier_r ( p1.x (), p1.y (), p2.x (), p2.y (),
p3.x (), p3.y (), p4.x (), p4.y (), 0, wx, wy );
x.append ( p4.x () );
y.append ( p4.y () );
for ( qint32 i = 0; i < x.count(); ++i ){
pvector.append( QPointF ( x[i], y[i] ) );
}
return pvector;
}
qreal VSpline::LengthBezier ( QPointF p1, QPointF p2, QPointF p3, QPointF p4 ) const{
/*QVector<qreal> px;
QVector<qreal> py;
QVector<qreal>& wpx = px;
QVector<qreal>& wpy = py;
px.append ( p1.x () );
py.append ( p1.y () );
PointBezier_r ( p1.x (), p1.y (), p2.x (), p2.y (),
p3.x (), p3.y (), p4.x (), p4.y (), 0, wpx, wpy);
px.append ( p4.x () );
py.append ( p4.y () );
qint32 i = 0;
qreal length = 0.0;
/*
* Наприклад маємо 10 точок. Від 0 до 9 і останню точку не опрацьовуємо.
* Тому від 0 до 8(<10-1).
*
for ( i = 0; i < px.count() - 1; ++i ){
length += QLineF ( QPointF ( px[i], py[i] ), QPointF ( px[i+1], py[i+1] ) ).length ();
}*/
QPainterPath splinePath;
QVector<QPointF> points = GetPoints (p1, p2, p3, p4);
splinePath.moveTo(points[0]);
for (qint32 i = 1; i < points.count(); ++i){
splinePath.lineTo(points[i]);
}
return splinePath.length();
}
void VSpline::PointBezier_r ( qreal x1, qreal y1, qreal x2, qreal y2,
qreal x3, qreal y3, qreal x4, qreal y4,
qint16 level, QVector<qreal> &px, QVector<qreal> &py) const{
const double curve_collinearity_epsilon = 1e-30;
const double curve_angle_tolerance_epsilon = 0.01;
const double m_angle_tolerance = 0.0;
enum curve_recursion_limit_e { curve_recursion_limit = 32 };
const double m_cusp_limit = 0.0;
double m_approximation_scale = 1.0;
double m_distance_tolerance_square;
m_distance_tolerance_square = 0.5 / m_approximation_scale;
m_distance_tolerance_square *= m_distance_tolerance_square;
if(level > curve_recursion_limit)
{
return;
}
// Calculate all the mid-points of the line segments
//----------------------
double x12 = (x1 + x2) / 2;
double y12 = (y1 + y2) / 2;
double x23 = (x2 + x3) / 2;
double y23 = (y2 + y3) / 2;
double x34 = (x3 + x4) / 2;
double y34 = (y3 + y4) / 2;
double x123 = (x12 + x23) / 2;
double y123 = (y12 + y23) / 2;
double x234 = (x23 + x34) / 2;
double y234 = (y23 + y34) / 2;
double x1234 = (x123 + x234) / 2;
double y1234 = (y123 + y234) / 2;
// Try to approximate the full cubic curve by a single straight line
//------------------
double dx = x4-x1;
double dy = y4-y1;
double d2 = fabs(((x2 - x4) * dy - (y2 - y4) * dx));
double d3 = fabs(((x3 - x4) * dy - (y3 - y4) * dx));
double da1, da2, k;
switch(((int)(d2 > curve_collinearity_epsilon) << 1) +
(int)(d3 > curve_collinearity_epsilon))
{
case 0:
// All collinear OR p1==p4
//----------------------
k = dx*dx + dy*dy;
if(k == 0)
{
d2 = CalcSqDistance(x1, y1, x2, y2);
d3 = CalcSqDistance(x4, y4, x3, y3);
}
else
{
k = 1 / k;
da1 = x2 - x1;
da2 = y2 - y1;
d2 = k * (da1*dx + da2*dy);
da1 = x3 - x1;
da2 = y3 - y1;
d3 = k * (da1*dx + da2*dy);
if(d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1)
{
// Simple collinear case, 1---2---3---4
// We can leave just two endpoints
return;
}
if(d2 <= 0)
d2 = this->CalcSqDistance(x2, y2, x1, y1);
else if(d2 >= 1)
d2 = CalcSqDistance(x2, y2, x4, y4);
else
d2 = CalcSqDistance(x2, y2, x1 + d2*dx, y1 + d2*dy);
if(d3 <= 0)
d3 = this->CalcSqDistance(x3, y3, x1, y1);
else if(d3 >= 1)
d3 = this->CalcSqDistance(x3, y3, x4, y4);
else
d3 = CalcSqDistance(x3, y3, x1 + d3*dx, y1 + d3*dy);
}
if(d2 > d3)
{
if(d2 < m_distance_tolerance_square)
{
px.append(x2);
py.append(y2);
//m_points.add(point_d(x2, y2));
return;
}
}
else
{
if(d3 < m_distance_tolerance_square)
{
px.append(x3);
py.append(y3);
//m_points.add(point_d(x3, y3));
return;
}
}
break;
case 1:
// p1,p2,p4 are collinear, p3 is significant
//----------------------
if(d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy))
{
if(m_angle_tolerance < curve_angle_tolerance_epsilon)
{
px.append(x23);
py.append(y23);
//m_points.add(point_d(x23, y23));
return;
}
// Angle Condition
//----------------------
da1 = fabs(atan2(y4 - y3, x4 - x3) - atan2(y3 - y2, x3 - x2));
if(da1 >= M_PI)
da1 = 2*M_PI - da1;
if(da1 < m_angle_tolerance)
{
px.append(x2);
py.append(y2);
px.append(x3);
py.append(y3);
//m_points.add(point_d(x2, y2));
//m_points.add(point_d(x3, y3));
return;
}
if(m_cusp_limit != 0.0)
{
if(da1 > m_cusp_limit)
{
px.append(x3);
py.append(y3);
//m_points.add(point_d(x3, y3));
return;
}
}
}
break;
case 2:
// p1,p3,p4 are collinear, p2 is significant
//----------------------
if(d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy))
{
if(m_angle_tolerance < curve_angle_tolerance_epsilon)
{
px.append(x23);
py.append(y23);
//m_points.add(point_d(x23, y23));
return;
}
// Angle Condition
//----------------------
da1 = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1));
if(da1 >= M_PI) da1 = 2*M_PI - da1;
if(da1 < m_angle_tolerance)
{
px.append(x2);
py.append(y2);
px.append(x3);
py.append(y3);
//m_points.add(point_d(x2, y2));
//m_points.add(point_d(x3, y3));
return;
}
if(m_cusp_limit != 0.0)
{
if(da1 > m_cusp_limit)
{
px.append(x2);
py.append(y2);
//m_points.add(point_d(x2, y2));
return;
}
}
}
break;
case 3:
// Regular case
//-----------------
if((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy))
{
// If the curvature doesn't exceed the distance_tolerance value
// we tend to finish subdivisions.
//----------------------
if(m_angle_tolerance < curve_angle_tolerance_epsilon)
{
px.append(x23);
py.append(y23);
//m_points.add(point_d(x23, y23));
return;
}
// Angle & Cusp Condition
//----------------------
k = atan2(y3 - y2, x3 - x2);
da1 = fabs(k - atan2(y2 - y1, x2 - x1));
da2 = fabs(atan2(y4 - y3, x4 - x3) - k);
if(da1 >= M_PI) da1 = 2*M_PI - da1;
if(da2 >= M_PI) da2 = 2*M_PI - da2;
if(da1 + da2 < m_angle_tolerance)
{
// Finally we can stop the recursion
//----------------------
px.append(x23);
py.append(y23);
//m_points.add(point_d(x23, y23));
return;
}
if(m_cusp_limit != 0.0)
{
if(da1 > m_cusp_limit)
{
px.append(x2);
py.append(y2);
return;
}
if(da2 > m_cusp_limit)
{
px.append(x3);
py.append(y3);
return;
}
}
}
break;
}
// Continue subdivision
//----------------------
PointBezier_r(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1, px, py);
PointBezier_r(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1, px, py);
}
qreal VSpline::CalcSqDistance (qreal x1, qreal y1, qreal x2, qreal y2) const{
qreal dx = x2 - x1;
qreal dy = y2 - y1;
return dx * dx + dy * dy;
}
QPainterPath VSpline::GetPath() const{
QPainterPath splinePath;
QVector<QPointF> points = GetPoints ();
splinePath.moveTo(points[0]);
for (qint32 i = 1; i < points.count(); ++i){
splinePath.lineTo(points[i]);
}
return splinePath;
}
/* Cubic equation solution. Real coefficients case.
int Cubic(double *x,double a,double b,double c);
Parameters:
x - solution array (size 3). On output:
3 real roots -> then x is filled with them;
1 real + 2 complex -> x[0] is real, x[1] is real part of
complex roots, x[2] - non-negative
imaginary part.
a, b, c - coefficients, as described
Returns: 3 - 3 real roots;
1 - 1 real root + 2 complex;
2 - 1 real root + complex roots imaginary part is zero
(i.e. 2 real roots).
*/
qint32 VSpline::Cubic(qreal *x, qreal a, qreal b, qreal c)const{
qreal q,r,r2,q3;
q = (a*a - 3.*b)/9.;
r = (a*(2.*a*a - 9.*b) + 27.*c)/54.;
r2 = r*r;
q3 = pow(q,3);
if(r2<q3) {
qreal t = acos(r/sqrt(q3));
a/=3.;
q = -2.*sqrt(q);
x[0] = q*cos(t/3.)-a;
x[1] = q*cos((t + M_2PI)/3.) - a;
x[2] = q*cos((t - M_2PI)/3.) - a;
return(3);
} else {
qreal aa,bb;
if(r<=0.){
r=-r;
}
aa = -pow(r + sqrt(r2-q3),1./3.);
if(aa!=0.){
bb=q/aa;
} else {
bb=0.;
}
a/=3.;
q = aa+bb;
r = aa-bb;
x[0] = q-a;
x[1] = (-0.5)*q-a;
x[2] = (sqrt(3.)*0.5)*fabs(r);
if(x[2]==0.){
return(2);
}
return(1);
}
}
qreal VSpline::calc_t (qreal curve_coord1, qreal curve_coord2, qreal curve_coord3,
qreal curve_coord4, qreal point_coord) const{
qreal P1, P2, P3, P4, Bt;
qreal a, b, c, d, ret_t;
qreal *t = (qreal *)malloc(3*sizeof(qreal));
P1 = curve_coord1;
P2 = curve_coord2;
P3 = curve_coord3;
P4 = curve_coord4;
Bt = point_coord;
a = -P1 + 3*P2 - 3*P3 + P4;
b = 3*P1 - 6*P2 + 3*P3;
c = -3*P1 + 3*P2;
d = -Bt + P1;
if(Cubic(t, b/a, c/a, d/a) == 3){
ret_t = t[2];
} else {
ret_t = t[0];
}
/*
* Повертається три значення, але експереминтально знайдено що шукане
* значення знаходиться в третьому.
*/
free(t);
if(ret_t<0 || ret_t>1){
qDebug()<<"Неправильне значення параметра. фунція calc_t";
throw"Неправильне значення параметра. фунція calc_t";
}
return ret_t;
}
/*
* Функція знаходить підходяще значення параметна t якому відповідає точка на сплайні.
*/
qreal VSpline::param_t (QPointF pBt)const{
qreal t_x, t_y;
t_x = calc_t (GetPointP1().x(), p2.x(), p3.x(), GetPointP4().x(), pBt.x());
t_y = calc_t (GetPointP1().y(), p2.y(), p3.y(), GetPointP4().y(), pBt.y());
/*
* Порівнюємо значення по х і по у і визначаємо найбільше. Це значення і
* буде шуканим.
*/
if(t_x>t_y)
return t_x;
else
return t_y;
}
//void VSpline::Mirror(const QPointF Pmirror){
// QPointF P1 = p1;
// P1 = QPointF(P1.x() - Pmirror.x(), P1.y() - Pmirror.y());
// P1 = QPointF(P1.x() * -1.0, P1.y() * 1.0);
// P1 = QPointF(P1.x() + Pmirror.x(), P1.y() + Pmirror.y());
// QPointF P2 = p2;
// P2 = QPointF(P2.x() - Pmirror.x(), P2.y() - Pmirror.y());
// P2 = QPointF(P2.x() * -1.0, P2.y() * 1.0);
// P2 = QPointF(P2.x() + Pmirror.x(), P2.y() + Pmirror.y());
// QPointF P3 = p3;
// P3 = QPointF(P3.x() - Pmirror.x(), P3.y() - Pmirror.y());
// P3 = QPointF(P3.x() * -1.0, P3.y() * 1.0);
// P3 = QPointF(P3.x() + Pmirror.x(), P3.y() + Pmirror.y());
// QPointF P4 = p4;
// P4 = QPointF(P4.x() - Pmirror.x(), P4.y() - Pmirror.y());
// P4 = QPointF(P4.x() * -1.0, P4.y() * 1.0);
// P4 = QPointF(P4.x() + Pmirror.x(), P4.y() + Pmirror.y());
// this->ModifiSpl(P1, P2, P3, P4);
//}

261
geometry/vspline.h Normal file
View File

@ -0,0 +1,261 @@
#ifndef VSPLINE_H
#define VSPLINE_H
#define M_2PI 6.28318530717958647692528676655900576
#include <QPainterPath>
#include <QVector>
#include <QMap>
#include "container/vpointf.h"
/**
* @brief VSpline клас, що реалізує сплайн.
*/
class VSpline{
public:
VSpline();
/**
* @brief VSpline конструктор.
* @param spline сплайн з якого копіюємо.
*/
VSpline (const VSpline &spline );
/**
* @brief VSpline конструктор.
* @param p1 початкова точка сплайна.
* @param p4 кінцева точка сплайна.
* @param angle1 кут в градусах першої напрямної.
* @param angle2 кут в градусах другої напрямної.
* @param kCurve коефіцієнт кривизни сплайна.
* @param kAsm1 коефіцієнт довжини першої напрямної.
* @param kAsm2 коефіцієнт довжини другої напрямної.
*/
VSpline (const QMap<qint64, VPointF> *points, qint64 p1, qint64 p4, qreal angle1,
qreal angle2, qreal kAsm1, qreal kAsm2, qreal kCurve);
/**
* @brief VSpline конструктор.
* @param p1 початкова точка сплайну.
* @param p2 перша контролююча точка сплайну.
* @param p3 друга контролююча точка сплайну.
* @param p4 кінцева точка сплайну.
*/
VSpline (const QMap<qint64, VPointF> *points, qint64 p1, QPointF p2, QPointF p3,
qint64 p4, qreal kCurve);
/**
* @brief ModifiSpl модифікує сплайн.
* @param p1 початкова точка сплайну.
* @param p4 кінцева точка сплайну.
* @param angle1 кут в градусах першої напрямної.
* @param angle2 кут в градусах другої напрямної.
* @param kCurve коефіцієнт кривизни сплайну.
* @param kAsm1 коефіцієнт довжини першої напрямної.
* @param kAsm2 коефіцієнт довжини другої напрямної.
*/
void ModifiSpl ( qint64 p1, qint64 p4, qreal angle1, qreal angle2, qreal kAsm1, qreal kAsm2,
qreal kCurve);
/**
* @brief ModifiSpl модифікує сплайн.
* @param p1 початкова точка сплайну.
* @param p2 перша контролююча точка сплайну.
* @param p3 друга контролююча точка сплайну.
* @param p4 кінцева точка сплайну.
*/
void ModifiSpl (qint64 p1, QPointF p2, QPointF p3, qint64 p4, qreal kCurve);
/**
* @brief RotationSpl поворот сплайна навколо точки на кут в градусах проти годиникової стрілки.
* @param pRotate точка навколо якої повертаємо.
* @param angle кут в градусах.
*/
// void RotationSpl ( QPointF pRotate, qreal angle );
/**
* @brief BiasSpl зміщує сплайн.
* @param mx зміщення по х координаті.
* @param my зміщення по у координаті.
*/
// void BiasSpl ( qreal mx, qreal my );
/**
* @brief GetP1 повертає першу точку сплайну.
* @return перша точка сплайну.
*/
qint64 GetP1 () const;
VPointF GetPointP1() const;
/**
* @brief GetP2 повертує першу контрольну точку сплайну.
* @return перша контрольна точка сплайну.
*/
QPointF GetP2 () const;
/**
* @brief GetP3 повертає другу контрольну точку сплайну.
* @return друга контрольна точка сплайну.
*/
QPointF GetP3 () const;
/**
* @brief GetP4 повертає останню точку сплайну.
* @return остання точка сплайну.
*/
qint64 GetP4 () const;
VPointF GetPointP4 () const;
/**
* @brief GetAngle1 повертає кут першої напрямної.
* @return кут в градусах.
*/
qreal GetAngle1 () const;
/**
* @brief GetAngle2 повертає кут другої напрямної.
* @return кут в градусах.
*/
qreal GetAngle2() const;
/**
* @brief GetLength повертає довжину сплайну.
* @return довжина сплайну.
*/
qreal GetLength () const;
QString GetName () const;
qreal GetKasm1() const;
qreal GetKasm2() const;
qreal GetKcurve() const;
const QMap<qint64, VPointF> *GetDataPoints() const;
/**
* @brief CrossingSplLine перевіряє перетин сплайну з лінією.
* @param line лінія з якою перевіряється перетин.
* @param intersectionPoint точка перетину.
* @return результат перевірки.
*/
QLineF::IntersectType CrossingSplLine(const QLineF &line, QPointF *intersectionPoint ) const;
/**
* @brief CutSpline розрізає сплайн.
* @param length дожина першого сплайну.
* @param curFir перший сплайн.
* @param curSec другий сплайн.
*/
// void CutSpline ( qreal length, VSpline* curFir, VSpline* curSec ) const;
/**
* @brief CutSpline розрізає сплайн.
* @param point точка що ділить сплайн.
* @param curFir перший сплайн.
* @param curSec другий сплайн.
*/
// void CutSpline (QPointF point, VSpline* curFir, VSpline* curSec ) const;
/**
* @brief PutAlongSpl розміщає точку на сплайні.
* @param moveP точка яка розміщується на сплайні.
* @param move довжина від початку сплайну.
*/
void PutAlongSpl ( QPointF &moveP, qreal move ) const;
/**
* @brief GetPoints повертає точки з яких складається сплайн.
* @return список точок.
*/
QVector<QPointF> GetPoints () const;
/**
* @brief GetPath повертає шлях сплайну.
* @return шлях.
*/
QPainterPath GetPath() const;
/**
* @brief Mirror вертикальне дзеркалення сплайну відносно точки.
* @param Pmirror точка відносно якої відбувається вертикальне дзеркалення сплайну.
*/
// void Mirror(const QPointF Pmirror);
protected:
/**
* @brief GetPoints повертає точки з яких складається сплайн.
* @param p1 початкова точка сплайну.
* @param p2 перша контролююча точка сплайну.
* @param p3 друга контролююча точка сплайну.
* @param p4 кінцева точка сплайну.
* @return список точок.
*/
QVector<QPointF> GetPoints ( QPointF p1, QPointF p2, QPointF p3, QPointF p4 ) const;
private:
/**
* @brief p1 початкова точка сплайну
*/
qint64 p1; // перша точка
/**
* @brief p2 перша контрольна точка сплайну.
*/
QPointF p2; // друга точка
/**
* @brief p3 друга контрольна точка сплайну.
*/
QPointF p3; // третя точка
/**
* @brief p4 кінцеві точка сплайну.
*/
qint64 p4; // четверта точка
/**
* @brief angle1 кут в градусах першої напрямної.
*/
qreal angle1; // кут нахилу дотичної в першій точці
/**
* @brief angle2 кут в градусах другої напрямної.
*/
qreal angle2; // кут нахилу дотичної в другій точці
qreal kAsm1;
qreal kAsm2;
qreal kCurve;
const QMap<qint64, VPointF> *points;
/**
* @brief LengthBezier повертає дожину сплайну за його чотирьма точками.
* @param p1 початкова точка сплайну.
* @param p2 перша контролююча точка сплайну.
* @param p3 друга контролююча точка сплайну.
* @param p4 кінцева точка сплайну.
* @return дожина сплайну.
*/
qreal LengthBezier ( QPointF p1, QPointF p2, QPointF p3, QPointF p4 ) const;
/**
* @brief PointBezier_r знаходить точки сплайну по його чотирьом точках.
* @param x1 х координата першої точки сплайну.
* @param y1 у координата другої точки сплайну.
* @param x2 х координата першої контрольної точки сплайну.
* @param y2 у координата першої контрольної точки сплайну.
* @param x3 х координата другої контрольної точки сплайну.
* @param y3 у координата другої контрольної точки сплайну.
* @param x4 х координата кінцевої точки сплайну.
* @param y4 у координата кінцевої точки сплайну.
* @param level рівень рекурсії. Напочатку повинен дорівнювати 0.
* @param px список х координат точок сплайну.
* @param py список у коодринат сплайну.
*/
void PointBezier_r ( qreal x1, qreal y1, qreal x2, qreal y2,
qreal x3, qreal y3, qreal x4, qreal y4,
qint16 level, QVector<qreal> &px, QVector<qreal> &py) const;
/**
* @brief CalcSqDistance розраховує довжину між точками.
* @param x1 х координата першої точки.
* @param y1 у координата другої точки.
* @param x2 х координата першої точки.
* @param y2 у координата другої точки.
* @return довжину.
*/
qreal CalcSqDistance ( qreal x1, qreal y1, qreal x2, qreal y2) const;
/**
* @brief Cubic знаходить розв'язок кубічного рівняння.
* @param x коефіцієнт.
* @param a коефіцієнт.
* @param b коефіцієнт.
* @param c коефіцієнт.
* @return повертає корені рівняння.
*/
qint32 Cubic(qreal *x, qreal a, qreal b, qreal c)const;
/**
* @brief calc_t знаходить параметр t якому відповідає точка на сплайні.
* @param curve_coord1 координата Х або У кривої.
* @param curve_coord2 координата Х або У кривої.
* @param curve_coord3 координата Х або У кривої.
* @param curve_coord4 координата Х або У кривої.
* @param point_coord координата Х або У точки на кривій.
* @return
*/
qreal calc_t (qreal curve_coord1, qreal curve_coord2, qreal curve_coord3,
qreal curve_coord4, qreal point_coord)const;
/**
* @brief param_t знаходить підходяще значення параметра t якому відповідає точка на сплайні
* @param pBt точка для якої шукається значення параметра t.
* @return підходяще значення t.
*/
qreal param_t (QPointF pBt)const;
};
#endif // VSPLINE_H

View File

@ -25,5 +25,6 @@
<file>icon/32x32/normal.png</file>
<file>icon/32x32/bisector.png</file>
<file>icon/32x32/intersect.png</file>
<file>icon/32x32/spline.png</file>
</qresource>
</RCC>

BIN
icon/32x32/spline.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

View File

@ -18,6 +18,8 @@
#include "tools/vtoolnormal.h"
#include "tools/vtoolbisector.h"
#include "tools/vtoollineintersect.h"
#include "tools/vtoolspline.h"
#include "geometry/vspline.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow)
@ -61,6 +63,8 @@ MainWindow::MainWindow(QWidget *parent) :
&MainWindow::ToolBisector);
connect(ui->toolButtonLineIntersect, &QToolButton::clicked, this,
&MainWindow::ToolLineIntersect);
connect(ui->toolButtonSpline, &QToolButton::clicked, this,
&MainWindow::ToolSpline);
data = new VContainer;
CreateManTableIGroup ();
@ -181,7 +185,7 @@ void MainWindow::ToolEndLine(bool checked){
helpLabel->setText("Заповніть усі поля.");
dialogEndLine = new DialogEndLine(data, this);
connect(scene, &VMainGraphicsScene::ChoosedObject, dialogEndLine,
&DialogEndLine::ChoosedPoint);
&DialogEndLine::ChoosedObject);
connect(dialogEndLine, &DialogEndLine::DialogClosed, this,
&MainWindow::ClosedDialogEndLine);
connect(doc, &VDomDocument::FullUpdateFromFile, dialogEndLine, &DialogEndLine::UpdateList);
@ -211,7 +215,7 @@ void MainWindow::ClosedDialogEndLine(int result){
VToolEndLine *point = new VToolEndLine(doc, data, id, typeLine, formula, angle, basePointId,
Tool::FromGui);
scene->addItem(point);
connect(point, &VToolPoint::ChoosedPoint, scene, &VMainGraphicsScene::ChoosedItem);
connect(point, &VToolPoint::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
}
@ -227,7 +231,7 @@ void MainWindow::ToolLine(bool checked){
ui->graphicsView->setCursor(cur);
helpLabel->setText("Виберіть точки.");
dialogLine = new DialogLine(data, this);
connect(scene, &VMainGraphicsScene::ChoosedObject, dialogLine, &DialogLine::ChoosedPoint);
connect(scene, &VMainGraphicsScene::ChoosedObject, dialogLine, &DialogLine::ChoosedObject);
connect(dialogLine, &DialogLine::DialogClosed, this, &MainWindow::ClosedDialogLine);
} else {
ui->toolButtonLine->setChecked(true);
@ -243,7 +247,7 @@ void MainWindow::ClosedDialogLine(int result){
qint64 id = data->getNextId();
VToolLine *line = new VToolLine(doc, data, id, firstPoint, secondPoint, Tool::FromGui);
scene->addItem(line);
connect(line, &VToolLine::ChoosedPoint, scene, &VMainGraphicsScene::ChoosedItem);
connect(line, &VToolLine::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
ArrowTool();
@ -258,7 +262,7 @@ void MainWindow::ToolAlongLine(bool checked){
ui->graphicsView->setCursor(cur);
helpLabel->setText("Виберіть точки.");
dialogAlongLine = new DialogAlongLine(data, this);
connect(scene, &VMainGraphicsScene::ChoosedObject, dialogAlongLine, &DialogAlongLine::ChoosedPoint);
connect(scene, &VMainGraphicsScene::ChoosedObject, dialogAlongLine, &DialogAlongLine::ChoosedObject);
connect(dialogAlongLine, &DialogLine::DialogClosed, this, &MainWindow::ClosedDialogAlongLine);
} else {
ui->toolButtonAlongLine->setChecked(true);
@ -287,7 +291,7 @@ void MainWindow::ClosedDialogAlongLine(int result){
VToolAlongLine *point = new VToolAlongLine(doc, data, id, formula, firstPointId, secondPointId,
typeLine, Tool::FromGui);
scene->addItem(point);
connect(point, &VToolAlongLine::ChoosedPoint, scene, &VMainGraphicsScene::ChoosedItem);
connect(point, &VToolAlongLine::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
}
ArrowTool();
@ -303,7 +307,7 @@ void MainWindow::ToolShoulderPoint(bool checked){
helpLabel->setText("Виберіть точки.");
dialogShoulderPoint = new DialogShoulderPoint(data, this);
connect(scene, &VMainGraphicsScene::ChoosedObject, dialogShoulderPoint,
&DialogShoulderPoint::ChoosedPoint);
&DialogShoulderPoint::ChoosedObject);
connect(dialogShoulderPoint, &DialogShoulderPoint::DialogClosed, this,
&MainWindow::ClosedDialogShoulderPoint);
} else {
@ -336,7 +340,7 @@ void MainWindow::ClosedDialogShoulderPoint(int result){
VToolShoulderPoint *point = new VToolShoulderPoint(doc, data, id, typeLine, formula, p1Line,
p2Line, pShoulder, Tool::FromGui);
scene->addItem(point);
connect(point, &VToolShoulderPoint::ChoosedPoint, scene, &VMainGraphicsScene::ChoosedItem);
connect(point, &VToolShoulderPoint::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
}
ArrowTool();
@ -352,7 +356,7 @@ void MainWindow::ToolNormal(bool checked){
helpLabel->setText("Виберіть точки.");
dialogNormal = new DialogNormal(data, this);
connect(scene, &VMainGraphicsScene::ChoosedObject, dialogNormal,
&DialogNormal::ChoosedPoint);
&DialogNormal::ChoosedObject);
connect(dialogNormal, &DialogNormal::DialogClosed, this,
&MainWindow::ClosedDialogNormal);
} else {
@ -383,7 +387,7 @@ void MainWindow::ClosedDialogNormal(int result){
VToolNormal *point = new VToolNormal(doc, data, id, typeLine, formula, angle, firstPointId,
secondPointId, Tool::FromGui);
scene->addItem(point);
connect(point, &VToolNormal::ChoosedPoint, scene, &VMainGraphicsScene::ChoosedItem);
connect(point, &VToolNormal::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
}
ArrowTool();
@ -399,7 +403,7 @@ void MainWindow::ToolBisector(bool checked){
helpLabel->setText("Виберіть точки.");
dialogBisector = new DialogBisector(data, this);
connect(scene, &VMainGraphicsScene::ChoosedObject, dialogBisector,
&DialogBisector::ChoosedPoint);
&DialogBisector::ChoosedObject);
connect(dialogBisector, &DialogBisector::DialogClosed, this,
&MainWindow::ClosedDialogBisector);
} else {
@ -431,7 +435,7 @@ void MainWindow::ClosedDialogBisector(int result){
VToolBisector *point = new VToolBisector(doc, data, id, typeLine, formula, firstPointId,
secondPointId, thirdPointId, Tool::FromGui);
scene->addItem(point);
connect(point, &VToolBisector::ChoosedPoint, scene, &VMainGraphicsScene::ChoosedItem);
connect(point, &VToolBisector::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
}
ArrowTool();
@ -447,7 +451,7 @@ void MainWindow::ToolLineIntersect(bool checked){
helpLabel->setText("Виберіть точки.");
dialogLineIntersect = new DialogLineIntersect(data, this);
connect(scene, &VMainGraphicsScene::ChoosedObject, dialogLineIntersect,
&DialogLineIntersect::ChoosedPoint);
&DialogLineIntersect::ChoosedObject);
connect(dialogLineIntersect, &DialogLineIntersect::DialogClosed, this,
&MainWindow::ClosedDialogLineIntersect);
} else {
@ -480,14 +484,52 @@ void MainWindow::ClosedDialogLineIntersect(int result){
data->AddLine(id, p2Line2Id);
VToolLineIntersect *point = new VToolLineIntersect(doc, data, id, p1Line1Id,
p2Line1Id, p1Line2Id,
p2Line2Id, Tool::FromFile);
p2Line2Id, Tool::FromGui);
scene->addItem(point);
connect(point, &VToolLineIntersect::ChoosedPoint, scene, &VMainGraphicsScene::ChoosedItem);
connect(point, &VToolLineIntersect::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
}
ArrowTool();
}
void MainWindow::ToolSpline(bool checked){
if(checked){
CanselTool();
tool = Tools::SplineTool;
QPixmap pixmap(":/cursor/spline_cursor.png");
QCursor cur(pixmap, 2, 3);
ui->graphicsView->setCursor(cur);
helpLabel->setText("Виберіть точки.");
dialogSpline = new DialogSpline(data, this);
connect(scene, &VMainGraphicsScene::ChoosedObject, dialogSpline,
&DialogSpline::ChoosedObject);
connect(dialogSpline, &DialogSpline::DialogClosed, this,
&MainWindow::ClosedDialogSpline);
} else {
ui->toolButtonSpline->setChecked(true);
}
}
void MainWindow::ClosedDialogSpline(int result){
if(result == QDialog::Accepted){
qint64 p1 = dialogSpline->getP1();
qint64 p4 = dialogSpline->getP4();
qreal kAsm1 = dialogSpline->getKAsm1();
qreal kAsm2 = dialogSpline->getKAsm2();
qreal angle1 = dialogSpline->getAngle1();
qreal angle2 = dialogSpline->getAngle2();
qreal kCurve = dialogSpline->getKCurve();
VSpline spline = VSpline(data->DataPoints(), p1, p4, angle1, angle2, kAsm1, kAsm2, kCurve);
qint64 id = data->AddSpline(spline);
data->AddLengthSpline(data->GetNameSpline(p1, p4), spline.GetLength());
VToolSpline *spl = new VToolSpline(doc, data, id, Tool::FromGui);
scene->addItem(spl);
connect(spl, &VToolSpline::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
ArrowTool();
}
void MainWindow::showEvent( QShowEvent *event ){
QMainWindow::showEvent( event );
if( event->spontaneous() ){
@ -638,6 +680,12 @@ void MainWindow::CanselTool(){
scene->setFocus(Qt::OtherFocusReason);
scene->clearSelection();
break;
case Tools::SplineTool:
delete dialogSpline;
ui->toolButtonSpline->setChecked(false);
scene->setFocus(Qt::OtherFocusReason);
scene->clearSelection();
break;
}
}
@ -668,9 +716,9 @@ void MainWindow::ClosedDialogSinglePoint(int result){
QPointF point = dialogSinglePoint->getPoint();
QString name = dialogSinglePoint->getName();
qint64 id = data->AddPoint(VPointF(point.x(), point.y(), name, 5, 10));
VToolSimplePoint *spoint = new VToolSimplePoint(doc, data, id, Tool::FromGui);
VToolSinglePoint *spoint = new VToolSinglePoint(doc, data, id, Tool::FromGui);
scene->addItem(spoint);
connect(spoint, &VToolPoint::ChoosedPoint, scene, &VMainGraphicsScene::ChoosedItem);
connect(spoint, &VToolPoint::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
ArrowTool();
ui->toolButtonSinglePoint->setEnabled(false);
qint32 index = comboBoxDraws->currentIndex();
@ -900,6 +948,7 @@ void MainWindow::SetEnableTool(bool enable){
ui->toolButtonNormal->setEnabled(enable);
ui->toolButtonBisector->setEnabled(enable);
ui->toolButtonLineIntersect->setEnabled(enable);
ui->toolButtonSpline->setEnabled(enable);
}
MainWindow::~MainWindow(){

View File

@ -17,7 +17,8 @@
#include "dialogs/dialognormal.h"
#include "dialogs/dialogbisector.h"
#include "dialogs/dialoglineintersect.h"
#include "tools/vtoolsimplepoint.h"
#include "dialogs/dialogspline.h"
#include "tools/vtoolsinglepoint.h"
#include "xml/vdomdocument.h"
#include "container/vcontainer.h"
@ -36,7 +37,8 @@ namespace Tools{
ShoulderPointTool,
NormalTool,
BisectorTool,
LineIntersectTool
LineIntersectTool,
SplineTool
};
}
@ -79,6 +81,8 @@ public slots:
void ClosedDialogBisector(int result);
void ToolLineIntersect(bool checked);
void ClosedDialogLineIntersect(int result);
void ToolSpline(bool checked);
void ClosedDialogSpline(int result);
protected:
virtual void keyPressEvent ( QKeyEvent * event );
virtual void showEvent( QShowEvent *event );
@ -98,6 +102,7 @@ private:
DialogNormal *dialogNormal;
DialogBisector *dialogBisector;
DialogLineIntersect *dialogLineIntersect;
DialogSpline *dialogSpline;
VDomDocument *doc;
VContainer *data;
QComboBox *comboBoxDraws;

View File

@ -57,7 +57,7 @@
</sizepolicy>
</property>
<property name="currentIndex">
<number>1</number>
<number>2</number>
</property>
<widget class="QWidget" name="page">
<property name="geometry">
@ -297,7 +297,7 @@
<x>0</x>
<y>0</y>
<width>154</width>
<height>45</height>
<height>58</height>
</rect>
</property>
<property name="sizePolicy">
@ -311,9 +311,25 @@
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QPushButton" name="pushButton_7">
<widget class="QToolButton" name="toolButtonSpline">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>PushButton</string>
<string>...</string>
</property>
<property name="icon">
<iconset resource="icon.qrc">
<normaloff>:/icon/32x32/spline.png</normaloff>:/icon/32x32/spline.png</iconset>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>

View File

@ -27,7 +27,7 @@ public slots:
virtual void FullUpdateFromGui(int result)=0;
signals:
void haveLiteChange();
void ChoosedPoint(qint64 id, Scene::Type type);
void ChoosedTool(qint64 id, Scene::Type type);
void FullUpdateTree();
protected:
VDomDocument *doc;

View File

@ -52,7 +52,7 @@ void VToolAlongLine::contextMenuEvent(QGraphicsSceneContextMenuEvent *event){
dialogAlongLine = QSharedPointer<DialogAlongLine>(new DialogAlongLine(VAbstractTool::data));
connect(qobject_cast< VMainGraphicsScene * >(this->scene()), &VMainGraphicsScene::ChoosedObject,
dialogAlongLine.data(), &DialogAlongLine::ChoosedPoint);
dialogAlongLine.data(), &DialogAlongLine::ChoosedObject);
connect(dialogAlongLine.data(), &DialogAlongLine::DialogClosed, this,
&VToolAlongLine::FullUpdateFromGui);
connect(doc, &VDomDocument::FullUpdateFromFile, dialogAlongLine.data(),

View File

@ -63,7 +63,7 @@ void VToolBisector::contextMenuEvent(QGraphicsSceneContextMenuEvent *event){
dialogBisector = QSharedPointer<DialogBisector>(new DialogBisector(VAbstractTool::data));
connect(qobject_cast< VMainGraphicsScene * >(this->scene()), &VMainGraphicsScene::ChoosedObject,
dialogBisector.data(), &DialogBisector::ChoosedPoint);
dialogBisector.data(), &DialogBisector::ChoosedObject);
connect(dialogBisector.data(), &DialogBisector::DialogClosed, this,
&VToolBisector::FullUpdateFromGui);
connect(doc, &VDomDocument::FullUpdateFromFile, dialogBisector.data(),

View File

@ -34,7 +34,7 @@ void VToolEndLine::contextMenuEvent(QGraphicsSceneContextMenuEvent *event){
dialogEndLine = QSharedPointer<DialogEndLine>(new DialogEndLine(VAbstractTool::data));
connect(qobject_cast< VMainGraphicsScene * >(this->scene()), &VMainGraphicsScene::ChoosedObject,
dialogEndLine.data(), &DialogEndLine::ChoosedPoint);
dialogEndLine.data(), &DialogEndLine::ChoosedObject);
connect(dialogEndLine.data(), &DialogEndLine::DialogClosed, this,
&VToolEndLine::FullUpdateFromGui);
connect(doc, &VDomDocument::FullUpdateFromFile, dialogEndLine.data(), &DialogEndLine::UpdateList);
@ -84,3 +84,4 @@ void VToolEndLine::AddToFile(){
AddToCalculation(domElement);
}

View File

@ -65,7 +65,7 @@ void VToolLine::contextMenuEvent(QGraphicsSceneContextMenuEvent *event){
dialogLine = QSharedPointer<DialogLine>(new DialogLine(VAbstractTool::data));
connect(qobject_cast< VMainGraphicsScene * >(this->scene()), &VMainGraphicsScene::ChoosedObject,
dialogLine.data(), &DialogLine::ChoosedPoint);
dialogLine.data(), &DialogLine::ChoosedObject);
connect(dialogLine.data(), &DialogLine::DialogClosed, this, &VToolLine::FullUpdateFromGui);
dialogLine->setFirstPoint(firstPoint);

View File

@ -49,7 +49,7 @@ void VToolLineIntersect::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
dialogLineIntersect = QSharedPointer<DialogLineIntersect>(new DialogLineIntersect(VAbstractTool::data));
connect(qobject_cast< VMainGraphicsScene * >(this->scene()), &VMainGraphicsScene::ChoosedObject,
dialogLineIntersect.data(), &DialogLineIntersect::ChoosedPoint);
dialogLineIntersect.data(), &DialogLineIntersect::ChoosedObject);
connect(dialogLineIntersect.data(), &DialogLineIntersect::DialogClosed, this,
&VToolLineIntersect::FullUpdateFromGui);

View File

@ -59,7 +59,7 @@ void VToolNormal::contextMenuEvent(QGraphicsSceneContextMenuEvent *event){
dialogNormal = QSharedPointer<DialogNormal>(new DialogNormal(VAbstractTool::data));
connect(qobject_cast< VMainGraphicsScene * >(this->scene()), &VMainGraphicsScene::ChoosedObject,
dialogNormal.data(), &DialogNormal::ChoosedPoint);
dialogNormal.data(), &DialogNormal::ChoosedObject);
connect(dialogNormal.data(), &DialogNormal::DialogClosed, this,
&VToolNormal::FullUpdateFromGui);
connect(doc, &VDomDocument::FullUpdateFromFile, dialogNormal.data(), &DialogNormal::UpdateList);

View File

@ -52,66 +52,6 @@ void VToolPoint::NameChangePosition(const QPointF pos){
VAbstractTool::data->UpdatePoint(id, point);
}
/*
* Взято з сайту http://hardfire.ru/cross_line_circle
*/
qint32 VToolPoint::LineIntersectCircle(QPointF center, qreal radius, QLineF line, QPointF &p1,
QPointF &p2) const{
const qreal eps = 1e-8;
//коефіцієнти для рівняння відрізку
qreal a = line.p2().y() - line.p1().y();
qreal b = line.p1().x() - line.p2().x();
// В даному випадку не використовується.
//qreal c = - a * line.p1().x() - b * line.p1().y();
// проекция центра окружности на прямую
QPointF p = ClosestPoint (line, center);
// сколько всего решений?
qint32 flag = 0;
qreal d = QLineF (center, p).length();
if (qAbs (d - radius) <= eps){
flag = 1;
} else {
if (radius > d){
flag = 2;
} else {
return 0;
}
}
// находим расстояние от проекции до точек пересечения
qreal k = sqrt (radius * radius - d * d);
qreal t = QLineF (QPointF (0, 0), QPointF (b, - a)).length();
// добавляем к проекции векторы направленные к точкам пеерсечения
p1 = add_vector (p, QPointF (0, 0), QPointF (- b, a), k / t);
p2 = add_vector (p, QPointF (0, 0), QPointF (b, - a), k / t);
return flag;
}
/*
* Добавление вектора к точке
* Взято з сайту http://hardfire.ru/add_vector
*/
QPointF VToolPoint::add_vector (QPointF p, QPointF p1, QPointF p2, qreal k) const{
return QPointF (p.x() + (p2.x() - p1.x()) * k, p.y() + (p2.y() - p1.y()) * k);
}
QPointF VToolPoint::ClosestPoint(QLineF line, QPointF p) const{
QLineF lineP2pointFrom = QLineF(line.p2(), p);
qreal angle = 180-line.angleTo(lineP2pointFrom)-90;
QLineF pointFromlineP2 = QLineF(p, line.p2());
pointFromlineP2.setAngle(pointFromlineP2.angle()+angle);
QPointF point;
QLineF::IntersectType type = pointFromlineP2.intersect(line,&point);
if ( type == QLineF::BoundedIntersection ){
return point;
} else{
if ( type == QLineF::NoIntersection || type == QLineF::UnboundedIntersection ){
Q_ASSERT_X(type != QLineF::BoundedIntersection, Q_FUNC_INFO, "Немає точки перетину.");
return point;
}
}
return point;
}
QPointF VToolPoint::LineIntersectRect(QRectF rec, QLineF line) const{
qreal x1, y1, x2, y2;
rec.getCoords(&x1, &y1, &x2, &y2);
@ -150,6 +90,59 @@ void VToolPoint::RefreshLine(){
}
}
qint32 VToolPoint::LineIntersectCircle(QPointF center, qreal radius, QLineF line, QPointF &p1,
QPointF &p2) const{
const qreal eps = 1e-8;
//коефіцієнти для рівняння відрізку
qreal a = line.p2().y() - line.p1().y();
qreal b = line.p1().x() - line.p2().x();
// В даному випадку не використовується.
//qreal c = - a * line.p1().x() - b * line.p1().y();
// проекция центра окружности на прямую
QPointF p = ClosestPoint (line, center);
// сколько всего решений?
qint32 flag = 0;
qreal d = QLineF (center, p).length();
if (qAbs (d - radius) <= eps){
flag = 1;
} else {
if (radius > d){
flag = 2;
} else {
return 0;
}
}
// находим расстояние от проекции до точек пересечения
qreal k = sqrt (radius * radius - d * d);
qreal t = QLineF (QPointF (0, 0), QPointF (b, - a)).length();
// добавляем к проекции векторы направленные к точкам пеерсечения
p1 = addVector (p, QPointF (0, 0), QPointF (- b, a), k / t);
p2 = addVector (p, QPointF (0, 0), QPointF (b, - a), k / t);
return flag;
}
QPointF VToolPoint::ClosestPoint(QLineF line, QPointF p) const{
QLineF lineP2pointFrom = QLineF(line.p2(), p);
qreal angle = 180-line.angleTo(lineP2pointFrom)-90;
QLineF pointFromlineP2 = QLineF(p, line.p2());
pointFromlineP2.setAngle(pointFromlineP2.angle()+angle);
QPointF point;
QLineF::IntersectType type = pointFromlineP2.intersect(line,&point);
if ( type == QLineF::BoundedIntersection ){
return point;
} else{
if ( type == QLineF::NoIntersection || type == QLineF::UnboundedIntersection ){
Q_ASSERT_X(type != QLineF::BoundedIntersection, Q_FUNC_INFO, "Немає точки перетину.");
return point;
}
}
return point;
}
QPointF VToolPoint::addVector(QPointF p, QPointF p1, QPointF p2, qreal k) const{
return QPointF (p.x() + (p2.x() - p1.x()) * k, p.y() + (p2.y() - p1.y()) * k);
}
void VToolPoint::LiteUpdateFromGui(qreal mx, qreal my){
QDomElement domElement = doc->elementById(QString().setNum(id));
if(domElement.isElement()){
@ -163,35 +156,28 @@ void VToolPoint::ChangedActivDraw(const QString newName){
if(nameActivDraw == newName){
this->setPen(QPen(Qt::black, widthHairLine));
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
this->setAcceptHoverEvents(true);
namePoint->setFlag(QGraphicsItem::ItemIsMovable, true);
namePoint->setFlag(QGraphicsItem::ItemIsSelectable, true);
namePoint->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
namePoint->setBrush(QBrush(Qt::black));
namePoint->setAcceptHoverEvents(true);
lineName->setPen(QPen(Qt::black, widthHairLine));
this->setAcceptHoverEvents(true);
VAbstractTool::ChangedActivDraw(newName);
} else {
this->setPen(QPen(Qt::gray, widthHairLine));
this->setFlag(QGraphicsItem::ItemIsSelectable, false);
this->setAcceptHoverEvents (false);
namePoint->setFlag(QGraphicsItem::ItemIsMovable, false);
namePoint->setFlag(QGraphicsItem::ItemIsSelectable, false);
namePoint->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
namePoint->setBrush(QBrush(Qt::gray));
namePoint->setAcceptHoverEvents(false);
lineName->setPen(QPen(Qt::gray, widthHairLine));
this->setAcceptHoverEvents (false);
VAbstractTool::ChangedActivDraw(newName);
}
}
void VToolPoint::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event ){
if(event->button() == Qt::LeftButton){
emit ChoosedPoint(id, Scene::Point);
}
QGraphicsItem::mouseReleaseEvent(event);
}
void VToolPoint::RefreshGeometry(){
VPointF point = VAbstractTool::data->GetPoint(id);
QRectF rec = QRectF(point.x(), point.y(), radius*2, radius*2);
@ -205,6 +191,13 @@ void VToolPoint::RefreshGeometry(){
RefreshLine();
}
void VToolPoint::mouseReleaseEvent(QGraphicsSceneMouseEvent *event){
if(event->button() == Qt::LeftButton){
emit ChoosedTool(id, Scene::Point);
}
QGraphicsItem::mouseReleaseEvent(event);
}
void VToolPoint::hoverMoveEvent(QGraphicsSceneHoverEvent *event){
Q_UNUSED(event);
this->setPen(QPen(Qt::black, widthMainLine));

View File

@ -1,9 +1,8 @@
#ifndef VTOOLPOINT_H
#define VTOOLPOINT_H
#include <QGraphicsEllipseItem>
#include <QGraphicsLineItem>
#include <QGraphicsEllipseItem>
#include "../widgets/vgraphicssimpletextitem.h"
#include "../options.h"
#include "vabstracttool.h"
@ -22,18 +21,18 @@ protected:
qreal radius;
VGraphicsSimpleTextItem *namePoint;
QGraphicsLineItem *lineName;
virtual void RefreshGeometry();
virtual void mouseReleaseEvent ( QGraphicsSceneMouseEvent * event );
virtual void RefreshGeometry();
virtual void hoverMoveEvent ( QGraphicsSceneHoverEvent * event );
virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event );
private:
qint32 LineIntersectCircle(QPointF center, qreal radius, QLineF line, QPointF &p1,
QPointF &p2) const;
QPointF LineIntersectRect(QRectF rec, QLineF line) const;
QPointF ClosestPoint(QLineF line, QPointF p) const;
QPointF add_vector (QPointF p, QPointF p1, QPointF p2, qreal k) const;
void LiteUpdateFromGui(qreal mx, qreal my);
void RefreshLine();
qint32 LineIntersectCircle(QPointF center, qreal radius, QLineF line, QPointF &p1,
QPointF &p2) const;
QPointF ClosestPoint(QLineF line, QPointF p) const;
QPointF addVector (QPointF p, QPointF p1, QPointF p2, qreal k) const;
};
#endif // VTOOLPOINT_H

View File

@ -75,7 +75,7 @@ void VToolShoulderPoint::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
QSharedPointer<DialogShoulderPoint>(new DialogShoulderPoint(VAbstractTool::data));
connect(qobject_cast< VMainGraphicsScene * >(this->scene()), &VMainGraphicsScene::ChoosedObject,
dialogShoulderPoint.data(), &DialogShoulderPoint::ChoosedPoint);
dialogShoulderPoint.data(), &DialogShoulderPoint::ChoosedObject);
connect(dialogShoulderPoint.data(), &DialogShoulderPoint::DialogClosed, this,
&VToolShoulderPoint::FullUpdateFromGui);
connect(doc, &VDomDocument::FullUpdateFromFile, dialogShoulderPoint.data(),

View File

@ -1,67 +1,9 @@
#include "vtoolsimplepoint.h"
#include <QPen>
#include <QBrush>
#include <QDebug>
#include <QGraphicsItem>
#include <cmath>
#include <QMenu>
#include <QGraphicsSceneContextMenuEvent>
#include "../options.h"
#include "../container/vpointf.h"
VToolSimplePoint::VToolSimplePoint (VDomDocument *doc, VContainer *data, qint64 id, Tool::Enum typeCreation,
QGraphicsItem * parent ):VToolPoint(doc, data, id, parent){
if(typeCreation == Tool::FromGui){
AddToFile();
}
VToolSimplePoint::VToolSimplePoint(VDomDocument *doc, VContainer *data, qint64 id,
QGraphicsItem *parent):VAbstractTool(doc, data, id),
QGraphicsEllipseItem(parent){
}
void VToolSimplePoint::AddToFile(){
VPointF point = VAbstractTool::data->GetPoint(id);
QDomElement domElement = doc->createElement("point");
AddAttribute(domElement, "id", id);
AddAttribute(domElement, "type", "simple");
AddAttribute(domElement, "name", point.name());
AddAttribute(domElement, "x", point.x()/PrintDPI*25.4);
AddAttribute(domElement, "y", point.y()/PrintDPI*25.4);
AddAttribute(domElement, "mx", point.mx()/PrintDPI*25.4);
AddAttribute(domElement, "my", point.my()/PrintDPI*25.4);
AddToCalculation(domElement);
}
void VToolSimplePoint::FullUpdateFromGui(int result){
if(result == QDialog::Accepted){
QPointF p = dialogSinglePoint->getPoint();
QDomElement domElement = doc->elementById(QString().setNum(id));
if(domElement.isElement()){
domElement.setAttribute("name", dialogSinglePoint->getName());
domElement.setAttribute("x", QString().setNum(p.x()/PrintDPI*25.4));
domElement.setAttribute("y", QString().setNum(p.y()/PrintDPI*25.4));
emit FullUpdateTree();
}
}
dialogSinglePoint.clear();
}
void VToolSimplePoint::contextMenuEvent ( QGraphicsSceneContextMenuEvent * event ){
if(!ignoreContextMenuEvent){
QMenu menu;
QAction *actionOption = menu.addAction("Властивості");
QAction *selectedAction = menu.exec(event->screenPos());
if(selectedAction == actionOption){
dialogSinglePoint = QSharedPointer<DialogSinglePoint>(new DialogSinglePoint(VAbstractTool::data));
connect(dialogSinglePoint.data(), &DialogSinglePoint::DialogClosed, this,
&VToolSimplePoint::FullUpdateFromGui);
VPointF p = VAbstractTool::data->GetPoint(id);
dialogSinglePoint->setData(p.name(), p.toQPointF());
dialogSinglePoint->exec();
}
}
}
void VToolSimplePoint::FullUpdateFromFile(){
RefreshGeometry();
}

View File

@ -1,25 +1,21 @@
#ifndef VTOOLSIMPLEPOINT_H
#define VTOOLSIMPLEPOINT_H
#include "../container/vcontainer.h"
#include "../xml/vdomdocument.h"
#include "vtoolpoint.h"
#include "../dialogs/dialogsinglepoint.h"
#include <QGraphicsEllipseItem>
#include <QGraphicsLineItem>
class VToolSimplePoint : public VToolPoint
#include "../options.h"
#include "vabstracttool.h"
class VToolSimplePoint: public VAbstractTool, public QGraphicsEllipseItem
{
Q_OBJECT
public:
VToolSimplePoint (VDomDocument *doc, VContainer *data, qint64 id,
Tool::Enum typeCreation, QGraphicsItem * parent = 0 );
VToolSimplePoint(VDomDocument *doc, VContainer *data, qint64 id, QGraphicsItem * parent = 0);
public slots:
virtual void FullUpdateFromFile();
virtual void FullUpdateFromGui(int result);
virtual void ChangedActivDraw(const QString newName);
protected:
virtual void contextMenuEvent ( QGraphicsSceneContextMenuEvent * event );
virtual void AddToFile();
private:
QSharedPointer<DialogSinglePoint> dialogSinglePoint;
virtual void RefreshGeometry();
};
#endif // VTOOLSIMPLEPOINT_H

View File

@ -0,0 +1,68 @@
#include "vtoolsinglepoint.h"
#include <QPen>
#include <QBrush>
#include <QDebug>
#include <QGraphicsItem>
#include <cmath>
#include <QMenu>
#include <QGraphicsSceneContextMenuEvent>
#include "../options.h"
#include "../container/vpointf.h"
VToolSinglePoint::VToolSinglePoint (VDomDocument *doc, VContainer *data, qint64 id, Tool::Enum typeCreation,
QGraphicsItem * parent ):VToolPoint(doc, data, id, parent){
if(typeCreation == Tool::FromGui){
AddToFile();
}
}
void VToolSinglePoint::AddToFile(){
VPointF point = VAbstractTool::data->GetPoint(id);
QDomElement domElement = doc->createElement("point");
AddAttribute(domElement, "id", id);
AddAttribute(domElement, "type", "single");
AddAttribute(domElement, "name", point.name());
AddAttribute(domElement, "x", point.x()/PrintDPI*25.4);
AddAttribute(domElement, "y", point.y()/PrintDPI*25.4);
AddAttribute(domElement, "mx", point.mx()/PrintDPI*25.4);
AddAttribute(domElement, "my", point.my()/PrintDPI*25.4);
AddToCalculation(domElement);
}
void VToolSinglePoint::contextMenuEvent ( QGraphicsSceneContextMenuEvent * event ){
if(!ignoreContextMenuEvent){
QMenu menu;
QAction *actionOption = menu.addAction("Властивості");
QAction *selectedAction = menu.exec(event->screenPos());
if(selectedAction == actionOption){
dialogSinglePoint = QSharedPointer<DialogSinglePoint>(new DialogSinglePoint(VAbstractTool::data));
VPointF p = VAbstractTool::data->GetPoint(id);
dialogSinglePoint->setData(p.name(), p.toQPointF());
connect(dialogSinglePoint.data(), &DialogSinglePoint::DialogClosed, this,
&VToolSinglePoint::FullUpdateFromGui);
dialogSinglePoint->exec();
}
}
}
void VToolSinglePoint::FullUpdateFromFile(){
RefreshGeometry();
}
void VToolSinglePoint::FullUpdateFromGui(int result){
if(result == QDialog::Accepted){
QPointF p = dialogSinglePoint->getPoint();
QString name = dialogSinglePoint->getName();
QDomElement domElement = doc->elementById(QString().setNum(id));
if(domElement.isElement()){
domElement.setAttribute("name", name);
domElement.setAttribute("x", QString().setNum(p.x()/PrintDPI*25.4));
domElement.setAttribute("y", QString().setNum(p.y()/PrintDPI*25.4));
emit FullUpdateTree();
}
}
dialogSinglePoint.clear();
}

27
tools/vtoolsinglepoint.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef VTOOLSINGLEPOINT_H
#define VTOOLSINGLEPOINT_H
#include "../container/vcontainer.h"
#include "../xml/vdomdocument.h"
#include "vtoolpoint.h"
#include "../dialogs/dialogsinglepoint.h"
class VToolSinglePoint : public VToolPoint
{
Q_OBJECT
public:
VToolSinglePoint (VDomDocument *doc, VContainer *data, qint64 id,
Tool::Enum typeCreation, QGraphicsItem * parent = 0 );
public slots:
virtual void FullUpdateFromFile();
virtual void FullUpdateFromGui(int result);
signals:
void FullUpdateTree();
protected:
virtual void contextMenuEvent ( QGraphicsSceneContextMenuEvent * event );
virtual void AddToFile();
private:
QSharedPointer<DialogSinglePoint> dialogSinglePoint;
};
#endif // VTOOLSINGLEPOINT_H

202
tools/vtoolspline.cpp Normal file
View File

@ -0,0 +1,202 @@
#include "vtoolspline.h"
#include "../geometry/vspline.h"
#include <QMenu>
#include <QDebug>
VToolSpline::VToolSpline(VDomDocument *doc, VContainer *data, qint64 id, Tool::Enum typeCreation,
QGraphicsItem *parent):VAbstractTool(doc, data, id), QGraphicsPathItem(parent){
VSpline spl = data->GetSpline(id);
QPainterPath path;
path.addPath(spl.GetPath());
path.setFillRule( Qt::WindingFill );
this->setPath(path);
this->setPen(QPen(Qt::black, widthHairLine));
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
this->setAcceptHoverEvents(true);
controlPoint1 = new VControlPointSpline(spl.GetP2(), spl.GetPointP1(), this);
connect(controlPoint1, &VControlPointSpline::ControlPointChangePosition, this,
&VToolSpline::ControlPoint1ChangePosition);
controlPoint2 = new VControlPointSpline(spl.GetP3(), spl.GetPointP4(), this);
connect(controlPoint2, &VControlPointSpline::ControlPointChangePosition, this,
&VToolSpline::ControlPoint2ChangePosition);
if(typeCreation == Tool::FromGui){
AddToFile();
}
}
void VToolSpline::FullUpdateFromFile(){
RefreshGeometry();
}
void VToolSpline::FullUpdateFromGui(int result){
if(result == QDialog::Accepted){
VSpline spl = VSpline (VAbstractTool::data->DataPoints(), dialogSpline->getP1(),
dialogSpline->getP4(), dialogSpline->getAngle1(), dialogSpline->getAngle2(),
dialogSpline->getKAsm1(), dialogSpline->getKAsm2(), dialogSpline->getKCurve());
disconnect(controlPoint1, &VControlPointSpline::ControlPointChangePosition, this,
&VToolSpline::ControlPoint1ChangePosition);
disconnect(controlPoint2, &VControlPointSpline::ControlPointChangePosition, this,
&VToolSpline::ControlPoint2ChangePosition);
controlPoint1->setPos(spl.GetP2());
controlPoint2->setPos(spl.GetP3());
connect(controlPoint1, &VControlPointSpline::ControlPointChangePosition, this,
&VToolSpline::ControlPoint1ChangePosition);
connect(controlPoint2, &VControlPointSpline::ControlPointChangePosition, this,
&VToolSpline::ControlPoint2ChangePosition);
spl = VSpline (VAbstractTool::data->DataPoints(), dialogSpline->getP1(), controlPoint1->pos(),
controlPoint2->pos(), dialogSpline->getP4(), dialogSpline->getKCurve());
QDomElement domElement = doc->elementById(QString().setNum(id));
if(domElement.isElement()){
domElement.setAttribute("point1", QString().setNum(spl.GetP1()));
domElement.setAttribute("point4", QString().setNum(spl.GetP4()));
domElement.setAttribute("angle1", QString().setNum(spl.GetAngle1()));
domElement.setAttribute("angle2", QString().setNum(spl.GetAngle2()));
domElement.setAttribute("kAsm1", QString().setNum(spl.GetKasm1()));
domElement.setAttribute("kAsm2", QString().setNum(spl.GetKasm2()));
domElement.setAttribute("kCurve", QString().setNum(spl.GetKcurve()));
emit FullUpdateTree();
}
}
dialogSpline.clear();
}
void VToolSpline::ControlPoint1ChangePosition(const QPointF pos){
VSpline spl = VAbstractTool::data->GetSpline(id);
spl.ModifiSpl (spl.GetP1(), pos, spl.GetP3(), spl.GetP4(), spl.GetKcurve());
QDomElement domElement = doc->elementById(QString().setNum(id));
if(domElement.isElement()){
domElement.setAttribute("angle1", QString().setNum(spl.GetAngle1()));
domElement.setAttribute("angle2", QString().setNum(spl.GetAngle2()));
domElement.setAttribute("kAsm1", QString().setNum(spl.GetKasm1()));
domElement.setAttribute("kAsm2", QString().setNum(spl.GetKasm2()));
domElement.setAttribute("kCurve", QString().setNum(spl.GetKcurve()));
emit FullUpdateTree();
}
}
void VToolSpline::ControlPoint2ChangePosition(const QPointF pos){
VSpline spl = VAbstractTool::data->GetSpline(id);
spl.ModifiSpl (spl.GetP1(), spl.GetP2(), pos, spl.GetP4(), spl.GetKcurve());
QDomElement domElement = doc->elementById(QString().setNum(id));
if(domElement.isElement()){
domElement.setAttribute("angle1", QString().setNum(spl.GetAngle1()));
domElement.setAttribute("angle2", QString().setNum(spl.GetAngle2()));
domElement.setAttribute("kAsm1", QString().setNum(spl.GetKasm1()));
domElement.setAttribute("kAsm2", QString().setNum(spl.GetKasm2()));
domElement.setAttribute("kCurve", QString().setNum(spl.GetKcurve()));
emit FullUpdateTree();
}
}
void VToolSpline::contextMenuEvent(QGraphicsSceneContextMenuEvent *event){
if(!ignoreContextMenuEvent){
QMenu menu;
QAction *actionOption = menu.addAction("Властивості");
QAction *selectedAction = menu.exec(event->screenPos());
if(selectedAction == actionOption){
dialogSpline = QSharedPointer<DialogSpline>(new DialogSpline(VAbstractTool::data));
connect(qobject_cast< VMainGraphicsScene * >(this->scene()), &VMainGraphicsScene::ChoosedObject,
dialogSpline.data(), &DialogSpline::ChoosedObject);
connect(dialogSpline.data(), &DialogSpline::DialogClosed, this,
&VToolSpline::FullUpdateFromGui);
VSpline spl = VAbstractTool::data->GetSpline(id);
dialogSpline->setP1(spl.GetP1());
dialogSpline->setP4(spl.GetP4());
dialogSpline->setAngle1(spl.GetAngle1());
dialogSpline->setAngle2(spl.GetAngle2());
dialogSpline->setKAsm1(spl.GetKasm1());
dialogSpline->setKAsm2(spl.GetKasm2());
dialogSpline->setKCurve(spl.GetKcurve());
dialogSpline->show();
}
}
}
void VToolSpline::AddToFile(){
VSpline spl = VAbstractTool::data->GetSpline(id);
QDomElement domElement = doc->createElement("spline");
AddAttribute(domElement, "id", id);
AddAttribute(domElement, "type", "simple");
AddAttribute(domElement, "point1", spl.GetP1());
AddAttribute(domElement, "point4", spl.GetP4());
AddAttribute(domElement, "angle1", spl.GetAngle1());
AddAttribute(domElement, "angle2", spl.GetAngle2());
AddAttribute(domElement, "kAsm1", spl.GetKasm1());
AddAttribute(domElement, "kAsm2", spl.GetKasm2());
AddAttribute(domElement, "kCurve", spl.GetKcurve());
AddToCalculation(domElement);
}
void VToolSpline::mouseReleaseEvent(QGraphicsSceneMouseEvent *event){
if(event->button() == Qt::LeftButton){
emit ChoosedTool(id, Scene::Spline);
}
QGraphicsItem::mouseReleaseEvent(event);
}
void VToolSpline::hoverMoveEvent(QGraphicsSceneHoverEvent *event){
Q_UNUSED(event);
this->setPen(QPen(Qt::black, widthMainLine));
}
void VToolSpline::hoverLeaveEvent(QGraphicsSceneHoverEvent *event){
Q_UNUSED(event);
this->setPen(QPen(Qt::black, widthHairLine));
}
void VToolSpline::RefreshGeometry(){
VSpline spl = VAbstractTool::data->GetSpline(id);
QPainterPath path;
path.addPath(spl.GetPath());
path.setFillRule( Qt::WindingFill );
this->setPath(path);
QPointF splinePoint = VAbstractTool::data->GetPoint(spl.GetP1());
QPointF controlPoint = spl.GetP2();
controlPoint1->RefreshLine(controlPoint, splinePoint);
splinePoint = VAbstractTool::data->GetPoint(spl.GetP4());
controlPoint = spl.GetP3();
controlPoint2->RefreshLine(controlPoint, splinePoint);
}
void VToolSpline::ChangedActivDraw(const QString newName){
if(nameActivDraw == newName){
this->setPen(QPen(Qt::black, widthHairLine));
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
this->setAcceptHoverEvents(true);
controlPoint1->setPen(QPen(Qt::black, widthHairLine));
controlPoint1->setFlag(QGraphicsItem::ItemIsSelectable, true);
controlPoint1->setFlag(QGraphicsItem::ItemIsMovable, true);
controlPoint1->setAcceptHoverEvents(true);
controlPoint2->setPen(QPen(Qt::black, widthHairLine));
controlPoint2->setFlag(QGraphicsItem::ItemIsSelectable, true);
controlPoint2->setFlag(QGraphicsItem::ItemIsMovable, true);
controlPoint2->setAcceptHoverEvents(true);
VAbstractTool::ChangedActivDraw(newName);
} else {
this->setPen(QPen(Qt::gray, widthHairLine));
this->setFlag(QGraphicsItem::ItemIsSelectable, false);
this->setAcceptHoverEvents (false);
controlPoint1->setPen(QPen(Qt::gray, widthHairLine));
controlPoint1->setFlag(QGraphicsItem::ItemIsSelectable, false);
controlPoint1->setFlag(QGraphicsItem::ItemIsMovable, false);
controlPoint1->setAcceptHoverEvents(false);
controlPoint2->setPen(QPen(Qt::gray, widthHairLine));
controlPoint2->setFlag(QGraphicsItem::ItemIsSelectable, false);
controlPoint2->setFlag(QGraphicsItem::ItemIsMovable, false);
controlPoint2->setAcceptHoverEvents(false);
VAbstractTool::ChangedActivDraw(newName);
}
}

36
tools/vtoolspline.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef VTOOLSPLINE_H
#define VTOOLSPLINE_H
#include "vabstracttool.h"
#include "../container/vcontainer.h"
#include "../xml/vdomdocument.h"
#include <QGraphicsPathItem>
#include "../dialogs/dialogspline.h"
#include "../widgets/vcontrolpointspline.h"
class VToolSpline:public VAbstractTool, public QGraphicsPathItem
{
Q_OBJECT
public:
VToolSpline(VDomDocument *doc, VContainer *data, qint64 id,
Tool::Enum typeCreation, QGraphicsItem * parent = 0);
public slots:
virtual void FullUpdateFromFile();
virtual void FullUpdateFromGui(int result);
void ControlPoint1ChangePosition(const QPointF pos);
void ControlPoint2ChangePosition(const QPointF pos);
virtual void ChangedActivDraw(const QString newName);
protected:
virtual void contextMenuEvent ( QGraphicsSceneContextMenuEvent * event );
virtual void AddToFile();
virtual void mouseReleaseEvent ( QGraphicsSceneMouseEvent * event );
virtual void hoverMoveEvent ( QGraphicsSceneHoverEvent * event );
virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event );
private:
QSharedPointer<DialogSpline> dialogSpline;
VControlPointSpline *controlPoint1;
VControlPointSpline *controlPoint2;
void RefreshGeometry();
};
#endif // VTOOLSPLINE_H

View File

@ -0,0 +1,119 @@
#include "vcontrolpointspline.h"
#include <QPen>
#include <QBrush>
#include <QGraphicsScene>
#include <QDebug>
VControlPointSpline::VControlPointSpline(const QPointF &controlPoint, const QPointF &splinePoint,
QGraphicsItem *parent):QGraphicsEllipseItem(parent){
radius = 1.5*PrintDPI/25.4;
//create circle
QRectF rec = QRectF(0, 0, radius*2, radius*2);
rec.translate(-rec.center().x(), -rec.center().y());
this->setRect(rec);
this->setPen(QPen(Qt::black, widthHairLine));
this->setBrush(QBrush(Qt::NoBrush));
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
this->setFlag(QGraphicsItem::ItemIsMovable, true);
this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
this->setAcceptHoverEvents(true);
this->setPos(controlPoint);
//Лінія, що з'єднує дві точки
QPointF p1, p2;
LineIntersectCircle(QPointF(), radius, QLineF( QPointF(), splinePoint-controlPoint), p1, p2);
controlLine = new QGraphicsLineItem(QLineF(splinePoint-controlPoint, p1), this);
controlLine->setPen(QPen(Qt::red, widthHairLine));
controlLine->setFlag(QGraphicsItem::ItemStacksBehindParent, true);
}
void VControlPointSpline::hoverMoveEvent(QGraphicsSceneHoverEvent *event){
Q_UNUSED(event);
this->setPen(QPen(Qt::black, widthMainLine));
}
void VControlPointSpline::hoverLeaveEvent(QGraphicsSceneHoverEvent *event){
Q_UNUSED(event);
this->setPen(QPen(Qt::black, widthHairLine));
}
QVariant VControlPointSpline::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value){
if (change == ItemPositionChange && scene()) {
// value - это новое положение.
QPointF newPos = value.toPointF();
qDebug()<<this->rect();
QRectF rect = scene()->sceneRect();
if (!rect.contains(newPos)) {
// Сохраняем элемент внутри прямоугольника сцены.
newPos.setX(qMin(rect.right(), qMax(newPos.x(), rect.left())));
newPos.setY(qMin(rect.bottom(), qMax(newPos.y(), rect.top())));
emit ControlPointChangePosition(newPos);
return newPos;
}
emit ControlPointChangePosition(newPos);
}
return QGraphicsItem::itemChange(change, value);
}
qint32 VControlPointSpline::LineIntersectCircle(QPointF center, qreal radius, QLineF line, QPointF &p1,
QPointF &p2) const{
const qreal eps = 1e-8;
//коефіцієнти для рівняння відрізку
qreal a = line.p2().y() - line.p1().y();
qreal b = line.p1().x() - line.p2().x();
// В даному випадку не використовується.
//qreal c = - a * line.p1().x() - b * line.p1().y();
// проекция центра окружности на прямую
QPointF p = ClosestPoint (line, center);
// сколько всего решений?
qint32 flag = 0;
qreal d = QLineF (center, p).length();
if (qAbs (d - radius) <= eps){
flag = 1;
} else {
if (radius > d){
flag = 2;
} else {
return 0;
}
}
// находим расстояние от проекции до точек пересечения
qreal k = sqrt (radius * radius - d * d);
qreal t = QLineF (QPointF (0, 0), QPointF (b, - a)).length();
// добавляем к проекции векторы направленные к точкам пеерсечения
p1 = addVector (p, QPointF (0, 0), QPointF (- b, a), k / t);
p2 = addVector (p, QPointF (0, 0), QPointF (b, - a), k / t);
return flag;
}
QPointF VControlPointSpline::ClosestPoint(QLineF line, QPointF p) const{
QLineF lineP2pointFrom = QLineF(line.p2(), p);
qreal angle = 180-line.angleTo(lineP2pointFrom)-90;
QLineF pointFromlineP2 = QLineF(p, line.p2());
pointFromlineP2.setAngle(pointFromlineP2.angle()+angle);
QPointF point;
QLineF::IntersectType type = pointFromlineP2.intersect(line,&point);
if ( type == QLineF::BoundedIntersection ){
return point;
} else{
if ( type == QLineF::NoIntersection || type == QLineF::UnboundedIntersection ){
Q_ASSERT_X(type != QLineF::BoundedIntersection, Q_FUNC_INFO, "Немає точки перетину.");
return point;
}
}
return point;
}
QPointF VControlPointSpline::addVector(QPointF p, QPointF p1, QPointF p2, qreal k) const{
return QPointF (p.x() + (p2.x() - p1.x()) * k, p.y() + (p2.y() - p1.y()) * k);
}
void VControlPointSpline::RefreshLine(const QPointF &controlPoint, const QPointF &splinePoint){
// QRectF rec = QRectF(0, 0, radius*2, radius*2);
// rec.translate(0-rec.center().x(), 0-rec.center().y());
// this->setRect(rec);
QPointF p1, p2;
LineIntersectCircle(QPointF(), radius, QLineF( QPointF(), splinePoint-controlPoint), p1, p2);
controlLine->setLine(QLineF(splinePoint-controlPoint, p1));
}

View File

@ -0,0 +1,30 @@
#ifndef VCONTROLPOINTSPLINE_H
#define VCONTROLPOINTSPLINE_H
#include <QGraphicsEllipseItem>
#include <QGraphicsLineItem>
#include <QObject>
#include "../options.h"
class VControlPointSpline : public QObject, public QGraphicsEllipseItem
{
Q_OBJECT
public:
VControlPointSpline(const QPointF &controlPoint, const QPointF &splinePoint, QGraphicsItem * parent = 0);
void RefreshLine(const QPointF &controlPoint, const QPointF &splinePoint);
signals:
void ControlPointChangePosition(const QPointF pos);
protected:
qreal radius;
QGraphicsLineItem *controlLine;
virtual void hoverMoveEvent ( QGraphicsSceneHoverEvent * event );
virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event );
QVariant itemChange ( GraphicsItemChange change, const QVariant &value );
private:
qint32 LineIntersectCircle(QPointF center, qreal radius, QLineF line, QPointF &p1,
QPointF &p2) const;
QPointF ClosestPoint(QLineF line, QPointF p) const;
QPointF addVector (QPointF p, QPointF p1, QPointF p2, qreal k) const;
};
#endif // VCONTROLPOINTSPLINE_H

View File

@ -1,7 +1,7 @@
#include "vdomdocument.h"
#include <QDebug>
#include "../tools/vtoolsimplepoint.h"
#include "../tools/vtoolsinglepoint.h"
#include "../tools/vtoolendline.h"
#include "../tools/vtoolline.h"
#include "../tools/vtoolalongline.h"
@ -9,6 +9,7 @@
#include "../tools/vtoolnormal.h"
#include "../tools/vtoolbisector.h"
#include "../tools/vtoollineintersect.h"
#include "../tools/vtoolspline.h"
#include "../options.h"
#include "../container/calculator.h"
@ -225,6 +226,8 @@ void VDomDocument::Parse(Document::Enum parse, VMainGraphicsScene *scene, QCombo
comboBoxDraws->clear();
} else {
data->ClearLengthLines();
data->ClearLengthArcs();
data->ClearLengthSplines();
}
QDomElement rootElement = this->documentElement();
QDomNode domNode = rootElement.firstChild();
@ -292,7 +295,7 @@ void VDomDocument::AddNewDraw(const QDomElement& node, QComboBox *comboBoxDraws)
QDomElement domElementPoint = domCal.toElement();
if(!domElementPoint.isNull()){
if(domElementPoint.tagName() == "point"){
if(domElementPoint.attribute("type","") == "simple"){
if(domElementPoint.attribute("type","") == "single"){
comboBoxDraws->addItem(name, false);
return;
} else {
@ -345,13 +348,16 @@ void VDomDocument::ParseCalculationElement(VMainGraphicsScene *scene, const QDom
if(domElement.tagName() == "line"){
ParseLineElement(scene, domElement, parse);
}
if(domElement.tagName() == "spline"){
ParseSplineElement(scene, domElement, parse, domElement.attribute("type", ""));
}
}
}
}
void VDomDocument::ParsePointElement(VMainGraphicsScene *scene, const QDomElement& domElement,
Document::Enum parse, const QString& type){
if(type == "simple"){
if(type == "single"){
if(!domElement.isNull()){
QString name;
qreal mx=5, my=10, x, y;
@ -366,9 +372,9 @@ void VDomDocument::ParsePointElement(VMainGraphicsScene *scene, const QDomElemen
data->UpdatePoint(id, VPointF(x, y, name, mx, my));
if(parse == Document::FullParse){
VToolSimplePoint *spoint = new VToolSimplePoint(this, data, id, Tool::FromFile);
VToolSinglePoint *spoint = new VToolSinglePoint(this, data, id, Tool::FromFile);
scene->addItem(spoint);
connect(spoint, &VToolSimplePoint::ChoosedPoint, scene, &VMainGraphicsScene::ChoosedItem);
connect(spoint, &VToolSinglePoint::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
}
}
@ -405,7 +411,7 @@ void VDomDocument::ParsePointElement(VMainGraphicsScene *scene, const QDomElemen
VToolEndLine *point = new VToolEndLine(this, data, id, typeLine, formula, angle,
basePointId, Tool::FromFile);
scene->addItem(point);
connect(point, &VToolPoint::ChoosedPoint, scene, &VMainGraphicsScene::ChoosedItem);
connect(point, &VToolPoint::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
}
}
@ -443,7 +449,7 @@ void VDomDocument::ParsePointElement(VMainGraphicsScene *scene, const QDomElemen
VToolAlongLine *point = new VToolAlongLine(this, data, id, formula, firstPointId,
secondPointId, typeLine, Tool::FromGui);
scene->addItem(point);
connect(point, &VToolAlongLine::ChoosedPoint, scene, &VMainGraphicsScene::ChoosedItem);
connect(point, &VToolAlongLine::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
}
}
@ -485,7 +491,7 @@ void VDomDocument::ParsePointElement(VMainGraphicsScene *scene, const QDomElemen
p1Line, p2Line, pShoulder,
Tool::FromGui);
scene->addItem(point);
connect(point, &VToolShoulderPoint::ChoosedPoint, scene,
connect(point, &VToolShoulderPoint::ChoosedTool, scene,
&VMainGraphicsScene::ChoosedItem);
}
}
@ -524,7 +530,7 @@ void VDomDocument::ParsePointElement(VMainGraphicsScene *scene, const QDomElemen
VToolNormal *point = new VToolNormal(this, data, id, typeLine, formula, angle,
firstPointId, secondPointId, Tool::FromFile);
scene->addItem(point);
connect(point, &VToolNormal::ChoosedPoint, scene, &VMainGraphicsScene::ChoosedItem);
connect(point, &VToolNormal::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
}
}
@ -565,7 +571,7 @@ void VDomDocument::ParsePointElement(VMainGraphicsScene *scene, const QDomElemen
firstPointId, secondPointId, thirdPointId,
Tool::FromFile);
scene->addItem(point);
connect(point, &VToolBisector::ChoosedPoint, scene, &VMainGraphicsScene::ChoosedItem);
connect(point, &VToolBisector::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
}
}
@ -606,9 +612,9 @@ void VDomDocument::ParsePointElement(VMainGraphicsScene *scene, const QDomElemen
if(parse == Document::FullParse){
VToolLineIntersect *point = new VToolLineIntersect(this, data, id, p1Line1Id,
p2Line1Id, p1Line2Id,
p2Line2Id, Tool::FromGui);
p2Line2Id, Tool::FromFile);
scene->addItem(point);
connect(point, &VToolLineIntersect::ChoosedPoint, scene,
connect(point, &VToolLineIntersect::ChoosedTool, scene,
&VMainGraphicsScene::ChoosedItem);
}
}
@ -631,12 +637,42 @@ void VDomDocument::ParseLineElement(VMainGraphicsScene *scene, const QDomElement
qint64 id = data->getNextId();
VToolLine *line = new VToolLine(this, data, id, firstPoint, secondPoint, Tool::FromFile);
scene->addItem(line);
connect(line, &VToolLine::ChoosedPoint, scene, &VMainGraphicsScene::ChoosedItem);
connect(line, &VToolLine::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
}
}
}
void VDomDocument::ParseSplineElement(VMainGraphicsScene *scene, const QDomElement &domElement,
Document::Enum parse, const QString &type){
if(type == "simple"){
if(!domElement.isNull()){
qreal angle1, angle2, kAsm1, kAsm2, kCurve;
qint64 id, point1, point4;
if(!domElement.isNull()){
id = domElement.attribute("id", "").toLongLong();
point1 = domElement.attribute("point1", "").toLongLong();
point4 = domElement.attribute("point4", "").toLongLong();
angle1 = domElement.attribute("angle1","").toDouble();
angle2 = domElement.attribute("angle2","").toDouble();
kAsm1 = domElement.attribute("kAsm1","").toDouble();
kAsm2 = domElement.attribute("kAsm2","").toDouble();
kCurve = domElement.attribute("kCurve","").toDouble();
VSpline spline = VSpline(data->DataPoints(), point1, point4, angle1, angle2, kAsm1, kAsm2, kCurve);
data->UpdateSpline(id, spline);
data->AddLengthSpline(data->GetNameSpline(point1, point4), spline.GetLength());
if(parse == Document::FullParse){
VToolSpline *spl = new VToolSpline(this, data, id, Tool::FromFile);
scene->addItem(spl);
connect(spl, &VToolSpline::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
}
}
}
return;
}
}
void VDomDocument::FullUpdateTree(){
VMainGraphicsScene *scene = new VMainGraphicsScene();
QComboBox *comboBoxDraws = new QComboBox();

View File

@ -59,6 +59,8 @@ private:
Document::Enum parse, const QString &type);
void ParseLineElement(VMainGraphicsScene *scene, const QDomElement& domElement,
Document::Enum parse);
void ParseSplineElement(VMainGraphicsScene *scene, const QDomElement& domElement,
Document::Enum parse, const QString& type);
void ParseIncrementsElement(const QDomNode& node);
void AddNewDraw(const QDomElement &node, QComboBox *comboBoxDraws)const;
};