extract explicit mesh with topology information from implicit surfaces with boolean operations, and do surface/volume integrating on them.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

280 lines
11 KiB

#include <iostream>
#include <fstream>
#include <cstdio>
#include <vector>
#include "io_primitive.h"
#include "math/math_defs.hpp"
#include "mimalloc.h"
#include "primitive_descriptor.h"
#include <solve.h>
void export_obj(const char* filename, const polymesh_t& mesh) {
std::ofstream f(filename);
if (!f) { std::cerr << "Cannot open " << filename << std::endl; return; }
for (uint32_t i = 0; i < mesh.num_vertices; ++i) {
auto& v = mesh.vertices[i];
f << "v " << v.x << " " << v.y << " " << v.z << "\n";
}
uint32_t offset = 0;
for (uint32_t fi = 0; fi < mesh.num_faces; ++fi) {
uint32_t count = mesh.vertex_counts[fi];
f << "f";
for (uint32_t j = 0; j < count; ++j)
f << " " << (mesh.faces[offset + j] + 1);
f << "\n";
offset += count;
}
std::cout << " -> " << filename << ": " << mesh.num_vertices << " verts, " << mesh.num_faces << " faces" << std::endl;
}
void run_test_case(const char* name,
polyline_pattern_descriptor_t& pattern_desc,
polyline_axis_descriptor_t& axis_desc)
{
auto dc = create_primitive_data_center();
auto pat = create_pattern(dc, &pattern_desc, PATTERN_TYPE_POLYLINE);
auto ax = create_extrude_axis(dc, &axis_desc, AXIS_TYPE_EXTRUDE_POLYLINE);
auto ext = create_param_primitive(&ax, &pat, dc, PRIMITIVE_TYPE_EXTRUDE);
auto rt = create_blobtree();
blobtree_add_primitive_node(rt, ext);
auto baked = bake_blobtree(rt);
destroy_blobtree(rt);
s_settings s{};
s.resolution = 32;
s.scene_aabb_margin = 1e-5;
s.restricted_primitive_bounding_test = true;
s.integrand_density = 32;
auto solver = create_solver(baked, s);
auto result = generate_polymesh(solver);
std::cout << name << ": " << (result.success ? "OK" : "FAIL")
<< " verts=" << result.mesh.num_vertices
<< " faces=" << result.mesh.num_faces << std::endl;
char filename[256];
snprintf(filename, sizeof(filename), "test_extrude_%s.obj", name);
export_obj(filename, result.mesh);
destroy_solver(solver);
destroy_baked_blobtree(baked);
destroy_primitive(ext);
destroy_primitive_data_center(dc);
}
int main()
{
const double b_quarter = std::tan(pi / 8); // tan(theta/4), theta=pi/2 -> quarter circle
// --- Curved axis: quarter-circle arc from (0,0,0) to (0,1,1) ---
polyline_axis_descriptor_t axis_curved{};
std::vector axis_pts_curved{ vector3d{0, 0, 0}, vector3d{0, 1, 1} };
axis_curved.point_number = 2;
axis_curved.points = axis_pts_curved.data();
std::vector axis_blg_curved{ b_quarter };
axis_curved.bulge_number = 1;
axis_curved.bulges = axis_blg_curved.data();
axis_curved.reference_normal = {1, 0, 0};
axis_curved.is_closed = false;
// --- Straight axis: from (0,0,0) to (0,0,1) ---
polyline_axis_descriptor_t axis_straight{};
std::vector axis_pts_straight{ vector3d{0, 0, 0}, vector3d{0, 0, 1} };
axis_straight.point_number = 2;
axis_straight.points = axis_pts_straight.data();
std::vector axis_blg_straight{ 0. };
axis_straight.bulge_number = 1;
axis_straight.bulges = axis_blg_straight.data();
axis_straight.reference_normal = {1, 0, 0};
axis_straight.is_closed = false;
// ==================================================================
// Test 1: Original semicircle (reference, all arcs, legacy bulge=1)
// ==================================================================
{
polyline_pattern_descriptor_t pat{};
pat.anchor = {0, 0};
std::vector pts{ vector2d{-.1, 0}, vector2d{.1, 0}, vector2d{-.1, 0} };
pat.point_number = 3;
pat.points = pts.data();
std::vector blg{ 1., 1. };
pat.bulge_number = 2;
pat.bulges = blg.data();
run_test_case("01_original_semicircle", pat, axis_curved);
}
// ==================================================================
// Test 2: Rectangle (all lines, bulge=0)
// ==================================================================
{
polyline_pattern_descriptor_t pat{};
pat.anchor = {0, 0};
std::vector pts{
vector2d{-.1, -.1}, vector2d{.1, -.1},
vector2d{.1, .1}, vector2d{-.1, .1},
vector2d{-.1, -.1}
};
pat.point_number = 5;
pat.points = pts.data();
std::vector blg{ 0., 0., 0., 0. };
pat.bulge_number = 4;
pat.bulges = blg.data();
run_test_case("02_rectangle", pat, axis_curved);
}
// ==================================================================
// Test 3: Curved diamond (4 quarter-circle arcs, total theta=2pi)
// ==================================================================
{
polyline_pattern_descriptor_t pat{};
pat.anchor = {0, 0};
std::vector pts{
vector2d{-.12, 0}, vector2d{0, .12},
vector2d{.12, 0}, vector2d{0, -.12},
vector2d{-.12, 0}
};
pat.point_number = 5;
pat.points = pts.data();
std::vector blg{ b_quarter, b_quarter, b_quarter, b_quarter };
pat.bulge_number = 4;
pat.bulges = blg.data();
run_test_case("03_curved_diamond", pat, axis_curved);
}
// ==================================================================
// Test 4: Rectangle with one rounded side (3 lines + 1 arc)
// ==================================================================
{
polyline_pattern_descriptor_t pat{};
pat.anchor = {0, 0};
std::vector pts{
vector2d{-.12, -.08}, vector2d{.12, -.08},
vector2d{.12, .08}, vector2d{-.12, .08},
vector2d{-.12, -.08}
};
pat.point_number = 5;
pat.points = pts.data();
std::vector blg{ 0., 0., 0., b_quarter };
pat.bulge_number = 4;
pat.bulges = blg.data();
run_test_case("04_rect_one_arc", pat, axis_curved);
}
// ==================================================================
// Test 5: Alternating line-arc hexagon (3 lines + 3 quarter arcs)
// ==================================================================
{
polyline_pattern_descriptor_t pat{};
pat.anchor = {0, 0};
std::vector pts{
vector2d{-.10, -.05}, vector2d{0., -.10},
vector2d{.10, -.05}, vector2d{.10, .05},
vector2d{0., .10}, vector2d{-.10, .05},
vector2d{-.10, -.05}
};
pat.point_number = 7;
pat.points = pts.data();
std::vector blg{ 0., b_quarter, 0., b_quarter, 0., b_quarter };
pat.bulge_number = 6;
pat.bulges = blg.data();
run_test_case("05_alternating_hex", pat, axis_curved);
}
// ==================================================================
// Test 6: Rectangle on straight axis (baseline, all lines)
// ==================================================================
{
polyline_pattern_descriptor_t pat{};
pat.anchor = {0, 0};
std::vector pts{
vector2d{-.1, -.1}, vector2d{.1, -.1},
vector2d{.1, .1}, vector2d{-.1, .1},
vector2d{-.1, -.1}
};
pat.point_number = 5;
pat.points = pts.data();
std::vector blg{ 0., 0., 0., 0. };
pat.bulge_number = 4;
pat.bulges = blg.data();
run_test_case("06_rect_straight_axis", pat, axis_straight);
}
// ==================================================================
// Test 7: Curved diamond on straight axis
// ==================================================================
{
polyline_pattern_descriptor_t pat{};
pat.anchor = {0, 0};
std::vector pts{
vector2d{-.12, 0}, vector2d{0, .12},
vector2d{.12, 0}, vector2d{0, -.12},
vector2d{-.12, 0}
};
pat.point_number = 5;
pat.points = pts.data();
std::vector blg{ b_quarter, b_quarter, b_quarter, b_quarter };
pat.bulge_number = 4;
pat.bulges = blg.data();
run_test_case("07_curved_diamond_straight", pat, axis_straight);
}
// ==================================================================
// Test 8: Pill/Stadium shape (2 lines + 2 quarter arcs, straight axis)
// ==================================================================
{
polyline_pattern_descriptor_t pat{};
pat.anchor = {0, 0};
std::vector pts{
vector2d{-.06, -.12}, vector2d{-.06, .12},
vector2d{ .06, .12}, vector2d{ .06, -.12},
vector2d{-.06, -.12}
};
pat.point_number = 5;
pat.points = pts.data();
std::vector blg{ 0., b_quarter, 0., b_quarter };
pat.bulge_number = 4;
pat.bulges = blg.data();
run_test_case("08_pill_shape", pat, axis_straight);
}
// ==================================================================
// Test 9: Mixed octagon (4 lines + 4 arcs, straight axis)
// ==================================================================
{
polyline_pattern_descriptor_t pat{};
pat.anchor = {0, 0};
std::vector pts{
vector2d{-.12, -.08}, vector2d{-.06, -.12},
vector2d{ .06, -.12}, vector2d{ .12, -.08},
vector2d{ .12, .08}, vector2d{ .06, .12},
vector2d{-.06, .12}, vector2d{-.12, .08},
vector2d{-.12, -.08}
};
pat.point_number = 9;
pat.points = pts.data();
std::vector blg{ b_quarter, 0., b_quarter, 0., b_quarter, 0., b_quarter, 0. };
pat.bulge_number = 8;
pat.bulges = blg.data();
run_test_case("09_mixed_octagon", pat, axis_straight);
}
// ==================================================================
// Test 10: Rounded triangle (2 lines + 1 arc, straight axis)
// ==================================================================
{
polyline_pattern_descriptor_t pat{};
pat.anchor = {0, 0};
std::vector pts{
vector2d{-.10, -.10}, vector2d{.10, -.10},
vector2d{-.10, .10}, vector2d{-.10, -.10}
};
pat.point_number = 4;
pat.points = pts.data();
std::vector blg{ 0., b_quarter, 0. };
pat.bulge_number = 3;
pat.bulges = blg.data();
run_test_case("10_rounded_triangle", pat, axis_straight);
}
std::cout << "\nAll tests completed." << std::endl;
return 0;
}