valentina/geometry/varc.cpp
2013-08-05 11:37:56 +03:00

295 lines
9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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() );
//}