Lagrange
All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Modules Pages
save_image_svg.h
1/*
2 * Copyright 2023 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/range.h>
19
20#include <fstream>
21
22namespace lagrange {
23namespace image_io {
24
26{
27 bool with_stroke = true;
28 bool with_fill = true;
29 bool use_uv_mesh = false;
30 uint32_t stroke_color = 0x000000;
31 uint32_t fill_color = 0xEBFF8C;
32 float scaling_factor = 1;
33 float stroke_width = 1;
34 float width = 0;
35 float height = 0;
36};
37
47template <typename DerivedV, typename DerivedF>
48void save_image_svg(
49 const fs::path& filename,
50 const Eigen::MatrixBase<DerivedV>& vertices,
51 const Eigen::MatrixBase<DerivedF>& facets,
52 const SVGSetting& settings = {})
53{
54 using Scalar = typename DerivedV::Scalar;
55 std::ofstream fout(filename.c_str());
56
57 const auto num_facets = facets.rows();
58
59 const Eigen::Matrix<Scalar, 1, 2> bbox_min = vertices.colwise().minCoeff().eval();
60 const Eigen::Matrix<Scalar, 1, 2> bbox_max = vertices.colwise().maxCoeff().eval();
61
62 std::string footer = "</svg>";
63
64 // Default image size is based on bbox.
65 float width = settings.width;
66 float height = settings.height;
67 if (settings.width <= 0) {
68 width = float(bbox_max[0] - bbox_min[0]) * settings.scaling_factor;
69 }
70 if (settings.height <= 0) {
71 height = float(bbox_max[1] - bbox_min[1]) * settings.scaling_factor;
72 }
73
74 fout << fmt::format(
75 "<?xml version=\"1.0\" encoding=\"utf-8\"?> <svg version=\"1.1\" id=\"Layer_1\" "
76 "xmlns=\"http://www.w3.org/2000/svg\" "
77 "xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" "
78 "y=\"0px\" viewBox=\"0 0 {} {}\" "
79 "style=\"enable-background:new 0 0 {} {};\" "
80 "xml:space=\"preserve\"> <style type=\"text/css\"> "
81 ".st0{{fill:{}; stroke:{}; stroke-miterlimit:10; stroke-width:{}px; "
82 "stroke-linejoin:\"round\";}} "
83 "</style> ",
84 width,
85 height,
86 width,
87 height,
88 settings.with_fill ? fmt::format("#{:06x}", settings.fill_color) : "none",
89 settings.with_stroke ? fmt::format("#{:06x}", settings.stroke_color) : "none",
90 settings.with_stroke ? settings.stroke_width : 0)
91 << std::endl;
92
93 for (auto i : range(num_facets)) {
94 fout << "<polygon class=\"st0\" points=\""
95 << (vertices(facets(i, 0), 0) - bbox_min[0]) * settings.scaling_factor << ","
96 << (bbox_max[1] - vertices(facets(i, 0), 1)) * settings.scaling_factor << " "
97 << (vertices(facets(i, 1), 0) - bbox_min[0]) * settings.scaling_factor << ","
98 << (bbox_max[1] - vertices(facets(i, 1), 1)) * settings.scaling_factor << " "
99 << (vertices(facets(i, 2), 0) - bbox_min[0]) * settings.scaling_factor << ","
100 << (bbox_max[1] - vertices(facets(i, 2), 1)) * settings.scaling_factor << "\"/>"
101 << std::endl;
102 }
103
104 fout << footer << std::endl;
105 fout.close();
106}
107
111template <typename MeshType>
112void save_image_svg(const fs::path& filename, const MeshType& mesh, const SVGSetting& settings = {})
113{
114 if (settings.use_uv_mesh) {
115 const auto& uv = mesh.get_uv();
116 const auto& uv_indices = mesh.get_uv_indices();
117 save_image_svg(filename, uv, uv_indices, settings);
118 } else {
119 const auto& vertices = mesh.get_vertices();
120 const auto& facets = mesh.get_facets();
121 save_image_svg(filename, vertices, facets, settings);
122 }
123}
124
125} // namespace image_io
126} // namespace lagrange
Definition: Mesh.h:48
internal::Range< Index > range(Index end)
Returns an iterable object representing the range [0, end).
Definition: range.h:176
Main namespace for Lagrange.
Definition: AABBIGL.h:30
Definition: save_image_svg.h:26
bool use_uv_mesh
Whether to use UV coordinates or vertex coordinates.
Definition: save_image_svg.h:29
float scaling_factor
Uniform scaling factor.
Definition: save_image_svg.h:32
uint32_t fill_color
Fill color.
Definition: save_image_svg.h:31
float height
Image height. Auto-compute if <=0.
Definition: save_image_svg.h:35
float stroke_width
Stroke width.
Definition: save_image_svg.h:33
bool with_stroke
Whether to stroke the edges.
Definition: save_image_svg.h:27
bool with_fill
Whether to fill the facets.
Definition: save_image_svg.h:28
uint32_t stroke_color
Stroke color.
Definition: save_image_svg.h:30
float width
Image width. Auto-compute if <=0.
Definition: save_image_svg.h:34