mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 23:06:13 +08:00
Using ExPolygons instead of polygons to represents shape of letters(text)
This commit is contained in:
parent
7faec616f0
commit
2b0408cc24
@ -60,7 +60,8 @@ std::optional<Emboss::Glyph> Privat::get_glyph(stbtt_fontinfo &font_info, int un
|
|||||||
stbtt__point *points = stbtt_FlattenCurves(vertices, num_verts,
|
stbtt__point *points = stbtt_FlattenCurves(vertices, num_verts,
|
||||||
flatness, &contour_lengths, &num_countour, font_info.userdata);
|
flatness, &contour_lengths, &num_countour, font_info.userdata);
|
||||||
|
|
||||||
glyph.polygons.reserve(num_countour);
|
Polygons glyph_polygons;
|
||||||
|
glyph_polygons.reserve(num_countour);
|
||||||
size_t pi = 0; // point index
|
size_t pi = 0; // point index
|
||||||
for (size_t ci = 0; ci < num_countour; ++ci) {
|
for (size_t ci = 0; ci < num_countour; ++ci) {
|
||||||
int length = contour_lengths[ci];
|
int length = contour_lengths[ci];
|
||||||
@ -85,10 +86,10 @@ std::optional<Emboss::Glyph> Privat::get_glyph(stbtt_fontinfo &font_info, int un
|
|||||||
|
|
||||||
// change outer cw to ccw and inner ccw to cw order
|
// change outer cw to ccw and inner ccw to cw order
|
||||||
std::reverse(pts.begin(), pts.end());
|
std::reverse(pts.begin(), pts.end());
|
||||||
glyph.polygons.emplace_back(pts);
|
glyph_polygons.emplace_back(pts);
|
||||||
}
|
}
|
||||||
// fix for bad defined fonts
|
// fix for bad defined fonts
|
||||||
glyph.polygons = union_(glyph.polygons);
|
glyph.polygons = union_ex(glyph_polygons);
|
||||||
// inner cw - hole
|
// inner cw - hole
|
||||||
// outer ccw - contour
|
// outer ccw - contour
|
||||||
return glyph;
|
return glyph;
|
||||||
@ -480,14 +481,14 @@ std::optional<Emboss::Glyph> Emboss::letter2glyph(const Font &font,
|
|||||||
return Privat::get_glyph(*font_info_opt, (int) letter, flatness);
|
return Privat::get_glyph(*font_info_opt, (int) letter, flatness);
|
||||||
}
|
}
|
||||||
|
|
||||||
Polygons Emboss::text2polygons(Font & font,
|
ExPolygons Emboss::text2shapes(Font & font,
|
||||||
const char * text,
|
const char * text,
|
||||||
const FontProp &font_prop)
|
const FontProp &font_prop)
|
||||||
{
|
{
|
||||||
std::optional<stbtt_fontinfo> font_info_opt;
|
std::optional<stbtt_fontinfo> font_info_opt;
|
||||||
|
|
||||||
Point cursor(0, 0);
|
Point cursor(0, 0);
|
||||||
Polygons result;
|
ExPolygons result;
|
||||||
|
|
||||||
std::wstring ws = boost::nowide::widen(text);
|
std::wstring ws = boost::nowide::widen(text);
|
||||||
for (wchar_t wc: ws){
|
for (wchar_t wc: ws){
|
||||||
@ -505,7 +506,7 @@ Polygons Emboss::text2polygons(Font & font,
|
|||||||
if (!font_info_opt.has_value()) {
|
if (!font_info_opt.has_value()) {
|
||||||
font_info_opt = Privat::load_font_info(font);
|
font_info_opt = Privat::load_font_info(font);
|
||||||
// can load font info?
|
// can load font info?
|
||||||
if (!font_info_opt.has_value()) return Polygons();
|
if (!font_info_opt.has_value()) return {};
|
||||||
}
|
}
|
||||||
glyph_opt = Privat::get_glyph(*font_info_opt, unicode,
|
glyph_opt = Privat::get_glyph(*font_info_opt, unicode,
|
||||||
font_prop.flatness);
|
font_prop.flatness);
|
||||||
@ -516,16 +517,16 @@ Polygons Emboss::text2polygons(Font & font,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// move glyph to cursor position
|
// move glyph to cursor position
|
||||||
Polygons polygons = glyph_opt->polygons; // copy
|
ExPolygons polygons = glyph_opt->polygons; // copy
|
||||||
for (Polygon &polygon : polygons)
|
for (ExPolygon &polygon : polygons)
|
||||||
polygon.translate(cursor);
|
polygon.translate(cursor);
|
||||||
cursor.x() += glyph_opt->advance_width + font_prop.char_gap;
|
cursor.x() += glyph_opt->advance_width + font_prop.char_gap;
|
||||||
polygons_append(result, polygons);
|
expolygons_append(result, polygons);
|
||||||
}
|
}
|
||||||
return union_(result);
|
return union_ex(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
indexed_triangle_set Emboss::polygons2model(const Polygons &shape2d,
|
indexed_triangle_set Emboss::polygons2model(const ExPolygons &shape2d,
|
||||||
const IProject &projection)
|
const IProject &projection)
|
||||||
{
|
{
|
||||||
indexed_triangle_set result;
|
indexed_triangle_set result;
|
||||||
@ -536,12 +537,17 @@ indexed_triangle_set Emboss::polygons2model(const Polygons &shape2d,
|
|||||||
std::vector<Vec3f> back_points;
|
std::vector<Vec3f> back_points;
|
||||||
back_points.reserve(count_point);
|
back_points.reserve(count_point);
|
||||||
|
|
||||||
for (const Polygon &polygon : shape2d) {
|
auto insert_point = [&projection, &front_points,
|
||||||
for (const Point &p : polygon.points) {
|
&back_points](const Polygon& polygon) {
|
||||||
|
for (const Point& p : polygon.points) {
|
||||||
auto p2 = projection.project(p);
|
auto p2 = projection.project(p);
|
||||||
front_points.emplace_back(p2.first);
|
front_points.emplace_back(p2.first);
|
||||||
back_points.emplace_back(p2.second);
|
back_points.emplace_back(p2.second);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
for (const ExPolygon &expolygon : shape2d) {
|
||||||
|
insert_point(expolygon.contour);
|
||||||
|
for (const Polygon &hole : expolygon.holes) insert_point(hole);
|
||||||
}
|
}
|
||||||
// insert back points, front are already in
|
// insert back points, front are already in
|
||||||
result.vertices.insert(result.vertices.end(),
|
result.vertices.insert(result.vertices.end(),
|
||||||
@ -561,7 +567,7 @@ indexed_triangle_set Emboss::polygons2model(const Polygons &shape2d,
|
|||||||
|
|
||||||
// quads around - zig zag by triangles
|
// quads around - zig zag by triangles
|
||||||
size_t polygon_offset = 0;
|
size_t polygon_offset = 0;
|
||||||
for (const Polygon &polygon : shape2d) {
|
auto add_quads = [&result,&polygon_offset, count_point](const Polygon& polygon) {
|
||||||
uint32_t polygon_points = polygon.points.size();
|
uint32_t polygon_points = polygon.points.size();
|
||||||
for (uint32_t p = 0; p < polygon_points; p++) {
|
for (uint32_t p = 0; p < polygon_points; p++) {
|
||||||
uint32_t i = polygon_offset + p;
|
uint32_t i = polygon_offset + p;
|
||||||
@ -575,6 +581,11 @@ indexed_triangle_set Emboss::polygons2model(const Polygons &shape2d,
|
|||||||
result.indices.emplace_back(ip2, ip, i2);
|
result.indices.emplace_back(ip2, ip, i2);
|
||||||
}
|
}
|
||||||
polygon_offset += polygon_points;
|
polygon_offset += polygon_points;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const ExPolygon &expolygon : shape2d) {
|
||||||
|
add_quads(expolygon.contour);
|
||||||
|
for (const Polygon &hole : expolygon.holes) add_quads(hole);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ public:
|
|||||||
// description of one letter
|
// description of one letter
|
||||||
struct Glyph
|
struct Glyph
|
||||||
{
|
{
|
||||||
Polygons polygons;
|
ExPolygons polygons;
|
||||||
int advance_width, left_side_bearing;
|
int advance_width, left_side_bearing;
|
||||||
};
|
};
|
||||||
// cache for glyph by unicode
|
// cache for glyph by unicode
|
||||||
@ -94,7 +94,7 @@ public:
|
|||||||
/// <param name="text">Characters to convert</param>
|
/// <param name="text">Characters to convert</param>
|
||||||
/// <param name="font_prop">User defined property of the font</param>
|
/// <param name="font_prop">User defined property of the font</param>
|
||||||
/// <returns>Inner polygon cw(outer ccw)</returns>
|
/// <returns>Inner polygon cw(outer ccw)</returns>
|
||||||
static Polygons text2polygons(Font & font,
|
static ExPolygons text2shapes(Font & font,
|
||||||
const char * text,
|
const char * text,
|
||||||
const FontProp &font_prop);
|
const FontProp &font_prop);
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ public:
|
|||||||
/// <param name="shape2d">text or image</param>
|
/// <param name="shape2d">text or image</param>
|
||||||
/// <param name="projection">Define transformation from 2d to 3d(orientation, position, scale, ...)</param>
|
/// <param name="projection">Define transformation from 2d to 3d(orientation, position, scale, ...)</param>
|
||||||
/// <returns>Projected shape into space</returns>
|
/// <returns>Projected shape into space</returns>
|
||||||
static indexed_triangle_set polygons2model(const Polygons &shape2d, const IProject& projection);
|
static indexed_triangle_set polygons2model(const ExPolygons &shape2d, const IProject& projection);
|
||||||
|
|
||||||
class ProjectZ : public IProject
|
class ProjectZ : public IProject
|
||||||
{
|
{
|
||||||
|
@ -78,6 +78,17 @@ public:
|
|||||||
inline bool operator==(const ExPolygon &lhs, const ExPolygon &rhs) { return lhs.contour == rhs.contour && lhs.holes == rhs.holes; }
|
inline bool operator==(const ExPolygon &lhs, const ExPolygon &rhs) { return lhs.contour == rhs.contour && lhs.holes == rhs.holes; }
|
||||||
inline bool operator!=(const ExPolygon &lhs, const ExPolygon &rhs) { return lhs.contour != rhs.contour || lhs.holes != rhs.holes; }
|
inline bool operator!=(const ExPolygon &lhs, const ExPolygon &rhs) { return lhs.contour != rhs.contour || lhs.holes != rhs.holes; }
|
||||||
|
|
||||||
|
inline size_t count_points(const ExPolygons &expolys)
|
||||||
|
{
|
||||||
|
size_t n_points = 0;
|
||||||
|
for (const auto &expoly : expolys) {
|
||||||
|
n_points += expoly.contour.points.size();
|
||||||
|
for (const auto &hole : expoly.holes)
|
||||||
|
n_points += hole.points.size();
|
||||||
|
}
|
||||||
|
return n_points;
|
||||||
|
}
|
||||||
|
|
||||||
// Count a nuber of polygons stored inside the vector of expolygons.
|
// Count a nuber of polygons stored inside the vector of expolygons.
|
||||||
// Useful for allocating space for polygons when converting expolygons to polygons.
|
// Useful for allocating space for polygons when converting expolygons to polygons.
|
||||||
inline size_t number_polygons(const ExPolygons &expolys)
|
inline size_t number_polygons(const ExPolygons &expolys)
|
||||||
@ -90,11 +101,8 @@ inline size_t number_polygons(const ExPolygons &expolys)
|
|||||||
|
|
||||||
inline Lines to_lines(const ExPolygon &src)
|
inline Lines to_lines(const ExPolygon &src)
|
||||||
{
|
{
|
||||||
size_t n_lines = src.contour.points.size();
|
|
||||||
for (size_t i = 0; i < src.holes.size(); ++ i)
|
|
||||||
n_lines += src.holes[i].points.size();
|
|
||||||
Lines lines;
|
Lines lines;
|
||||||
lines.reserve(n_lines);
|
lines.reserve(count_points(src));
|
||||||
for (size_t i = 0; i <= src.holes.size(); ++ i) {
|
for (size_t i = 0; i <= src.holes.size(); ++ i) {
|
||||||
const Polygon &poly = (i == 0) ? src.contour : src.holes[i - 1];
|
const Polygon &poly = (i == 0) ? src.contour : src.holes[i - 1];
|
||||||
for (Points::const_iterator it = poly.points.begin(); it != poly.points.end()-1; ++it)
|
for (Points::const_iterator it = poly.points.begin(); it != poly.points.end()-1; ++it)
|
||||||
@ -106,14 +114,8 @@ inline Lines to_lines(const ExPolygon &src)
|
|||||||
|
|
||||||
inline Lines to_lines(const ExPolygons &src)
|
inline Lines to_lines(const ExPolygons &src)
|
||||||
{
|
{
|
||||||
size_t n_lines = 0;
|
|
||||||
for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++ it_expoly) {
|
|
||||||
n_lines += it_expoly->contour.points.size();
|
|
||||||
for (size_t i = 0; i < it_expoly->holes.size(); ++ i)
|
|
||||||
n_lines += it_expoly->holes[i].points.size();
|
|
||||||
}
|
|
||||||
Lines lines;
|
Lines lines;
|
||||||
lines.reserve(n_lines);
|
lines.reserve(count_points(src));
|
||||||
for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++ it_expoly) {
|
for (ExPolygons::const_iterator it_expoly = src.begin(); it_expoly != src.end(); ++ it_expoly) {
|
||||||
for (size_t i = 0; i <= it_expoly->holes.size(); ++ i) {
|
for (size_t i = 0; i <= it_expoly->holes.size(); ++ i) {
|
||||||
const Points &points = ((i == 0) ? it_expoly->contour : it_expoly->holes[i - 1]).points;
|
const Points &points = ((i == 0) ? it_expoly->contour : it_expoly->holes[i - 1]).points;
|
||||||
|
@ -6,8 +6,27 @@
|
|||||||
|
|
||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
|
|
||||||
Triangulation::Indices Triangulation::triangulate(const Points & points,
|
namespace Slic3r::Private {
|
||||||
const HalfEdges &half_edges)
|
|
||||||
|
inline void insert_points(Points& points, const Polygon &polygon) {
|
||||||
|
points.insert(points.end(), polygon.points.begin(), polygon.points.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void insert_edge(Slic3r::Triangulation::HalfEdges &edges, uint32_t &offset, const Polygon &polygon) {
|
||||||
|
const Points &pts = polygon.points;
|
||||||
|
for (uint32_t i = 1; i < pts.size(); ++i) {
|
||||||
|
uint32_t i2 = i + offset;
|
||||||
|
edges.insert({i2 - 1, i2});
|
||||||
|
}
|
||||||
|
uint32_t size = static_cast<uint32_t>(pts.size());
|
||||||
|
// add connection from first to last point
|
||||||
|
edges.insert({offset + size - 1, offset});
|
||||||
|
offset += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Triangulation::Indices Triangulation::triangulate(const Points &points, const HalfEdges &half_edges)
|
||||||
{
|
{
|
||||||
// IMPROVE use int point insted of float !!!
|
// IMPROVE use int point insted of float !!!
|
||||||
|
|
||||||
@ -62,10 +81,10 @@ Triangulation::Indices Triangulation::triangulate(const Points & points,
|
|||||||
|
|
||||||
Triangulation::Indices Triangulation::triangulate(const Polygon &polygon)
|
Triangulation::Indices Triangulation::triangulate(const Polygon &polygon)
|
||||||
{
|
{
|
||||||
const Points & pts = polygon.points;
|
const Points &pts = polygon.points;
|
||||||
std::set<std::pair<uint32_t, uint32_t>> edges;
|
HalfEdges edges;
|
||||||
for (uint32_t i = 1; i < pts.size(); ++i) edges.insert({i - 1, i});
|
uint32_t offset = 0;
|
||||||
edges.insert({(uint32_t) pts.size() - 1, uint32_t(0)});
|
Private::insert_edge(edges, offset, polygon);
|
||||||
Triangulation::Indices indices = triangulate(pts, edges);
|
Triangulation::Indices indices = triangulate(pts, edges);
|
||||||
remove_outer(indices, edges);
|
remove_outer(indices, edges);
|
||||||
return indices;
|
return indices;
|
||||||
@ -76,23 +95,38 @@ Triangulation::Indices Triangulation::triangulate(const Polygons &polygons)
|
|||||||
size_t count = count_points(polygons);
|
size_t count = count_points(polygons);
|
||||||
Points points;
|
Points points;
|
||||||
points.reserve(count);
|
points.reserve(count);
|
||||||
for (const Polygon &polygon : polygons)
|
|
||||||
points.insert(points.end(), polygon.points.begin(),
|
|
||||||
polygon.points.end());
|
|
||||||
|
|
||||||
std::set<std::pair<uint32_t, uint32_t>> edges;
|
HalfEdges edges;
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
|
|
||||||
for (const Polygon &polygon : polygons) {
|
for (const Polygon &polygon : polygons) {
|
||||||
const Points &pts = polygon.points;
|
Private::insert_points(points, polygon);
|
||||||
for (uint32_t i = 1; i < pts.size(); ++i) {
|
Private::insert_edge(edges, offset, polygon);
|
||||||
uint32_t i2 = i + offset;
|
|
||||||
edges.insert({i2 - 1, i2});
|
|
||||||
}
|
|
||||||
uint32_t size = static_cast<uint32_t>(pts.size());
|
|
||||||
// add connection from first to last point
|
|
||||||
edges.insert({offset + size - 1, offset});
|
|
||||||
offset += size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Triangulation::Indices indices = triangulate(points, edges);
|
||||||
|
remove_outer(indices, edges);
|
||||||
|
return indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
Triangulation::Indices Triangulation::triangulate(const ExPolygons &expolygons)
|
||||||
|
{
|
||||||
|
size_t count = count_points(expolygons);
|
||||||
|
Points points;
|
||||||
|
points.reserve(count);
|
||||||
|
|
||||||
|
HalfEdges edges;
|
||||||
|
uint32_t offset = 0;
|
||||||
|
|
||||||
|
for (const ExPolygon &expolygon : expolygons) {
|
||||||
|
Private::insert_points(points, expolygon.contour);
|
||||||
|
Private::insert_edge(edges, offset, expolygon.contour);
|
||||||
|
for (const Polygon &hole : expolygon.holes) {
|
||||||
|
Private::insert_points(points, hole);
|
||||||
|
Private::insert_edge(edges, offset, hole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Triangulation::Indices indices = triangulate(points, edges);
|
Triangulation::Indices indices = triangulate(points, edges);
|
||||||
remove_outer(indices, edges);
|
remove_outer(indices, edges);
|
||||||
return indices;
|
return indices;
|
||||||
|
@ -30,6 +30,7 @@ public:
|
|||||||
const HalfEdges &half_edges);
|
const HalfEdges &half_edges);
|
||||||
static Indices triangulate(const Polygon &polygon);
|
static Indices triangulate(const Polygon &polygon);
|
||||||
static Indices triangulate(const Polygons &polygons);
|
static Indices triangulate(const Polygons &polygons);
|
||||||
|
static Indices triangulate(const ExPolygons &expolygons);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Filter out triagles without both side edge or inside half edges
|
/// Filter out triagles without both side edge or inside half edges
|
||||||
|
@ -221,13 +221,13 @@ ModelVolume *GLGizmoEmboss::get_selected_volume(const Selection &selection,
|
|||||||
bool GLGizmoEmboss::process() {
|
bool GLGizmoEmboss::process() {
|
||||||
if (!m_font.has_value()) return false;
|
if (!m_font.has_value()) return false;
|
||||||
|
|
||||||
Polygons polygons = Emboss::text2polygons(*m_font, m_text.c_str(), m_font_prop);
|
ExPolygons shapes = Emboss::text2shapes(*m_font, m_text.c_str(), m_font_prop);
|
||||||
if (polygons.empty()) return false;
|
if (shapes.empty()) return false;
|
||||||
|
|
||||||
float scale = m_font_prop.size_in_mm / m_font->ascent;
|
float scale = m_font_prop.size_in_mm / m_font->ascent;
|
||||||
auto project = std::make_unique<Emboss::ProjectScale>(
|
auto project = std::make_unique<Emboss::ProjectScale>(
|
||||||
std::make_unique<Emboss::ProjectZ>(m_font_prop.emboss / scale), scale);
|
std::make_unique<Emboss::ProjectZ>(m_font_prop.emboss / scale), scale);
|
||||||
indexed_triangle_set its = Emboss::polygons2model(polygons, *project);
|
indexed_triangle_set its = Emboss::polygons2model(shapes, *project);
|
||||||
if (its.indices.empty()) return false;
|
if (its.indices.empty()) return false;
|
||||||
|
|
||||||
// add object
|
// add object
|
||||||
@ -302,8 +302,7 @@ bool GLGizmoEmboss::process() {
|
|||||||
|
|
||||||
void GLGizmoEmboss::close() {
|
void GLGizmoEmboss::close() {
|
||||||
// close gizmo == open it again
|
// close gizmo == open it again
|
||||||
GLGizmosManager &gizmos_mgr = m_parent.get_gizmos_manager();
|
m_parent.get_gizmos_manager().open_gizmo(GLGizmosManager::Emboss);
|
||||||
gizmos_mgr.open_gizmo(GLGizmosManager::EType::Emboss);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoEmboss::draw_add_button() {
|
void GLGizmoEmboss::draw_add_button() {
|
||||||
@ -408,7 +407,7 @@ void GLGizmoEmboss::draw_window()
|
|||||||
process();
|
process();
|
||||||
|
|
||||||
|
|
||||||
if (ImGui::Button(_L("Close").c_str())) process();
|
if (ImGui::Button(_L("Close").c_str())) close();
|
||||||
|
|
||||||
// Option to create text volume when reselect volumes
|
// Option to create text volume when reselect volumes
|
||||||
m_imgui->disabled_begin(!m_font.has_value());
|
m_imgui->disabled_begin(!m_font.has_value());
|
||||||
|
@ -51,9 +51,9 @@ TEST_CASE("Add TriangleMeshes", "[MeshBoolean]")
|
|||||||
|
|
||||||
#include "libslic3r/Emboss.hpp"
|
#include "libslic3r/Emboss.hpp"
|
||||||
|
|
||||||
Polygons ttf2polygons(const char * font_name, char letter, float flatness = 1.f) {
|
ExPolygons ttf2polygons(const char * font_name, char letter, float flatness = 1.f) {
|
||||||
auto font = Emboss::load_font(font_name);
|
auto font = Emboss::load_font(font_name);
|
||||||
if (!font.has_value()) return Polygons();
|
if (!font.has_value()) return ExPolygons();
|
||||||
return Emboss::letter2glyph(*font, letter, flatness)->polygons;
|
return Emboss::letter2glyph(*font, letter, flatness)->polygons;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -619,13 +619,13 @@ TEST_CASE("Emboss polygon", "[MeshBoolean]")
|
|||||||
const char *font_name = "C:/windows/fonts/arialbd.ttf";
|
const char *font_name = "C:/windows/fonts/arialbd.ttf";
|
||||||
char letter = '%';
|
char letter = '%';
|
||||||
float flatness = 2.;
|
float flatness = 2.;
|
||||||
Polygons polygons = ttf2polygons(font_name, letter, flatness);
|
ExPolygons espolygons = ttf2polygons(font_name, letter, flatness);
|
||||||
store_to_svg(polygons);
|
|
||||||
|
|
||||||
//TriangleMesh tm = make_sphere(1., 1.); tm.scale(10.f);
|
//TriangleMesh tm = make_sphere(1., 1.); tm.scale(10.f);
|
||||||
|
|
||||||
TriangleMesh tm = make_cube(10., 5., 2.);
|
TriangleMesh tm = make_cube(10., 5., 2.);
|
||||||
tm.translate(Vec3f(0, 0, 1.7));
|
tm.translate(Vec3f(0, 0, 1.7));
|
||||||
|
Polygons polygons;
|
||||||
polygons = {Polygon({{1, 1}, {1, 2}, {2, 2}, {2, 1}})}; // rectangle CW
|
polygons = {Polygon({{1, 1}, {1, 2}, {2, 2}, {2, 1}})}; // rectangle CW
|
||||||
polygons = {Polygon({{1, 1}, {2, 1}, {2, 2}, {1, 2}})}; // rectangle CCW
|
polygons = {Polygon({{1, 1}, {2, 1}, {2, 2}, {1, 2}})}; // rectangle CCW
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user