SANKORE-459

preferencesAboutTextFull
Anatoly Mihalchenko 13 years ago
parent 7f26289b50
commit 9c8a49f8c6
  1. 460
      src/adaptors/UBSvgSubsetAdaptor.h
  2. 450
      src/frameworks/UBGeometryUtils.cpp
  3. 84
      src/frameworks/UBGeometryUtils.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 <http://www.gnu.org/licenses/>.
*/
#ifndef UBSVGSUBSETADAPTOR_H_
#define UBSVGSUBSETADAPTOR_H_
#include <QtGui>
#include <QtXml>
#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<UBGraphicsPolygonItem*> 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<QPointF> points)
{
const QVector<QPointF> 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 <http://www.gnu.org/licenses/>.
*/
#ifndef UBSVGSUBSETADAPTOR_H_
#define UBSVGSUBSETADAPTOR_H_
#include <QtGui>
#include <QtXml>
#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<UBGraphicsPolygonItem*> 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<QPointF> 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_ */

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<QPointF> UBGeometryUtils::crashPointList(const QVector<QPointF> points)
{
QVector<QPointF> 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 <http://www.gnu.org/licenses/>.
*/
#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<QPointF> &points)
{
// QVector<QPointF> result(points);
int position = 1;
while(position < points.size())
{
if (points.at(position) == points.at(position - 1))
{
points.remove(position);
}
else
{
++position;
}
}
}

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef UBGEOMETRYUTILS_H_
#define UBGEOMETRYUTILS_H_
#include <QtGui>
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<QPointF> crashPointList(const QVector<QPointF> 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 <http://www.gnu.org/licenses/>.
*/
#ifndef UBGEOMETRYUTILS_H_
#define UBGEOMETRYUTILS_H_
#include <QtGui>
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<QPointF> &points);
};
#endif /* UBGEOMETRYUTILS_H_ */

Loading…
Cancel
Save