1 #include "RubberBandTool.h"
14 #include "geos/geom/CoordinateArraySequence.h"
15 #include "geos/geom/CoordinateSequence.h"
16 #include "geos/geom/Coordinate.h"
17 #include "geos/geom/LineString.h"
18 #include "geos/geom/MultiLineString.h"
19 #include "geos/geom/Polygon.h"
22 #include "Constants.h"
23 #include "MdiCubeViewport.h"
24 #include "PolygonTools.h"
25 #include "SerialNumberList.h"
35 RubberBandTool::RubberBandTool(
QWidget *parent) :
Tool(parent) {
39 p_mouseLoc =
new QPoint;
41 p_bandingMode = LineMode;
48 RubberBandTool::~RubberBandTool() {
74 QPen pen(QColor(255, 0, 0));
75 QPen greenPen(QColor(0, 255, 0));
76 pen.setStyle(Qt::SolidLine);
77 greenPen.setStyle(Qt::SolidLine);
86 switch(p_bandingMode) {
93 if(figureIsPoint() && !p_tracking) {
94 painter->drawLine((*p_vertices)[0].x() - 10, (*p_vertices)[0].y() - 10,
95 (*p_vertices)[0].x() + 10, (*p_vertices)[0].y() + 10);
96 painter->drawLine((*p_vertices)[0].x() - 10, (*p_vertices)[0].y() + 10,
97 (*p_vertices)[0].x() + 10, (*p_vertices)[0].y() - 10);
108 if(!p_tracking && p_vertices->size() > 0) {
109 painter->drawLine((*p_vertices)[0], (*p_vertices)[ p_vertices->size() - 1 ]);
115 if(p_vertices->size() != 0) {
117 int width = 2 * (verticesList[1].x() - verticesList[0].x());
118 int height = 2 * (verticesList[1].y() - verticesList[0].y());
121 painter->drawEllipse(verticesList[0].x() - width / 2, verticesList[0].y() - height / 2,
129 case RectangleMode: {
130 if(figureIsPoint() && !p_tracking) {
131 painter->drawLine((*p_vertices)[0].x() - 10, (*p_vertices)[0].y() - 10,
132 (*p_vertices)[0].x() + 10, (*p_vertices)[0].y() + 10);
133 painter->drawLine((*p_vertices)[0].x() - 10, (*p_vertices)[0].y() + 10,
134 (*p_vertices)[0].x() + 10, (*p_vertices)[0].y() - 10);
137 if(p_tracking && p_vertices->size() > 0) {
140 else if(p_vertices->size() > 0) {
142 painter->drawLine((*p_vertices)[0], (*p_vertices)[ p_vertices->size() - 1 ]);
148 case RotatedRectangleMode: {
149 if(p_vertices->size() == 2) {
150 QPoint missingVertex;
151 calcRectCorners((*p_vertices)[0], (*p_vertices)[1], *p_mouseLoc, missingVertex);
152 painter->drawLine(*p_mouseLoc, missingVertex);
153 painter->drawLine(missingVertex, (*p_vertices)[0]);
155 else if(p_vertices->size() == 4) {
156 painter->drawLine((*p_vertices)[0], (*p_vertices)[ 3 ]);
162 if(p_indicatorColors) {
163 painter->setPen(greenPen);
164 if(p_vertices->size() > 1) {
165 painter->drawLine((*p_vertices)[0], (*p_vertices)[1]);
167 else if(p_vertices->size() == 1) {
168 painter->drawLine((*p_vertices)[0], *p_mouseLoc);
171 painter->setPen(pen);
176 case SegmentedLineMode:
191 double slope = ((double)corner2.y() - (double)corner1.y()) / ((
double)corner2.x() - (double)corner1.x());
193 if((fabs(slope) > DBL_EPSILON) && (slope < DBL_MAX) && (slope > -DBL_MAX)) {
198 double parallelB = -1 * slope * corner3.x() + corner3.y();
203 double perpSlope = -1.0 / slope;
204 double perpLineMode1b = perpSlope * (-1 * corner1.x()) + corner1.y();
205 double perpLineMode2b = perpSlope * (-1 * corner2.x()) + corner2.y();
210 double perpLineMode1k = perpLineMode1b - parallelB;
211 double perpLineMode2k = perpLineMode2b - parallelB;
218 double perpLineMode1IntersectX = perpLineMode1k / (slope - perpSlope);
219 double perpLineMode2IntersectX = perpLineMode2k / (slope - perpSlope);
223 corner3.setX((
int)perpLineMode2IntersectX);
224 corner3.setY((
int)(perpLineMode2IntersectX * slope + parallelB));
225 corner4.setX((
int)perpLineMode1IntersectX);
226 corner4.setY((
int)(perpLineMode1IntersectX * slope + parallelB));
228 else if(fabs(slope) < DBL_EPSILON) {
229 corner3.setX(corner2.x());
230 corner3.setY(corner3.y());
231 corner4.setX(corner1.x());
232 corner4.setY(corner3.y());
235 corner3.setX(corner3.x());
236 corner3.setY(corner2.y());
237 corner4.setX(corner3.x());
238 corner4.setY(corner1.y());
249 for(
int vertex = 1; vertex < p_vertices->size(); vertex++) {
250 QPoint start = (*p_vertices)[vertex - 1];
251 QPoint end = (*p_vertices)[vertex];
253 painter->drawLine(start, end);
256 if(p_tracking && (p_vertices->size() > 0)) {
257 QPoint start = (*p_vertices)[p_vertices->size() - 1];
258 QPoint end = *p_mouseLoc;
260 painter->drawLine(start, end);
272 QPoint upperRight = QPoint(lowerRight.x(), upperLeft.y());
273 QPoint lowerLeft = QPoint(upperLeft.x(), lowerRight.y());
275 paintRectangle(upperLeft, upperRight, lowerLeft, lowerRight, painter);
288 QPoint lowerLeft, QPoint lowerRight, QPainter *painter) {
289 painter->drawLine(upperLeft, upperRight);
290 painter->drawLine(upperRight, lowerRight);
291 painter->drawLine(lowerRight, lowerLeft);
292 painter->drawLine(lowerLeft, upperLeft);
303 RubberBandMode oldMode = p_bandingMode;
304 p_bandingMode = mode;
305 p_indicatorColors = showIndicatorColors;
309 p_drawActiveOnly =
false;
313 if(oldMode != mode) {
334 p_drawActiveOnly = activeOnly;
344 p_doubleClicking =
true;
347 switch(p_bandingMode) {
353 case RotatedRectangleMode:
356 case SegmentedLineMode:
360 emit bandingComplete();
390 if((s & Qt::LeftButton) != Qt::LeftButton && !p_allClicks) {
394 switch(p_bandingMode) {
404 p_vertices->push_back(p);
407 case RotatedRectangleMode:
408 if(p_vertices->size() == 4) {
412 if(p_vertices->size() == 0) {
413 p_vertices->push_back(p);
418 case SegmentedLineMode:
425 if(p_vertices->size() == 0 || (*p_vertices)[ p_vertices->size() - 1 ] != p) {
426 p_vertices->push_back(p);
476 if ((s & Qt::ControlModifier) == Qt::ControlModifier)
483 if((s & Qt::LeftButton) == Qt::LeftButton || p_allClicks) {
490 switch(p_bandingMode) {
492 if(p_vertices->size() == 3) {
496 p_vertices->push_back(*p_mouseLoc);
499 if(p_vertices->size() == 3) {
501 emit bandingComplete();
509 case RectangleMode: {
512 emit bandingComplete();
516 case RotatedRectangleMode: {
517 if(p_vertices->size() == 1) {
518 p_vertices->push_back(*p_mouseLoc);
520 else if(p_vertices->size() == 2) {
523 emit bandingComplete();
528 case SegmentedLineMode:
533 p_doubleClicking =
false;
539 if (curViewport == activeViewport ||
541 curViewport->viewport()->repaint();
555 if (p_vertices->size()) {
556 QPoint lastVertex = p_vertices->at(p_vertices->size() - 1);
558 int deltaX = abs(p.x() - lastVertex.x());
559 int deltaY = abs(p.y() - lastVertex.y());
562 p.setY(lastVertex.y());
564 p.setX(lastVertex.x());
596 if ((p_mouseButton & Qt::ControlModifier) == Qt::ControlModifier)
601 switch(p_bandingMode) {
603 case RotatedRectangleMode:
604 if(p_vertices->size() == 2) {
605 emit measureChange();
612 if(p_vertices->size() == 1) {
613 emit measureChange();
618 emit measureChange();
621 case SegmentedLineMode:
623 if(p_mouseDown && p != (*p_vertices)[ p_vertices->size() - 1 ]) {
624 p_vertices->push_back(p);
627 if (p_bandingMode == SegmentedLineMode)
628 emit measureChange();
636 if (curViewport == activeViewport ||
638 curViewport->viewport()->repaint();
675 if(!figureComplete())
679 switch(p_bandingMode) {
682 case SegmentedLineMode:
686 case RectangleMode: {
687 QPoint corner1 = QPoint(p_mouseLoc->x(),
vertices[0].y());
688 QPoint corner2 = QPoint(p_mouseLoc->x(), p_mouseLoc->y());
689 QPoint corner3 = QPoint(
vertices[0].x(), p_mouseLoc->y());
696 case RotatedRectangleMode: {
697 QPoint missingVertex;
698 calcRectCorners((*p_vertices)[0], (*p_vertices)[1], *p_mouseLoc, missingVertex);
706 int xradius = abs(p_mouseLoc->x() -
vertices[0].x()) / 2;
707 int yradius = xradius;
709 if(p_mouseLoc->x() -
vertices[0].x() < 0) {
713 if(p_mouseLoc->y() -
vertices[0].y() < 0) {
730 double xradius = (p_mouseLoc->x() -
vertices[0].x()) / 2.0;
731 double yradius = (p_mouseLoc->y() -
vertices[0].y()) / 2.0;
756 p_doubleClicking =
false;
760 Angle RubberBandTool::angle() {
763 if(currentMode() == AngleMode) {
786 double theta1 = atan2((
double)(verticesList[0].y() - verticesList[1].y()), (
double)(verticesList[0].x() - verticesList[1].x()));
787 double theta2 = atan2((
double)(verticesList[2].y() - verticesList[1].y()), (
double)(verticesList[2].x() - verticesList[1].x()));
788 double angle = (theta1 - theta2);
794 while(angle >
PI * 2) {
800 angle = (
PI * 2.0) - angle;
824 geos::geom::Geometry *
geometry = NULL;
827 switch(p_bandingMode) {
829 if(verticesList.size() != 3)
832 geos::geom::CoordinateSequence *points1 =
new geos::geom::CoordinateArraySequence();
833 geos::geom::CoordinateSequence *points2 =
new geos::geom::CoordinateArraySequence();
835 points1->add(geos::geom::Coordinate(verticesList[0].x(), verticesList[0].y()));
836 points1->add(geos::geom::Coordinate(verticesList[1].x(), verticesList[1].y()));
837 points2->add(geos::geom::Coordinate(verticesList[1].x(), verticesList[1].y()));
838 points2->add(geos::geom::Coordinate(verticesList[2].x(), verticesList[2].y()));
840 geos::geom::LineString *line1 = globalFactory->createLineString(points1);
841 geos::geom::LineString *line2 = globalFactory->createLineString(points2);
842 std::vector<geos::geom::Geometry *> *lines =
new std::vector<geos::geom::Geometry *>;
843 lines->push_back(line1);
844 lines->push_back(line2);
846 geos::geom::MultiLineString *angle = globalFactory->createMultiLineString(lines);
853 if(verticesList.size() != 2)
863 double h = verticesList[0].x();
864 double k = verticesList[0].y();
865 double a = abs(verticesList[0].x() - verticesList[1].x());
866 double b = abs(verticesList[0].y() - verticesList[1].y());
873 double originalX = 0.0, originalY = 0.0;
874 geos::geom::CoordinateSequence *points =
new geos::geom::CoordinateArraySequence();
877 for(
double x = h - a; x <= h + a; x += 0.2) {
878 double y = sqrt(pow(b, 2) * (1.0 - pow((x - h), 2) / pow(a, 2))) + k;
879 points->add(geos::geom::Coordinate(x, y));
888 for(
double x = h + a; x >= h - a; x -= 0.2) {
889 double y = -1.0 * sqrt(pow(b, 2) * (1.0 - pow((x - h), 2) / pow(a, 2))) + k;
890 points->add(geos::geom::Coordinate(x, y));
893 points->add(geos::geom::Coordinate(originalX, originalY));
895 geometry = globalFactory->createPolygon(
896 globalFactory->createLinearRing(points), NULL
902 case RotatedRectangleMode:
904 if(verticesList.size() < 3)
907 geos::geom::CoordinateSequence *points =
new geos::geom::CoordinateArraySequence();
909 for(
int vertex = 0; vertex < verticesList.size(); vertex++) {
910 points->add(geos::geom::Coordinate(verticesList[vertex].x(), verticesList[vertex].y()));
913 points->add(geos::geom::Coordinate(verticesList[0].x(), verticesList[0].y()));
915 geometry = globalFactory->createPolygon(globalFactory->createLinearRing(points), NULL);
921 if(verticesList.size() != 2)
924 geos::geom::CoordinateSequence *points =
new geos::geom::CoordinateArraySequence();
925 points->add(geos::geom::Coordinate(verticesList[0].x(), verticesList[0].y()));
926 points->add(geos::geom::Coordinate(verticesList[1].x(), verticesList[1].y()));
927 geos::geom::LineString *line = globalFactory->createLineString(points);
932 case SegmentedLineMode: {
933 if(verticesList.size() < 2)
935 geos::geom::CoordinateSequence *points =
new geos::geom::CoordinateArraySequence();
937 for(
int vertex = 0; vertex < verticesList.size(); vertex++) {
938 points->add(geos::geom::Coordinate(verticesList[vertex].x(), verticesList[vertex].y()));
941 geos::geom::LineString *line = globalFactory->createLineString(points);
969 if(currentMode() == RectangleMode && figureValid()) {
975 if(verticesList[0].x() < verticesList[2].x()) {
976 x1 = verticesList[0].x();
977 x2 = verticesList[2].x();
981 x1 = verticesList[2].x();
982 x2 = verticesList[0].x();
986 if(verticesList[0].y() < verticesList[2].y()) {
987 y1 = verticesList[0].y();
988 y2 = verticesList[2].y();
992 y1 = verticesList[2].y();
993 y2 = verticesList[0].y();
996 rect = QRect(x1, y1, x2 - x1, y2 - y1);
1000 QMessageBox::information((
QWidget *)parent(),
1001 "Error",
"**PROGRAMMER ERROR** Invalid RectangleMode");
1013 return p_mouseButton;
1017 return figureComplete() && figureValid();
1021 bool RubberBandTool::figureComplete() {
1022 bool complete =
false;
1024 switch(p_bandingMode) {
1026 complete = (p_vertices->size() == 2 && p_tracking) || (p_vertices->size() == 3);
1029 complete = (p_vertices->size() == 1 && p_tracking) || (p_vertices->size() == 2);
1033 complete = (p_vertices->size() == 1 && p_tracking) || (p_vertices->size() == 4);
1036 case RotatedRectangleMode:
1037 complete = (p_vertices->size() == 2 && p_tracking) || (p_vertices->size() == 4);
1042 complete = (p_vertices->size() == 1 && p_tracking) || (p_vertices->size() == 2);
1045 case SegmentedLineMode:
1046 complete = (p_vertices->size() > 1 && !p_tracking) || (p_vertices->size() > 0);
1050 complete = (p_vertices->size() > 2 && !p_tracking);
1056 bool RubberBandTool::figureValid() {
1057 if(!figureComplete())
1062 switch(p_bandingMode) {
1066 valid = verticesList[0].x() != verticesList[1].x() || verticesList[0].y() != verticesList[1].y();
1067 valid &= verticesList[2].x() != verticesList[1].x() || verticesList[2].y() != verticesList[1].y();
1072 if(p_pointTolerance == 0) {
1073 valid = verticesList[0].x() != verticesList[1].x() || verticesList[0].y() != verticesList[1].y();
1078 case RectangleMode: {
1080 if(p_pointTolerance == 0) {
1081 valid = verticesList[0].x() != verticesList[2].x() && verticesList[0].y() != verticesList[2].y();
1086 case RotatedRectangleMode: {
1088 valid = verticesList[0].x() != verticesList[1].x() || verticesList[0].y() != verticesList[1].y();
1089 valid &= verticesList[1].x() != verticesList[2].x() || verticesList[1].y() != verticesList[2].y();
1096 valid = verticesList[0].x() != verticesList[1].x() && verticesList[0].y() != verticesList[1].y();
1100 case SegmentedLineMode: {
1101 valid = verticesList.size() > 1;
1107 geos::geom::Geometry *poly =
geometry();
1108 valid = poly && poly->isValid();
1117 void RubberBandTool::enablePoints(
unsigned int pixTolerance) {
1118 p_pointTolerance = pixTolerance;
1121 bool RubberBandTool::figureIsPoint() {
1124 bool isPoint =
true;
1127 switch(p_bandingMode) {
1129 case RotatedRectangleMode:
1133 case SegmentedLineMode:
1138 isPoint = (abs(verticesList[0].x() - verticesList[1].x()) +
1139 abs(verticesList[0].y() - verticesList[1].y()) < (int)p_pointTolerance);
1143 case RectangleMode: {
1144 isPoint = (abs(verticesList[0].x() - verticesList[2].x()) +
1145 abs(verticesList[0].y() - verticesList[2].y()) < (int)p_pointTolerance);
1161 RubberBandTool::RubberBandMode RubberBandTool::currentMode() {
1162 return p_bandingMode;
1166 double RubberBandTool::area() {
1171 void RubberBandTool::enableAllClicks() {
1176 void RubberBandTool::escapeKeyPress() {
1181 void RubberBandTool::scaleChanged() {