/* Last edited on 2025-05-07 17:32:37 by stolfi */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define debug TRUE hedge_t *toposlice_holes_fig_create_mesh_orig(bool_t ghosts, uint32_t *kf_ini_P, uint32_t *kf_fin_P); /* Creates the half-edge mesh structure with the original (undivided) main face, the one to display. The mesh includes some ghost sides and corners; they are visible ({.show = TRUE}) iff {ghosts} is true. The procedure returns in {*kf_ini_P} and {*kf_fin_P} the index (ID) of the main face. */ hedge_t *toposlice_holes_fig_create_mesh_mono(uint32_t *kf_ini_P, uint32_t *kf_fin_P); /* Creates the half-edge mesh structure for the original main face decomposed into monotone parts. The procedure returns in {*kf_ini_P} and {*kf_fin_P} the indices (IDs) of the first and last face in the monotone decompositions of the original main face. */ void toposlice_holes_fig_define_common_vertices(hedge_t *H); /* Appends to the vertex list of {H} the vertices of the complex face, excluding the ghost corners. All vertices are marked visible ({v.show = TRUE}). */ void toposlice_holes_fig_define_holes(hedge_t *H); /* Defines all the non-ghost edges, and all faces except the main one. The {.next} and {.left} pointers of the main face (or its parts) are set to {NULL} and should be properly set afterwards. */ void toposlice_holes_fig_paint_faces(epswr_figure_t *eps, hedge_t *H, uint32_t kf_ini, uint32_t kf_fin); /* Paints the faces {H->F[kf_ini..kf_fin] with various colors. */ void toposlice_holes_fig_draw_labels(epswr_figure_t *eps, hedge_t *H, bool_t pinches, bool_t ghosts); /* Labels selected edges and vertices of {H}. If {pinches} is true, labels the pinch vertices. If {ghosts} is true, assumes that face {f07} of {H} is the original (undivided) face with ghost vertices {v27,v28} and ghost edges {e30,e31,e32,e33,e34}, and labels them. */ void toposlice_holes_fig_draw_arrows(epswr_figure_t *eps, hedge_t *H); /* Draw arrowheads on the border arcs of face {f07} (including ghost ones). */ void toposlice_holes_fig_draw_arrows_labels(epswr_figure_t *eps, hedge_t *H); #define sex hedge_set_next void toposlice_holes_fig_make(char *name, int32_t phase) { if (debug) { fprintf(stderr, " > enter %s (phase = %d)...\n", __FUNCTION__, phase); } /* Create the half-edge structure {H}: */ hedge_t *H = NULL; uint32_t kf_ini, kf_fin; if ((phase == 0) || (phase == 1)) { bool_t ghosts = (phase == 1); H = toposlice_holes_fig_create_mesh_orig(ghosts, &kf_ini, &kf_fin); } else { H = toposlice_holes_fig_create_mesh_mono(&kf_ini, &kf_fin); } double dunit = H->dunit; /* Get the figure's bounds and create the EPS file {eps}: */ double xmin, xmax, ymin, ymax; /* Figure range in mm. */ hedge_draw_get_plot_bounds(H, &xmin, &xmax, &ymin, &ymax); double hsz = (xmax - xmin)*epswr_pt_per_mm; double vsz = (ymax - ymin)*epswr_pt_per_mm; double mrg = 2*epswr_pt_per_mm; epswr_figure_t *eps = epswr_new_named_figure ( "out", NULL, name, -1, NULL, hsz,vsz, mrg,mrg,mrg,mrg, TRUE ); epswr_set_client_window(eps, xmin, xmax, ymin, ymax); epswr_set_label_font(eps, "Times-Italic", 80); /* Paint the non-hole faces: */ toposlice_holes_fig_paint_faces(eps, H, kf_ini, kf_fin); /* Draw the edges: */ epswr_set_pen_color(eps, 0,0,0); epswr_set_pen_width(eps, 0.75*dunit); epswr_set_pen_dashing(eps, 0,0); epswr_set_fill_color(eps, 0,0,0); bool_t show_ghosts = (phase == 1); hedge_draw_mesh(eps, H, show_ghosts); if (phase == 1) { /* Draw arros on arcs around the main face, an labels on important edges: */ toposlice_holes_fig_draw_arrows(eps, H); } if ((phase == 0) || (phase == 1)) { bool_t label_pinches = (phase == 0); bool_t label_ghosts = (phase == 1); toposlice_holes_fig_draw_labels(eps, H, label_pinches, label_ghosts); } /* Vertex numbers for debugging: */ bool_t evnums = FALSE; /* Should we show the edge and vertex numbers? */ if (evnums) { double etim = 0.50; hedge_draw_vert_ids(eps, H, 3*dunit); hedge_draw_edge_ids(eps, H, etim, 4.00*dunit, 8.00*dunit, 5.00*dunit); } /* epswr_set_fill_color(eps, 0,0,0); */ /* hedge_draw_face_label(eps, f00, "e.left", 0.5,0.5, -0.5*dlab, +0.4*dlab); */ epswr_end_figure(eps); if (debug) { fprintf(stderr, " < exit %s...\n", __FUNCTION__); } } void toposlice_holes_fig_paint_faces(epswr_figure_t *eps, hedge_t *H, uint32_t kf_ini, uint32_t kf_fin) { int32_t nf = (int32_t)(kf_fin + 1 - kf_ini); if (nf == 1) { /* Paint face {fp[0]} in gray: */ epswr_set_fill_color(eps, 0.900,0.900,0.900); hedge_fill_face(eps, H->F.e[kf_ini]); } else if (nf >= 2) { /* Paint the monotone parts of original face {f00} in gray: */ for (uint32_t kf = 0; kf < nf; kf++) { uint32_t dkf = (kf % 3); double R = 0.850; double G = 0.850 + dkf*0.050; double B = 0.950 - dkf*0.050; epswr_set_fill_color(eps, R, G, B); hedge_fill_face(eps, H->F.e[kf_ini + kf]); } } } void toposlice_holes_fig_define_common_vertices(hedge_t *H) { (void)hedge_add_vert(H, 100, 400, 0, TRUE); /* v00 */ (void)hedge_add_vert(H, 200, 430, 0, TRUE); /* v01 */ (void)hedge_add_vert(H, 200, 370, 0, TRUE); /* v02 */ (void)hedge_add_vert(H, 280, 260, 0, TRUE); /* v03 */ (void)hedge_add_vert(H, 280, 180, 0, TRUE); /* v04 */ (void)hedge_add_vert(H, 180, 180, 0, TRUE); /* v05 */ (void)hedge_add_vert(H, 180, 260, 0, TRUE); /* v06 */ (void)hedge_add_vert(H, 250, 430, 0, TRUE); /* v07 */ (void)hedge_add_vert(H, 250, 370, 0, TRUE); /* v08 */ (void)hedge_add_vert(H, 280, 540, 0, TRUE); /* v09 */ (void)hedge_add_vert(H, 180, 540, 0, TRUE); /* v10 */ (void)hedge_add_vert(H, 180, 620, 0, TRUE); /* v11 */ (void)hedge_add_vert(H, 280, 620, 0, TRUE); /* v12 */ (void)hedge_add_vert(H, 350, 485, 0, TRUE); /* v13 */ (void)hedge_add_vert(H, 350, 650, 0, TRUE); /* v14 */ (void)hedge_add_vert(H, 150, 650, 0, TRUE); /* v15 */ (void)hedge_add_vert(H, 100, 550, 0, TRUE); /* v16 */ (void)hedge_add_vert(H, 100, 250, 0, TRUE); /* v17 */ (void)hedge_add_vert(H, 150, 150, 0, TRUE); /* v18 */ (void)hedge_add_vert(H, 350, 150, 0, TRUE); /* v19 */ (void)hedge_add_vert(H, 350, 315, 0, TRUE); /* v20 */ (void)hedge_add_vert(H, 320, 430, 0, TRUE); /* v21 */ (void)hedge_add_vert(H, 320, 370, 0, TRUE); /* v22 */ (void)hedge_add_vert(H, 230, 220, 0, TRUE); /* v23 */ (void)hedge_add_vert(H, 230, 580, 0, TRUE); /* v24 */ (void)hedge_add_vert(H, 140, 430, 0, TRUE); /* v25 */ (void)hedge_add_vert(H, 140, 370, 0, TRUE); /* v26 */ assert(H->nv-1 == 26); } void toposlice_holes_fig_define_holes(hedge_t *H) { hedge_arc_t **a = H->A.e; hedge_vert_t **v = H->V.e; hedge_face_t **f = H->F.e; (void)hedge_add_edge(H, v24, v09, 0); /* e00 */ (void)hedge_add_edge(H, v24, v11, 0); /* e01 */ (void)hedge_add_edge(H, v03, v23, 0); /* e02 */ (void)hedge_add_edge(H, v04, v05, 0); /* e03 */ (void)hedge_add_edge(H, v05, v23, 0); /* e04 */ (void)hedge_add_edge(H, v06, v03, 0); /* e05 */ (void)hedge_add_edge(H, v21, v22, 0); /* e06 */ (void)hedge_add_edge(H, v09, v10, 0); /* e07 */ (void)hedge_add_edge(H, v10, v24, 0); /* e08 */ (void)hedge_add_edge(H, v11, v12, 0); /* e09 */ (void)hedge_add_edge(H, v12, v24, 0); /* e10 */ (void)hedge_add_edge(H, v20, v13, 0); /* e11 */ (void)hedge_add_edge(H, v13, v14, 0); /* e12 */ (void)hedge_add_edge(H, v14, v15, 0); /* e13 */ (void)hedge_add_edge(H, v15, v16, 0); /* e14 */ (void)hedge_add_edge(H, v16, v00, 0); /* e15 */ (void)hedge_add_edge(H, v00, v17, 0); /* e16 */ (void)hedge_add_edge(H, v17, v18, 0); /* e17 */ (void)hedge_add_edge(H, v18, v19, 0); /* e18 */ (void)hedge_add_edge(H, v19, v20, 0); /* e19 */ (void)hedge_add_edge(H, v25, v01, 0); /* e20 */ (void)hedge_add_edge(H, v02, v26, 0); /* e21 */ (void)hedge_add_edge(H, v07, v21, 0); /* e22 */ (void)hedge_add_edge(H, v08, v07, 0); /* e23 */ (void)hedge_add_edge(H, v01, v02, 0); /* e24 */ (void)hedge_add_edge(H, v23, v04, 0); /* e25 */ (void)hedge_add_edge(H, v23, v06, 0); /* e26 */ (void)hedge_add_edge(H, v22, v08, 0); /* e27 */ (void)hedge_add_edge(H, v00, v25, 0); /* e28 */ (void)hedge_add_edge(H, v26, v00, 0); /* e29 */ assert(H->na/2-1 == 29); /* f00 Outer face. */ sex( e11->twin, e19->twin); sex( e19->twin, e18->twin); sex( e18->twin, e17->twin); sex( e17->twin, e16->twin); sex( e16->twin, e15->twin); sex( e15->twin, e14->twin); sex( e14->twin, e13->twin); sex( e13->twin, e12->twin); sex( e12->twin, e11->twin); (void)hedge_add_face(H, 340, 400, 0, FALSE, e11->twin); assert(H->nf-1 == f00->id); /* f01 Left proximal wing hole */ sex( e02->twin, e05->twin ); sex( e05->twin, e26->twin ); sex( e26->twin, e02->twin ); (void)hedge_add_face(H, 250, 230, 0, FALSE, e02->twin); assert(H->nf-1 == f01->id); /* f02 Right proximal wing hole. */ sex( e00->twin, e08->twin ); sex( e08->twin, e07->twin ); sex( e07->twin, e00->twin ); (void)hedge_add_face(H, 250, 570, 0, FALSE, e00->twin); assert(H->nf-1 == f02->id); /* f03 Pentagonal hole. */ sex( e24->twin, e20->twin ); sex( e20->twin, e28->twin ); sex( e28->twin, e29->twin ); sex( e29->twin, e21->twin ); sex( e21->twin, e24->twin ); (void)hedge_add_face(H, 200, 400, 0, FALSE, e24->twin); assert(H->nf-1 == f03->id); /* f04 Central square hole. */ sex( e22->twin, e23->twin ); sex( e23->twin, e27->twin ); sex( e27->twin, e06->twin ); sex( e06->twin, e22->twin ); (void)hedge_add_face(H, 130, 400, 0, FALSE, e22->twin); assert(H->nf-1 == f04->id); /* f05 Left distal wing hole */ sex( e03->twin, e25->twin ); sex( e25->twin, e04->twin ); sex( e04->twin, e03->twin ); (void)hedge_add_face(H, 250, 370, 0, FALSE, e03->twin); assert(H->nf-1 == f05->id); /* f06 Right distal wing hole */ sex( e10->twin, e09->twin ); sex( e09->twin, e01->twin ); sex( e01->twin, e10->twin ); (void)hedge_add_face(H, 250, 630, 0, FALSE, e10->twin); assert(H->nf-1 == f06->id); } hedge_t *toposlice_holes_fig_create_mesh_orig(bool_t ghosts, uint32_t *kf_ini_P, uint32_t *kf_fin_P) { if (debug) { fprintf(stderr, " > enter %s...\n", __FUNCTION__); } hedge_t *H = hedge_new(100, 100, 100); H->dunit = 2.0; hedge_arc_t **a = H->A.e; hedge_vert_t **v = H->V.e; hedge_face_t **f = H->F.e; /* Vertices: */ toposlice_holes_fig_define_common_vertices(H); assert(H->nv-1 == 26); /* Additional vertices: ghost corners: */ (void)hedge_add_vert(H, 190, 315, 0, ghosts); /* v27 */ (void)hedge_add_vert(H, 220, 485, 0, ghosts); /* v28 */ assert(H->nv-1 == 28); /* Edges: */ toposlice_holes_fig_define_holes(H); assert(H->na/2-1 == 29); assert(H->nf-1 == 6); /* Additional edges: ghost sides: */ (void)hedge_add_edge(H, v27, v06, 0); /* e30 */ (void)hedge_add_edge(H, v27, v08, 0); /* e31 */ (void)hedge_add_edge(H, v20, v27, 0); /* e32 */ (void)hedge_add_edge(H, v13, v28, 0); /* e33 */ (void)hedge_add_edge(H, v10, v25, 0); /* e34 */ assert(H->na/2-1 == 34); /* f07 - main face, undivided */ sex( e11, e33 ); sex( e33, e33->twin ); sex( e33->twin, e12 ); sex( e12, e13 ); sex( e13, e14 ); sex( e14, e15 ); sex( e15, e28 ); sex( e28, e34->twin ); sex( e34->twin, e08 ); sex( e08, e01 ); sex( e01, e09 ); sex( e09, e10 ); sex( e10, e00 ); sex( e00, e07 ); sex( e07, e34 ); sex( e34, e20 ); sex( e20, e24 ); sex( e24, e21 ); sex( e21, e29 ); sex( e29, e16 ); sex( e16, e17 ); sex( e17, e18 ); sex( e18, e19 ); sex( e19, e32 ); sex( e32, e30 ); sex( e30, e05 ); sex( e05, e02 ); sex( e02, e25 ); sex( e25, e03 ); sex( e03, e04 ); sex( e04, e26 ); sex( e26, e30->twin ); sex( e30->twin, e31 ); sex( e31, e23 ); sex( e23, e22 ); sex( e22, e06 ); sex( e06, e27 ); sex( e27, e31->twin ); sex( e31->twin, e32->twin ); sex( e32->twin, e11 ); (void)hedge_add_face(H, 200, 400, 0, TRUE, e11); assert(H->nf-1 == f07->id); hedge_check_topology(H); (*kf_ini_P) = f07->id; (*kf_fin_P) = f07->id; if (debug) { fprintf(stderr, " < exit %s...\n", __FUNCTION__); } return H; } hedge_t *toposlice_holes_fig_create_mesh_mono(uint32_t *kf_ini_P, uint32_t *kf_fin_P) { if (debug) { fprintf(stderr, " > enter %s...\n", __FUNCTION__); } hedge_t *H = hedge_new(100, 100, 100); H->dunit = 2.0; hedge_arc_t **a = H->A.e; hedge_vert_t **v = H->V.e; hedge_face_t **f = H->F.e; /* Vertices: */ toposlice_holes_fig_define_common_vertices(H); assert(H->nv-1 == 26); /* Edges: */ toposlice_holes_fig_define_holes(H); assert(H->na/2-1 == 29); assert(H->nf-1 == 6); /* Additional edges: partiotioning diagonals: */ (void)hedge_add_edge(H, v19, v04, 0); /* e30 */ (void)hedge_add_edge(H, v06, v02, 0); /* e31 */ (void)hedge_add_edge(H, v03, v22, 0); /* e32 */ (void)hedge_add_edge(H, v01, v10, 0); /* e33 */ (void)hedge_add_edge(H, v07, v09, 0); /* e34 */ (void)hedge_add_edge(H, v12, v14, 0); /* e35 */ assert(H->na/2-1 == 35); /* f07 - lower left mono piece */ sex( e30, e03 ); sex( e03, e04 ); sex( e04, e26 ); sex( e26, e31 ); sex( e31, e21 ); sex( e21, e29 ); sex( e29, e16 ); sex( e16, e17 ); sex( e17, e18 ); sex( e18, e30 ); (void)hedge_add_face(H, 200, 400, 0, TRUE, e30); assert(H->nf-1 == f07->id); /* f08 - central mono piece */ sex( e32, e27 ); sex( e27, e23 ); sex( e23, e34 ); sex( e34, e07 ); sex( e07, e33->twin ); sex( e33->twin, e24 ); sex( e24, e31->twin ); sex( e31->twin, e05 ); sex( e05, e32 ); (void)hedge_add_face(H, 200, 400, 0, TRUE, e32); assert(H->nf-1 == f08->id); /* f09 - upper left mono piece */ sex( e33, e08 ); sex( e08, e01 ); sex( e01, e09 ); sex( e09, e35 ); sex( e35, e13 ); sex( e13, e14 ); sex( e14, e15 ); sex( e15, e28 ); sex( e28, e20 ); sex( e20, e33 ); (void)hedge_add_face(H, 200, 400, 0, TRUE, e33); assert(H->nf-1 == f09->id); /* f10 - right side mono piece */ sex( e19, e11 ); sex( e11, e12 ); sex( e12, e35->twin ); sex( e35->twin, e10 ); sex( e10, e00 ); sex( e00, e34->twin ); sex( e34->twin, e22 ); sex( e22, e06 ); sex( e06, e32->twin ); sex( e32->twin, e02 ); sex( e02, e25 ); sex( e25, e30->twin ); sex( e30->twin, e19 ); (void)hedge_add_face(H, 200, 400, 0, TRUE, e19); assert(H->nf-1 == f10->id); hedge_check_topology(H); (*kf_ini_P) = f07->id; (*kf_fin_P) = f10->id; if (debug) { fprintf(stderr, " < exit %s...\n", __FUNCTION__); } return H; } void toposlice_holes_fig_draw_arrows(epswr_figure_t *eps, hedge_t *H) { hedge_arc_t **a = H->A.e; double dunit = H->dunit; double etim = 0.35; /* Relative position of arrowhead tip along edge. */ epswr_set_fill_color(eps, 0,0,0); epswr_set_pen_width(eps, 0.75*dunit); hedge_arc_t *a0 = e11; hedge_arc_t *ai = a0; do { hedge_draw_arc_arrowhead(eps, ai, etim, 0.9*dunit); ai = ai->next; } while (ai != a0); } void toposlice_holes_fig_draw_labels(epswr_figure_t *eps, hedge_t *H, bool_t pinches, bool_t ghosts) { hedge_arc_t **a = H->A.e; hedge_vert_t **v = H->V.e; double dunit = H->dunit; double etim = 0.35; /* Relative position of arrowhead tip along edge. */ epswr_set_fill_color(eps, 0,0,0); epswr_set_pen_width(eps, 0.75*dunit); auto void elab(hedge_arc_t *e, char *lab, double hAlign, double vAlign, double du, double dv); /* Draw label {lab} near the arc {e} with label position parameters {hAlign,vAlign,du,dv}. */ auto void vlab(hedge_vert_t *u, char *lab, double hAlign, double vAlign, double du, double dv); /* Draw label {lab} near the vertex {u} with label position parameters {hAlign,vAlign,du,dv}. */ epswr_set_fill_color(eps, 0,0,0); epswr_set_pen_width(eps, 0.75*dunit); if (pinches) { vlab(v23, "r", 0.5,0.0, 00.0, +2.0); vlab(v24, "s", 0.5,1.0, 00.0, -2.0); vlab(v00, "t", 0.0,0.5, +5.0, 00.0); } if (ghosts) { /* Label ghost edges, in order along border of face {f07}: */ elab(e32, "a", 1.0,0.5, -1.0, +3.0); elab(e30, "b", 0.0,1.0, -2.0, +1.5); elab(e31, "c", 1.0,0.0, -1.5, +1.0); elab(e33, "d", 1.0,1.0, -1.0, +2.5); elab(e34->twin, "e", 1.0,0.0, -2.0, +1.5); /* Label ghost vertices: */ vlab(v27, "p", 1.0,0.0, -2.0, -1.5); vlab(v28, "q", 1.0,0.0, -2.0, -1.0); } void elab ( hedge_arc_t *e, char *lab, double hAlign, double vAlign, double du, double dv ) { assert(lab != NULL); double dlab = 4.0; /* Displacement from point on arc and label ref point. */ hedge_draw_arc_label(eps, e, etim, lab, hAlign,vAlign, du*dlab,dv*dlab); } void vlab ( hedge_vert_t *u, char *lab, double hAlign, double vAlign, double du, double dv ) { assert(lab != NULL); double dlab = 2*dunit; /* Unit of displacement from vertex and label ref point. */ hedge_draw_vert_label(eps, u, lab, hAlign,vAlign, du*dlab,dv*dlab); } }