/** * @RDE_HEADER@ * $Id$ * $HeadURL$ * $Author$ */ #pragma once #include #include #include #include #include "symbology_xml_export.h" #include "symbol_types.h" namespace SymbologyXML { static const int primitiveKey = 42; /** \brief Abstracion of graphical items of a Symbol. Primitive Objects are used by Symbol to represent the graphical representation of a Symbol. @author Stephan Kuhagen */ class SYMBOLOGY_XML_EXPORT Primitive { public: //! Enum defining all types of graphic-primitives enum t_primitive {ELLIPSE, LINE, POLYGON, RECT, ICON, TEXT}; explicit Primitive(t_primitive type); Primitive(const Primitive& other); ~Primitive(); //! Compare-Operator bool operator==(const Primitive& other) const; bool operator!=(const Primitive& other) const; //! Assignment-Operator Primitive& operator=(const Primitive& other); //! Return the unique ID of this Primitive unsigned int id() const { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return _id; } //! Return the type of this primitive t_primitive type() const { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return _type; } //! Return true, if this primitive is valid. bool isValid() const { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return _valid; } /** Set the points defining the geometry for this primitive. \param pointList: A list containing the points. \return true on success (Primitive is valid), else otherwise */ bool setPoints(const QPolygonF &pointList); //! Return the points defining the geometry of this Primitive QPolygonF getPoints() const { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return _points; } /** Set this to true, if the Primitive should be filled. \param flag */ void setFill(bool flag); /** Return true, if this Primitive should be filled. For LINE this always returns false. \return true, if the Primitive should be filled, false otherwise */ bool fill() const { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return _fill; } /** Set the Primitives linewidth \param width: The new linewidth */ void setLineWidth(double width); /** Get the Primitives linewidth \return width */ double getLineWidth() const { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return _lineWidth; } //! Set the linestyle of the Primitive enum t_linestyle {SOLID, DASHED, DOTTED, DASHED_DOTTED}; /** Set the Primitives linestyle \param style: The new linestyle */ void setLineStyle(t_linestyle style); /** Get the Primitives linestyle \return style */ t_linestyle getLineStyle() const { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return _lineStyle; } /** Set the Color of the Primitive. Most times this remains unset, which means that the color is set by the processing code. For the Map and certain additional Symbol-Files a color is needed, though. */ void setColor(const QColor &color) { DEBUG_LOG(logger) << LOGFUNCTION ; _color = color; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } /** Get the Color of the Primitive. This may be a invalid Color. */ QColor getColor() const { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return _color; } /** Set this to true, if the Primitive should be closed. This only applies to POLYGON and ELLIPSE \param flag */ void setClosed(bool flag); /** Return true, if this Primitive should be closed. This only applies to POLYGON and ELLIPSE \return true, if the Primitive should be closed, false otherwise */ bool closed() const { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return _closed; } /** Set the start-angle for a non-closed ellipse-primitive. | a(90) Start-Point is 3 on a analog clock. The angle is set | | counterclockwise, i.e. 90 means 12 on a analog clock. | a(180) --O-- a(0) This is ignored, if closed() is true. This only applies | | to ELLIPSE. | a(270) \param start: the Angle, where the ellipse starts */ void setStartAngle(double start); /** Return the start-angle of a non-closed ELLIPSE \return start-angle */ double getStartAngle() const { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return _startAngle; } /** Set the extent-angle for a non-closed ellipse-primitive. The angle is set counterclockwise starting at start-angle. This is ignored, if closed() is true. This only applies to ELLIPSE \param extent: the extent of the ELLIPSE */ void setExtent(double extent); /** Return the extent of a non-closed ELLIPSE \return extent */ double getExtent() const { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return _extent; } /** Return the bounding box of this primitive. If the primitive is not valid, the result is undefined. The linewidth is not added to the bounding box, upper and lower limits may be the same value, depending on the shape of the Primitive. \param x0: Pointer storing the smaller x-value of the bounding box \param y0: Pointer storing the smaller y-value of the bounding box \param x1: Pointer storing the greater x-value of the bounding box \param y1: Pointer storing the greater y-value of the bounding box \param ignoreEllipseType: If true, get the full bbox for an ELLIPSE, even if it is an Arc */ bool getBoundingBox(double& x0, double& y0, double& x1, double& y1, bool ignoreEllipseType = false) const; /** Get the center fo the bounding box of the defining points. For all types except ELLIPSE this means the center of the bounding box. For open ELLIPSE (i.e. "arc") this means the center of the two points that define the ELLIPSE-Area. \param x: Pointer storing the x-value of the bounding box \param y: Pointer storing the y-value of the bounding box */ void getCenter(double &x, double &y) const; /** Move the primitive. \param x: The x-value to move \param y: The y-value to move */ void move(const QPointF &diff); /** Scale the primitive. Scaling is done around the center of its bounding box. The factor must be greater than 0.0. \param factorX: Scale-factor in X-direction (>0.0) \param factorY: Scale-factor in Y-direction (>0.0) */ void scale(double factorX, double factorY); /** Sets the textof this primitive. \param text: The Text */ void setText(const QString &text); /** Gets the text of this primitive. \return The Text */ QString text() const; /** Sets the font of this primitive. \param font: The Font */ void setFont(const QFont &font); /** Gets the font of this primitive. \return The font */ QFont font() const; /** Sets the id of the icon of this primitive. \param id: ID of the icon */ void setIcon(int id); /** Gets the id of the icon of this primitive. \return ID of the icon */ int icon() const; /** Sets the id of the icon of this primitive. \param id: ID of the icon */ void setIconType(SymbolTypes::t_icon_type iconType); /** Gets the id of the icon of this primitive. \return ID of the icon */ SymbolTypes::t_icon_type iconType() const; /** Sets the position of this primitive. param position of the primitive */ void setPosition(SymbolTypes::t_sector_position position); /** Gets the position of this primitive. \return position of the primitive */ SymbolTypes::t_sector_position position() const; /** Sets the rectpos of this primitive. param rectpos of the primitive */ void setRectpos(SymbolTypes::t_sector_rectpos rectpos); /** Gets the rectpos of this primitive. \return rectPos of the primitive */ SymbolTypes::t_sector_rectpos rectpos() const; //! scalemode enum t_scalemode { Scalemode_Undefined, Scalemode_Proport, Scalemode_Unproport }; /** Sets the scalemode of this primitive. param scalemode of the primitive */ void setScalemode(t_scalemode scalemode); /** Gets the scalemode of this primitive. \return scalemode of the primitive */ t_scalemode scalemode() const; /** Gets a scalemode as string param scalemode \return scalemode as string */ static QString scalemode(t_scalemode scalemode); /** Gets a scalemode as enum param scalemode as string \return scalemode as enum */ static t_scalemode scalemode(const QString &scalemode); /** Sets the rotation of this Primitive around the center of its full bounding box (i.e. for an arc, this is the bounding box of the full ellipse). The rotation is not actually calculated, but only set as property. To calculated the rotation (and reset the property and possibly change the type) use rotate(double angle). \param angle: The new rotation angle */ void setRotation(double angle); /** Get the value of the rotation-property. \return The rotation-angle */ double getRotation() const { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return _rotation; } /** Rotate the Primitive around the center of its Bounding Box. Since ELLIPSE-Primitives are normally parallel to x/y-Axes, rotating an ELLIPSE results in a change of type to POLYGON and an approximation of the rotated ELLIPSE-Shape (@ellipseToPolygon()). If the Rotation-Angle is a multiple of (+/-)90°, the ELLIPSE will be correctly rotated without conversion. The same applies to RECT. This method resets the rotation-property to 0.0, because the rotation is now actually calculated. */ void rotate(); /** Rotate a point around with another point as center. Used as helper for rotate(). Because it may be usefull elsewhere, it's static public. \param px: Point-x \param py: Point-y \param cx: Center-x \param cy: Center-y \param rx: Pointer for result-x \param ry: Pointer for result-y \param angle: Rotation-angle in degree. */ static void rotatePoint(double px, double py, double cx, double cy, double *rx, double *ry, double angle); /** Set if this Primitive should be transformed, when the Symbol tries to match the geometry to Dimension/Affiliation. Default is to transform. \param transform: If false, skip this Primitive on geometry-transformations */ void setTransform(bool transform) { DEBUG_LOG(logger) << LOGFUNCTION ; _transform = transform; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; } /** Return a matrix-ID for geometry-transformation for a given combination of dimension and affiliation or -1, if no suitable transformation is known. \param dimen: Dimension-key \param affil: Affiliation-key \return ID of the Matrix for dimen and affil */ int getTransform() const { DEBUG_LOG(logger) << LOGFUNCTION ; DEBUG_LOG(logger) << "END " << LOGFUNCTION ; return _transform; } private: //! NGLLogger NGL::INGLLogger& logger; /** Return the bounding box of this primitive, if _type is ELLIPSE. This is a helper for getBoundingBox. \param x0: Pointer storing the smaller x-value of the bounding box \param y0: Pointer storing the smaller y-value of the bounding box \param x1: Pointer storing the greater x-value of the bounding box \param y1: Pointer storing the greater y-value of the bounding box \param tx0: x0-value of the full bounding box \param ty0: y0-value of the full bounding box \param tx1: x1-value of the full bounding box \param ty1: y1-value of the full bounding box */ bool getBoundingBoxEllipse(double &x0, double &y0, double &x1, double &y1, double tx0, double ty0, double tx1, double ty1) const; /** Convert a ELLIPSE-type Primitive to a POLYGON-Type by approximation. This method does nothing, if this is not an ELLIPSE. \param approxSteps: How many points the approximation for a rotated ELLIPSE should at least have. This may not be less than 10 steps. */ void ellipseToPolygon(unsigned int approxSteps); /** Convert a RECT-type Primitive to a POLYGON-Type. This method does nothing, if this is not a RECT. */ void rectToPolygon(); static unsigned int _idCount; unsigned int _id; QString _text; bool _transform = false; bool _valid = false; bool _fill = false; bool _closed = false; t_primitive _type; QPolygonF _points; double _lineWidth = 0.01; double _startAngle = 0; double _extent = 360; double _rotation = 0; t_linestyle _lineStyle = SOLID; QFont _font; QColor _color; // 1: iconId -> _iconId // 2. ICON-TYPE -> _iconType // 3. sectorPosition -> _position // 4. wantedBox of possibly modified ICON -> is stored in _points int _iconId = -1; // enumeration value of ICON if this primitive is of type 'ICON' SymbolTypes::t_icon_type _iconType = SymbolTypes::ICON_TYPE_UNDEFINED; // enumeration value of ICON (sector, intrMob, Arming, MISC... SymbolTypes::t_sector_position _position = SymbolTypes::SECTOR_POSITION_UNDEFINED; // SECTOR 1, 2, MAIN, FF SymbolTypes::t_sector_rectpos _rectpos = SymbolTypes::SECTOR_RECTPOS_DEFAULT; // SECTOR rectangle position t_scalemode _scalemode = Scalemode_Undefined; // mode of scaling (prop./unprop.) }; // class Primitive } // namespace SymbologyXML Q_DECLARE_METATYPE(SymbologyXML::Primitive*)