Add svg conversion.

This commit is contained in:
jmsgrogan 2023-01-17 17:41:27 +00:00
parent 1f85954e98
commit dfbc87cb09
33 changed files with 602 additions and 79 deletions

View file

@ -0,0 +1,157 @@
#include "SvgPainter.h"
#include "SvgDocument.h"
#include "Scene.h"
#include "SceneItem.h"
#include "SceneModel.h"
#include "SceneText.h"
#include "AbstractGeometricItem.h"
#include "AbstractMesh.h"
#include "TriMesh.h"
#include "AbstractFace.h"
#include "Circle.h"
#include "SvgShapeElements.h"
#include "XmlAttribute.h"
std::unique_ptr<SvgDocument> SvgPainter::paint(Scene* scene, double width, double height) const
{
auto doc = std::make_unique<SvgDocument>();
doc->setViewBox(0.0, 0.0, width, height);
scene->update();
for (auto item : scene->getItems())
{
if (item->getType() == SceneItem::Type::MODEL)
{
auto model = dynamic_cast<SceneModel*>(item);
if (model->getGeometry())
{
paintPrimitive(doc.get(), model);
}
else
{
paintMesh(doc.get(), model, scene->shouldShowMeshOutline());
}
}
else
{
auto text = dynamic_cast<SceneText*>(item);
paintText(doc.get(), text);
}
}
return std::move(doc);
}
void SvgPainter::paintMesh(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 SvgPainter::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(model->getOutlineThickness() / transform.getScaleX());
}
else
{
element->setNoStroke();
}
element->addAttribute(std::move(toTransform(transform)));
}
void SvgPainter::paintPrimitive(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 is_ellipse = model_circle->getMinorRadius() != model_circle->getRadius();
auto circle = std::make_unique<SvgCircle>(model_circle->isEllipse() ? SvgCircle::Type::ELLIPSE : SvgCircle::Type::REGULAR);
circle->setRadius(model_circle->getRadius());
if (model_circle->isEllipse())
{
circle->setMinorRadius(model_circle->getMinorRadius());
}
setStyle(model, circle.get());
document->getRoot()->addChild(std::move(circle));
}
}
void SvgPainter::paintText(SvgDocument* document, SceneText* model) const
{
}
std::unique_ptr<XmlAttribute> SvgPainter::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);
}