static gboolean TryVisibilityAroundBlock(P2trPSLG *PSLG, P2trVector2 *P, P2trPSLG *ToSee, P2trPSLG *KnownBlocks, GQueue *BlocksForTest, /* Try on the edges of this block */ const P2trBoundedLine *BlockBeingTested, const P2trVector2 *SideOfBlock) { const P2trVector2 *S = SideOfBlock; P2trVector2 ClosestIntersection; P2trBoundedLine PS; p2tr_bounded_line_init (&PS, P, S); if (find_closest_intersection (ToSee, &PS.infinite, P, &ClosestIntersection)) { P2trPSLGIter iter; P2trBoundedLine PK; const P2trBoundedLine *Segment = NULL; p2tr_bounded_line_init (&PK, P, &ClosestIntersection); /* Now we must make sure that the bounded line PK is inside * the polygon, because otherwise it is not considered as a * valid visibility path */ p2tr_pslg_iter_init (&iter, PSLG); while (p2tr_pslg_iter_next (&iter, &Segment)) { if (Segment == BlockBeingTested) continue; /* If we have two segments with a shared point, * the point should not be blocked by any of them */ if (p2tr_vector2_is_same (SideOfBlock, &(Segment->start)) || p2tr_vector2_is_same (SideOfBlock, &(Segment->end))) continue; if (p2tr_bounded_line_intersect (Segment, &PK)) { if (g_queue_find (BlocksForTest, Segment)) { g_queue_push_tail (BlocksForTest, (P2trBoundedLine*)Segment); } /* obstruction found! */ return FALSE; } } if (LineIsOutsidePolygon (&PK, PSLG)) return FALSE; /* No obstruction! */ return TRUE; } /* No intersection for this attempt, continue */ return FALSE; }
gboolean p2tr_cdt_visible_from_edge (P2trCDT *self, P2trEdge *e, P2trVector2 *p) { P2trBoundedLine line; p2tr_bounded_line_init (&line, &P2TR_EDGE_START(e)->c, &e->end->c); return p2tr_visibility_is_visible_from_edges (self->outline, p, &line, 1); }
static gboolean p2tr_cdt_visible_from_tri (P2trCDT *self, P2trTriangle *tri, P2trVector2 *p) { P2trBoundedLine lines[3]; gint i; for (i = 0; i < 3; i++) p2tr_bounded_line_init (&lines[i], &P2TR_EDGE_START(tri->edges[i])->c, &tri->edges[i]->end->c); return p2tr_visibility_is_visible_from_edges (self->outline, p, lines, 3); }
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; }