/************************************************************************ ** ** @file vabstractcurve.cpp ** @author Roman Telezhynskyi ** @date 25 6, 2014 ** ** @brief ** @copyright ** This source code is part of the Valentine project, a pattern making ** program, whose allow create and modeling patterns of clothing. ** Copyright (C) 2013-2015 Valentina project ** All Rights Reserved. ** ** Valentina is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** Valentina is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with Valentina. If not, see . ** *************************************************************************/ #include "vabstractcurve.h" #include #include #include #include #include #include #include #include "vabstractcurve_p.h" VAbstractCurve::VAbstractCurve(const GOType &type, const quint32 &idObject, const Draw &mode) :VGObject(type, idObject, mode), d (new VAbstractCurveData()) {} //--------------------------------------------------------------------------------------------------------------------- VAbstractCurve::VAbstractCurve(const VAbstractCurve &curve) :VGObject(curve), d (curve.d) {} //--------------------------------------------------------------------------------------------------------------------- VAbstractCurve &VAbstractCurve::operator=(const VAbstractCurve &curve) { if ( &curve == this ) { return *this; } VGObject::operator=(curve); d = curve.d; return *this; } //--------------------------------------------------------------------------------------------------------------------- VAbstractCurve::~VAbstractCurve() {} //--------------------------------------------------------------------------------------------------------------------- QVector VAbstractCurve::GetSegmentPoints(const QVector &points, const QPointF &begin, const QPointF &end, bool reverse) { QVector segment = points; if (reverse) { segment = GetReversePoints(segment); } QPointF start = begin; QPointF finish = end; if (begin == end) { start = segment.first(); finish = segment.last(); } segment = FromBegin(segment, start); segment = ToEnd(segment, finish); return segment; } //--------------------------------------------------------------------------------------------------------------------- QVector VAbstractCurve::GetSegmentPoints(const QPointF &begin, const QPointF &end, bool reverse) const { return GetSegmentPoints(GetPoints(), begin, end, reverse); } //--------------------------------------------------------------------------------------------------------------------- QVector VAbstractCurve::FromBegin(const QVector &points, const QPointF &begin, bool *ok) { if (points.count() >= 2) { if (points.first().toPoint() == begin.toPoint()) { if (ok != nullptr) { *ok = true; } return points; } QVector segment; bool theBegin = false; for (qint32 i = 0; i < points.count()-1; ++i) { if (theBegin == false) { if (IsPointOnLineSegment(begin, points.at(i), points.at(i+1))) { theBegin = true; segment.append(begin); if (i == points.count()-2) { segment.append(points.at(i+1)); } continue; } } else { segment.append(points.at(i)); if (i == points.count()-2) { segment.append(points.at(i+1)); } } } if (segment.isEmpty()) { if (ok != nullptr) { *ok = false; } return points; } else { if (ok != nullptr) { *ok = true; } return segment; } } else { if (ok != nullptr) { *ok = false; } return points; } } //--------------------------------------------------------------------------------------------------------------------- QVector VAbstractCurve::ToEnd(const QVector &points, const QPointF &end, bool *ok) { QVector reversed = GetReversePoints(points); reversed = FromBegin(reversed, end, ok); return GetReversePoints(reversed); } //--------------------------------------------------------------------------------------------------------------------- QPainterPath VAbstractCurve::GetPath(PathDirection direction) const { QPainterPath path; QVector points = GetPoints(); if (points.count() >= 2) { for (qint32 i = 0; i < points.count()-1; ++i) { path.moveTo(points.at(i)); path.lineTo(points.at(i+1)); } if (direction == PathDirection::Show && points.count() >= 3) { path.addPath(ShowDirection(points)); } } else { qDebug()<<"points.count() < 2"< points = GetPoints(); if (points.size() < 2) { return -1; } if (points.first().toPoint() == point.toPoint()) { return 0; } bool ok = false; const QVector segment = ToEnd(points, point, &ok); if (not ok) { return -1; } return PathLength(segment); } //--------------------------------------------------------------------------------------------------------------------- /** * @brief IntersectLine return list of points for real intersection with line * @param line line that intersect with curve * @return list of intersection points */ QVector VAbstractCurve::IntersectLine(const QLineF &line) const { return CurveIntersectLine(this->GetPoints(), line); } //--------------------------------------------------------------------------------------------------------------------- bool VAbstractCurve::IsIntersectLine(const QLineF &line) const { const QVector points = IntersectLine(line); return not points.isEmpty(); } //--------------------------------------------------------------------------------------------------------------------- quint32 VAbstractCurve::GetDuplicate() const { return d->duplicate; } //--------------------------------------------------------------------------------------------------------------------- void VAbstractCurve::SetDuplicate(quint32 number) { d->duplicate = number; CreateName(); } //--------------------------------------------------------------------------------------------------------------------- QString VAbstractCurve::GetColor() const { return d->color; } //--------------------------------------------------------------------------------------------------------------------- void VAbstractCurve::SetColor(const QString &color) { d->color = color; } //--------------------------------------------------------------------------------------------------------------------- QVector VAbstractCurve::CurveIntersectLine(const QVector &points, const QLineF &line) { QVector intersections; for ( auto i = 0; i < points.count()-1; ++i ) { QPointF crosPoint; const auto type = line.intersect(QLineF(points.at(i), points.at(i+1)), &crosPoint); if ( type == QLineF::BoundedIntersection ) { intersections.append(crosPoint); } } return intersections; } //--------------------------------------------------------------------------------------------------------------------- QPainterPath VAbstractCurve::ShowDirection(const QVector &points) const { QPainterPath path; if (points.count() >= 2) { /*Need find coordinate midle of curve. Universal way is take all points and find sum.*/ const qreal seek_length = qAbs(GetLength())/2.0; qreal found_length = 0; QLineF arrow; for (qint32 i = 1; i <= points.size()-1; ++i) { arrow = QLineF(points.at(i-1), points.at(i)); found_length += arrow.length();//Length that we aready find if (seek_length <= found_length)// if have found more that need stop. { //subtract length in last line and you will find position of the middle point. arrow.setLength(arrow.length() - (found_length - seek_length)); break; } } //Reverse line because we want start arrow from this point arrow = QLineF(arrow.p2(), arrow.p1()); const qreal angle = arrow.angle();//we each time change line angle, better save original angle value arrow.setLength(14);//arrow length in pixels arrow.setAngle(angle-35); path.moveTo(arrow.p1()); path.lineTo(arrow.p2()); arrow.setAngle(angle+35); path.moveTo(arrow.p1()); path.lineTo(arrow.p2()); } return path; } //--------------------------------------------------------------------------------------------------------------------- qreal VAbstractCurve::PathLength(const QVector &path) { QPainterPath splinePath; splinePath.moveTo(path.at(0)); for (qint32 i = 1; i < path.count(); ++i) { splinePath.lineTo(path.at(i)); } return splinePath.length(); }