/** * @RDE_HEADER@ * $Id$ * $HeadURL$ * $Author$ */ #include "primitive.h" #include #include #include "symbol_reader.h" #include namespace SymbologyXML { unsigned int Primitive::_idCount = 0; Primitive::Primitive(t_primitive type) : logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("AdvSymbologyXML.Primitive")) , _id(++_idCount) , _type(type) { TRACE_LOG(logger) << LOGFUNCTION ; TRACE_LOG(logger) << "END " << LOGFUNCTION ; } // Primitive::Primitive(t_primitive type) Primitive::Primitive(const Primitive& other) : logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("AdvSymbologyXML.Primitive")) { TRACE_LOG(logger) << LOGFUNCTION ; ++_idCount; _id = _idCount; // _id is NOT copied ( see operator= ) *this = other; // _id is NOT copied ( see operator= ) TRACE_LOG(logger) << "END " << LOGFUNCTION ; } // Primitive::Primitive(const Primitive& other) Primitive& Primitive::operator=(const Primitive& other) { DEBUG_LOG(logger) << LOGFUNCTION ; //// _id = other._id; Do NOT have identical _id _type = other._type; _valid = other._valid; _points = other._points; _fill = other._fill; _lineWidth = other._lineWidth; _lineStyle = other._lineStyle; _closed = other._closed; _startAngle = other._startAngle; _extent = other._extent; _rotation = other._rotation; _transform = other._transform; _color = other._color; _iconId = other._iconId; _iconType = other._iconType; _text = other._text; _position = other._position; _rectpos = other._rectpos; _scalemode = other._scalemode; _font = other._font; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return *this; } // Primitive& Primitive::operator=(const Primitive& other) Primitive::~Primitive() { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } // Primitive::~Primitive() bool Primitive::operator==(const Primitive& other) const { DEBUG_LOG(logger) << LOGFUNCTION ; if ( _id == other._id ) { DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return true; } bool result = true; result &= _type == other._type; result &= _valid == other._valid; result &= _points == other._points; result &= _fill == other._fill; result &= _lineWidth == other._lineWidth; result &= _lineStyle == other._lineStyle; result &= _closed == other._closed; result &= _startAngle == other._startAngle; result &= _extent == other._extent; result &= _rotation == other._rotation; result &= _transform == other._transform; result &= _color == other._color; result &= _iconId == other._iconId; result &= _iconType == other._iconType; result &= _position == other._position; result &= _rectpos == other._rectpos; result &= _scalemode == other._scalemode; result &= _text == other._text; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return result; } // bool Primitive::operator==(const Primitive& other) bool Primitive::operator!=(const Primitive& other) const { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return !(*this == other); } // bool Primitive::operator!=(const Primitive& other) void Primitive::setFill(bool flag) { DEBUG_LOG(logger) << LOGFUNCTION ; _fill = flag & (_type != LINE); DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } // void Primitive::setFill(bool flag) void Primitive::setClosed(bool flag) { DEBUG_LOG(logger) << LOGFUNCTION ; _closed = flag; if ( (_type == ELLIPSE) && _closed ) { _extent = 360.0; } DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } // void Primitive::setClosed(bool flag) bool Primitive::setPoints(const QPolygonF &pointList) { DEBUG_LOG(logger) << LOGFUNCTION ; bool ok = true; switch (_type) { case ELLIPSE: case LINE: case RECT: case ICON: case TEXT: if ( pointList.size() != 2 ) { ok = false; } break; case POLYGON: if ( pointList.size() < 3 ) { ok = false; } break; default: _valid = false; } _points.clear(); _points = pointList; _valid = ok; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return _valid; } // bool Primitive::setPoints(QList pointList) void Primitive::setLineWidth(double width) { DEBUG_LOG(logger) << LOGFUNCTION ; _lineWidth = width; _valid = (width > 0.0); DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } // void Primitive::setLineWidth(double width) void Primitive::setLineStyle(t_linestyle style) { DEBUG_LOG(logger) << LOGFUNCTION ; _lineStyle = style; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } // void Primitive::setLineStyle(t_linestyle style) void Primitive::setStartAngle(double start) { DEBUG_LOG(logger) << LOGFUNCTION ; if (_type == ELLIPSE) { _startAngle = fmod(start, 360.0); } DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } // void Primitive::setStartAngle(double start) void Primitive::setExtent(double extent) { DEBUG_LOG(logger) << LOGFUNCTION ; if (_type == ELLIPSE) { if ( extent < -360.0 ) { _extent = -360.0; } else if ( extent > 360.0 ) { _extent = 360.0; } else { _extent = extent; } } DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } // void Primitive::setExtent(double extent) bool Primitive::getBoundingBox(double &x0, double &y0, double &x1, double &y1, bool ignoreEllipseType) const { DEBUG_LOG(logger) << LOGFUNCTION ; if ( !isValid() ) { WARNING_LOG(logger) << "Primitive::getBoundingBox - primitive not valid"; return false; } const QRectF br = _points.boundingRect(); // Check for open Ellipse if ( (_type == ELLIPSE) && !_closed && !ignoreEllipseType) { return getBoundingBoxEllipse(x0, y0, x1, y1, br.x(), br.y(), br.x() + br.width(), br.y() + br.height()); } x0 = br.x(); y0 = br.y(); x1 = br.x() + br.width(); y1 = br.y() + br.height(); DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return true; } // void Primitive::getBoundingBox(double* x0, ...) const void Primitive::getCenter(double &x, double &y) const { DEBUG_LOG(logger) << LOGFUNCTION ; double x0, y0, x1, y1; if (getBoundingBox(x0, y0, x1, y1, true)) { x = (x0+x1)/2.0; y = (y0+y1)/2.0; } else { x = y = 0; } DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } // void Primitive::getCenter(double* x, double* y) const void Primitive::move(const QPointF &diff) { _points.translate(diff); } void Primitive::scale(double factorX, double factorY) { DEBUG_LOG(logger) << LOGFUNCTION ; if ( (factorX <= 0.0) || (factorY <= 0.0) ) { // Factor too small, ignore DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return; } // Get bounding box center double x0, x1, y0, y1; if (!getBoundingBox(x0, y0, x1, y1)) return; double cx = (x0+x1)/2.0; double cy = (y0+y1)/2.0; // Transform all points to origin and multiply with factor for (int i = 0; i < _points.size(); ++i) { double tmpx = (_points.at(i)).x() - cx; double tmpy = (_points.at(i)).y() - cy; tmpx = (tmpx*factorX)+cx; tmpy = (tmpy*factorY)+cy; _points[i].setX(tmpx); _points[i].setY(tmpy); } DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } // void Primitive::scale(double factorX, double factorY) void Primitive::setText(const QString &text) { _text = text; } QString Primitive::text() const { return _text; } void Primitive::setIcon(int id) { _iconId = id; } int Primitive::icon() const { return _iconId; } void Primitive::setIconType(SymbolTypes::t_icon_type iconType) { _iconType = iconType; } SymbolTypes::t_icon_type Primitive::iconType() const { return _iconType; } void Primitive::setPosition(SymbolTypes::t_sector_position position) { _position = position; } SymbolTypes::t_sector_position Primitive::position() const { return _position; } void Primitive::setRectpos(SymbolTypes::t_sector_rectpos rectpos) { _rectpos = rectpos; } SymbolTypes::t_sector_rectpos Primitive::rectpos() const { return _rectpos; } void Primitive::setScalemode(Primitive::t_scalemode scalemode) { _scalemode = scalemode; } Primitive::t_scalemode Primitive::scalemode() const { return _scalemode; } QString Primitive::scalemode(Primitive::t_scalemode scalemode) { QString ret; switch(scalemode) { case Scalemode_Undefined: ret = QStringLiteral("undefined"); break; case Scalemode_Proport: ret = QStringLiteral("proport"); break; case Scalemode_Unproport: ret = QStringLiteral("unproport"); break; default: ret = QStringLiteral("undefined"); break; } return ret; } Primitive::t_scalemode Primitive::scalemode(const QString &scalemode) { Primitive::t_scalemode ret = Scalemode_Undefined; if(scalemode == QStringLiteral("proport")) { ret = Scalemode_Proport; } else if(scalemode == QStringLiteral("unproport")) { ret = Scalemode_Unproport; } return ret; } void Primitive::setRotation(double angle) { DEBUG_LOG(logger) << LOGFUNCTION ; _rotation = fmod(angle, 360.0); DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } // void Primitive::setRotation(double angle) bool Primitive::getBoundingBoxEllipse(double &x0, double &y0, double &x1, double &y1, double tx0, double ty0, double tx1, double ty1) const { DEBUG_LOG(logger) << LOGFUNCTION ; if ( !isValid() || (_type != ELLIPSE) ) { DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return false; } double extent = closed()?360.0:_extent; QList pointsX; QList pointsY; double end = _startAngle+extent; // Add start/end-point double centerX = (tx0+tx1)/2.0; double centerY = (ty0+ty1)/2.0; double startX = cos(-_startAngle*2*M_PI/360.0); startX = centerX+(startX*(tx1-tx0)/2.0); double startY = sin(_startAngle*2*M_PI/360.0); startY = centerY+(startY*(ty1-ty0)/2.0); double endX = cos(-end*2*M_PI/360.0); endX = centerX+(endX*(tx1-tx0)/2.0); double endY = sin(end*2*M_PI/360.0); endY = centerY+(endY*(ty1-ty0)/2.0); pointsX.append(startX); pointsX.append(endX); pointsY.append(startY); pointsY.append(endY); // Check 0°, 90°, 180°, 270° if ( extent >= 0.0 ) { // Counter-clockwise if ( ((_startAngle <= 0.0) && (end >= 0.0)) || ((_startAngle <= -360.0) && (end >= -360.0)) || ((_startAngle <= 360.0) && (end >= 360.0)) || ((_startAngle <= -720.0) && (end >= -720.0)) ) { // 0°/-360°/360° is in pointsX.append(tx1); } // Counter-clockwise if ( ((_startAngle <= 90.0) && (end >= 90.0)) || ((_startAngle <= -270.0) && (end >= -270.0)) || ((_startAngle <= 450.0) && (end >= 450.0)) || ((_startAngle <= -630.0) && (end >= -630.0)) ) { // 90°/-270°/450° is in pointsY.append(ty1); } if ( ((_startAngle <= 180.0) && (end >= 180.0)) || ((_startAngle <= -180.0) && (end >= -180.0)) || ((_startAngle <= 540.0) && (end >= 540.0)) || ((_startAngle <= -540.0) && (end >= -540.0)) ) { // 180°/-180°/540° is in pointsX.append(tx0); } if ( ((_startAngle <= 270.0) && (end >= 270.0)) || ((_startAngle <= -90.0) && (end >= -90.0)) || ((_startAngle <= 630.0) && (end >= 630.0)) || ((_startAngle <= -450.0) && (end >= -450.0)) ) { // 270°/-90°/630° is in pointsY.append(ty0); } } else { // Clockwise if ( ((_startAngle >= 0.0) && (end <= 0.0)) || ((_startAngle >= -360.0) && (end <= -360.0)) || ((_startAngle >= 360.0) && (end <= 360.0)) || ((_startAngle >= -720.0) && (end <= -720.0)) ) { // 0°/-360°/360° is in pointsX.append(tx1); } if ( ((_startAngle >= 90.0) && (end <= 90.0)) || ((_startAngle >= -270.0) && (end <= -270.0)) || ((_startAngle >= 450.0) && (end <= 450.0)) || ((_startAngle >= -630.0) && (end <= -630.0)) ) { // 90°/-270°/450° is in pointsY.append(ty1); } if ( ((_startAngle >= 180.0) && (end <= 180.0)) || ((_startAngle >= -180.0) && (end <= -180.0)) || ((_startAngle >= 540.0) && (end <= 540.0)) || ((_startAngle >= -540.0) && (end <= -540.0)) ) { // 180°/-180°/540° is in pointsX.append(tx0); } if ( ((_startAngle >= 270.0) && (end <= 270.0)) || ((_startAngle >= -90.0) && (end <= -90.0)) || ((_startAngle >= 630.0) && (end <= 630.0)) || ((_startAngle >= -450.0) && (end <= -450.0)) ) { // 270°/-90°/630° is in pointsY.append(ty0); } } double lx0 = pointsX.at(0); double ly0 = pointsY.at(0); double lx1 = lx0; double ly1 = ly0; // Find min/max for X/Y for (int i = 1; i < pointsX.size(); ++i) { if ( pointsX.at(i) < lx0 ) { lx0 = pointsX.at(i); } else if ( pointsX.at(i) > lx1 ) { lx1 = pointsX.at(i); } } for (int i = 1; i < pointsY.size(); ++i) { if ( pointsY.at(i) < ly0 ) { ly0 = pointsY.at(i); } else if ( pointsY.at(i) > ly1 ) { ly1 = pointsY.at(i); } } x0 = lx0; y0 = ly0; x1 = lx1; y1 = ly1; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return true; } // void Primitive::getBoundingBoxEllipse(double* x0, ...) const void Primitive::rotate() { DEBUG_LOG(logger) << LOGFUNCTION ; // Ellipse needs special handling and temporary hiding of its type bool isEllipseType = (_type == ELLIPSE); // Get center of bounding box double x0, y0, x1, y1, cx, cy; if ( isEllipseType ) { _type = LINE; } if (!getBoundingBox(x0, y0, x1, y1)) return; if ( isEllipseType ) { _type = ELLIPSE; } cx = (x0+x1)/2.0; cy = (y0+y1)/2.0; if ( (_type == RECT) && ( fmod(_rotation, 90.0) != 0.0 ) ) { // Convert Rectangle to Polygon, because we need to rotate all four points // This does not change the bbox, so its okay, to do this here rectToPolygon(); } else if ( _type == ELLIPSE ) { if ( fmod(_rotation, 90.0) == 0.0 ) { // Rotate ELLIPSE in multiple of 90°: Set the _startAngle to rotated // value and then rotate the defining points. // This does not change the bbox, so its okay, to do this here _startAngle = _startAngle+(fmod(_rotation, 360.0)); } else { const double temp = std::abs(_extent); ellipseToPolygon(lrint(temp/2)); } } // Rotate all points for (int i = 0; i < _points.size(); ++i) { double px = _points.at(i).x(); double py = _points.at(i).y(); rotatePoint(px, py, cx, cy, &px, &py, _rotation); _points[i] = QPointF(px, py); } // Reset the rotation-property _rotation = 0.0; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } // void Primitive::rotate() void Primitive::ellipseToPolygon(unsigned int approxSteps) { DEBUG_LOG(logger) << LOGFUNCTION ; if ( _type != ELLIPSE ) { DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return; } // Get the full Bounding Box _type = POLYGON; double x0, y0, x1, y1; if (!getBoundingBox(x0, y0, x1,y1)) return; // Get center for translation of points double cx = (x0+x1)/2.0; double cy = (y0+y1)/2.0; // Get Bounding Box size for scaling double sx = (x1-x0)/2.0; double sy = (y1-y0)/2.0; _points.clear(); unsigned int steps = (approxSteps>10)?approxSteps:10; if (steps > 20) steps = 20; double stepSize = _extent/(double)steps; for (unsigned int i = 0; i <= steps; ++i) { double stepAngle = _startAngle+(double)i*stepSize; double px, py; rotatePoint(1.0, 0.0, 0.0, 0.0, &px, &py, stepAngle); _points.append(QPointF(px*sx+cx, py*sy+cy)); } DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } // void Primitive::ellipseToPolygon(unsigned int approxSteps) void Primitive::rectToPolygon() { DEBUG_LOG(logger) << LOGFUNCTION ; if ( _type != RECT ) { DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return; } QPolygonF points; points.append(_points.at(0)); points.append(QPointF(_points.at(0).x(), _points.at(1).y())); points.append(_points.at(1)); points.append(QPointF(_points.at(1).x(), _points.at(0).y())); _points = points; _type = POLYGON; _closed = true; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } // void Primitive::rectToPolygon() void Primitive::rotatePoint(double px, double py, double cx, double cy, double *rx, double *ry, double angle) { // This is a static method, so no logging is used here // angle to rad double radAngle = ((2*M_PI)/360.0)*angle; // Translate double tx = px-cx; double ty = py-cy; // Rotate double nx = tx*cos(radAngle)-ty*sin(radAngle); double ny = tx*sin(radAngle)+ty*cos(radAngle); // Translate back and write result *rx = nx+cx; *ry = ny+cy; } // void Primitive::rotatePoint(double px...) }; // namespace SymbologyXML