Improve node to svg conversion.
This commit is contained in:
parent
64f0b3e77a
commit
26ecae46b3
22 changed files with 403 additions and 126 deletions
|
@ -5,16 +5,22 @@
|
|||
|
||||
#include "SceneItem.h"
|
||||
#include "SceneModel.h"
|
||||
#include "SceneText.h"
|
||||
|
||||
#include "AbstractGeometricItem.h"
|
||||
#include "AbstractMesh.h"
|
||||
#include "TriMesh.h"
|
||||
#include "AbstractFace.h"
|
||||
|
||||
#include "SvgShapeElements.h"
|
||||
#include "Circle.h"
|
||||
|
||||
std::unique_ptr<SvgDocument> SvgConverter::convert(Scene* scene)
|
||||
#include "SvgShapeElements.h"
|
||||
#include "XmlAttribute.h"
|
||||
|
||||
std::unique_ptr<SvgDocument> SvgConverter::convert(Scene* scene, double width, double height) const
|
||||
{
|
||||
auto doc = std::make_unique<SvgDocument>();
|
||||
doc->setViewBox(0.0, 0.0, width, height);
|
||||
|
||||
scene->update();
|
||||
|
||||
|
@ -22,44 +28,125 @@ std::unique_ptr<SvgDocument> SvgConverter::convert(Scene* scene)
|
|||
{
|
||||
if (item->getType() == SceneItem::Type::MODEL)
|
||||
{
|
||||
auto mesh = dynamic_cast<SceneModel*>(item)->getMesh();
|
||||
auto transform = item->getTransform();
|
||||
|
||||
if (mesh->getType() == AbstractMesh::MeshType::TRI)
|
||||
auto model = dynamic_cast<SceneModel*>(item);
|
||||
if (model->getGeometry())
|
||||
{
|
||||
for(const auto& face : dynamic_cast<TriMesh*>(mesh)->getFaces())
|
||||
{
|
||||
auto svg_tri = std::make_unique<SvgPolygon>();
|
||||
|
||||
std::vector<DiscretePoint> points(3);
|
||||
unsigned count = 0;
|
||||
|
||||
auto face_locs = face->getNodeLocations();
|
||||
for(auto& loc : face_locs)
|
||||
{
|
||||
const auto x = loc.getX() * transform.getScaleX() + transform.getLocation().getX();
|
||||
const auto y = loc.getY() * transform.getScaleY() + transform.getLocation().getY();
|
||||
points[count] = {static_cast<unsigned>(x), static_cast<unsigned>(y)};
|
||||
count++;
|
||||
}
|
||||
svg_tri->setPoints(points);
|
||||
svg_tri->setFill(item->getFillColor());
|
||||
doc->getRoot()->addChild(std::move(svg_tri));
|
||||
|
||||
if (scene->shouldShowMeshOutline())
|
||||
{
|
||||
auto mesh_outline = std::make_unique<SvgPolyline>();
|
||||
points.push_back(points[0]);
|
||||
mesh_outline->setPoints(points);
|
||||
mesh_outline->setStrokeColor({0, 0, 0});
|
||||
mesh_outline->setStrokeWidth(0.1);
|
||||
doc->getRoot()->addChild(std::move(mesh_outline));
|
||||
}
|
||||
}
|
||||
convertPrimitive(doc.get(), model);
|
||||
}
|
||||
else
|
||||
{
|
||||
convertMesh(doc.get(), model, scene->shouldShowMeshOutline());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto text = dynamic_cast<SceneText*>(item);
|
||||
convertText(doc.get(), text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return std::move(doc);
|
||||
}
|
||||
|
||||
void SvgConverter::convertMesh(SvgDocument* document, SceneModel* model, bool showOutline) const
|
||||
{
|
||||
auto mesh = model->getMesh();
|
||||
auto transform = model->getTransform();
|
||||
|
||||
if (mesh->getType() == AbstractMesh::MeshType::TRI)
|
||||
{
|
||||
for (const auto& face : dynamic_cast<TriMesh*>(mesh)->getFaces())
|
||||
{
|
||||
auto svg_tri = std::make_unique<SvgPolygon>();
|
||||
|
||||
std::vector<Point> points(3);
|
||||
unsigned count = 0;
|
||||
|
||||
auto face_locs = face->getNodeLocations();
|
||||
for (const auto& loc : face_locs)
|
||||
{
|
||||
const auto x = loc.getX() * transform.getScaleX() + transform.getLocation().getX();
|
||||
const auto y = loc.getY() * transform.getScaleY() + transform.getLocation().getY();
|
||||
points[count] = { x, y };
|
||||
count++;
|
||||
}
|
||||
svg_tri->setPoints(points);
|
||||
svg_tri->setFill(model->getFillColor());
|
||||
document->getRoot()->addChild(std::move(svg_tri));
|
||||
|
||||
if (showOutline)
|
||||
{
|
||||
auto mesh_outline = std::make_unique<SvgPolyline>();
|
||||
points.push_back(points[0]);
|
||||
mesh_outline->setPoints(points);
|
||||
mesh_outline->setStrokeColor({ 0, 0, 0 });
|
||||
mesh_outline->setStrokeWidth(0.1);
|
||||
document->getRoot()->addChild(std::move(mesh_outline));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SvgConverter::setStyle(SceneModel* model, SvgShapeElement* element) const
|
||||
{
|
||||
auto transform = model->getTransform();
|
||||
|
||||
if (model->hasFillColor())
|
||||
{
|
||||
element->setFill(model->getFillColor());
|
||||
}
|
||||
else
|
||||
{
|
||||
element->setNoFill();
|
||||
}
|
||||
if (model->hasOutlineColor())
|
||||
{
|
||||
element->setStrokeColor(model->getOutlineColor());
|
||||
element->setStrokeWidth(1.0 / transform.getScaleX());
|
||||
}
|
||||
else
|
||||
{
|
||||
element->setNoStroke();
|
||||
}
|
||||
element->addAttribute(std::move(toTransform(transform)));
|
||||
}
|
||||
|
||||
void SvgConverter::convertPrimitive(SvgDocument* document, SceneModel* model) const
|
||||
{
|
||||
if (model->getGeometry()->getType() == AbstractGeometricItem::Type::RECTANGLE)
|
||||
{
|
||||
auto rect = std::make_unique<SvgRectangle>();
|
||||
rect->setWidth(1.0);
|
||||
rect->setHeight(1.0);
|
||||
|
||||
setStyle(model, rect.get());
|
||||
document->getRoot()->addChild(std::move(rect));
|
||||
}
|
||||
else if (model->getGeometry()->getType() == AbstractGeometricItem::Type::CIRCLE)
|
||||
{
|
||||
auto model_circle = dynamic_cast<Circle*>(model->getGeometry());
|
||||
|
||||
auto circle = std::make_unique<SvgCircle>();
|
||||
circle->setRadius(model_circle->getRadius());
|
||||
|
||||
setStyle(model, circle.get());
|
||||
document->getRoot()->addChild(std::move(circle));
|
||||
}
|
||||
}
|
||||
|
||||
void SvgConverter::convertText(SvgDocument* document, SceneText* model) const
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr<XmlAttribute> SvgConverter::toTransform(const Transform& transform) const
|
||||
{
|
||||
auto svg_transform = std::make_unique<XmlAttribute>("transform");
|
||||
|
||||
std::string ops;
|
||||
ops += "translate(" + std::to_string(transform.getLocation().getX()) + " " + std::to_string(transform.getLocation().getY()) + ") ";
|
||||
ops += "scale(" + std::to_string(transform.getScaleX()) + " " + std::to_string(transform.getScaleY()) + ") ";
|
||||
svg_transform->setValue(ops);
|
||||
|
||||
return std::move(svg_transform);
|
||||
}
|
||||
|
|
|
@ -3,10 +3,28 @@
|
|||
#include <memory>
|
||||
|
||||
class SvgDocument;
|
||||
class SvgShapeElement;
|
||||
class XmlAttribute;
|
||||
|
||||
class Scene;
|
||||
class SceneModel;
|
||||
class SceneText;
|
||||
|
||||
class Transform;
|
||||
|
||||
class SvgConverter
|
||||
{
|
||||
public:
|
||||
std::unique_ptr<SvgDocument> convert(Scene* scene);
|
||||
std::unique_ptr<SvgDocument> convert(Scene* scene, double width = 800.0, double height = 800.0) const;
|
||||
|
||||
private:
|
||||
void convertMesh(SvgDocument* document, SceneModel* model, bool showOutline = false) const;
|
||||
|
||||
void convertPrimitive(SvgDocument* document, SceneModel* model) const;
|
||||
|
||||
void convertText(SvgDocument* document, SceneText* model) const;
|
||||
|
||||
void setStyle(SceneModel* model, SvgShapeElement* element) const;
|
||||
|
||||
std::unique_ptr<XmlAttribute> toTransform(const Transform& transform) const;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue