/** * 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; }
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; }
P2trCDT* p2tr_cdt_new (P2tCDT *cdt) { P2tTrianglePtrArray cdt_tris = p2t_cdt_get_triangles (cdt); GHashTable *point_map = g_hash_table_new (g_direct_hash, g_direct_equal); P2trCDT *rmesh = g_slice_new (P2trCDT); gint i, j; rmesh->mesh = p2tr_mesh_new (); rmesh->outline = p2tr_pslg_new (); /* First iteration over the CDT - create all the points */ for (i = 0; i < cdt_tris->len; i++) { P2tTriangle *cdt_tri = triangle_index (cdt_tris, i); for (j = 0; j < 3; j++) { P2tPoint *cdt_pt = p2t_triangle_get_point(cdt_tri, j); P2trPoint *new_pt = g_hash_table_lookup (point_map, cdt_pt); if (new_pt == NULL) { new_pt = p2tr_point_new2 (cdt_pt->x, cdt_pt->y); g_hash_table_insert (point_map, cdt_pt, new_pt); } } } /* Second iteration over the CDT - create all the edges and find the * outline */ for (i = 0; i < cdt_tris->len; i++) { P2tTriangle *cdt_tri = triangle_index (cdt_tris, i); for (j = 0; j < 3; j++) { P2tPoint *start = p2t_triangle_get_point (cdt_tri, j); P2tPoint *end = p2t_triangle_get_point (cdt_tri, (j + 1) % 3); int edge_index = p2t_triangle_edge_index (cdt_tri, start, end); P2trPoint *start_new = g_hash_table_lookup (point_map, start); P2trPoint *end_new = g_hash_table_lookup (point_map, end); if (! p2tr_point_has_edge_to (start_new, end_new)) { gboolean constrained = cdt_tri->constrained_edge[edge_index]; P2trEdge *edge = p2tr_mesh_new_edge (rmesh->mesh, start_new, end_new, constrained); /* If the edge is constrained, we should add it to the * outline */ if (constrained) p2tr_pslg_add_new_line(rmesh->outline, &start_new->c, &end_new->c); /* We only wanted to create the edge now. We will use it * later */ p2tr_edge_unref (edge); } } } /* Third iteration over the CDT - create all the triangles */ for (i = 0; i < cdt_tris->len; i++) { P2tTriangle *cdt_tri = triangle_index (cdt_tris, i); P2trPoint *pt1 = g_hash_table_lookup (point_map, p2t_triangle_get_point (cdt_tri, 0)); P2trPoint *pt2 = g_hash_table_lookup (point_map, p2t_triangle_get_point (cdt_tri, 1)); P2trPoint *pt3 = g_hash_table_lookup (point_map, p2t_triangle_get_point (cdt_tri, 2)); P2trTriangle *new_tri = p2tr_mesh_new_triangle (rmesh->mesh, p2tr_point_get_edge_to(pt1, pt2), p2tr_point_get_edge_to(pt2, pt3), p2tr_point_get_edge_to(pt3, pt1)); /* We won't do any usage of the triangle, so just unref it */ p2tr_triangle_unref (new_tri); } return rmesh; }
P2trCDT* p2tr_cdt_new (P2tCDT *cdt) { P2tTrianglePtrArray cdt_tris = p2t_cdt_get_triangles (cdt); GHashTable *point_map = g_hash_table_new (g_direct_hash, g_direct_equal); P2trCDT *rmesh = g_slice_new (P2trCDT); GHashTableIter iter; P2trPoint *pt_iter = NULL; P2trVEdgeSet *new_edges = p2tr_vedge_set_new (); guint i, j; rmesh->mesh = p2tr_mesh_new (); rmesh->outline = p2tr_pslg_new (); /* First iteration over the CDT - create all the points */ for (i = 0; i < cdt_tris->len; i++) { P2tTriangle *cdt_tri = triangle_index (cdt_tris, i); for (j = 0; j < 3; j++) { P2tPoint *cdt_pt = p2t_triangle_get_point(cdt_tri, j); P2trPoint *new_pt = (P2trPoint*) g_hash_table_lookup (point_map, cdt_pt); if (new_pt == NULL) { new_pt = p2tr_mesh_new_point2 (rmesh->mesh, cdt_pt->x, cdt_pt->y); g_hash_table_insert (point_map, cdt_pt, new_pt); } } } /* Second iteration over the CDT - create all the edges and find the * outline */ for (i = 0; i < cdt_tris->len; i++) { P2tTriangle *cdt_tri = triangle_index (cdt_tris, i); for (j = 0; j < 3; j++) { P2tPoint *start = p2t_triangle_get_point (cdt_tri, j); P2tPoint *end = p2t_triangle_get_point (cdt_tri, (j + 1) % 3); int edge_index = p2t_triangle_edge_index (cdt_tri, start, end); P2trPoint *start_new = (P2trPoint*) g_hash_table_lookup (point_map, start); P2trPoint *end_new = (P2trPoint*) g_hash_table_lookup (point_map, end); if (! p2tr_point_has_edge_to (start_new, end_new)) { gboolean constrained = cdt_tri->constrained_edge[edge_index] || cdt_tri->neighbors_[edge_index] == NULL; P2trEdge *edge = p2tr_mesh_new_edge (rmesh->mesh, start_new, end_new, constrained); /* If the edge is constrained, we should add it to the * outline */ if (constrained) p2tr_pslg_add_new_line(rmesh->outline, &start_new->c, &end_new->c); /* We only wanted to create the edge now. We will use it * later */ p2tr_vedge_set_add (new_edges, edge); } } } /* Third iteration over the CDT - create all the triangles */ for (i = 0; i < cdt_tris->len; i++) { P2tTriangle *cdt_tri = triangle_index (cdt_tris, i); P2trPoint *pt1 = (P2trPoint*) g_hash_table_lookup (point_map, p2t_triangle_get_point (cdt_tri, 0)); P2trPoint *pt2 = (P2trPoint*) g_hash_table_lookup (point_map, p2t_triangle_get_point (cdt_tri, 1)); P2trPoint *pt3 = (P2trPoint*) g_hash_table_lookup (point_map, p2t_triangle_get_point (cdt_tri, 2)); P2trTriangle *new_tri = p2tr_mesh_new_triangle (rmesh->mesh, p2tr_point_get_edge_to(pt1, pt2, FALSE), p2tr_point_get_edge_to(pt2, pt3, FALSE), p2tr_point_get_edge_to(pt3, pt1, FALSE)); /* We won't do any usage of the triangle, so just unref it */ p2tr_triangle_unref (new_tri); } /* And do an extra flip fix */ p2tr_cdt_flip_fix (rmesh, new_edges); p2tr_vedge_set_free (new_edges); /* Now finally unref the points we added into the map */ g_hash_table_iter_init (&iter, point_map); while (g_hash_table_iter_next (&iter, NULL, (gpointer*)&pt_iter)) p2tr_point_unref (pt_iter); g_hash_table_destroy (point_map); return rmesh; }
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; }