Пример #1
0
P2trEdge*
p2tr_point_edge_cw (P2trPoint* self,
                    P2trEdge *e)
{
  GList *node;

  if (P2TR_EDGE_START(e) != self)
      p2tr_exception_programmatic ("Not an edge of this point!");

  node = g_list_find (self->outgoing_edges, e);
  if (node == NULL)
    p2tr_exception_programmatic ("Could not find the CW sibling edge"
        "because the edge is not present in the outgoing-edges list!");

    return (P2trEdge*) g_list_cyclic_prev (self->outgoing_edges, node);
}
Пример #2
0
/*     ^ e1
 *    /
 *   /_ e1.Tri (e2.Mirror.Tri)
 *  /  |
 * *---------> e2
 *
 * Check if the angle marked is a part of the triangulation
 * domain
 */
static gboolean
p2tr_cluster_cw_tri_between_is_in_domain (P2trEdge *e1, P2trEdge *e2)
{
  if (P2TR_EDGE_START(e1) != P2TR_EDGE_START(e2) || e1->tri != e2->mirror->tri)
    p2tr_exception_programmatic ("Non clockwise adjacent edges!");
  return e1->tri != NULL;
}
Пример #3
0
void
_p2tr_point_remove_edge (P2trPoint *self, P2trEdge* e)
{
  GList *node;
  
  if (P2TR_EDGE_START(e) != self)
    p2tr_exception_programmatic ("Could not remove the given outgoing "
        "edge because doesn't start on this point!");

  node = g_list_find (self->outgoing_edges, e);
  if (node == NULL)
    p2tr_exception_programmatic ("Could not remove the given outgoing "
        "edge because it's not present in the outgoing-edges list!");

  self->outgoing_edges = g_list_delete_link (self->outgoing_edges, node);

  p2tr_edge_unref (e);
}
Пример #4
0
P2trEdge*
p2tr_point_get_edge_to (P2trPoint *start,
                        P2trPoint *end)
{
    P2trEdge* result = p2tr_point_has_edge_to (start, end);
    if (result == NULL)
      p2tr_exception_programmatic ("Tried to get an edge that doesn't exist!");
    else
      return result;
}
Пример #5
0
/**
 * Return the edge cluster of the specified edge from the specified end
 * point. THE EDGES IN THE CLUSTER MUST BE UNREFFED!
 * @param[in] P The point which is shared between all edges of the cluster
 * @param[in] E The edge whose cluster should be returned
 * @return The cluster of @ref E from the point @ref P
 */
P2trCluster*
p2tr_cluster_get_for (P2trPoint   *P,
                      P2trEdge    *E)
{
  P2trCluster *cluster = g_slice_new (P2trCluster);
  gdouble temp_angle;
  P2trEdge *current, *next;
  
  cluster->min_angle = G_MAXDOUBLE;
  g_queue_init (&cluster->edges);

  if (P == E->end)
    P = P2TR_EDGE_START (E);
  else if (P != P2TR_EDGE_START (E))
    p2tr_exception_programmatic ("Unexpected point for the edge!");

  g_queue_push_head (&cluster->edges, E);

  current = E;
  next = p2tr_point_edge_cw (P, current);
  
  while (next != g_queue_peek_head (&cluster->edges)
      && (temp_angle = p2tr_edge_angle_between (current->mirror, next)) <= P2TR_CLUSTER_LIMIT_ANGLE
      && p2tr_cluster_cw_tri_between_is_in_domain (current, next))
    {
      g_queue_push_tail (&cluster->edges, next);
      p2tr_edge_ref (next);
      current = next;
      next = p2tr_point_edge_cw (P, current);
      cluster->min_angle = MIN (cluster->min_angle, temp_angle);
    }

  current = E;
  next = p2tr_point_edge_ccw(P, current);
  while (next != g_queue_peek_tail (&cluster->edges)
      && (temp_angle = p2tr_edge_angle_between (current->mirror, next)) <= P2TR_CLUSTER_LIMIT_ANGLE
      && p2tr_cluster_cw_tri_between_is_in_domain (next, current))
    {
      g_queue_push_head (&cluster->edges, next);
      p2tr_edge_ref (next);
      current = next;
      next = p2tr_point_edge_ccw (P, current);
      cluster->min_angle = MIN(cluster->min_angle, temp_angle);
    }

  return cluster;
}
Пример #6
0
gdouble
p2tr_edge_angle_between(P2trEdge *e1, P2trEdge *e2)
{
  /* A = E1.angle, a = abs (A)
   * B = E1.angle, b = abs (B)
   *
   * W is the angle we wish to find. Note the fact that we want
   * to find the angle so that the edges go CLOCKWISE around it.
   *
   * Case 1: Signs of A and B agree | Case 2: Signs of A and B disagree
   *         and A > 0              |         and A > 0
   *                                |
   * a = A, b = B                   | a = A, b = -B
   *             ^^                 |
   *         E2 //                  |           /
   *           //\                  |          /
   *          //b|                  |         /a
   * - - - - * - |W- - - - - - - -  | - - - - * - - - - 
   *         ^^a'|                  |       ^^ \\b
   *         ||_/                   |      // W \\
   *      E1 ||\                    |  E1 // \_/ \\ E2
   *        '||a\                   |    //       \\
   *     - - - - - -                |   //         vv
   *                                |
   * W = A' + B = (180 - A) + B     | W = 180 - (a + b) = 180 - (A - B) 
   * W = 180 - A + B                | W = 180 - A + B
   * 
   * By the illustration above, we can see that in general the angle W
   * can be computed by W = 180 - A + B in every case. The only thing to
   * note is that the range of the result of the computation is
   * [180 - 360, 180 + 360] = [-180, +540] so we may need to subtract
   * 360 to put it back in the range [-180, +180].
   */
  gdouble result;
  
  if (e1->end != P2TR_EDGE_START(e2))
    p2tr_exception_programmatic ("The end-point of the first edge isn't"
        " the end-point of the second edge!");

  result = G_PI - e1->angle + e2->angle;
  if (result > 2 * G_PI)
      result -= 2 * G_PI;

  return result;
}
Пример #7
0
/**
 * Triangulate a polygon by creating edges to a center point.
 * 1. If there is a NULL point in the polygon, two triangles are not
 *    created (these are the two that would have used it)
 * 2. THE RETURNED TRIANGLES MUST BE UNREFFED!
 */
