Beispiel #1
0
void
p2tr_cdt_validate_edges (P2trCDT *self)
{
    P2trHashSetIter iter;
    P2trEdge *e;

    p2tr_hash_set_iter_init (&iter, self->mesh->edges);
    while (p2tr_hash_set_iter_next (&iter, (gpointer*)&e))
    {
        if (! e->constrained && e->tri == NULL)
            p2tr_exception_geometric ("Found a non constrained edge without a triangle");

        if (e->tri != NULL)
        {
            gboolean found = FALSE;
            gint i = 0;

            for (i = 0; i < 3; i++)
                if (e->tri->edges[i] == e)
                {
                    found = TRUE;
                    break;
                }

            if (! found)
                p2tr_exception_geometric ("An edge has a triangle to which it does not belong!");
        }
    }
}
Beispiel #2
0
/**
 * Insert a point so that is splits an existing edge. This function
 * assumes that the point is on the edge itself and between its
 * end-points.
 * If the edge being split is constrained, then the function returns a
 * list containing both parts resulted from the splitting. In that case,
 * THE RETURNED EDGES MUST BE UNREFERENCED!
 */
GList*
p2tr_cdt_split_edge (P2trCDT   *self,
                     P2trEdge  *e,
                     P2trPoint *C)
{
    /*      W
     *     /|\
     *    / | \
     *   /  |  \      E.Mirror.Tri: YXW
     * X*---*---*Y    E: X->Y
     *   \  |C /      E.Tri: XYV
     *    \ | /
     *     \|/
     *      V
     */
    P2trPoint *X = P2TR_EDGE_START (e), *Y = e->end;
    P2trPoint *V = (e->tri != NULL) ? p2tr_triangle_get_opposite_point(e->tri, e) : NULL;
    P2trPoint *W = (e->mirror->tri != NULL) ? p2tr_triangle_get_opposite_point (e->mirror->tri, e->mirror) : NULL;
    gboolean   constrained = e->constrained;
    P2trEdge  *XC, *CY;
    GList     *new_tris = NULL, *fan = NULL, *new_edges = NULL;

    p2tr_edge_remove (e);

    XC = p2tr_mesh_new_edge (self->mesh, X, C, constrained);
    CY = p2tr_mesh_new_edge (self->mesh, C, Y, constrained);

    fan = p2tr_utils_new_reversed_pointer_list (4, W, X, V, Y);
    new_tris = p2tr_cdt_triangulate_fan (self, C, fan);
    g_list_free (fan);

    /* Now make this a CDT again
     * The new triangles will be unreffed by the flip_fix function, which
     * is good since we receive them with an extra reference!
     */
    p2tr_cdt_flip_fix (self, new_tris);
    g_list_free (new_tris);

    if (constrained)
    {
        /* If this was a subsegment, then both parts of the subsegment
         * should exist */
        if (p2tr_edge_is_removed (XC) || p2tr_edge_is_removed (CY))
            p2tr_exception_geometric ("Subsegments gone!");
        else
        {
            new_edges = g_list_prepend (new_edges, CY);
            new_edges = g_list_prepend (new_edges, XC);
        }
    }
    else
    {
        p2tr_edge_unref (XC);
        p2tr_edge_unref (CY);
    }

    p2tr_cdt_on_new_point (self, C);

    return new_edges;
}
Beispiel #3
0
void
p2tr_cdt_validate_cdt (P2trCDT *self)
{
    P2trHashSetIter iter;
    P2trTriangle *tri;

    p2tr_hash_set_iter_init (&iter, self->mesh->triangles);
    while (p2tr_hash_set_iter_next (&iter, (gpointer*)&tri))
        if (! p2tr_cdt_has_empty_circum_circle(self, tri))
            p2tr_exception_geometric ("Not a CDT!");
}
Beispiel #4
0
P2trPoint*
p2tr_cdt_insert_point (P2trCDT           *self,
                       const P2trVector2 *pc,
                       P2trTriangle      *point_location_guess)
{
  P2trTriangle *tri;
  P2trPoint    *pt;
  gboolean      inserted = FALSE;
  gint          i;

  P2TR_CDT_VALIDATE_UNUSED (self);

  if (point_location_guess == NULL)
    tri = p2tr_mesh_find_point (self->mesh, pc);
  else
    tri = p2tr_mesh_find_point_local (self->mesh, pc, point_location_guess);

  if (tri == NULL)
    p2tr_exception_geometric ("Tried to add point outside of domain!");

  pt = p2tr_mesh_new_point (self->mesh, pc);

  /* If the point falls on a line, we should split the line */
  for (i = 0; i < 3; i++)
    {
      P2trEdge *edge = tri->edges[i];
      if (p2tr_math_orient2d (& P2TR_EDGE_START(edge)->c,
              &edge->end->c, pc) == P2TR_ORIENTATION_LINEAR)
        {
          GList *parts = p2tr_cdt_split_edge (self, edge, pt), *eIter;
          for (eIter = parts; eIter != NULL; eIter = eIter->next)
            p2tr_edge_unref ((P2trEdge*)eIter->data);
          g_list_free(parts);

          inserted = TRUE;
          break;
        }
    }

  if (! inserted)
    /* If we reached this line, then the point is inside the triangle */
    p2tr_cdt_insert_point_into_triangle (self, pt, tri);

  /* We no longer need the triangle */
  p2tr_triangle_unref (tri);

  P2TR_CDT_VALIDATE_UNUSED (self);
  return pt;
}
Beispiel #5
0
P2trPoint*
p2tr_cdt_insert_point (P2trCDT           *self,
                       const P2trVector2 *pc,
                       P2trTriangle      *point_location_guess)
{
    P2trTriangle *tri;
    P2trPoint    *pt;
    gboolean      inserted = FALSE;
    gint          i;

    if (point_location_guess == NULL)
        tri = p2tr_mesh_find_point (self->mesh, pc);
    else
        tri = p2tr_mesh_find_point_local (self->mesh, pc, point_location_guess);

    if (tri == NULL)
        p2tr_exception_geometric ("Tried to add point outside of domain!");

    pt = p2tr_mesh_new_point (self->mesh, pc);

    /* If the point falls on a line, we should split the line */
    for (i = 0; i < 3; i++)
    {
        P2trEdge *edge = tri->edges[i];
        if (p2tr_math_orient2d (& P2TR_EDGE_START(edge)->c,
                                &edge->end->c, pc) == P2TR_ORIENTATION_LINEAR)
        {
            p2tr_cdt_split_edge (self, edge, pt);
            inserted = TRUE;
            break;
        }
    }

    if (! inserted)
        /* If we reached this line, then the point is inside the triangle */
        p2tr_cdt_insert_point_into_triangle (self, pt, tri);

    p2tr_cdt_on_new_point (self, pt);

    return pt;
}