/** * Check if a point is "visible" from any one or more of the edges in a * given group. * Formally: Check if there is a line from @ref P to any of the edges in * @ref Edges so that the line does not cross any of the lines of the * PSLG @ref PSLG */ static gboolean IsVisibleFromEdges (P2trPSLG *PSLG, P2trVector2 *P, P2trPSLG *Edges) { gboolean found_visibility_path = FALSE; P2trPSLG *KnownBlocks = p2tr_pslg_new (); GQueue *BlocksForTest = g_queue_new (); P2trVector2 W; find_point_in_polygon (Edges, &W); if (TryVisibilityAroundBlock(PSLG, P, Edges, KnownBlocks, BlocksForTest, NULL, &W)) found_visibility_path = TRUE; while (! g_queue_is_empty (BlocksForTest) && ! found_visibility_path) { const P2trBoundedLine *Block = (P2trBoundedLine*)g_queue_pop_head (BlocksForTest); if (p2tr_pslg_contains_line (KnownBlocks, Block)) continue; else if (TryVisibilityAroundBlock(PSLG, P, Edges, KnownBlocks, BlocksForTest, Block, &Block->start) || TryVisibilityAroundBlock(PSLG, P, Edges, KnownBlocks, BlocksForTest, Block, &Block->end)) { found_visibility_path = TRUE; } else p2tr_pslg_add_existing_line (KnownBlocks, Block); } p2tr_pslg_free (KnownBlocks); g_queue_free (BlocksForTest); return found_visibility_path; }
void p2tr_cdt_free_full (P2trCDT* self, gboolean clear_mesh) { p2tr_pslg_free (self->outline); if (clear_mesh) p2tr_mesh_clear (self->mesh); p2tr_mesh_unref (self->mesh); g_slice_free (P2trCDT, self); }
gboolean p2tr_visibility_is_visible_from_edges (P2trPSLG *pslg, P2trVector2 *p, const P2trBoundedLine *lines, guint line_count) { P2trPSLG *edges = p2tr_pslg_new (); gint i; gboolean result; for (i = 0; i < line_count; i++) p2tr_pslg_add_existing_line (edges, &lines[i]); result = IsVisibleFromEdges (pslg, p, edges); p2tr_pslg_free (edges); return result; }
gboolean p2tr_pslg_visibility_check (P2trPSLG *pslg, P2trVector2 *point, P2trPSLG *polygon) { P2trPSLG *known_blocks; GArray *second_points; gboolean found_visibility_path = FALSE; /* W <- Some point in T (for example, center of weight) */ P2trVector2 W; find_point_in_polygon (polygon, &W); /* KnownBlocks <- {} */ known_blocks = p2tr_pslg_new (); /* SecondPoint <- {W} */ second_points = g_array_new (FALSE, FALSE, sizeof(P2trVector2)); g_array_append_val (second_points, W); while ((! found_visibility_path) && second_points->len > 0) { P2trVector2 S; P2trBoundedLine PS; P2trVector2 poly_intersection; /* S <- Some point from SecondPoint */ p2tr_vector2_copy (&S, &g_array_index(second_points, P2trVector2, 0)); /* SecondPoint <- SecondPoint \ {S} */ g_array_remove_index_fast (second_points, 0); /* PS <- The infinite line going through P and S */ p2tr_bounded_line_init (&PS, &S, point); /* IF PS intersects @Poly */ if (find_closest_intersection (polygon, &PS.infinite, point, &poly_intersection)) { P2trBoundedLine PS_exact, *B; /* IF there is an edge B=(u,v) (from E) that intersects PS */ p2tr_bounded_line_init (&PS_exact, point, &poly_intersection); B = pslg_line_intersection (pslg, &PS_exact); if (B != NULL) { /* IF B is not in KnownBlocks: */ if (! p2tr_pslg_contains_line (known_blocks, B)) { /* SecondPoint <- SecondPoint + {u,v} */ g_array_append_val (second_points, B->start); g_array_append_val (second_points, B->end); /* KnownBlocks <- KnownBlocks + {B} */ p2tr_pslg_add_existing_line (known_blocks, B); } } else { found_visibility_path = TRUE; } } } g_array_free (second_points, TRUE); p2tr_pslg_free (known_blocks); return found_visibility_path; }