diff --git a/client-api/C++/examples/all_commands.cpp b/client-api/C++/examples/all_commands.cpp index e0a7254..bc9ee92 100644 --- a/client-api/C++/examples/all_commands.cpp +++ b/client-api/C++/examples/all_commands.cpp @@ -330,6 +330,13 @@ int main() cout << "3." << endl; + VIBES_TEST( vibes::newFigure("Happy birthday") ); + VIBES_TEST( vibes::drawCake(1, -1, 0, 3, "black[red]") ); + VIBES_TEST( vibes::drawCake(3, 1, 45., 1, "black[blue]") ); + VIBES_TEST( vibes::drawCake(-1, -3, -20., 2, "black[green]") ); + VIBES_TEST( vibes::drawCake(3, -2, -180., 2.5, "black[yellow]") ); + VIBES_TEST( vibes::axisAuto() ); + /* vibes::Params p2 = vibesParams("action", "draw", "figure", "fig_name", diff --git a/client-api/C++/src/vibes.cpp b/client-api/C++/src/vibes.cpp index 968d686..dae2963 100644 --- a/client-api/C++/src/vibes.cpp +++ b/client-api/C++/src/vibes.cpp @@ -763,6 +763,22 @@ namespace vibes fflush(channel.get()); } + void drawCake(const double &cx, const double &cy, const double &rot, const double &length, Params params) + { + beginDrawingIfNeeded(); + Vec2d vc = { cx, cy }; + Params msg; + msg["action"] = "draw"; + msg["figure"] = params.pop("figure",current_fig); + msg["shape"] = (params, "type", "cake", + "center", vc, + "length", length, + "orientation", rot); + + fputs(Value(msg).toJSONString().append("\n\n").c_str(), channel.get()); + fflush(channel.get()); + } + void newGroup(const std::string &name, Params params) { diff --git a/client-api/C++/src/vibes.h b/client-api/C++/src/vibes.h index bcc782f..4f6c705 100644 --- a/client-api/C++/src/vibes.h +++ b/client-api/C++/src/vibes.h @@ -393,6 +393,9 @@ namespace vibes { const double &,ulb, const double &, yub, const double &,width, const double &, height, const double &, rot); + /// Draw a Cake at position (cx,cy) + VIBES_FUNC_COLOR_PARAM_4(drawCake,const double &,cx, const double &,cy, const double &,rot, const double &,length) + /// @} /// @name Objects grouping and deletion /// @{ diff --git a/client-api/python/vibes/vibes.py b/client-api/python/vibes/vibes.py index da6fa52..e307be8 100644 --- a/client-api/python/vibes/vibes.py +++ b/client-api/python/vibes/vibes.py @@ -581,3 +581,23 @@ def drawRaster(cls, filename, xlb, yub, width, height, rot=0, **kwargs): if "color" in kwargs: msg["shape"]["format"] = kwargs['color'] cls._write(msg, **kwargs) + + @classmethod + def drawCake(cls, cx, cy, length, color='r', **kwargs): + """Draw a cake centered at (cx, cy) with heading and size length + + Args: + cx,cy (double): position of the Cake + heading (double): heading of the vehicle in degree + lenght (double): length of the vehicle + + """ + msg = {'action': 'draw', + 'shape': {'type': 'cake', + 'center': [cx, cy], + 'length': length, + 'orientation': oritentation, + 'format': color + } + } + cls._write(msg, **kwargs) diff --git a/viewer/vibesgraphicsitem.cpp b/viewer/vibesgraphicsitem.cpp index cc1126b..441e992 100644 --- a/viewer/vibesgraphicsitem.cpp +++ b/viewer/vibesgraphicsitem.cpp @@ -247,6 +247,10 @@ VibesGraphicsItem * VibesGraphicsItem::newWithType(const QString type) { return new VibesGraphicsRaster(); } + else if (type == "cake") + { + return new VibesGraphicsCake(); + } return 0; } @@ -2268,3 +2272,219 @@ bool VibesGraphicsRaster::computeProjection(int dimX, int dimY) // Update successful return true; } + +// +// VibesGraphicsCake +// + +bool VibesGraphicsCake::parseJsonGraphics(const QJsonObject &json) +{ + // Now process shape-specific properties + // (we can only update properties of a shape, but mutation into another type is not supported) + if (json.contains("type")) + { + // Retrieve type + QString type = json["type"].toString(); + + // JSON type for VibesGraphicsCake is "cake" + if (type == "cake") + { + if (json.contains("center") && json.contains("length") && json.contains("orientation")) + { + int center_size = json["center"].toArray().size(); + if (center_size == 2 && json["length"].toDouble() > 0.) + { + // Set dimension + this->_nbDim = center_size; + + // Update successful + return true; + } + } + } + } + + // Unknown or empty JSON, update failed + return false; +} + +bool VibesGraphicsCake::computeProjection(int dimX, int dimY) +{ + const QJsonObject & json = this->_json; + + QJsonArray center = json["center"].toArray(); + double length = json["length"].toDouble(); + double orientation = json["orientation"].toDouble(); + + // Get shape color (or default if not specified) + const QBrush & brush = vibesDefaults.brush(jsonValue("FaceColor").toString()); + const QPen & pen = vibesDefaults.pen(jsonValue("EdgeColor").toString(),jsonValue("LineStyle").toString(), QString::number(7.0*jsonValue("LineWidth").toString().toDouble()/length)); + + const QBrush & cake_brush = vibesDefaults.brush("#ffde85"); + const QPen & cake_pen = vibesDefaults.pen("black","-", "0.1"); + const QPen & text_pen = vibesDefaults.pen("#525252","-", "0.5"); + + const QBrush & cream_brush = vibesDefaults.brush("#fcf7e8"); + + const QPen & empty_pen = vibesDefaults.pen("transparent","-", jsonValue("LineWidth").toString()); + + + Q_ASSERT(json.contains("type")); + Q_ASSERT(json["type"].toString() == "cake"); + + Q_ASSERT(center.size() == 2); + Q_ASSERT(this->_nbDim == center.size()); + Q_ASSERT(length > 0.); + + // Get center + const QPointF & centerPoint = QPointF(center[dimX].toDouble(), center[dimY].toDouble()); + + /* This shape is inspired by the MOOS middleware GUI (see pMarineViewer) */ + + // If the shape has already been drawn, it has at least one child + // Update child items if they exist + if (this->childItems().size() > 0) + { + // This cake is already perfect, please don't change it + } + // Else draw the shape for the first time + else{ + // Set body shape + { + QGraphicsEllipseItem * disk = new QGraphicsEllipseItem(center[dimX].toDouble()-length/2.0, center[dimY].toDouble()-length/8.0, length, length/4.); + + disk->setPen(cake_pen); + disk->setBrush(cake_brush); + disk->setTransformOriginPoint(centerPoint); + disk->setRotation(orientation); + this->addToGroup(disk); + } + + { + QGraphicsRectItem * rect = new QGraphicsRectItem(center[dimX].toDouble()-length/2.0, center[dimY].toDouble(), length, length/2.); + rect->setPen(empty_pen); + rect->setBrush(cake_brush); + rect->setTransformOriginPoint(centerPoint); + rect->setRotation(orientation); + this->addToGroup(rect); + + } + + { + QGraphicsEllipseItem * disk = new QGraphicsEllipseItem(center[dimX].toDouble()-length/2.0, center[dimY].toDouble()+length/4., length, length/4.); + + disk->setPen(empty_pen); + disk->setBrush(cream_brush); + disk->setTransformOriginPoint(centerPoint); + disk->setRotation(orientation); + this->addToGroup(disk); + } + + { + QGraphicsRectItem * rect = new QGraphicsRectItem(center[dimX].toDouble()-length/2.0, center[dimY].toDouble()+length/4. + length/8., length, length/8.); + rect->setPen(empty_pen); + rect->setBrush(cream_brush); + rect->setTransformOriginPoint(centerPoint); + rect->setRotation(orientation); + this->addToGroup(rect); + } + + { + QPainterPath lef_line_details; + lef_line_details.moveTo(center[dimX].toDouble()-length/2.0, center[dimY].toDouble()); + lef_line_details.lineTo(center[dimX].toDouble()-length/2.0, center[dimY].toDouble()+length/2.); + + QGraphicsPathItem * left_line = new QGraphicsPathItem(lef_line_details); + + QPainterPath right_line_details; + right_line_details.moveTo(center[dimX].toDouble()+length/2.0, center[dimY].toDouble()); + right_line_details.lineTo(center[dimX].toDouble()+length/2.0, center[dimY].toDouble()+length/2.); + + QGraphicsPathItem * right_line = new QGraphicsPathItem(right_line_details); + + left_line->setPen(cake_pen); + right_line->setPen(cake_pen); + + left_line->setTransformOriginPoint(centerPoint); + right_line->setTransformOriginPoint(centerPoint); + + left_line->setRotation(orientation); + right_line->setRotation(orientation); + + this->addToGroup(left_line); + this->addToGroup(right_line); + } + + { + QGraphicsEllipseItem * disk = new QGraphicsEllipseItem(center[dimX].toDouble()-length/2.0, center[dimY].toDouble()+length/2.-length/8.0, length, length/4.); + + disk->setPen(cake_pen); + disk->setBrush(cream_brush); + disk->setTransformOriginPoint(centerPoint); + disk->setRotation(orientation); + this->addToGroup(disk); + } + + { + QGraphicsEllipseItem * disk_1 = new QGraphicsEllipseItem(center[dimX].toDouble()-length/2.0, center[dimY].toDouble()+length/2.-length/16., length/8., length/8.); + QGraphicsEllipseItem * disk_2 = new QGraphicsEllipseItem(center[dimX].toDouble()+length/2.0-length/8., center[dimY].toDouble()+length/2.-length/16., length/8., length/8.); + QGraphicsEllipseItem * disk_3 = new QGraphicsEllipseItem(center[dimX].toDouble()-length/2.0+length/4., center[dimY].toDouble()+length/2.+length/16., length/8., length/8.); + QGraphicsEllipseItem * disk_4 = new QGraphicsEllipseItem(center[dimX].toDouble()+length/8., center[dimY].toDouble()+length/2.+length/16., length/8., length/8.); + QGraphicsEllipseItem * disk_5 = new QGraphicsEllipseItem(center[dimX].toDouble()-length/2.0+length/4., center[dimY].toDouble()+length/2.-length/8., length/8., length/8.); + QGraphicsEllipseItem * disk_6 = new QGraphicsEllipseItem(center[dimX].toDouble()+length/8., center[dimY].toDouble()+length/2.-length/8., length/8., length/8.); + + QGraphicsSimpleTextItem * text = new QGraphicsSimpleTextItem("10"); + text->setTransform(QTransform(1, 0, 0, -1, center[dimX].toDouble()-length/4.0-length/8.0,center[dimY].toDouble()+length)); + text->setScale(0.04*length); + text->setPen(text_pen); + text->setBrush(brush); + + disk_1->setPen(pen); + disk_2->setPen(pen); + disk_3->setPen(pen); + disk_4->setPen(pen); + disk_5->setPen(pen); + disk_6->setPen(pen); + + disk_1->setBrush(brush); + disk_2->setBrush(brush); + disk_3->setBrush(brush); + disk_4->setBrush(brush); + disk_5->setBrush(brush); + disk_6->setBrush(brush); + + disk_1->setTransformOriginPoint(centerPoint); + disk_2->setTransformOriginPoint(centerPoint); + disk_3->setTransformOriginPoint(centerPoint); + disk_4->setTransformOriginPoint(centerPoint); + disk_5->setTransformOriginPoint(centerPoint); + disk_6->setTransformOriginPoint(centerPoint); + + disk_1->setRotation(orientation); + disk_2->setRotation(orientation); + disk_3->setRotation(orientation); + disk_4->setRotation(orientation); + disk_5->setRotation(orientation); + disk_6->setRotation(orientation); + + this->addToGroup(disk_1); + this->addToGroup(disk_2); + this->addToGroup(disk_3); + this->addToGroup(disk_4); + + if (orientation == 0) + this->addToGroup(text); + + this->addToGroup(disk_5); + this->addToGroup(disk_6); + + } + + + } + + + + // Update successful + return true; +} \ No newline at end of file diff --git a/viewer/vibesgraphicsitem.h b/viewer/vibesgraphicsitem.h index 72f0708..8aec42c 100644 --- a/viewer/vibesgraphicsitem.h +++ b/viewer/vibesgraphicsitem.h @@ -140,7 +140,9 @@ class VibesGraphicsItem VibesGraphicsTextType, // Do not remove the following value! It signals the end of VibesGraphicsItem types VibesGraphicsLastType, - VibesGraphicsRasterType + VibesGraphicsRasterType, + // Happy birthday + VibesGraphicsCakeType }; // Constructor VibesGraphicsItem(QGraphicsItem * qGraphicsItem); @@ -436,4 +438,13 @@ class VibesGraphicsRaster : public QGraphicsItemGroup, public VibesGraphicsItem bool computeProjection(int dimX, int dimY); }; +class VibesGraphicsCake : public QGraphicsItemGroup, public VibesGraphicsItem +{ + VIBES_GRAPHICS_ITEM(VibesGraphicsCake, QGraphicsItemGroup) + VIBES_GEOMETRY_CHANGING_PROPERTIES("center","length","orientation") +protected: + bool parseJsonGraphics(const QJsonObject &json); + bool computeProjection(int dimX, int dimY); +}; + #endif // VIBESGRAPHICSITEM_H