gb_mesh_edge_ref_t gb_tessellator_mesh_make_edge(gb_tessellator_impl_t* impl, gb_point_ref_t org, gb_point_ref_t dst) { // check tb_assert(impl && impl->mesh); // make edge gb_mesh_edge_ref_t edge = gb_mesh_edge_make(impl->mesh); tb_assert_and_check_return_val(edge, tb_null); // init edge.winding gb_tessellator_edge_winding_set(edge, 0); gb_tessellator_edge_winding_set(gb_mesh_edge_sym(edge), 0); // init edge.region gb_tessellator_edge_region_set(edge, tb_null); gb_tessellator_edge_region_set(gb_mesh_edge_sym(edge), tb_null); // init edge.faces.inside, lface == rface gb_tessellator_face_inside_set(gb_mesh_edge_lface(edge), 0); // init edge.org if (org) gb_tessellator_vertex_point_set(gb_mesh_edge_org(edge), org); // init edge.dst if (dst) gb_tessellator_vertex_point_set(gb_mesh_edge_dst(edge), dst); // ok return edge; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t gb_tessellator_mesh_make(gb_tessellator_impl_t* impl, gb_polygon_ref_t polygon) { // check tb_assert(impl && polygon); // the points gb_point_ref_t points = polygon->points; tb_uint16_t const* counts = polygon->counts; tb_assert_and_check_return_val(points && counts, tb_false); // not exists mesh? if (!impl->mesh) { // init func tb_element_t edge_element = tb_element_mem(sizeof(gb_tessellator_edge_t), tb_null, tb_null); tb_element_t face_element = tb_element_mem(sizeof(gb_tessellator_face_t), tb_null, tb_null); tb_element_t vertex_element = tb_element_mem(sizeof(gb_tessellator_vertex_t), tb_null, tb_null); #ifdef __gb_debug__ // init func cstr for gb_mesh_dump edge_element.cstr = gb_tessellator_edge_cstr; face_element.cstr = gb_tessellator_face_cstr; vertex_element.cstr = gb_tessellator_vertex_cstr; #endif // init mesh impl->mesh = gb_mesh_init(edge_element, face_element, vertex_element); /* init the order * * the new edges/faces/vertice will be inserted to the head of list */ gb_mesh_edge_order_set(impl->mesh, GB_MESH_ORDER_INSERT_HEAD); gb_mesh_face_order_set(impl->mesh, GB_MESH_ORDER_INSERT_HEAD); gb_mesh_vertex_order_set(impl->mesh, GB_MESH_ORDER_INSERT_HEAD); // init listener gb_mesh_listener_set(impl->mesh, gb_tessellator_listener, impl->mesh); gb_mesh_listener_event_add(impl->mesh, GB_MESH_EVENT_FACE_SPLIT | GB_MESH_EVENT_EDGE_SPLIT); } // check gb_mesh_ref_t mesh = impl->mesh; tb_assert_and_check_return_val(mesh, tb_false); // clear mesh first gb_mesh_clear(mesh); // done gb_point_ref_t point = tb_null; tb_uint16_t count = *counts++; tb_size_t index = 0; gb_mesh_edge_ref_t edge = tb_null; gb_mesh_edge_ref_t edge_first = tb_null; while (index < count) { // the point point = points++; // first point? if (!index) { // must be closed contour tb_assertf(gb_point_eq(point, point + count - 1), "this contour(%lu: %{point} => %{point}) is not closed!", count, point, point + count - 1); // clear the edge edge = tb_null; // clear the first edge edge_first = tb_null; // trace tb_trace_d("move_to: %{point}", point); } // closed? else if (index + 1 == count) { // trace tb_trace_d("closed: %{point}", point); // connect an edge to the first edge edge = gb_mesh_edge_connect(mesh, edge, edge_first); // init edge.faces.inside gb_tessellator_face_inside_set(gb_mesh_edge_lface(edge), 0); gb_tessellator_face_inside_set(gb_mesh_edge_rface(edge), 0); } else { // trace tb_trace_d("line_to: %{point}", point); // exists the first edge? if (edge_first) { // append an edge edge = gb_mesh_edge_append(mesh, edge); } else { // make a new non-loop edge edge = gb_mesh_edge_make(mesh); // save the first edge edge_first = edge; } } // has new edge? if (edge) { // init edge.winding gb_tessellator_edge_winding_set(edge, 1); gb_tessellator_edge_winding_set(gb_mesh_edge_sym(edge), -1); // init edge.region gb_tessellator_edge_region_set(edge, tb_null); gb_tessellator_edge_region_set(gb_mesh_edge_sym(edge), tb_null); // init edge.dst gb_tessellator_vertex_point_set(gb_mesh_edge_dst(edge), point); } // next point index++; // next polygon if (index == count) { // next count = *counts++; index = 0; } } #ifdef __gb_debug__ // check mesh gb_mesh_check(mesh); #endif // ok? return !gb_mesh_is_empty(mesh); }
static tb_void_t gb_demo_utils_mesh_tetrahedron() { // trace tb_trace_i("=========================================================================="); // init mesh gb_mesh_ref_t mesh = gb_mesh_init(tb_element_str(tb_true), tb_element_str(tb_true), tb_element_str(tb_true)); if (mesh) { // init listener gb_mesh_listener_set(mesh, gb_demo_utils_mesh_listener, mesh); gb_mesh_listener_event_add(mesh, GB_MESH_EVENT_FACE_MERGE | GB_MESH_EVENT_FACE_SPLIT | GB_MESH_EVENT_EDGE_MERGE | GB_MESH_EVENT_EDGE_SPLIT); // make a clockwise self-loop edge gb_mesh_edge_ref_t edge0 = gb_mesh_edge_make_loop(mesh, tb_false); if (edge0) { /* make a tetrahedron * * e1 * v0 --------------> v1----------------- * | . rface | | * e0 | . | e2 lface | * | face1 e5 . | | e4 * v3 <-------------- v2 | * | e3 | * | | face0 * <----------------------------------- * */ gb_mesh_edge_ref_t edge1 = gb_mesh_edge_insert(mesh, edge0, edge0); gb_mesh_edge_ref_t edge2 = gb_mesh_edge_insert(mesh, edge1, edge0); gb_mesh_edge_ref_t edge3 = gb_mesh_edge_insert(mesh, edge2, edge0); // save face name gb_mesh_face_data_set(mesh, gb_mesh_edge_lface(edge0), "lface"); gb_mesh_face_data_set(mesh, gb_mesh_edge_rface(edge0), "rface"); gb_mesh_edge_ref_t edge4 = gb_mesh_edge_connect(mesh, edge1, edge0); gb_mesh_edge_ref_t edge5 = gb_mesh_edge_connect(mesh, gb_mesh_edge_sym(edge3), gb_mesh_edge_sym(edge0)); // save face name gb_mesh_face_data_set(mesh, gb_mesh_edge_lface(edge4), "face0"); gb_mesh_face_data_set(mesh, gb_mesh_edge_lface(edge5), "face1"); // save edge name gb_mesh_edge_data_set(mesh, edge0, "e0"); gb_mesh_edge_data_set(mesh, edge1, "e1"); gb_mesh_edge_data_set(mesh, edge2, "e2"); gb_mesh_edge_data_set(mesh, edge3, "e3"); gb_mesh_edge_data_set(mesh, edge4, "e4"); gb_mesh_edge_data_set(mesh, edge5, "e5"); // save vertex name gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge0), "v0"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge1), "v1"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge2), "v2"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge3), "v3"); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("tetrahedron: make"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif // delete two gb_mesh_edge_delete(mesh, edge4); gb_mesh_edge_delete(mesh, edge5); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("tetrahedron: kill"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif // remove all gb_mesh_edge_remove(mesh, edge2); gb_mesh_edge_remove(mesh, edge3); gb_mesh_edge_remove(mesh, edge0); gb_mesh_edge_remove(mesh, edge1); // check tb_assert_abort(gb_mesh_is_empty(mesh)); } // exit mesh gb_mesh_exit(mesh); } }
static tb_void_t gb_demo_utils_mesh_split() { // trace tb_trace_i("=========================================================================="); // init mesh gb_mesh_ref_t mesh = gb_mesh_init(tb_element_str(tb_true), tb_element_str(tb_true), tb_element_str(tb_true)); if (mesh) { // init listener gb_mesh_listener_set(mesh, gb_demo_utils_mesh_listener, mesh); gb_mesh_listener_event_add(mesh, GB_MESH_EVENT_FACE_MERGE | GB_MESH_EVENT_FACE_SPLIT | GB_MESH_EVENT_EDGE_MERGE | GB_MESH_EVENT_EDGE_SPLIT); // make a clockwise self-loop edge gb_mesh_edge_ref_t edge0 = gb_mesh_edge_make_loop(mesh, tb_false); if (edge0) { /* make a quadrangle * * e1 * v0 --------------> v1 * | | * e0 | rface | e2 lface * | | * v3 <-------------- v2 * e3 * */ gb_mesh_edge_ref_t edge1 = gb_mesh_edge_insert(mesh, edge0, edge0); gb_mesh_edge_ref_t edge2 = gb_mesh_edge_insert(mesh, edge1, edge0); gb_mesh_edge_ref_t edge3 = gb_mesh_edge_insert(mesh, edge2, edge0); // save face name gb_mesh_face_data_set(mesh, gb_mesh_edge_lface(edge0), "lface"); gb_mesh_face_data_set(mesh, gb_mesh_edge_rface(edge0), "rface"); // save edge name gb_mesh_edge_data_set(mesh, edge0, "e0"); gb_mesh_edge_data_set(mesh, edge1, "e1"); gb_mesh_edge_data_set(mesh, edge2, "e2"); gb_mesh_edge_data_set(mesh, edge3, "e3"); // save vertex name gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge0), "v0"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge1), "v1"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge2), "v2"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge3), "v3"); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("split: make"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif /* split a quadrangle * * e1 e4 * v0 ------ v4 -----> v1 * | | * e0 | rface | e2 lface * | | * v3 <----- v5 <---- v2 * e5 e3 * */ gb_mesh_edge_ref_t edge4 = gb_mesh_edge_split(mesh, edge1); gb_mesh_edge_ref_t edge5 = gb_mesh_edge_split(mesh, edge3); // save edge name gb_mesh_edge_data_set(mesh, edge4, "e4"); gb_mesh_edge_data_set(mesh, edge5, "e5"); // save vertex name gb_mesh_vertex_data_set(mesh, gb_mesh_edge_org(edge4), "v4"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_org(edge5), "v5"); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("split: done"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif } // exit mesh gb_mesh_exit(mesh); } }
static tb_void_t gb_demo_utils_mesh_quadrangle() { // trace tb_trace_i("=========================================================================="); // init mesh gb_mesh_ref_t mesh = gb_mesh_init(tb_element_str(tb_true), tb_element_str(tb_true), tb_element_str(tb_true)); if (mesh) { // init listener gb_mesh_listener_set(mesh, gb_demo_utils_mesh_listener, mesh); gb_mesh_listener_event_add(mesh, GB_MESH_EVENT_FACE_MERGE | GB_MESH_EVENT_FACE_SPLIT | GB_MESH_EVENT_EDGE_MERGE | GB_MESH_EVENT_EDGE_SPLIT); // make a counter-clockwise self-loop edge gb_mesh_edge_ref_t edge0 = gb_mesh_edge_make_loop(mesh, tb_true); if (edge0) { /* make a quadrangle * * e0 * v0 <-------------- v3 * | | * e1 | lface | e3 rface * | | * v1 --------------> v2 * e2 * */ gb_mesh_edge_ref_t edge1 = gb_mesh_edge_insert(mesh, edge0, edge0); gb_mesh_edge_ref_t edge2 = gb_mesh_edge_insert(mesh, edge1, edge0); gb_mesh_edge_ref_t edge3 = gb_mesh_edge_insert(mesh, edge2, edge0); // save face name gb_mesh_face_data_set(mesh, gb_mesh_edge_lface(edge0), "lface"); gb_mesh_face_data_set(mesh, gb_mesh_edge_rface(edge0), "rface"); // save edge name gb_mesh_edge_data_set(mesh, edge0, "e0"); gb_mesh_edge_data_set(mesh, edge1, "e1"); gb_mesh_edge_data_set(mesh, edge2, "e2"); gb_mesh_edge_data_set(mesh, edge3, "e3"); // save vertex name gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge0), "v0"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge1), "v1"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge2), "v2"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge3), "v3"); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("quadrangle: make"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif /* remove one * * v3 * e1 . | * . | e3 rface * . lface | * v1 --------------> v2 * e2 */ gb_mesh_edge_remove(mesh, edge0); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("quadrangle: kill"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif // remove all gb_mesh_edge_remove(mesh, edge2); gb_mesh_edge_remove(mesh, edge3); gb_mesh_edge_remove(mesh, edge1); // check tb_assert_abort(gb_mesh_is_empty(mesh)); } // exit mesh gb_mesh_exit(mesh); } }
static tb_void_t gb_demo_utils_mesh_radiation() { // trace tb_trace_i("=========================================================================="); // init mesh gb_mesh_ref_t mesh = gb_mesh_init(tb_element_str(tb_true), tb_element_str(tb_true), tb_element_str(tb_true)); if (mesh) { // init listener gb_mesh_listener_set(mesh, gb_demo_utils_mesh_listener, mesh); gb_mesh_listener_event_add(mesh, GB_MESH_EVENT_FACE_MERGE | GB_MESH_EVENT_FACE_SPLIT | GB_MESH_EVENT_EDGE_MERGE | GB_MESH_EVENT_EDGE_SPLIT); // make a edge gb_mesh_edge_ref_t edge1 = gb_mesh_edge_make(mesh); if (edge1) { // the face gb_mesh_face_ref_t face = gb_mesh_edge_lface(edge1); tb_assert_abort(face == gb_mesh_edge_rface(edge1)); // save face name gb_mesh_face_data_set(mesh, face, "face"); /* make a radiation * * v4 * / \ * | * | * | e4 * | * | * | * <---------------- v0 ----------------> * v1 e1 | e3 v3 * | * | * | e2 * | * | * \ / * v2 */ gb_mesh_edge_ref_t edge2 = gb_mesh_edge_append(mesh, gb_mesh_edge_sym(edge1)); gb_mesh_edge_ref_t edge3 = gb_mesh_edge_append(mesh, gb_mesh_edge_sym(edge1)); gb_mesh_edge_ref_t edge4 = gb_mesh_edge_append(mesh, gb_mesh_edge_sym(edge1)); // save edge name gb_mesh_edge_data_set(mesh, edge1, "e1"); gb_mesh_edge_data_set(mesh, edge2, "e2"); gb_mesh_edge_data_set(mesh, edge3, "e3"); gb_mesh_edge_data_set(mesh, edge4, "e4"); // save vertex name gb_mesh_vertex_data_set(mesh, gb_mesh_edge_org(edge1), "v0"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge1), "v1"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge2), "v2"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge3), "v3"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge4), "v4"); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("radiation: make"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif /* remove one * * v4 * / \ * | * | * | e4 * | * | * | * v0 ----------------> * | e3 v3 * | * | * | e2 * | * | * \ / * v2 */ gb_mesh_edge_remove(mesh, edge1); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("radiation: kill"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif // remove all gb_mesh_edge_remove(mesh, edge2); gb_mesh_edge_remove(mesh, edge3); gb_mesh_edge_remove(mesh, edge4); // check tb_assert_abort(gb_mesh_is_empty(mesh)); } // exit mesh gb_mesh_exit(mesh); } }
static tb_void_t gb_demo_utils_mesh_splice() { // trace tb_trace_i("=========================================================================="); // init mesh gb_mesh_ref_t mesh = gb_mesh_init(tb_element_str(tb_true), tb_element_str(tb_true), tb_element_str(tb_true)); if (mesh) { // init listener gb_mesh_listener_set(mesh, gb_demo_utils_mesh_listener, mesh); gb_mesh_listener_event_add(mesh, GB_MESH_EVENT_FACE_MERGE | GB_MESH_EVENT_FACE_SPLIT | GB_MESH_EVENT_EDGE_MERGE | GB_MESH_EVENT_EDGE_SPLIT); /* make a edge * * lface * * O -----> D * * lface */ gb_mesh_edge_ref_t edge = gb_mesh_edge_make(mesh); if (edge) { // save face name gb_mesh_face_data_set(mesh, gb_mesh_edge_lface(edge), "lface"); // save vertex name gb_mesh_vertex_data_set(mesh, gb_mesh_edge_org(edge), "org"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge), "dst"); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("splice: make"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif /* splice * * ------- * | | * | rface | * | | * O/D <--- * * lface * */ gb_mesh_edge_splice(mesh, edge, gb_mesh_edge_sym(edge)); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("splice: done"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif /* splice * * lface * * O -----> D * * lface * */ gb_mesh_edge_splice(mesh, edge, gb_mesh_edge_sym(edge)); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("splice: done"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif } // exit mesh gb_mesh_exit(mesh); } }