Lagrange
Loading...
Searching...
No Matches
save_image_svg.h
1/*
2 * Copyright 2020 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13
14#include <lagrange/Logger.h>
15#include <lagrange/Mesh.h>
16#include <lagrange/common.h>
17#include <lagrange/fs/filesystem.h>
18#include <lagrange/utils/fmt/format.h>
19#include <lagrange/utils/range.h>
20
21#include <fstream>
22
23namespace lagrange {
24namespace image_io {
25
27{
28 bool with_stroke = true;
29 bool with_fill = true;
30 bool use_uv_mesh = false;
31 uint32_t stroke_color = 0x000000;
32 uint32_t fill_color = 0xEBFF8C;
33 float scaling_factor = 1;
34 float stroke_width = 1;
35 float width = 0;
36 float height = 0;
37};
38
48template <typename DerivedV, typename DerivedF>
49void save_image_svg(
50 const fs::path& filename,
51 const Eigen::MatrixBase<DerivedV>& vertices,
52 const Eigen::MatrixBase<DerivedF>& facets,
53 const SVGSetting& settings = {})
54{
55 using Scalar = typename DerivedV::Scalar;
56 std::ofstream fout(filename.c_str());
57
58 const auto num_facets = facets.rows();
59
60 const Eigen::Matrix<Scalar, 1, 2> bbox_min = vertices.colwise().minCoeff().eval();
61 const Eigen::Matrix<Scalar, 1, 2> bbox_max = vertices.colwise().maxCoeff().eval();
62
63 std::string footer = "</svg>";
64
65 // Default image size is based on bbox.
66 float width = settings.width;
67 float height = settings.height;
68 if (settings.width <= 0) {
69 width = float(bbox_max[0] - bbox_min[0]) * settings.scaling_factor;
70 }
71 if (settings.height <= 0) {
72 height = float(bbox_max[1] - bbox_min[1]) * settings.scaling_factor;
73 }
74
75 fout << format(
76 "<?xml version=\"1.0\" encoding=\"utf-8\"?> <svg version=\"1.1\" id=\"Layer_1\" "
77 "xmlns=\"http://www.w3.org/2000/svg\" "
78 "xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" "
79 "y=\"0px\" viewBox=\"0 0 {} {}\" "
80 "style=\"enable-background:new 0 0 {} {};\" "
81 "xml:space=\"preserve\"> <style type=\"text/css\"> "
82 ".st0{{fill:{}; stroke:{}; stroke-miterlimit:10; stroke-width:{}px; "
83 "stroke-linejoin:\"round\";}} "
84 "</style> ",
85 width,
86 height,
87 width,
88 height,
89 settings.with_fill ? format("#{:06x}", settings.fill_color) : "none",
90 settings.with_stroke ? format("#{:06x}", settings.stroke_color) : "none",
91 settings.with_stroke ? settings.stroke_width : 0)
92 << std::endl;
93
94 for (auto i : range(num_facets)) {
95 fout << "<polygon class=\"st0\" points=\""
96 << (vertices(facets(i, 0), 0) - bbox_min[0]) * settings.scaling_factor << ","
97 << (bbox_max[1] - vertices(facets(i, 0), 1)) * settings.scaling_factor << " "
98 << (vertices(facets(i, 1), 0) - bbox_min[0]) * settings.scaling_factor << ","
99 << (bbox_max[1] - vertices(facets(i, 1), 1)) * settings.scaling_factor << " "
100 << (vertices(facets(i, 2), 0) - bbox_min[0]) * settings.scaling_factor << ","
101 << (bbox_max[1] - vertices(facets(i, 2), 1)) * settings.scaling_factor << "\"/>"
102 << std::endl;
103 }
104
105 fout << footer << std::endl;
106 fout.close();
107}
108
112template <typename MeshType>
113void save_image_svg(const fs::path& filename, const MeshType& mesh, const SVGSetting& settings = {})
114{
115 if (settings.use_uv_mesh) {
116 const auto& uv = mesh.get_uv();
117 const auto& uv_indices = mesh.get_uv_indices();
118 save_image_svg(filename, uv, uv_indices, settings);
119 } else {
120 const auto& vertices = mesh.get_vertices();
121 const auto& facets = mesh.get_facets();
122 save_image_svg(filename, vertices, facets, settings);
123 }
124}
125
126} // namespace image_io
127} // namespace lagrange
@ Scalar
Mesh attribute must have exactly 1 channel.
Definition AttributeFwd.h:56
internal::Range< Index > range(Index end)
Returns an iterable object representing the range [0, end).
Definition range.h:176
Main namespace for Lagrange.
Definition save_image_svg.h:27
bool use_uv_mesh
Whether to use UV coordinates or vertex coordinates.
Definition save_image_svg.h:30
float scaling_factor
Uniform scaling factor.
Definition save_image_svg.h:33
uint32_t fill_color
Fill color.
Definition save_image_svg.h:32
float height
Image height. Auto-compute if <=0.
Definition save_image_svg.h:36
float stroke_width
Stroke width.
Definition save_image_svg.h:34
bool with_stroke
Whether to stroke the edges.
Definition save_image_svg.h:28
bool with_fill
Whether to fill the facets.
Definition save_image_svg.h:29
uint32_t stroke_color
Stroke color.
Definition save_image_svg.h:31
float width
Image width. Auto-compute if <=0.
Definition save_image_svg.h:35