19 #include "vectorimage.h"
22 VectorImage::VectorImage()
27 VectorImage::~VectorImage()
31 bool VectorImage::read(QString filePath)
33 QFileInfo fileInfo(filePath);
34 if ( fileInfo.isDir() )
40 if (!file.open(QFile::ReadOnly))
47 if (!doc.setContent(&file))
return false;
48 QDomDocumentType type = doc.doctype();
49 if (type.name() !=
"PencilVectorImage")
return false;
51 QDomElement element = doc.documentElement();
52 if (element.tagName() ==
"image")
55 if (element.attribute(
"type") ==
"vector")
57 loadDomElement( element );
63 Status VectorImage::write(QString filePath, QString format)
65 QStringList debugInfo = QStringList() <<
"VectorImage::write" << QString(
"filePath = " ).append( filePath ) << QString(
"format = " ).append( format );
67 bool result = file.open(QIODevice::WriteOnly);
71 qDebug() <<
"VectorImage - Cannot write file" << filePath << file.error();
72 return Status( Status::FAIL, debugInfo << QString(
"file.error() = ").append( file.errorString() ) );
77 QXmlStreamWriter xmlStream( &file );
78 xmlStream.setAutoFormatting(
true);
79 xmlStream.writeStartDocument();
80 xmlStream.writeDTD(
"<!DOCTYPE PencilVectorImage>" );
82 xmlStream.writeStartElement(
"image" );
83 xmlStream.writeAttribute(
"type",
"vector" );
84 Status st = createDomElement( xmlStream );
87 QStringList xmlDetails = st.detailsList();
88 for ( QString detail : xmlDetails )
90 detail.prepend(
" " );
92 return Status( Status::FAIL, debugInfo <<
"- xml creation failed" << xmlDetails );
95 xmlStream.writeEndElement();
96 xmlStream.writeEndDocument();
102 qDebug() <<
"--- Not the VEC format!";
103 return Status( Status::FAIL, debugInfo <<
"Unrecognized format" );
107 Status VectorImage::createDomElement( QXmlStreamWriter& xmlStream )
109 QStringList debugInfo = QStringList() <<
"VectorImage::createDomElement";
110 for (
int i = 0; i < m_curves.size(); i++ )
112 Status st = m_curves[ i ].createDomElement( xmlStream );
115 QStringList curveDetails = st.detailsList();
116 for ( QString detail : curveDetails )
118 detail.prepend(
" " );
120 return Status( Status::FAIL, debugInfo << QString(
"- m_curves[%1] failed to write" ).arg( i ) << curveDetails );
123 for (
int i = 0; i < area.size(); i++ )
125 Status st = area[ i ].createDomElement( xmlStream );
128 QStringList areaDetails = st.detailsList();
129 for ( QString detail : areaDetails )
131 detail.prepend(
" " );
133 return Status( Status::FAIL, debugInfo << QString(
"- area[%1] failed to write" ).arg( i ) << areaDetails );
139 void VectorImage::loadDomElement(QDomElement element)
141 QDomNode atomTag = element.firstChild();
142 while (!atomTag.isNull())
144 QDomElement atomElement = atomTag.toElement();
145 if (!atomElement.isNull())
147 if (atomElement.tagName() ==
"curve")
150 newCurve.loadDomElement(atomElement);
151 m_curves.append(newCurve);
153 if (atomElement.tagName() ==
"area")
156 newArea.loadDomElement(atomElement);
160 atomTag = atomTag.nextSibling();
166 void VectorImage::addPoint(
int curveNumber,
int vertexNumber, qreal t)
169 m_curves[curveNumber].addPoint(vertexNumber, t);
171 for(
int j=0; j < area.size(); j++)
174 for(
int k=0; k< area.at(j).mVertex.size(); k++)
176 if (area[j].getVertexRef(k).curveNumber == curveNumber)
178 if (area[j].getVertexRef(k).vertexNumber >= vertexNumber)
180 area[j].mVertex[k].vertexNumber++;
185 for(
int k=1; k< area.at(j).mVertex.size(); k++)
187 if (
VertexRef(curveNumber, vertexNumber+1) == area.at(j).mVertex.at(k) )
189 if (
VertexRef(curveNumber, vertexNumber-1) == area.at(j).mVertex.at(k-1) )
191 area[j].mVertex.insert(k,
VertexRef(curveNumber, vertexNumber) );
194 if (
VertexRef(curveNumber, vertexNumber-1) == area.at(j).mVertex.at(k) )
196 if (
VertexRef(curveNumber, vertexNumber+1) == area.at(j).mVertex.at(k-1) )
198 area[j].mVertex.insert(k,
VertexRef(curveNumber, vertexNumber) );
205 void VectorImage::removeCurveAt(
int i)
208 for(
int j=0; j < area.size(); j++)
210 for(
int k=0; k< area.at(j).mVertex.size(); k++)
212 if (area.at(j).mVertex[k].curveNumber > i) { area[j].mVertex[k].curveNumber--; }
216 m_curves.removeAt(i);
219 void VectorImage::insertCurve(
int position,
BezierCurve& newCurve, qreal factor,
bool interacts)
221 if (newCurve.getVertexSize() < 1) {
233 qreal tol = qMax( newCurve.getWidth() / factor, 3.0 / factor);
236 checkCurveExtremity(newCurve, tol);
237 checkCurveIntersections(newCurve, tol);
243 if (position < 0 || position > m_curves.size() - 1) {
244 m_curves.append(newCurve);
249 for(
int i=0; i < area.size(); i++)
251 for(
int j=0; j< area.at(i).mVertex.size(); j++)
253 if (area.at(i).mVertex[j].curveNumber >= position) {
254 area[i].mVertex[j].curveNumber++;
258 m_curves.insert(position, newCurve);
262 updateImageSize(newCurve);
269 void VectorImage::addCurve(
BezierCurve& newCurve, qreal factor,
bool interacts)
271 insertCurve(-1, newCurve, factor, interacts);
274 void VectorImage::checkCurveExtremity(
BezierCurve& newCurve, qreal tolerance)
277 QPointF P = newCurve.getVertex(-1);
278 QPointF Q = newCurve.getVertex(newCurve.getVertexSize()-1);
279 if ( BezierCurve::eLength(P-Q) < tolerance)
281 newCurve.setVertex(newCurve.getVertexSize()-1, P);
284 for(
int i=0; i < m_curves.size(); i++)
286 for(
int j=0; j < m_curves.at(i).getVertexSize(); j++)
288 QPointF P = newCurve.getVertex(-1);
289 QPointF Q = newCurve.getVertex(newCurve.getVertexSize()-1);
290 QPointF P1 = m_curves.at(i).getVertex(j-1);
291 QPointF P2 = m_curves.at(i).getVertex(j);
292 qreal tol3 = 2.0*sqrt( 0.25*((P1-P2).x()*(P1-P2).x() + (P1-P2).y()*(P1-P2).y()) + tolerance*tolerance );
293 qreal dist1 = BezierCurve::eLength(P-P1);
294 qreal dist2 = BezierCurve::eLength(P-P2);
295 if (dist1 <= 0.2*tolerance)
297 newCurve.setVertex(-1, P1);
301 if (dist2 <= 0.2*tolerance)
303 newCurve.setVertex(-1, P2);
307 if ( dist1+dist2 <= 3*tol3 )
309 QPointF nearestPoint = P;
311 qreal distance = BezierCurve::findDistance(m_curves[i], j, P, nearestPoint, t);
312 if (distance < tolerance)
314 newCurve.setOrigin(nearestPoint);
323 dist1 = BezierCurve::eLength(Q-P1);
324 dist2 = BezierCurve::eLength(Q-P2);
325 if (dist1 <= 0.2*tolerance)
327 newCurve.setLastVertex(P1);
331 if (dist2 <= 0.2*tolerance)
333 newCurve.setLastVertex(P2);
337 if ( dist1+dist2 <= 3*tol3 )
339 QPointF nearestPoint = Q;
341 qreal distance = BezierCurve::findDistance(m_curves[i], j, Q, nearestPoint, t);
342 if (distance < tolerance)
344 newCurve.setLastVertex(nearestPoint);
356 void VectorImage::checkCurveIntersections(
BezierCurve& newCurve, qreal tolerance)
361 for(
int k=0; k < newCurve.getVertexSize(); k++)
363 for(
int j=k+1; j < newCurve.getVertexSize(); j++)
366 bool intersection = BezierCurve::findIntersection(newCurve, k, newCurve, j, intersections);
371 newCurve.addPoint(k, intersections[0].t1);
375 newCurve.addPoint(j, intersections[0].t2);
382 for(
int k=0; k < newCurve.getVertexSize(); k++)
388 for(
int i=0; i < m_curves.size(); i++)
394 QPointF P = m_curves.at(i).getVertex(-1);
395 QPointF Q = m_curves.at(i).getVertex(m_curves.at(i).getVertexSize()-1);
396 QPointF P1 = newCurve.getVertex(k-1);
397 QPointF P2 = newCurve.getVertex(k);
398 qreal tol3 = 2.0*sqrt( 0.25*((P1-P2).x()*(P1-P2).x() + (P1-P2).y()*(P1-P2).y()) + tolerance*tolerance );
399 qreal dist1 = BezierCurve::eLength(P-P1);
400 qreal dist2 = BezierCurve::eLength(P-P2);
402 if (dist1 < 0.2*tolerance)
404 m_curves[i].setVertex(-1, P1);
408 if (dist2 < 0.2*tolerance)
410 m_curves[i].setVertex(-1, P2);
414 if ( dist1+dist2 < 3*tol3 )
417 QPointF nearestPoint = P;
419 qreal distance = BezierCurve::findDistance(newCurve, k, P, nearestPoint, t);
421 if (distance < tolerance)
431 dist1 = BezierCurve::eLength(Q-P1);
432 dist2 = BezierCurve::eLength(Q-P2);
433 if (dist1 < 0.2*tolerance)
435 m_curves[i].setVertex(m_curves.at(i).getVertexSize()-1, P1);
439 if (dist2 < 0.2*tolerance)
441 m_curves[i].setVertex(m_curves.at(i).getVertexSize()-1, P2);
445 if ( dist1+dist2 < 3*tol3 )
448 QPointF nearestPoint = Q;
450 qreal distance = BezierCurve::findDistance(newCurve, k, Q, nearestPoint, t);
452 if (distance < tolerance)
464 for(
int j=0; j < m_curves.at(i).getVertexSize(); j++)
467 bool intersection = BezierCurve::findIntersection(newCurve, k, m_curves.at(i), j, intersections);
471 QPointF intersectionPoint = intersections[0].point;
472 qreal t1 = intersections[0].t1;
473 qreal t2 = intersections[0].t2;
474 if ( BezierCurve::eLength(intersectionPoint - newCurve.getVertex(k-1)) <= 0.1*tolerance )
476 newCurve.setVertex(k-1, intersectionPoint);
481 if ( BezierCurve::eLength(intersectionPoint - newCurve.getVertex(k)) <= 0.1*tolerance )
483 newCurve.setVertex(k, intersectionPoint);
489 newCurve.addPoint(k, t1);
494 if ( BezierCurve::eLength(intersectionPoint - m_curves.at(i).getVertex(j-1)) <= 0.1*tolerance )
496 m_curves[i].setVertex(j-1, intersectionPoint);
501 if ( BezierCurve::eLength(intersectionPoint - m_curves.at(i).getVertex(j)) <= 0.1*tolerance )
503 m_curves[i].setVertex(j, intersectionPoint);
519 void VectorImage::select(QRectF rectangle)
521 for(
int i=0; i< m_curves.size(); i++)
523 if ( m_curves[i].intersects(rectangle) )
525 setSelected(i,
true);
529 setSelected(i,
false);
532 for(
int i=0; i< area.size(); i++)
534 if ( rectangle.contains(area[i].mPath.boundingRect()) )
536 setAreaSelected(i,
true);
540 setAreaSelected(i,
false);
546 void VectorImage::setSelected(
int curveNumber,
bool YesOrNo)
548 m_curves[curveNumber].setSelected(YesOrNo);
549 if (YesOrNo) mSelectionRect |= m_curves[curveNumber].getBoundingRect();
553 void VectorImage::setSelected(
int curveNumber,
int vertexNumber,
bool YesOrNo)
555 m_curves[curveNumber].setSelected(vertexNumber, YesOrNo);
556 QPointF vertex = getVertex(curveNumber, vertexNumber);
557 if (YesOrNo) mSelectionRect |= QRectF(vertex.x(), vertex.y(), 0.0, 0.0);
561 void VectorImage::setSelected(
VertexRef vertexRef,
bool YesOrNo)
563 setSelected(vertexRef.curveNumber, vertexRef.vertexNumber, YesOrNo);
566 void VectorImage::setSelected(
QList<int> curveList,
bool YesOrNo)
568 for(
int i=0; i<curveList.size(); i++)
570 setSelected(curveList.at(i), YesOrNo);
576 for(
int i=0; i<vertexList.size(); i++)
578 setSelected(vertexList.at(i), YesOrNo);
582 void VectorImage::setAreaSelected(
int areaNumber,
bool YesOrNo)
584 area[areaNumber].setSelected(YesOrNo);
585 if (YesOrNo) mSelectionRect |= area[areaNumber].mPath.boundingRect();
589 bool VectorImage::isAreaSelected(
int areaNumber)
591 return area[areaNumber].isSelected();
594 bool VectorImage::isSelected(
int curveNumber)
596 return m_curves[curveNumber].isSelected();
599 bool VectorImage::isSelected(
int curveNumber,
int vertexNumber)
601 return m_curves[curveNumber].isSelected(vertexNumber);
604 bool VectorImage::isSelected(
VertexRef vertexRef)
606 return isSelected(vertexRef.curveNumber, vertexRef.vertexNumber);
609 bool VectorImage::isSelected(
QList<int> curveList)
612 for(
int i=0; i<curveList.size(); i++)
614 result &= isSelected(curveList.at(i));
622 for(
int i=0; i<vertexList.size(); i++)
624 result &= isSelected(vertexList.at(i));
629 int VectorImage::getFirstSelectedCurve()
632 for(
int i=0; i<m_curves.size() && result == -1; i++)
634 if ( isSelected(i) ) result = i;
639 int VectorImage::getFirstSelectedArea()
642 for(
int i=0; i<area.size() && result == -1; i++)
644 if ( isAreaSelected(i) ) result = i;
649 void VectorImage::selectAll()
651 for(
int i=0; i< m_curves.size(); i++)
654 setSelected(i,
true);
656 mSelectionTransformation.reset();
660 void VectorImage::deselectAll()
662 for(
int i=0; i< m_curves.size(); i++)
664 m_curves[i].setSelected(
false);
666 for(
int i=0; i< area.size(); i++)
668 area[i].setSelected(
false);
670 mSelectionRect = QRectF(0,0,0,0);
671 mSelectionTransformation.reset();
675 void VectorImage::setSelectionRect(QRectF rectangle)
677 mSelectionRect = rectangle;
681 void VectorImage::calculateSelectionRect()
683 mSelectionRect = QRectF(0,0,0,0);
684 for(
int i=0; i< m_curves.size(); i++)
686 if ( m_curves.at(i).isPartlySelected()) mSelectionRect |= m_curves[i].getBoundingRect();
690 void VectorImage::setSelectionTransformation(QTransform transform)
692 mSelectionTransformation = transform;
696 void VectorImage::deleteSelection()
699 for(
int i=0; i< area.size(); i++)
701 if ( area[i].isSelected())
708 for(
int i=0; i< m_curves.size(); i++)
710 if ( m_curves[i].isSelected())
713 for(
int j=0; j < area.size(); j++)
715 bool toBeDeleted =
false;
716 for(
int k=0; k< area.at(j).mVertex.size(); k++)
718 if (area.at(j).mVertex[k].curveNumber == i) { toBeDeleted =
true; }
719 if (area.at(j).mVertex[k].curveNumber > i) { area[j].mVertex[k].curveNumber = area[j].mVertex[k].curveNumber - 1; }
727 m_curves.removeAt(i);
742 void VectorImage::removeVertex(
int i,
int m)
745 for(
int j=0; j < area.size(); j++)
747 bool toBeDeleted =
false;
748 for(
int k=0; k< area.at(j).mVertex.size(); k++)
750 if (area.at(j).mVertex[k].curveNumber == i && area.at(j).mVertex[k].vertexNumber == m) { toBeDeleted =
true; }
760 if (m_curves[i].getVertexSize() > 1)
767 if ( m == -1 || m == getCurveSize(i) - 1 )
769 m_curves[i].removeVertex(m);
772 for(
int j=0; j < area.size(); j++)
774 for(
int k=0; k< area.at(j).mVertex.size(); k++)
776 if (area.at(j).mVertex[k].curveNumber == i && area.at(j).mVertex[k].vertexNumber > m) { area[j].mVertex[k].vertexNumber--; }
782 int n = getCurveSize(i);
784 for(
int p = m; p < n; p++)
786 m_curves[i].removeVertex( getCurveSize(i)-1 );
788 for(
int p=-1; p <= m; p++)
790 newCurve.removeVertex(-1);
793 if (newCurve.getVertexSize() > 0) m_curves.append( newCurve);
795 for(
int j=0; j < area.size(); j++)
797 for(
int k=0; k< area.at(j).mVertex.size(); k++)
799 if (area.at(j).mVertex[k].curveNumber == i && area.at(j).mVertex[k].vertexNumber > m)
801 area[j].mVertex[k].curveNumber = m_curves.size()-1;
802 area[j].mVertex[k].vertexNumber = area[j].mVertex[k].vertexNumber-m-1;
807 if ( getCurveSize(i) < 1)
823 void VectorImage::deleteSelectedPoints()
825 for(
int i=0; i< m_curves.size(); i++)
827 for(
int m=-1; m < getCurveSize(i); m++)
829 if (m_curves.at(i).isSelected(m))
840 mSelectionRect = QRect(0,0,0,0);
841 int n = m_curves.size();
844 bool hasSelection = getFirstSelectedCurve() < -1;
846 for(
int i=0; i < vectorImage.m_curves.size() ; i++)
850 if ( !hasSelection || vectorImage.m_curves.at(i).isSelected() )
852 m_curves.append( vectorImage.m_curves.at(i) );
854 mSelectionRect |= vectorImage.m_curves[i].getBoundingRect();
857 for(
int i=0; i < vectorImage.area.size() ; i++)
861 for(
int j=0; j < newArea.mVertex.size(); j++)
863 int curveNumber = newArea.mVertex.at(j).curveNumber;
864 int vertexNumber = newArea.mVertex.at(j).vertexNumber;
868 if ( !hasSelection || vectorImage.m_curves.at(curveNumber).isSelected() )
870 newArea.mVertex[j] =
VertexRef( selectedCurves.indexOf(curveNumber) + n, vertexNumber );
877 if (ok) area.append( newArea );
882 QColor VectorImage::getColour(
int colourNumber)
884 return mObject->getColour(colourNumber).colour;
887 int VectorImage::getColourNumber(QPointF point)
890 int areaNumber = getLastAreaNumber(point);
891 if (areaNumber != -1)
893 result = area[areaNumber].mColourNumber;
898 bool VectorImage::usesColour(
int index)
900 for(
int i=0; i< area.size(); i++)
902 if (area[i].mColourNumber == index)
return true;
904 for(
int i=0; i< m_curves.size(); i++)
906 if (m_curves[i].getColourNumber() == index)
return true;
911 void VectorImage::removeColour(
int index)
913 for(
int i=0; i< area.size(); i++)
915 if (area[i].getColourNumber() > index) area[i].decreaseColourNumber();
917 for(
int i=0; i< m_curves.size(); i++)
919 if (m_curves[i].getColourNumber() > index) m_curves[i].decreaseColourNumber();
923 void VectorImage::paintImage(QPainter& painter,
928 painter.setRenderHint(QPainter::Antialiasing, antialiasing);
930 painter.setClipping(
false);
931 painter.setOpacity(1.0);
932 QTransform painterMatrix = painter.transform();
934 QRect mappedViewRect = QRect(0,0, painter.device()->width(), painter.device()->height() );
935 painterMatrix.inverted().mapRect( mappedViewRect );
940 for(
int i=0; i< area.size(); i++)
942 updateArea( area[i] );
945 QColor colour = getColour(area[i].mColourNumber);
948 painter.setWorldMatrixEnabled(
false );
950 if (area[i].isSelected())
952 painter.setBrush( QBrush( QColor(255-colour.red(),255-colour.green(),255-colour.blue()), Qt::Dense6Pattern) );
955 painter.setPen(QPen(QBrush(colour), 1, Qt::NoPen, Qt::RoundCap,Qt::RoundJoin));
956 painter.setBrush( QBrush( colour, Qt::SolidPattern ));
959 painter.drawPath( painter.transform().map( area[ i ].mPath ) );
961 painter.setWorldMatrixEnabled(
true );
964 painter.setRenderHint(QPainter::Antialiasing, antialiasing);
965 painter.setClipping(
false);
975 curve.drawPath( painter, mObject, mSelectionTransformation, simplified, showThinCurves );
976 painter.setClipping(
false);
980 void VectorImage::outputImage(QImage* image,
986 image->fill(qRgba(0,0,0,0));
987 QPainter painter( image );
988 painter.setTransform( myView );
989 paintImage( painter, simplified, showThinCurves, antialiasing );
992 void VectorImage::clear()
994 while (m_curves.size() > 0) { m_curves.removeAt(0); }
995 while (area.size() > 0) { area.removeAt(0); }
999 void VectorImage::clean()
1001 for(
int i=0; i<m_curves.size(); i++)
1003 if (m_curves.at(i).getVertexSize() == 0) { qDebug() <<
"CLEAN " << i; m_curves.removeAt(i); i--; }
1007 void VectorImage::applySelectionTransformation()
1009 applySelectionTransformation(mSelectionTransformation);
1012 void VectorImage::applySelectionTransformation(QTransform transf)
1014 for(
int i=0; i< m_curves.size(); i++)
1016 if ( m_curves.at(i).isPartlySelected()) {
1017 m_curves[i].transform(transf);
1020 calculateSelectionRect();
1021 mSelectionTransformation.reset();
1025 void VectorImage::applyColourToSelection(
int colourNumber)
1027 for (
int i = 0; i < m_curves.size(); i++)
1029 if ( m_curves.at(i).isSelected()) m_curves[i].setColourNumber(colourNumber);
1031 for (
int i = 0; i < area.size(); i++)
1033 if ( area.at(i).isSelected()) area[i].setColourNumber(colourNumber);
1038 void VectorImage::applyWidthToSelection(qreal width)
1040 for(
int i = 0; i < m_curves.size(); i++)
1042 if ( m_curves.at(i).isSelected() ) m_curves[ i ].setWidth( width );
1047 void VectorImage::applyFeatherToSelection(qreal feather)
1049 for(
int i=0; i< m_curves.size(); i++)
1051 if ( m_curves.at(i).isSelected() ) m_curves[i].setFeather(feather);
1056 void VectorImage::applyOpacityToSelection(qreal opacity)
1059 for(
int i=0; i< m_curves.size(); i++)
1066 void VectorImage::applyInvisibilityToSelection(
bool YesOrNo)
1068 for(
int i=0; i< m_curves.size(); i++)
1070 if ( m_curves.at(i).isSelected()) m_curves[i].setInvisibility(YesOrNo);
1075 void VectorImage::applyVariableWidthToSelection(
bool YesOrNo)
1077 for(
int i=0; i< m_curves.size(); i++)
1079 if ( m_curves.at(i).isSelected()) {
1080 m_curves[i].setVariableWidth(YesOrNo);
1086 QList<int> VectorImage::getCurvesCloseTo(QPointF P1, qreal maxDistance)
1089 for(
int j=0; j<m_curves.size(); j++)
1092 if (m_curves[j].isPartlySelected()) {
1093 myCurve = m_curves[j].transformed(mSelectionTransformation);
1095 myCurve = m_curves[j];
1097 if ( myCurve.intersects(P1, maxDistance) ) {
1105 VertexRef VectorImage::getClosestVertexTo(QPointF P1, qreal maxDistance)
1110 qreal distance = 400.0*400.0;
1111 for(
int j=0; j<m_curves.size(); j++)
1113 for(
int k=-1; k<m_curves.at(j).getVertexSize(); k++)
1116 QPointF P2 = getVertex(j, k);
1117 qreal distance2 = (P1.x()-P2.x())*(P1.x()-P2.x()) + (P1.y()-P2.y())*(P1.y()-P2.y());
1118 if ( distance2 < distance && distance2 < maxDistance*maxDistance)
1120 distance = distance2;
1128 QList<VertexRef> VectorImage::getVerticesCloseTo(QPointF P1, qreal maxDistance)
1131 for(
int j=0; j<m_curves.size(); j++)
1133 for(
int k=-1; k<m_curves.at(j).getVertexSize(); k++)
1135 QPointF P2 = getVertex(j, k);
1136 qreal distance = (P1.x()-P2.x())*(P1.x()-P2.x()) + (P1.y()-P2.y())*(P1.y()-P2.y());
1137 if ( distance < maxDistance*maxDistance )
1149 for(
int j=0; j<listOfPoints->size(); j++)
1151 QPointF P2 = getVertex(listOfPoints->at(j));
1152 qreal distance = (P1.x()-P2.x())*(P1.x()-P2.x()) + (P1.y()-P2.y())*(P1.y()-P2.y());
1153 if ( distance < maxDistance*maxDistance )
1155 result.append(listOfPoints->at(j));
1164 return getVerticesCloseTo( getVertex(P1ref), maxDistance);
1169 return getVerticesCloseTo( getVertex(P1ref), maxDistance, listOfPoints);
1176 for(
int j=0; j<listOfPoints->size(); j++)
1178 QPointF P2 = getVertex(listOfPoints->at(j));
1179 qreal distance = (P1.x()-P2.x())*(P1.x()-P2.x()) + (P1.y()-P2.y())*(P1.y()-P2.y());
1180 if ( distance < maxDistance*maxDistance )
1182 result.append(listOfPoints->at(j));
1183 listOfPoints->removeAt(j);
1191 return getAndRemoveVerticesCloseTo(getVertex(P1Ref), maxDistance, listOfPoints);
1194 QPointF VectorImage::getVertex(
int curveNumber,
int vertexNumber)
1196 QPointF result = QPointF(11.11, 11.11);
1197 if (curveNumber > -1 && curveNumber < m_curves.size())
1200 if ( myCurve.isPartlySelected() ) myCurve = myCurve.transformed(mSelectionTransformation);
1201 if ( vertexNumber > -2 && vertexNumber < myCurve.getVertexSize())
1203 result = myCurve.getVertex(vertexNumber);
1209 QPointF VectorImage::getVertex(
VertexRef vertexRef)
1211 return getVertex(vertexRef.curveNumber, vertexRef.vertexNumber);
1214 QPointF VectorImage::getC1(
int curveNumber,
int vertexNumber)
1216 QPointF result = QPointF(11.11, 11.11);
1217 if (curveNumber > -1 && curveNumber < m_curves.size())
1220 if ( myCurve.isPartlySelected() ) myCurve = myCurve.transformed(mSelectionTransformation);
1221 if ( vertexNumber > -1 && vertexNumber < myCurve.getVertexSize())
1223 result = myCurve.getC1(vertexNumber);
1229 QPointF VectorImage::getC1(
VertexRef vertexRef)
1231 return getC1(vertexRef.curveNumber, vertexRef.vertexNumber);
1234 QPointF VectorImage::getC2(
int curveNumber,
int vertexNumber)
1236 QPointF result = QPointF(11.11, 11.11);
1237 if (curveNumber > -1 && curveNumber < m_curves.size())
1240 if ( myCurve.isPartlySelected() ) myCurve = myCurve.transformed(mSelectionTransformation);
1241 if ( vertexNumber > -1 && vertexNumber < myCurve.getVertexSize())
1243 result = myCurve.getC2(vertexNumber);
1249 QPointF VectorImage::getC2(
VertexRef vertexRef)
1251 return getC2(vertexRef.curveNumber, vertexRef.vertexNumber);
1258 if (curveNumber > -1 && curveNumber < m_curves.size())
1262 for(
int k=-1; k<myCurve.getVertexSize(); k++)
1265 result.append(vertexRef);
1275 for(
int j=0; j<m_curves.size(); j++)
1277 for(
int k=-1; k<m_curves.at(j).getVertexSize(); k++)
1280 result.append(vertexRef);
1287 int VectorImage::getCurveSize(
int curveNumber)
1289 if ( curveNumber > -1 && curveNumber < m_curves.size())
1291 return m_curves.at(curveNumber).getVertexSize();
1299 void VectorImage::fillPath(
QList<QPointF> contourPath,
int colour,
float tolerance)
1303 for (QPointF point : contourPath) {
1304 VertexRef vertex = getClosestVertexTo(point, tolerance);
1305 if (vertex.curveNumber != -1 && !vertexPath.contains(vertex)) {
1306 vertexPath.append(vertex);
1311 addArea( bezierArea );
1318 QImage* image =
new QImage( mSize, QImage::Format_ARGB32_Premultiplied );
1319 image->fill(Qt::white);
1320 QPainter painter( image );
1323 QTransform translate;
1324 translate.translate( mSize.width() / 2.f , mSize.height() / 2.f );
1325 painter.setTransform( translate );
1326 paintImage( painter,
true,
true,
false );
1331 qreal maxWidth = mSize.width();
1332 qreal maxHeight = mSize.height();
1335 int highestY = point.y();
1339 QPointF startPoint((maxWidth / 2) + point.x(), (maxHeight / 2) + point.y());
1340 queue.append( startPoint.toPoint() );
1343 QRgb colourFrom = image->pixel(startPoint.x(), startPoint.y());
1344 QRgb colourTo = Qt::green;
1346 QPoint currentPoint;
1349 bool foundLeftBound, foundRightBound;
1354 while ( queue.size() > 0 ) {
1357 currentPoint = queue.at(0);
1361 if (image->pixel(currentPoint.x(), currentPoint.y()) == colourFrom) {
1362 leftX = currentPoint.x();
1363 rightX = currentPoint.x();
1365 foundLeftBound =
false;
1366 foundRightBound =
false;
1368 while (!foundLeftBound) {
1373 qWarning() <<
" Out of bound left ";
1378 QPoint leftPoint = QPoint(leftX, currentPoint.y());
1381 if ( image->pixel(leftPoint.x(), leftPoint.y()) != colourFrom &&
1382 image->pixel(leftPoint.x(), leftPoint.y()) != colourTo ) {
1384 foundLeftBound =
true;
1387 QPointF contourPoint( leftPoint.x() - (maxWidth / 2), leftPoint.y() - (maxHeight / 2));
1390 bool foundFillAfter =
false;
1393 while (leftPoint.x() - increment > 0 && increment < 3 && !foundFillAfter) {
1394 QPoint pointAfter = QPoint(leftPoint.x() - increment, leftPoint.y());
1396 if (image->pixel(pointAfter.x(), pointAfter.y()) == colourTo) {
1397 foundFillAfter =
true;
1404 if (foundFillAfter) {
1407 contourPoints.removeOne(contourPoint);
1409 contourPoints.append(contourPoint);
1414 while (!foundRightBound) {
1418 if ( rightX > maxWidth - 1 ) {
1419 qWarning() <<
" Out of bound right ";
1424 QPoint rightPoint = QPoint(rightX, currentPoint.y());
1427 if ( image->pixel(rightPoint.x(), rightPoint.y()) != colourFrom &&
1428 image->pixel(rightPoint.x(), rightPoint.y()) != colourTo) {
1430 foundRightBound =
true;
1433 QPointF contourPoint( rightPoint.x() - (maxWidth / 2), rightPoint.y() - (maxHeight / 2));
1436 bool foundFillAfter =
false;
1439 while (rightPoint.x() + increment < maxWidth && increment < 3 && !foundFillAfter) {
1440 QPoint pointAfter = QPoint(rightPoint.x() + increment, rightPoint.y());
1442 if (image->pixel(pointAfter.x(), pointAfter.y()) == colourTo) {
1443 foundFillAfter =
true;
1449 if (foundFillAfter) {
1452 contourPoints.removeOne(contourPoint);
1454 contourPoints.append(contourPoint);
1459 int lineY = currentPoint.y();
1460 int topY = lineY - 1;
1461 int bottomY = lineY + 1;
1463 if ( topY < 1 || bottomY > maxHeight - 1 ) {
1464 qWarning() <<
" Out of bound top / bottom ";
1469 for (
int x = leftX + 1; x < rightX; x++) {
1472 QPoint linePoint = QPoint(x, lineY);
1473 image->setPixel(linePoint.x(), linePoint.y(), colourTo);
1475 QPoint topPoint = QPoint(x, topY);
1477 if ( image->pixel(topPoint.x(), topPoint.y()) != colourFrom &&
1478 image->pixel(topPoint.x(), topPoint.y()) != colourTo) {
1481 QPointF contourPoint( topPoint.x() - (maxWidth / 2), topPoint.y() - (maxHeight / 2));
1484 bool foundFillAfter =
false;
1487 while (topPoint.y() - increment > 0 && increment < 3 && !foundFillAfter) {
1488 QPoint pointAfter = QPoint(topPoint.x(), topPoint.y() - increment);
1490 if (image->pixel(pointAfter.x(), pointAfter.y()) == colourTo) {
1491 foundFillAfter =
true;
1497 if (foundFillAfter) {
1500 contourPoints.removeOne(contourPoint);
1502 contourPoints.append(contourPoint);
1505 queue.append(topPoint);
1508 QPoint bottomPoint = QPoint(x, bottomY);
1510 if ( image->pixel(bottomPoint.x(), bottomPoint.y()) != colourFrom &&
1511 image->pixel(bottomPoint.x(), bottomPoint.y()) != colourTo ) {
1513 QPointF contourPoint( bottomPoint.x() - (maxWidth / 2), bottomPoint.y() - (maxHeight / 2));
1516 bool foundFillAfter =
false;
1519 while (bottomPoint.y() + increment < maxHeight && increment < 3 && !foundFillAfter) {
1520 QPoint pointAfter = QPoint(bottomPoint.x(), bottomPoint.y() + increment);
1522 if (image->pixel(pointAfter.x(), pointAfter.y()) == colourTo) {
1523 foundFillAfter =
true;
1529 if (foundFillAfter) {
1532 contourPoints.removeOne(contourPoint);
1539 if (highestY < bottomY) {
1542 contourPoints.insert(0, contourPoint);
1544 contourPoints.append(contourPoint);
1549 queue.append(bottomPoint);
1554 return contourPoints;
1557 void VectorImage::fill(QPointF point,
int colour,
float tolerance)
1560 QList<int> closestCurves = getCurvesCloseTo( point, tolerance );
1562 if (closestCurves.size() > 0)
1565 for (
int i = 0; i < closestCurves.size(); i++) {
1566 int curveNumber = closestCurves[i];
1567 m_curves[curveNumber].setColourNumber(colour);
1575 int areaNum = getLastAreaNumber(point);
1576 if (areaNum > -1 && area[areaNum].mColourNumber == colour) {
1581 QList<QPointF> contourPoints = getfillContourPoints(point.toPoint());
1586 QPointF currentPoint;
1588 if (contourPoints.size() > 0) {
1589 currentPoint = QPointF(contourPoints[0].x(), contourPoints[0].y());
1590 mainContourPath.append(currentPoint);
1591 contourPoints.removeAt(0);
1594 bool completedPath =
false;
1595 bool foundError = (contourPoints.size() < 1 && !completedPath);
1600 while (!completedPath && !foundError) {
1602 bool foundNextPoint =
false;
1605 while (i < contourPoints.size() && !foundNextPoint) {
1606 QPointF point = contourPoints.at(i);
1608 if (mainContourPath.contains(point)) {
1609 contourPoints.removeAt(i);
1612 qreal deltaX = currentPoint.x() - point.x();
1613 qreal deltaY = currentPoint.y() - point.y();
1615 if ( (deltaX < maxDelta && deltaX > minDelta) &&
1616 (deltaY < maxDelta && deltaY > minDelta)) {
1618 currentPoint = QPointF(point.x(), point.y());
1619 mainContourPath.append(currentPoint);
1620 contourPoints.removeAt(i);
1622 foundNextPoint =
true;
1632 if (!foundNextPoint) {
1634 qreal deltaX = currentPoint.x() - mainContourPath[0].x();
1635 qreal deltaY = currentPoint.y() - mainContourPath[0].y();
1637 if ( (deltaX < maxDelta && deltaX > minDelta) &&
1638 (deltaY < maxDelta && deltaY > minDelta)) {
1639 completedPath =
true;
1640 foundNextPoint =
true;
1642 else if (maxDelta == 2){
1647 foundNextPoint =
true;
1650 qWarning() <<
" couldn't find next point after " << currentPoint.x() <<
", " << currentPoint.y();
1653 else if (contourPoints.size() < 1) {
1655 completedPath =
true;
1656 foundNextPoint =
true;
1659 foundError = ( (contourPoints.size() < 1 && !completedPath) || !foundNextPoint );
1665 if (completedPath) {
1666 fillPath(mainContourPath, colour, 10.0);
1671 int areaNum = getLastAreaNumber(point);
1674 int clickedColorNum = area[areaNum].getColourNumber();
1676 if (clickedColorNum != colour) {
1677 area[areaNum].setColourNumber(colour);
1683 void VectorImage::addArea(
BezierArea bezierArea)
1685 updateArea(bezierArea);
1686 area.append( bezierArea );
1690 int VectorImage::getFirstAreaNumber(QPointF point)
1693 for(
int i=0; i<area.size() && result==-1; i++)
1695 if ( area[i].mPath.controlPointRect().contains( point ) )
1697 if ( area[i].mPath.contains( point ) )
1706 int VectorImage::getLastAreaNumber(QPointF point)
1708 return getLastAreaNumber(point, area.size()-1);
1711 int VectorImage::getLastAreaNumber(QPointF point,
int maxAreaNumber)
1714 for(
int i=maxAreaNumber; i>-1 && result==-1; i--)
1716 if ( area[i].mPath.controlPointRect().contains( point ) )
1718 if ( area[i].mPath.contains( point ) )
1727 void VectorImage::removeArea(QPointF point)
1729 int areaNumber = getLastAreaNumber(point);
1730 if ( areaNumber != -1)
1732 area.removeAt(areaNumber);
1737 void VectorImage::updateArea(
BezierArea& bezierArea)
1739 QPainterPath newPath;
1740 for(
int i=0; i<bezierArea.mVertex.size(); i++)
1742 QPointF myPoint = getVertex(bezierArea.mVertex[i]);
1748 newPath.moveTo( myPoint );
1752 if (bezierArea.mVertex[i-1].curveNumber == bezierArea.mVertex[i].curveNumber )
1754 if (bezierArea.mVertex[i-1].vertexNumber < bezierArea.mVertex[i].vertexNumber )
1756 myC1 = getC1(bezierArea.mVertex[i]);
1757 myC2 = getC2(bezierArea.mVertex[i]);
1761 myC1 = getC2(bezierArea.mVertex[i-1]);
1762 myC2 = getC1(bezierArea.mVertex[i-1]);
1764 newPath.cubicTo(myC1, myC2, myPoint);
1768 if ( bezierArea.mVertex[i].vertexNumber == -1)
1770 newPath.lineTo( myPoint );
1774 newPath.lineTo( myPoint );
1779 newPath.closeSubpath();
1780 bezierArea.mPath = newPath;
1781 bezierArea.mPath.setFillRule( Qt::WindingFill );
1786 return BezierCurve::eLength(getVertex(r1)-getVertex(r2));
1789 void VectorImage::updateImageSize(
BezierCurve& updatedCurve) {
1800 QRectF rect = updatedCurve.getBoundingRect();
1802 QPoint topLeft = rect.topLeft().toPoint();
1803 QPoint bottomRight = rect.bottomRight().toPoint();
1805 int widthFromLeft = ((topLeft.x() * -1) * 2) + 2;
1807 if (widthFromLeft > mSize.width()) {
1808 mSize.setWidth(widthFromLeft);
1811 int widthFromRight = (bottomRight.x() * 2) + 2;
1813 if (widthFromRight > mSize.width()) {
1814 mSize.setWidth(widthFromRight);
1817 int heightFromTop = ((topLeft.y() * -1) * 2) + 2;
1819 if (heightFromTop > mSize.height()) {
1820 mSize.setHeight(heightFromTop);
1823 int heightFromBottom = (bottomRight.y() * 2) + 2;
1825 if (heightFromBottom > mSize.height()) {
1826 mSize.setHeight(heightFromBottom);