diff --git a/src/adaptors/UBSvgSubsetAdaptor.h b/src/adaptors/UBSvgSubsetAdaptor.h index d3dc75fa..89915585 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.h +++ b/src/adaptors/UBSvgSubsetAdaptor.h @@ -1,225 +1,235 @@ -/* - * This program 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. - * - * This program 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 this program. If not, see . - */ - -#ifndef UBSVGSUBSETADAPTOR_H_ -#define UBSVGSUBSETADAPTOR_H_ - -#include -#include - -#include "frameworks/UBGeometryUtils.h" - -class UBGraphicsSvgItem; -class UBGraphicsPolygonItem; -class UBGraphicsPixmapItem; -class UBGraphicsPDFItem; -class UBGraphicsWidgetItem; -class UBGraphicsVideoItem; -class UBGraphicsAudioItem; -class UBGraphicsAppleWidgetItem; -class UBGraphicsW3CWidgetItem; -class UBGraphicsTextItem; -class UBGraphicsCurtainItem; -class UBGraphicsRuler; -class UBGraphicsCompass; -class UBGraphicsProtractor; -class UBGraphicsScene; -class UBDocumentProxy; -class UBGraphicsStroke; -class UBPersistenceManager; -class UBGraphicsTriangle; -class UBGraphicsCache; - -class UBSvgSubsetAdaptor -{ - private: - - UBSvgSubsetAdaptor() {;} - virtual ~UBSvgSubsetAdaptor() {;} - - public: - - static UBGraphicsScene* loadScene(UBDocumentProxy* proxy, const int pageIndex); - static void persistScene(UBDocumentProxy* proxy, UBGraphicsScene* pScene, const int pageIndex); - static void upgradeScene(UBDocumentProxy* proxy, const int pageIndex); - - static QUuid sceneUuid(UBDocumentProxy* proxy, const int pageIndex); - static void setSceneUuid(UBDocumentProxy* proxy, const int pageIndex, QUuid pUuid); - - static void convertPDFObjectsToImages(UBDocumentProxy* proxy); - static void convertSvgImagesToImages(UBDocumentProxy* proxy); - - static const QString nsSvg; - static const QString nsXLink; - static const QString nsXHtml; - static const QString nsUb; - static const QString xmlTrue; - static const QString xmlFalse; - - static const QString sFontSizePrefix; - static const QString sPixelUnit; - static const QString sFontWeightPrefix; - static const QString sFontStylePrefix; - - private: - - static UBGraphicsScene* loadScene(UBDocumentProxy* proxy, const QByteArray& pArray); - - static QDomDocument loadSceneDocument(UBDocumentProxy* proxy, const int pPageIndex); - - static QString uniboardDocumentNamespaceUriFromVersion(int fileVersion); - - static const QString sFormerUniboardDocumentNamespaceUri; - - static QString toSvgTransform(const QMatrix& matrix); - static QMatrix fromSvgTransform(const QString& transform); - - class UBSvgSubsetReader - { - public: - - UBSvgSubsetReader(UBDocumentProxy* proxy, const QByteArray& pXmlData); - - virtual ~UBSvgSubsetReader(){} - - UBGraphicsScene* loadScene(); - - private: - - UBGraphicsPolygonItem* polygonItemFromLineSvg(const QColor& pDefaultBrushColor); - - UBGraphicsPolygonItem* polygonItemFromPolygonSvg(const QColor& pDefaultBrushColor); - - QList polygonItemsFromPolylineSvg(const QColor& pDefaultColor); - - UBGraphicsPixmapItem* pixmapItemFromSvg(); - - UBGraphicsSvgItem* svgItemFromSvg(); - - UBGraphicsPDFItem* pdfItemFromPDF(); - - UBGraphicsVideoItem* videoItemFromSvg(); - - UBGraphicsAudioItem* audioItemFromSvg(); - - UBGraphicsAppleWidgetItem* graphicsAppleWidgetFromSvg(); - - UBGraphicsW3CWidgetItem* graphicsW3CWidgetFromSvg(); - - UBGraphicsTextItem* textItemFromSvg(); - - UBGraphicsCurtainItem* curtainItemFromSvg(); - - UBGraphicsRuler* rulerFromSvg(); - - UBGraphicsCompass* compassFromSvg(); - - UBGraphicsProtractor* protractorFromSvg(); - - UBGraphicsTriangle* triangleFromSvg(); - - UBGraphicsCache* cacheFromSvg(); - - void graphicsItemFromSvg(QGraphicsItem* gItem); - - QXmlStreamReader mXmlReader; - int mFileVersion; - UBDocumentProxy *mProxy; - QString mDocumentPath; - - QColor mGroupDarkBackgroundColor; - QColor mGroupLightBackgroundColor; - qreal mGroupZIndex; - bool mGroupHasInfo; - - QString mNamespaceUri; - }; - - class UBSvgSubsetWriter - { - public: - - UBSvgSubsetWriter(UBDocumentProxy* proxy, UBGraphicsScene* pScene, const int pageIndex); - - bool persistScene(); - - virtual ~UBSvgSubsetWriter(){} - - private: - - void polygonItemToSvgPolygon(UBGraphicsPolygonItem* polygonItem, bool groupHoldsInfo); - void polygonItemToSvgLine(UBGraphicsPolygonItem* polygonItem, bool groupHoldsInfo); - void strokeToSvgPolyline(UBGraphicsStroke* stroke, bool groupHoldsInfo); - void strokeToSvgPolygon(UBGraphicsStroke* stroke, bool groupHoldsInfo); - - inline QString pointsToSvgPointsAttribute(const QVector points) - { - const QVector crashedPoints = UBGeometryUtils::crashPointList(points); - - int pointsCount = crashedPoints.size(); - QString svgPoints; - - int length = 0; - QString sBuf; - for(int j = 0; j < pointsCount; j++) - { - const QPointF & point = crashedPoints.at(j); - sBuf.sprintf("%.2f,%.2f ", point.x(), point.y()); - svgPoints.insert(length, sBuf); - length += sBuf.length(); - } - return svgPoints; - } - - inline qreal trickAlpha(qreal alpha) - { - qreal trickAlpha = alpha; - if(trickAlpha >= 0.2 && trickAlpha < 0.6){ - trickAlpha /= 5; - }else if (trickAlpha < 0.8) - trickAlpha /= 3; - - return trickAlpha; - } - - void pixmapItemToLinkedImage(UBGraphicsPixmapItem *pixmapItem); - void svgItemToLinkedSvg(UBGraphicsSvgItem *svgItem); - void pdfItemToLinkedPDF(UBGraphicsPDFItem *pdfItem); - void videoItemToLinkedVideo(UBGraphicsVideoItem *videoItem); - void audioItemToLinkedAudio(UBGraphicsAudioItem* audioItem); - void graphicsItemToSvg(QGraphicsItem *item); - void graphicsAppleWidgetToSvg(UBGraphicsAppleWidgetItem *item); - void graphicsW3CWidgetToSvg(UBGraphicsW3CWidgetItem *item); - void graphicsWidgetToSvg(UBGraphicsWidgetItem *item); - void textItemToSvg(UBGraphicsTextItem *item); - void curtainItemToSvg(UBGraphicsCurtainItem *item); - void rulerToSvg(UBGraphicsRuler *item); - void compassToSvg(UBGraphicsCompass *item); - void protractorToSvg(UBGraphicsProtractor *item); - void cacheToSvg(UBGraphicsCache* item); - void triangleToSvg(UBGraphicsTriangle *item); - void writeSvgElement(); - - private: - - UBGraphicsScene* mScene; - QXmlStreamWriter mXmlWriter; - QString mDocumentPath; - int mPageIndex; - - }; -}; - -#endif /* UBSVGSUBSETADAPTOR_H_ */ +/* + * This program 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. + * + * This program 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 this program. If not, see . + */ + +#ifndef UBSVGSUBSETADAPTOR_H_ +#define UBSVGSUBSETADAPTOR_H_ + +#include +#include + +#include "frameworks/UBGeometryUtils.h" + +class UBGraphicsSvgItem; +class UBGraphicsPolygonItem; +class UBGraphicsPixmapItem; +class UBGraphicsPDFItem; +class UBGraphicsWidgetItem; +class UBGraphicsVideoItem; +class UBGraphicsAudioItem; +class UBGraphicsAppleWidgetItem; +class UBGraphicsW3CWidgetItem; +class UBGraphicsTextItem; +class UBGraphicsCurtainItem; +class UBGraphicsRuler; +class UBGraphicsCompass; +class UBGraphicsProtractor; +class UBGraphicsScene; +class UBDocumentProxy; +class UBGraphicsStroke; +class UBPersistenceManager; +class UBGraphicsTriangle; +class UBGraphicsCache; + +class UBSvgSubsetAdaptor +{ + private: + + UBSvgSubsetAdaptor() {;} + virtual ~UBSvgSubsetAdaptor() {;} + + public: + + static UBGraphicsScene* loadScene(UBDocumentProxy* proxy, const int pageIndex); + static void persistScene(UBDocumentProxy* proxy, UBGraphicsScene* pScene, const int pageIndex); + static void upgradeScene(UBDocumentProxy* proxy, const int pageIndex); + + static QUuid sceneUuid(UBDocumentProxy* proxy, const int pageIndex); + static void setSceneUuid(UBDocumentProxy* proxy, const int pageIndex, QUuid pUuid); + + static void convertPDFObjectsToImages(UBDocumentProxy* proxy); + static void convertSvgImagesToImages(UBDocumentProxy* proxy); + + static const QString nsSvg; + static const QString nsXLink; + static const QString nsXHtml; + static const QString nsUb; + static const QString xmlTrue; + static const QString xmlFalse; + + static const QString sFontSizePrefix; + static const QString sPixelUnit; + static const QString sFontWeightPrefix; + static const QString sFontStylePrefix; + + private: + + static UBGraphicsScene* loadScene(UBDocumentProxy* proxy, const QByteArray& pArray); + + static QDomDocument loadSceneDocument(UBDocumentProxy* proxy, const int pPageIndex); + + static QString uniboardDocumentNamespaceUriFromVersion(int fileVersion); + + static const QString sFormerUniboardDocumentNamespaceUri; + + static QString toSvgTransform(const QMatrix& matrix); + static QMatrix fromSvgTransform(const QString& transform); + + class UBSvgSubsetReader + { + public: + + UBSvgSubsetReader(UBDocumentProxy* proxy, const QByteArray& pXmlData); + + virtual ~UBSvgSubsetReader(){} + + UBGraphicsScene* loadScene(); + + private: + + UBGraphicsPolygonItem* polygonItemFromLineSvg(const QColor& pDefaultBrushColor); + + UBGraphicsPolygonItem* polygonItemFromPolygonSvg(const QColor& pDefaultBrushColor); + + QList polygonItemsFromPolylineSvg(const QColor& pDefaultColor); + + UBGraphicsPixmapItem* pixmapItemFromSvg(); + + UBGraphicsSvgItem* svgItemFromSvg(); + + UBGraphicsPDFItem* pdfItemFromPDF(); + + UBGraphicsVideoItem* videoItemFromSvg(); + + UBGraphicsAudioItem* audioItemFromSvg(); + + UBGraphicsAppleWidgetItem* graphicsAppleWidgetFromSvg(); + + UBGraphicsW3CWidgetItem* graphicsW3CWidgetFromSvg(); + + UBGraphicsTextItem* textItemFromSvg(); + + UBGraphicsCurtainItem* curtainItemFromSvg(); + + UBGraphicsRuler* rulerFromSvg(); + + UBGraphicsCompass* compassFromSvg(); + + UBGraphicsProtractor* protractorFromSvg(); + + UBGraphicsTriangle* triangleFromSvg(); + + UBGraphicsCache* cacheFromSvg(); + + void graphicsItemFromSvg(QGraphicsItem* gItem); + + QXmlStreamReader mXmlReader; + int mFileVersion; + UBDocumentProxy *mProxy; + QString mDocumentPath; + + QColor mGroupDarkBackgroundColor; + QColor mGroupLightBackgroundColor; + qreal mGroupZIndex; + bool mGroupHasInfo; + + QString mNamespaceUri; + }; + + class UBSvgSubsetWriter + { + public: + + UBSvgSubsetWriter(UBDocumentProxy* proxy, UBGraphicsScene* pScene, const int pageIndex); + + bool persistScene(); + + virtual ~UBSvgSubsetWriter(){} + + private: + + void polygonItemToSvgPolygon(UBGraphicsPolygonItem* polygonItem, bool groupHoldsInfo); + void polygonItemToSvgLine(UBGraphicsPolygonItem* polygonItem, bool groupHoldsInfo); + void strokeToSvgPolyline(UBGraphicsStroke* stroke, bool groupHoldsInfo); + void strokeToSvgPolygon(UBGraphicsStroke* stroke, bool groupHoldsInfo); + + inline QString pointsToSvgPointsAttribute(QVector points) + { + UBGeometryUtils::crashPointList(points); + + int pointsCount = points.size(); + QString svgPoints; + + int length = 0; + QString sBuf; + + for(int j = 0; j < pointsCount; j++) + { + sBuf = "%1,%2 "; + const QPointF & point = points.at(j); + + QString temp1 = "%1", temp2 = "%2"; + + temp1 = temp1.arg(point.x()); + temp2 = temp2.arg(point.y()); + + QLocale loc(QLocale::C); + sBuf = sBuf.arg(loc.toFloat(temp1)).arg(loc.toFloat(temp2)); + + svgPoints.insert(length, sBuf); + length += sBuf.length(); + } + return svgPoints; + } + + inline qreal trickAlpha(qreal alpha) + { + qreal trickAlpha = alpha; + if(trickAlpha >= 0.2 && trickAlpha < 0.6){ + trickAlpha /= 5; + }else if (trickAlpha < 0.8) + trickAlpha /= 3; + + return trickAlpha; + } + + void pixmapItemToLinkedImage(UBGraphicsPixmapItem *pixmapItem); + void svgItemToLinkedSvg(UBGraphicsSvgItem *svgItem); + void pdfItemToLinkedPDF(UBGraphicsPDFItem *pdfItem); + void videoItemToLinkedVideo(UBGraphicsVideoItem *videoItem); + void audioItemToLinkedAudio(UBGraphicsAudioItem* audioItem); + void graphicsItemToSvg(QGraphicsItem *item); + void graphicsAppleWidgetToSvg(UBGraphicsAppleWidgetItem *item); + void graphicsW3CWidgetToSvg(UBGraphicsW3CWidgetItem *item); + void graphicsWidgetToSvg(UBGraphicsWidgetItem *item); + void textItemToSvg(UBGraphicsTextItem *item); + void curtainItemToSvg(UBGraphicsCurtainItem *item); + void rulerToSvg(UBGraphicsRuler *item); + void compassToSvg(UBGraphicsCompass *item); + void protractorToSvg(UBGraphicsProtractor *item); + void cacheToSvg(UBGraphicsCache* item); + void triangleToSvg(UBGraphicsTriangle *item); + void writeSvgElement(); + + private: + + UBGraphicsScene* mScene; + QXmlStreamWriter mXmlWriter; + QString mDocumentPath; + int mPageIndex; + + }; +}; + +#endif /* UBSVGSUBSETADAPTOR_H_ */ diff --git a/src/frameworks/UBGeometryUtils.cpp b/src/frameworks/UBGeometryUtils.cpp index 51a44c05..68c6f1b5 100644 --- a/src/frameworks/UBGeometryUtils.cpp +++ b/src/frameworks/UBGeometryUtils.cpp @@ -1,226 +1,224 @@ -/* - * This program 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. - * - * This program 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 this program. If not, see . - */ - -#include "UBGeometryUtils.h" - -#include "core/memcheck.h" - -const double PI = 4.0 * atan(1.0); - -UBGeometryUtils::UBGeometryUtils() -{ - // NOOP -} - -UBGeometryUtils::~UBGeometryUtils() -{ - // NOOP -} - -QPolygonF UBGeometryUtils::lineToPolygon(const QLineF& pLine, const qreal& pWidth) -{ - qreal x1 = pLine.x1(); - qreal y1 = pLine.y1(); - - qreal x2 = pLine.x2(); - qreal y2 = pLine.y2(); - - qreal alpha = (90.0 - pLine.angle()) * PI / 180.0; - qreal hypothenuse = pWidth / 2; - - // TODO UB 4.x PERF cache sin/cos table - qreal opposite = sin(alpha) * hypothenuse; - qreal adjacent = cos(alpha) * hypothenuse; - - QPointF p1a(x1 - adjacent, y1 - opposite); - QPointF p1b(x1 + adjacent, y1 + opposite); - - QPointF p2a(x2 - adjacent, y2 - opposite); - QPointF p2b(x2 + adjacent, y2 + opposite); - - QPainterPath painterPath; - - painterPath.moveTo(p1a); - painterPath.lineTo(p2a); - - painterPath.arcTo(x2 - hypothenuse, y2 - hypothenuse, pWidth, pWidth, (90.0 + pLine.angle()), -180.0); - - //painterPath.lineTo(p2b); - painterPath.lineTo(p1b); - - painterPath.arcTo(x1 - hypothenuse, y1 - hypothenuse, pWidth, pWidth, -1 * (90.0 - pLine.angle()), -180.0); - - painterPath.closeSubpath(); - - return painterPath.toFillPolygon(); -} - -QPolygonF UBGeometryUtils::lineToPolygon(const QPointF& pStart, const QPointF& pEnd, - const qreal& pStartWidth, const qreal& pEndWidth) -{ - - qreal x1 = pStart.x(); - qreal y1 = pStart.y(); - - qreal x2 = pEnd.x(); - qreal y2 = pEnd.y(); - - QLineF line(pStart, pEnd); - - qreal alpha = (90.0 - line.angle()) * PI / 180.0; - qreal hypothenuseStart = pStartWidth / 2; - - qreal hypothenuseEnd = pEndWidth / 2; - - qreal sinAlpha = sin(alpha); - qreal cosAlpha = cos(alpha); - - // TODO UB 4.x PERF cache sin/cos table - qreal oppositeStart = sinAlpha * hypothenuseStart; - qreal adjacentStart = cosAlpha * hypothenuseStart; - - QPointF p1a(x1 - adjacentStart, y1 - oppositeStart); - QPointF p1b(x1 + adjacentStart, y1 + oppositeStart); - - qreal oppositeEnd = sinAlpha * hypothenuseEnd; - qreal adjacentEnd = cosAlpha * hypothenuseEnd; - - QPointF p2a(x2 - adjacentEnd, y2 - oppositeEnd); - - QPainterPath painterPath; - - painterPath.moveTo(p1a); - painterPath.lineTo(p2a); - - painterPath.arcTo(x2 - hypothenuseEnd, y2 - hypothenuseEnd, pEndWidth, pEndWidth, (90.0 + line.angle()), -180.0); - - painterPath.lineTo(p1b); - - painterPath.arcTo(x1 - hypothenuseStart, y1 - hypothenuseStart, pStartWidth, pStartWidth, -1 * (90.0 - line.angle()), -180.0); - - painterPath.closeSubpath(); - - return painterPath.toFillPolygon(); -} - -QPolygonF UBGeometryUtils::arcToPolygon(const QLineF& startRadius, qreal spanAngleInDegrees, qreal width) -{ - qreal startAngleInDegrees = - startRadius.angle(); - if (startAngleInDegrees > 180) - startAngleInDegrees -= 360; - else if (startAngleInDegrees < -180) - startAngleInDegrees += 360; - - qreal radiusLength = startRadius.length(); - qreal angle = 2 * asin(width / (2 * radiusLength)) * 180 / PI; - bool overlap = abs(spanAngleInDegrees) > 360 - angle; - if (overlap) - spanAngleInDegrees = spanAngleInDegrees < 0 ? -360 : 360; - - qreal endAngleInDegrees = startAngleInDegrees + spanAngleInDegrees; - - qreal innerRadius = radiusLength - width / 2; - QRectF innerSquare( - startRadius.p1().x() - innerRadius, - startRadius.p1().y() - innerRadius, - 2 * innerRadius, - 2 * innerRadius); - qreal outerRadius = radiusLength + width / 2; - QRectF outerSquare( - startRadius.p1().x() - outerRadius, - startRadius.p1().y() - outerRadius, - 2 * outerRadius, - 2 * outerRadius); - QRectF startSquare( - startRadius.p2().x() - width / 2, - startRadius.p2().y() - width / 2, - width, - width); - QRectF endSquare( - startRadius.p1().x() + radiusLength * cos(endAngleInDegrees * PI / 180.0) - width / 2, - startRadius.p1().y() + radiusLength * sin(endAngleInDegrees * PI / 180.0) - width / 2, - width, - width); - - QPainterPath painterPath( - QPointF( - startRadius.p1().x() + innerRadius * cos(startAngleInDegrees * PI / 180.0), - startRadius.p1().y() + innerRadius * sin(startAngleInDegrees * PI / 180.0))); - startAngleInDegrees = - startAngleInDegrees; - endAngleInDegrees = - endAngleInDegrees; - spanAngleInDegrees = - spanAngleInDegrees; - - if (overlap) - { - painterPath.addEllipse(outerSquare); - QPainterPath innerPainterPath; - innerPainterPath.addEllipse(innerSquare); - painterPath = painterPath.subtracted(innerPainterPath); - } - else - { - painterPath.arcTo(innerSquare, startAngleInDegrees, spanAngleInDegrees); - painterPath.arcTo(endSquare, 180.0 + endAngleInDegrees, spanAngleInDegrees > 0 ? -180.0 : 180.0); - painterPath.arcTo(outerSquare, endAngleInDegrees, - spanAngleInDegrees); - painterPath.arcTo(startSquare, startAngleInDegrees, spanAngleInDegrees > 0 ? -180.0 : 180.0); - painterPath.closeSubpath(); - } - - return painterPath.toFillPolygon(); -} - -QPointF UBGeometryUtils::pointConstrainedInRect(QPointF point, QRectF rect) -{ - return QPointF(qMax(rect.x(), qMin(rect.x() + rect.width(), point.x())), qMax(rect.y(), qMin(rect.y() + rect.height(), point.y()))); -} - - -QPoint UBGeometryUtils::pointConstrainedInRect(QPoint point, QRect rect) -{ - return QPoint(qMax(rect.x(), qMin(rect.x() + rect.width(), point.x())), qMax(rect.y(), qMin(rect.y() + rect.height(), point.y()))); -} - - -QRectF UBGeometryUtils::lineToInnerRect(const QLineF& pLine, const qreal& pWidth) -{ - qreal centerX = (pLine.x1() + pLine.x2()) / 2; - qreal centerY = (pLine.y1() + pLine.y2()) / 2; - - qreal side = sqrt((pWidth * pWidth) / 2); - qreal halfSide = side / 2; - - return QRectF(centerX - halfSide, centerY - halfSide, side, side); -} - - -QVector UBGeometryUtils::crashPointList(const QVector points) -{ - QVector result(points); - int position = 1; - - while(position < result.size()) - { - if (result.at(position) == result.at(position - 1)) - { - result.remove(position); - } - else - { - ++position; - } - } - - return result; -} +/* + * This program 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. + * + * This program 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 this program. If not, see . + */ + +#include "UBGeometryUtils.h" + +#include "core/memcheck.h" + +const double PI = 4.0 * atan(1.0); + +UBGeometryUtils::UBGeometryUtils() +{ + // NOOP +} + +UBGeometryUtils::~UBGeometryUtils() +{ + // NOOP +} + +QPolygonF UBGeometryUtils::lineToPolygon(const QLineF& pLine, const qreal& pWidth) +{ + qreal x1 = pLine.x1(); + qreal y1 = pLine.y1(); + + qreal x2 = pLine.x2(); + qreal y2 = pLine.y2(); + + qreal alpha = (90.0 - pLine.angle()) * PI / 180.0; + qreal hypothenuse = pWidth / 2; + + // TODO UB 4.x PERF cache sin/cos table + qreal opposite = sin(alpha) * hypothenuse; + qreal adjacent = cos(alpha) * hypothenuse; + + QPointF p1a(x1 - adjacent, y1 - opposite); + QPointF p1b(x1 + adjacent, y1 + opposite); + + QPointF p2a(x2 - adjacent, y2 - opposite); + QPointF p2b(x2 + adjacent, y2 + opposite); + + QPainterPath painterPath; + + painterPath.moveTo(p1a); + painterPath.lineTo(p2a); + + painterPath.arcTo(x2 - hypothenuse, y2 - hypothenuse, pWidth, pWidth, (90.0 + pLine.angle()), -180.0); + + //painterPath.lineTo(p2b); + painterPath.lineTo(p1b); + + painterPath.arcTo(x1 - hypothenuse, y1 - hypothenuse, pWidth, pWidth, -1 * (90.0 - pLine.angle()), -180.0); + + painterPath.closeSubpath(); + + return painterPath.toFillPolygon(); +} + +QPolygonF UBGeometryUtils::lineToPolygon(const QPointF& pStart, const QPointF& pEnd, + const qreal& pStartWidth, const qreal& pEndWidth) +{ + + qreal x1 = pStart.x(); + qreal y1 = pStart.y(); + + qreal x2 = pEnd.x(); + qreal y2 = pEnd.y(); + + QLineF line(pStart, pEnd); + + qreal alpha = (90.0 - line.angle()) * PI / 180.0; + qreal hypothenuseStart = pStartWidth / 2; + + qreal hypothenuseEnd = pEndWidth / 2; + + qreal sinAlpha = sin(alpha); + qreal cosAlpha = cos(alpha); + + // TODO UB 4.x PERF cache sin/cos table + qreal oppositeStart = sinAlpha * hypothenuseStart; + qreal adjacentStart = cosAlpha * hypothenuseStart; + + QPointF p1a(x1 - adjacentStart, y1 - oppositeStart); + QPointF p1b(x1 + adjacentStart, y1 + oppositeStart); + + qreal oppositeEnd = sinAlpha * hypothenuseEnd; + qreal adjacentEnd = cosAlpha * hypothenuseEnd; + + QPointF p2a(x2 - adjacentEnd, y2 - oppositeEnd); + + QPainterPath painterPath; + + painterPath.moveTo(p1a); + painterPath.lineTo(p2a); + + painterPath.arcTo(x2 - hypothenuseEnd, y2 - hypothenuseEnd, pEndWidth, pEndWidth, (90.0 + line.angle()), -180.0); + + painterPath.lineTo(p1b); + + painterPath.arcTo(x1 - hypothenuseStart, y1 - hypothenuseStart, pStartWidth, pStartWidth, -1 * (90.0 - line.angle()), -180.0); + + painterPath.closeSubpath(); + + return painterPath.toFillPolygon(); +} + +QPolygonF UBGeometryUtils::arcToPolygon(const QLineF& startRadius, qreal spanAngleInDegrees, qreal width) +{ + qreal startAngleInDegrees = - startRadius.angle(); + if (startAngleInDegrees > 180) + startAngleInDegrees -= 360; + else if (startAngleInDegrees < -180) + startAngleInDegrees += 360; + + qreal radiusLength = startRadius.length(); + qreal angle = 2 * asin(width / (2 * radiusLength)) * 180 / PI; + bool overlap = abs(spanAngleInDegrees) > 360 - angle; + if (overlap) + spanAngleInDegrees = spanAngleInDegrees < 0 ? -360 : 360; + + qreal endAngleInDegrees = startAngleInDegrees + spanAngleInDegrees; + + qreal innerRadius = radiusLength - width / 2; + QRectF innerSquare( + startRadius.p1().x() - innerRadius, + startRadius.p1().y() - innerRadius, + 2 * innerRadius, + 2 * innerRadius); + qreal outerRadius = radiusLength + width / 2; + QRectF outerSquare( + startRadius.p1().x() - outerRadius, + startRadius.p1().y() - outerRadius, + 2 * outerRadius, + 2 * outerRadius); + QRectF startSquare( + startRadius.p2().x() - width / 2, + startRadius.p2().y() - width / 2, + width, + width); + QRectF endSquare( + startRadius.p1().x() + radiusLength * cos(endAngleInDegrees * PI / 180.0) - width / 2, + startRadius.p1().y() + radiusLength * sin(endAngleInDegrees * PI / 180.0) - width / 2, + width, + width); + + QPainterPath painterPath( + QPointF( + startRadius.p1().x() + innerRadius * cos(startAngleInDegrees * PI / 180.0), + startRadius.p1().y() + innerRadius * sin(startAngleInDegrees * PI / 180.0))); + startAngleInDegrees = - startAngleInDegrees; + endAngleInDegrees = - endAngleInDegrees; + spanAngleInDegrees = - spanAngleInDegrees; + + if (overlap) + { + painterPath.addEllipse(outerSquare); + QPainterPath innerPainterPath; + innerPainterPath.addEllipse(innerSquare); + painterPath = painterPath.subtracted(innerPainterPath); + } + else + { + painterPath.arcTo(innerSquare, startAngleInDegrees, spanAngleInDegrees); + painterPath.arcTo(endSquare, 180.0 + endAngleInDegrees, spanAngleInDegrees > 0 ? -180.0 : 180.0); + painterPath.arcTo(outerSquare, endAngleInDegrees, - spanAngleInDegrees); + painterPath.arcTo(startSquare, startAngleInDegrees, spanAngleInDegrees > 0 ? -180.0 : 180.0); + painterPath.closeSubpath(); + } + + return painterPath.toFillPolygon(); +} + +QPointF UBGeometryUtils::pointConstrainedInRect(QPointF point, QRectF rect) +{ + return QPointF(qMax(rect.x(), qMin(rect.x() + rect.width(), point.x())), qMax(rect.y(), qMin(rect.y() + rect.height(), point.y()))); +} + + +QPoint UBGeometryUtils::pointConstrainedInRect(QPoint point, QRect rect) +{ + return QPoint(qMax(rect.x(), qMin(rect.x() + rect.width(), point.x())), qMax(rect.y(), qMin(rect.y() + rect.height(), point.y()))); +} + + +QRectF UBGeometryUtils::lineToInnerRect(const QLineF& pLine, const qreal& pWidth) +{ + qreal centerX = (pLine.x1() + pLine.x2()) / 2; + qreal centerY = (pLine.y1() + pLine.y2()) / 2; + + qreal side = sqrt((pWidth * pWidth) / 2); + qreal halfSide = side / 2; + + return QRectF(centerX - halfSide, centerY - halfSide, side, side); +} + + +void UBGeometryUtils::crashPointList(QVector &points) +{ + // QVector result(points); + int position = 1; + + while(position < points.size()) + { + if (points.at(position) == points.at(position - 1)) + { + points.remove(position); + } + else + { + ++position; + } + } +} diff --git a/src/frameworks/UBGeometryUtils.h b/src/frameworks/UBGeometryUtils.h index 011c810f..b006478d 100644 --- a/src/frameworks/UBGeometryUtils.h +++ b/src/frameworks/UBGeometryUtils.h @@ -1,42 +1,42 @@ -/* - * This program 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. - * - * This program 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 this program. If not, see . - */ - -#ifndef UBGEOMETRYUTILS_H_ -#define UBGEOMETRYUTILS_H_ - -#include - -class UBGeometryUtils -{ - private: - UBGeometryUtils(); - virtual ~UBGeometryUtils(); - - public: - static QPolygonF lineToPolygon(const QLineF& pLine, const qreal& pWidth); - static QRectF lineToInnerRect(const QLineF& pLine, const qreal& pWidth); - - static QPolygonF arcToPolygon(const QLineF& startRadius, qreal spanAngle, qreal width); - - static QPolygonF lineToPolygon(const QPointF& pStart, const QPointF& pEnd, - const qreal& pStartWidth, const qreal& pEndWidth); - - static QPointF pointConstrainedInRect(QPointF point, QRectF rect); - static QPoint pointConstrainedInRect(QPoint point, QRect rect); - - static QVector crashPointList(const QVector points); -}; - -#endif /* UBGEOMETRYUTILS_H_ */ +/* + * This program 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. + * + * This program 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 this program. If not, see . + */ + +#ifndef UBGEOMETRYUTILS_H_ +#define UBGEOMETRYUTILS_H_ + +#include + +class UBGeometryUtils +{ + private: + UBGeometryUtils(); + virtual ~UBGeometryUtils(); + + public: + static QPolygonF lineToPolygon(const QLineF& pLine, const qreal& pWidth); + static QRectF lineToInnerRect(const QLineF& pLine, const qreal& pWidth); + + static QPolygonF arcToPolygon(const QLineF& startRadius, qreal spanAngle, qreal width); + + static QPolygonF lineToPolygon(const QPointF& pStart, const QPointF& pEnd, + const qreal& pStartWidth, const qreal& pEndWidth); + + static QPointF pointConstrainedInRect(QPointF point, QRectF rect); + static QPoint pointConstrainedInRect(QPoint point, QRect rect); + + static void crashPointList(QVector &points); +}; + +#endif /* UBGEOMETRYUTILS_H_ */