static GList*
p2tr_cdt_triangulate_fan (P2trCDT   *self,
                          P2trPoint *center,
                          GList     *edge_pts)
{
    GList *new_tris = NULL;
    GList *iter;

    /* We can not triangulate unless at least two points are given */
    if (edge_pts == NULL || edge_pts->next == NULL)
    {
        p2tr_exception_programmatic ("Not enough points to triangulate as"
                                     " a star!");
    }

    for (iter = edge_pts; iter != NULL; iter = iter->next)
    {
        P2trPoint *A = (P2trPoint*) iter->data;
        P2trPoint *B = (P2trPoint*) g_list_cyclic_next (edge_pts, iter)->data;
        P2trEdge *AB, *BC, *CA;
        P2trTriangle *tri;

        if (A == NULL || B == NULL)
            continue;

        AB = p2tr_point_get_edge_to (A, B);
        BC = p2tr_mesh_new_or_existing_edge (self->mesh, B, center, FALSE);
        CA = p2tr_mesh_new_or_existing_edge (self->mesh, center, A, FALSE);

        tri = p2tr_mesh_new_triangle (self->mesh, AB, BC, CA);
        new_tris = g_list_prepend (new_tris, tri);

        p2tr_edge_unref (BC);
        p2tr_edge_unref (CA);
    }

    return new_tris;
}
Пример #8
0
/**
 * Triangulate a polygon by creating edges to a center point.
 * 1. If there is a NULL point in the polygon, two triangles are not
 *    created (these are the two that would have used it)
 * 2. THE RETURNED EDGES MUST BE UNREFFED!
 */
static P2trVEdgeSet*
p2tr_cdt_triangulate_fan (P2trCDT   *self,
                          P2trPoint *center,
                          GList     *edge_pts)
{
  P2trVEdgeSet* fan_edges = p2tr_vedge_set_new ();
  GList *iter;

  /* We can not triangulate unless at least two points are given */
  if (edge_pts == NULL || edge_pts->next == NULL)
    {
      p2tr_exception_programmatic ("Not enough points to triangulate as"
          " a star!");
    }

  for (iter = edge_pts; iter != NULL; iter = iter->next)
    {
      P2trPoint *A = (P2trPoint*) iter->data;
      P2trPoint *B = (P2trPoint*) g_list_cyclic_next (edge_pts, iter)->data;
      P2trEdge *AB, *BC, *CA;

      if (A == NULL || B == NULL)
        continue;

      AB = p2tr_point_get_edge_to (A, B, TRUE);
      BC = p2tr_mesh_new_or_existing_edge (self->mesh, B, center, FALSE);
      CA = p2tr_mesh_new_or_existing_edge (self->mesh, center, A, FALSE);

      p2tr_triangle_unref (p2tr_mesh_new_triangle (self->mesh, AB, BC, CA));

      p2tr_vedge_set_add (fan_edges, CA);
      p2tr_vedge_set_add (fan_edges, BC);
      p2tr_vedge_set_add (fan_edges, AB);
    }

  return fan_edges;
}