Esempio n. 1
0
File: edge.c Progetto: MicBosi/GTS
/**
 * gts_edge_belongs_to_tetrahedron:
 * @e: a #GtsEdge.
 *
 * Returns: %TRUE if @e is used by faces forming a tetrahedron, %FALSE
 * otherwise.
 */
gboolean gts_edge_belongs_to_tetrahedron (GtsEdge * e)
{
    GSList * i;
    GtsVertex * v1, * v2;

    g_return_val_if_fail (e != NULL, FALSE);

    v1 = GTS_SEGMENT (e)->v1;
    v2 = GTS_SEGMENT (e)->v2;
    i = e->triangles;
    while (i) {
        GtsEdge * e1, * e2;
        GtsVertex * vt1;
        GSList * j = i->next;
        triangle_vertices_edges (i->data, e, &vt1, &e1, &e2);
        while (j) {
            GtsSegment * s5;
            GtsEdge * e3, * e4;
            GtsVertex * vt2;

            triangle_vertices_edges (j->data, e, &vt2, &e3, &e4);
            s5 = gts_vertices_are_connected (vt1, vt2);
            if (GTS_IS_EDGE (s5) &&
                    gts_triangle_use_edges (e1, e3, GTS_EDGE (s5)) &&
                    gts_triangle_use_edges (e2, e4, GTS_EDGE (s5)))
                return TRUE;
            j = j->next;
        }
        i = i->next;
    }

    return FALSE;
}
Esempio n. 2
0
static GtsVertex * triangle_use_vertices (GtsTriangle * t,
        GtsVertex * A,
        GtsVertex * B)
{
    GtsVertex
    * v1 = GTS_SEGMENT (t->e1)->v1,
      * v2 = GTS_SEGMENT (t->e1)->v2,
        * v3 = gts_triangle_vertex (t);

    if (v1 == A) {
        if (v2 == B)
            return v3;
        g_assert (v3 == B);
        return v2;
    }
    if (v2 == A) {
        if (v1 == B)
            return v3;
        g_assert (v3 == B);
        return v1;
    }
    if (v3 == A) {
        if (v1 == B)
            return v2;
        g_assert (v2 == B);
        return v1;
    }
    g_assert_not_reached ();
    return NULL;
}
Esempio n. 3
0
File: edge.c Progetto: MicBosi/GTS
/**
 * gts_edge_is_contact:
 * @e: a #GtsEdge.
 *
 * Returns: the number of sets of connected triangles sharing @e as a
 * contact edge.
 */
guint gts_edge_is_contact (GtsEdge * e)
{
    GSList * i, * triangles;
    guint ncomponent = 0;

    g_return_val_if_fail (e != NULL, 0);

    triangles = gts_vertex_triangles (GTS_SEGMENT (e)->v1, NULL);
    i = triangles = gts_vertex_triangles (GTS_SEGMENT (e)->v2, triangles);
    while (i) {
        GTS_OBJECT (i->data)->reserved = i;
        i = i->next;
    }

    i = e->triangles;
    while (i) {
        GtsTriangle * t = i->data;
        if (GTS_OBJECT (t)->reserved) {
            GtsEdge * e1;
            GTS_OBJECT (t)->reserved = NULL;
            e1 = next_edge (t, NULL, e);
            triangle_next (e1, e);
            triangle_next (next_edge (t, e1, e), e);
            ncomponent++;
        }
        i = i->next;
    }

    g_slist_foreach (triangles, (GFunc) gts_object_reset_reserved, NULL);
    g_slist_free (triangles);

    return ncomponent;
}
Esempio n. 4
0
File: edge.c Progetto: MicBosi/GTS
/**
 * gts_edge_is_duplicate:
 * @e: a #GtsEdge.
 *
 * Returns: the first #GtsEdge different from @e which shares the
 * same endpoints or %NULL if there is none.
 */
GtsEdge * gts_edge_is_duplicate (GtsEdge * e)
{
    GSList * i;
    GtsVertex * v2;

    g_return_val_if_fail (e != NULL, NULL);

    v2 = GTS_SEGMENT (e)->v2;
    i = GTS_SEGMENT (e)->v1->segments;
    if (GTS_SEGMENT (e)->v1 == v2) /* e is degenerate: special treatment */
        while (i) {
            GtsSegment * s = i->data;
            if (s != GTS_SEGMENT (e) &&
                    GTS_IS_EDGE (s) &&
                    s->v1 == v2 && s->v2 == v2)
                return GTS_EDGE (s);
            i = i->next;
        }
    else /* e is not degenerate */
        while (i) {
            GtsSegment * s = i->data;
            if (s != GTS_SEGMENT (e) &&
                    GTS_IS_EDGE (s) &&
                    (s->v1 == v2 || s->v2 == v2))
                return GTS_EDGE (s);
            i = i->next;
        }
    return NULL;
}
Esempio n. 5
0
/**
 * gts_triangle_interpolate_height:
 * @t: a #GtsTriangle.
 * @p: a #GtsPoint.
 *
 * Fills the z-coordinate of point @p belonging to the plane
 * projection of triangle @t with the linearly interpolated value of
 * the z-coordinates of the vertices of @t.
 */
void gts_triangle_interpolate_height (GtsTriangle * t, GtsPoint * p)
{
    GtsPoint * p1, * p2, * p3;
    gdouble x1, x2, y1, y2, det;

    g_return_if_fail (t != NULL);
    g_return_if_fail (p != NULL);

    p1 = GTS_POINT (GTS_SEGMENT (t->e1)->v1);
    p2 = GTS_POINT (GTS_SEGMENT (t->e1)->v2);
    p3 = GTS_POINT (gts_triangle_vertex (t));

    x1 = p2->x - p1->x;
    y1 = p2->y - p1->y;
    x2 = p3->x - p1->x;
    y2 = p3->y - p1->y;
    det = x1*y2 - x2*y1;
    if (det == 0.)
        p->z = (p1->z + p2->z + p3->z)/3.;
    else {
        gdouble x = p->x - p1->x;
        gdouble y = p->y - p1->y;
        gdouble a = (x*y2 - y*x2)/det;
        gdouble b = (y*x1 - x*y1)/det;

        p->z = (1. - a - b)*p1->z + a*p2->z + b*p3->z;
    }
}
Esempio n. 6
0
/**
 * gts_bbox_triangle:
 * @klass: a #GtsBBoxClass.
 * @t: a #GtsTriangle.
 *
 * Returns: a new #GtsBBox bounding box of @t.
 */
GtsBBox * gts_bbox_triangle (GtsBBoxClass * klass,
			     GtsTriangle * t)
{
  GtsBBox * bbox;
  GtsPoint * p;

  g_return_val_if_fail (t != NULL, NULL);
  g_return_val_if_fail (klass != NULL, NULL);

  p = GTS_POINT (GTS_SEGMENT (t->e1)->v1);
  bbox = gts_bbox_new (klass, t, p->x, p->y, p->z, p->x, p->y, p->z);

  p = GTS_POINT (GTS_SEGMENT (t->e1)->v2);
  if (p->x > bbox->x2) bbox->x2 = p->x;
  if (p->x < bbox->x1) bbox->x1 = p->x;
  if (p->y > bbox->y2) bbox->y2 = p->y;
  if (p->y < bbox->y1) bbox->y1 = p->y;
  if (p->z > bbox->z2) bbox->z2 = p->z;
  if (p->z < bbox->z1) bbox->z1 = p->z;
  p = GTS_POINT (gts_triangle_vertex (t));
  if (p->x > bbox->x2) bbox->x2 = p->x;
  if (p->x < bbox->x1) bbox->x1 = p->x;
  if (p->y > bbox->y2) bbox->y2 = p->y;
  if (p->y < bbox->y1) bbox->y1 = p->y;
  if (p->z > bbox->z2) bbox->z2 = p->z;
  if (p->z < bbox->z1) bbox->z1 = p->z;
  
  return bbox;
}
Esempio n. 7
0
File: edge.c Progetto: MicBosi/GTS
static void edge_clone (GtsObject * clone, GtsObject * object)
{
    (* GTS_OBJECT_CLASS (gts_edge_class ())->parent_class->clone) (clone,
            object);
    GTS_SEGMENT (clone)->v1 = GTS_SEGMENT (clone)->v2 = NULL;
    GTS_EDGE (clone)->triangles = NULL;
}
Esempio n. 8
0
static gboolean triangle_obtuse (GtsVertex * v, GtsFace * f)
{
  GtsEdge * e = gts_triangle_edge_opposite (GTS_TRIANGLE (f), v);

  return (angle_obtuse (v, f) ||
          angle_obtuse (GTS_SEGMENT (e)->v1, f) ||
          angle_obtuse (GTS_SEGMENT (e)->v2, f));
} 
Esempio n. 9
0
static gboolean angle_obtuse (GtsVertex * v, GtsFace * f)
{
  GtsEdge * e = gts_triangle_edge_opposite (GTS_TRIANGLE (f), v);
  GtsVector vec1, vec2;

  gts_vector_init (vec1, GTS_POINT (v), GTS_POINT (GTS_SEGMENT (e)->v1));
  gts_vector_init (vec2, GTS_POINT (v), GTS_POINT (GTS_SEGMENT (e)->v2));

  return (gts_vector_scalar (vec1, vec2) < 0.0);
}
Esempio n. 10
0
static gboolean triangle_is_hole (GtsTriangle * t)
{
  GtsEdge * e1, * e2, * e3;
  GtsVertex * v1, * v2, * v3;

  gts_triangle_vertices_edges (t, NULL, &v1, &v2, &v3, &e1, &e2, &e3);

  if ((GTS_IS_CONSTRAINT (e1) && GTS_SEGMENT (e1)->v2 != v1) ||
      (GTS_IS_CONSTRAINT (e2) && GTS_SEGMENT (e2)->v2 != v2) ||
      (GTS_IS_CONSTRAINT (e3) && GTS_SEGMENT (e3)->v2 != v3))
    return TRUE;
  return FALSE;
}
Esempio n. 11
0
/**
 * gts_triangles_are_compatible:
 * @t1: a #GtsTriangle.
 * @t2: a #GtsTriangle.
 * @e: a #GtsEdge used by both @t1 and @t2.
 *
 * Checks if @t1 and @t2 have compatible orientations i.e. if @t1 and
 * @t2 can be part of the same surface without conflict in the surface
 * normal orientation.
 *
 * Returns: %TRUE if @t1 and @t2 are compatible, %FALSE otherwise.
 */
gboolean gts_triangles_are_compatible (GtsTriangle * t1,
                                       GtsTriangle * t2,
                                       GtsEdge * e)
{
    GtsEdge * e1 = NULL, * e2 = NULL;

    g_return_val_if_fail (t1 != NULL, FALSE);
    g_return_val_if_fail (t2 != NULL, FALSE);
    g_return_val_if_fail (e != NULL, FALSE);

    if (t1->e1 == e) e1 = t1->e2;
    else if (t1->e2 == e) e1 = t1->e3;
    else if (t1->e3 == e) e1 = t1->e1;
    else
        g_assert_not_reached ();
    if (t2->e1 == e) e2 = t2->e2;
    else if (t2->e2 == e) e2 = t2->e3;
    else if (t2->e3 == e) e2 = t2->e1;
    else
        g_assert_not_reached ();
    if (GTS_SEGMENT (e1)->v1 == GTS_SEGMENT (e2)->v1 ||
            GTS_SEGMENT (e1)->v1 == GTS_SEGMENT (e2)->v2 ||
            GTS_SEGMENT (e1)->v2 == GTS_SEGMENT (e2)->v1 ||
            GTS_SEGMENT (e1)->v2 == GTS_SEGMENT (e2)->v2)
        return FALSE;
    return TRUE;
}
Esempio n. 12
0
/**
 * gts_triangle_perimeter:
 * @t: a #GtsTriangle.
 *
 * Returns: the perimeter of the triangle @t.
 */
gdouble gts_triangle_perimeter (GtsTriangle * t)
{
    GtsVertex * v;

    g_return_val_if_fail (t != NULL, 0.0);

    v = gts_triangle_vertex (t);
    return
        gts_point_distance (GTS_POINT (GTS_SEGMENT (t->e1)->v1),
                            GTS_POINT (GTS_SEGMENT (t->e1)->v2)) +
        gts_point_distance (GTS_POINT (GTS_SEGMENT (t->e1)->v1),
                            GTS_POINT (v)) +
        gts_point_distance (GTS_POINT (GTS_SEGMENT (t->e1)->v2),
                            GTS_POINT (v));
}
Esempio n. 13
0
static void surface_distance_foreach_boundary (GtsEdge * e,
					       gpointer * data)
{
  gdouble * delta = data[1];
  GtsRange * range = data[2];
  gdouble * total_length = data[3], length;
  GtsRange range_edge;

  if (gts_edge_is_boundary (e, NULL)) {
    GtsSegment * s =  GTS_SEGMENT (e);

    gts_bb_tree_segment_distance (data[0], s, data[4], *delta, &range_edge);

    if (range_edge.min < range->min)
      range->min = range_edge.min;
    if (range_edge.max > range->max)
      range->max = range_edge.max;
    range->n += range_edge.n;
    
    length = gts_point_distance (GTS_POINT (s->v1), GTS_POINT (s->v2));
    *total_length += length;
    range->sum += length*range_edge.mean;
    range->sum2 += length*range_edge.mean*range_edge.mean;
  }
}
Esempio n. 14
0
/** 
 * gts_vertex_gaussian_curvature:
 * @v: a #GtsVertex.  
 * @s: a #GtsSurface.
 * @Kg: the Discrete Gaussian Curvature approximation at @v.
 *
 * Computes the Discrete Gaussian Curvature approximation at @v.
 *
 * This approximation is from the paper:
 * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds
 * Mark Meyer, Mathieu Desbrun, Peter Schroder, Alan H. Barr
 * VisMath '02, Berlin (Germany) 
 * http://www-grail.usc.edu/pubs.html
 *
 * Returns: %TRUE if the operator could be evaluated, %FALSE if the
 * evaluation failed for some reason (@v is boundary or is the
 * endpoint of a non-manifold edge.)
 */
gboolean gts_vertex_gaussian_curvature (GtsVertex * v, GtsSurface * s, 
                                        gdouble * Kg)
{
  GSList * faces, * edges, * i;
  gdouble area = 0.0;
  gdouble angle_sum = 0.0;

  g_return_val_if_fail (v != NULL, FALSE);
  g_return_val_if_fail (s != NULL, FALSE);
  g_return_val_if_fail (Kg != NULL, FALSE);

  /* this operator is not defined for boundary edges */
  if (gts_vertex_is_boundary (v, s)) return (FALSE);
    
  faces = gts_vertex_faces (v, s, NULL);
  g_return_val_if_fail (faces != NULL, FALSE);

  edges = gts_vertex_fan_oriented (v, s);
  if (edges == NULL) {
    g_slist_free (faces);
    return (FALSE);
  }

  i = faces;
  while (i) {
    GtsFace * f = i->data;

    area += region_area (v, f);
    i = i->next;
  } 
  g_slist_free (faces);

  i = edges;
  while (i) {
    GtsEdge * e = i->data;
    GtsVertex * v1 = GTS_SEGMENT (e)->v1;
    GtsVertex * v2 = GTS_SEGMENT (e)->v2;

    angle_sum += angle_from_cotan (v, v1, v2);
    i = i->next;
  }
  g_slist_free (edges);

  *Kg = (2.0*M_PI - angle_sum)/area;
 
  return TRUE;
}
Esempio n. 15
0
File: edge.c Progetto: MicBosi/GTS
static GtsEdge * next_edge (GtsTriangle * t,
                            GtsEdge * e1,
                            GtsEdge * e)
{
    GtsVertex * v1 = GTS_SEGMENT (e)->v1;
    GtsVertex * v2 = GTS_SEGMENT (e)->v2;

    if (t->e1 != e1 && t->e1 != e &&
            (edge_use_vertex (t->e1, v1) || edge_use_vertex (t->e1, v2)))
        return t->e1;
    else if (t->e2 != e1 && t->e2 != e &&
             (edge_use_vertex (t->e2, v1) || edge_use_vertex (t->e2, v2)))
        return t->e2;
    else if (t->e3 != e1 && t->e3 != e &&
             (edge_use_vertex (t->e3, v1) || edge_use_vertex (t->e3, v2)))
        return t->e3;
    g_assert_not_reached ();
    return NULL;
}
Esempio n. 16
0
static void triangle_plane (GtsTriangle * f, GtsVector p)
{
  GtsPoint * v1, * v2, * v3;
  gdouble x1, x2, y1, y2, det;

  v1 = GTS_POINT (GTS_SEGMENT (f->e1)->v1);
  v2 = GTS_POINT (GTS_SEGMENT (f->e1)->v2);
  v3 = GTS_POINT (gts_triangle_vertex (f));

  x1 = v2->x - v1->x;
  y1 = v2->y - v1->y;
  x2 = v3->x - v1->x;
  y2 = v3->y - v1->y;
  det = x1*y2 - x2*y1;
  g_assert (det != 0.);

  p[0] = (y2*(v2->z - v1->z) - y1*(v3->z - v1->z))/det;
  p[1] = (-x2*(v2->z - v1->z) + x1*(v3->z - v1->z))/det;
  p[2] = ((- v1->x*y2 + v1->y*x2)*(v2->z - v1->z) +
	  (- v1->y*x1 + v1->x*y1)*(v3->z - v1->z))/det + v1->z;
}
Esempio n. 17
0
/**
 * gts_triangle_edge_opposite:
 * @t: a #GtsTriangle.
 * @v: a #GtsVertex of @t.
 *
 * Returns: the edge of @t opposite @v or %NULL if @v is not a vertice of @t.
 */
GtsEdge * gts_triangle_edge_opposite (GtsTriangle * t, GtsVertex * v)
{
    GtsSegment * s1, * s2, * s3;

    g_return_val_if_fail (t != NULL, NULL);
    g_return_val_if_fail (v != NULL, NULL);

    s1 = GTS_SEGMENT (t->e1);
    s2 = GTS_SEGMENT (t->e2);

    if (s1->v1 != v && s1->v2 != v) {
        if (s2->v1 != v && s2->v2 != v)
            return NULL;
        return t->e1;
    }
    if (s2->v1 != v && s2->v2 != v)
        return t->e2;
    s3 = GTS_SEGMENT (t->e3);
    g_assert (s3->v1 != v && s3->v2 != v);
    return t->e3;
}
Esempio n. 18
0
File: edge.c Progetto: MicBosi/GTS
static void triangle_vertices_edges (GtsTriangle * t,
                                     GtsEdge * e,
                                     GtsVertex ** v,
                                     GtsEdge ** ee1,
                                     GtsEdge ** ee2)
{
    GtsEdge * e1 = t->e1, * e2 = t->e2, * e3 = t->e3;
    GtsVertex * v1 = GTS_SEGMENT (e)->v1;

    if (e1 == e)        e1 = e3;
    else if (e2 == e)   e2 = e3;
    else                g_assert (e3 == e);

    if (GTS_SEGMENT (e2)->v1 == v1 || GTS_SEGMENT (e2)->v2 == v1) {
        e3 = e1;
        e1 = e2;
        e2 = e3;
    }
    if (GTS_SEGMENT (e1)->v1 == v1)
        *v = GTS_SEGMENT (e1)->v2;
    else
        *v = GTS_SEGMENT (e1)->v1;
    *ee1 = e1;
    *ee2 = e2;
}
Esempio n. 19
0
File: misc.c Progetto: MicBosi/GTS
void gts_write_triangle (GtsTriangle * t, 
			 GtsPoint * o,
			 FILE * fptr)
{
  gdouble xo = o ? o->x : 0.0;
  gdouble yo = o ? o->y : 0.0;
  gdouble zo = o ? o->z : 0.0;

  g_return_if_fail (t != NULL && fptr != NULL);

  fprintf (fptr, "(hdefine geometry \"t%d\" { =\n", id (t));
  fprintf (fptr, "OFF 3 1 0\n"
	   "%g %g %g\n%g %g %g\n%g %g %g\n3 0 1 2\n})\n"
	   "(geometry \"t%d\" { : \"t%d\"})\n"
	   "(normalization \"t%d\" none)\n",
	   GTS_POINT (GTS_SEGMENT (t->e1)->v1)->x - xo, 
	   GTS_POINT (GTS_SEGMENT (t->e1)->v1)->y - yo,
	   GTS_POINT (GTS_SEGMENT (t->e1)->v1)->z - zo,
	   GTS_POINT (GTS_SEGMENT (t->e1)->v2)->x - xo, 
	   GTS_POINT (GTS_SEGMENT (t->e1)->v2)->y - yo, 
	   GTS_POINT (GTS_SEGMENT (t->e1)->v2)->z - zo,
	   GTS_POINT (gts_triangle_vertex (t))->x - xo,
	   GTS_POINT (gts_triangle_vertex (t))->y - yo,
	   GTS_POINT (gts_triangle_vertex (t))->z - zo,
	   id (t), id (t), id (t));
}
Esempio n. 20
0
File: edge.c Progetto: MicBosi/GTS
/**
 * gts_edge_swap:
 * @e: a #GtsEdge.
 * @s: a #GtsSurface.
 *
 * Performs an "edge swap" on the two triangles sharing @e and
 * belonging to @s.
 */
void gts_edge_swap (GtsEdge * e, GtsSurface * s)
{
    GtsTriangle * t1 = NULL, * t2 = NULL, * t;
    GtsFace * f;
    GSList * i;
    GtsVertex * v1, * v2, * v3, * v4, * v5, * v6;
    GtsEdge * e1, * e2, * e3, * e4;
    GtsSegment * v3v6;

    g_return_if_fail (e != NULL);
    g_return_if_fail (s != NULL);

    i = e->triangles;
    while (i) {
        if (GTS_IS_FACE (i->data) && gts_face_has_parent_surface (i->data, s)) {
            if (!t1)
                t1 = i->data;
            else if (!t2)
                t2 = i->data;
            else
                g_return_if_fail (gts_edge_face_number (e, s) == 2);
        }
        i = i->next;
    }
    g_assert (t1 && t2);

    gts_triangle_vertices_edges (t1, e, &v1, &v2, &v3, &e, &e1, &e2);
    gts_triangle_vertices_edges (t2, e, &v4, &v5, &v6, &e, &e3, &e4);
    g_assert (v2 == v4 && v1 == v5);

    v3v6 = gts_vertices_are_connected (v3, v6);
    if (!GTS_IS_EDGE (v3v6))
        v3v6 = GTS_SEGMENT (gts_edge_new (s->edge_class, v3, v6));
    f = gts_face_new (s->face_class, e1, GTS_EDGE (v3v6), e4);
    if ((t = gts_triangle_is_duplicate (GTS_TRIANGLE (f))) &&
            GTS_IS_FACE (t)) {
        gts_object_destroy (GTS_OBJECT (f));
        f = GTS_FACE (t);
    }
    gts_surface_add_face (s, f);

    f = gts_face_new (s->face_class, GTS_EDGE (v3v6), e2, e3);
    if ((t = gts_triangle_is_duplicate (GTS_TRIANGLE (f))) &&
            GTS_IS_FACE (t)) {
        gts_object_destroy (GTS_OBJECT (f));
        f = GTS_FACE (t);
    }
    gts_surface_add_face (s, f);

    gts_surface_remove_face (s, GTS_FACE (t1));
    gts_surface_remove_face (s, GTS_FACE (t2));
}
Esempio n. 21
0
/**
 * gts_bbox_overlaps_triangle:
 * @bb: a #GtsBBox.
 * @t: a #GtsTriangle.
 *
 * This is a wrapper around the fast overlap test of Tomas
 * Akenine-Moller (http://www.cs.lth.se/home/Tomas_Akenine_Moller/).
 *
 * Returns: %TRUE if @bb overlaps with @t, %FALSE otherwise.
 */
gboolean gts_bbox_overlaps_triangle (GtsBBox * bb, GtsTriangle * t)
{
  double bc[3], bh[3], tv[3][3];
  GtsPoint * p1, * p2, * p3;

  g_return_val_if_fail (bb != NULL, FALSE);
  g_return_val_if_fail (t != NULL, FALSE);

  bc[0] = (bb->x2 + bb->x1)/2.;
  bh[0] = (bb->x2 - bb->x1)/2.;
  bc[1] = (bb->y2 + bb->y1)/2.;
  bh[1] = (bb->y2 - bb->y1)/2.;
  bc[2] = (bb->z2 + bb->z1)/2.;
  bh[2] = (bb->z2 - bb->z1)/2.;
  p1 = GTS_POINT (GTS_SEGMENT (t->e1)->v1);
  p2 = GTS_POINT (GTS_SEGMENT (t->e1)->v2);
  p3 = GTS_POINT (gts_triangle_vertex (t));
  tv[0][0] = p1->x; tv[0][1] = p1->y; tv[0][2] = p1->z;
  tv[1][0] = p2->x; tv[1][1] = p2->y; tv[1][2] = p2->z;
  tv[2][0] = p3->x; tv[2][1] = p3->y; tv[2][2] = p3->z;

  return triBoxOverlap (bc, bh, tv);
}
Esempio n. 22
0
static void smooth_fold (GtsVertex * v, gpointer * data)
{
  gdouble * maxcosine2 = data[2];
  GSList * i = v->segments;
  gboolean folded = FALSE;
  guint * nfold = data[3];

  while (i && !folded) {
    if (GTS_IS_EDGE (i->data)) {
      GtsEdge * e = i->data;

      if (gts_triangles_are_folded (e->triangles, 
				    GTS_SEGMENT (e)->v1,
				    GTS_SEGMENT (e)->v2,
				    *maxcosine2))
	folded = TRUE;
    }
    i = i->next;
  }
  if (folded) {
    (*nfold)++;
    smooth_vertex (v, data);
  }
}
Esempio n. 23
0
/**
 * gts_segment_new:
 * @klass: a #GtsSegmentClass.
 * @v1: a #GtsVertex.
 * @v2: another #GtsVertex different from @v1.
 *
 * Returns: a new #GtsSegment linking @v1 and @v2.
 */
GtsSegment * gts_segment_new (GtsSegmentClass * klass, 
			      GtsVertex * v1, GtsVertex * v2)
{
  GtsSegment * s;

  g_return_val_if_fail (v1 != NULL, NULL);
  g_return_val_if_fail (v2 != NULL, NULL);
  g_return_val_if_fail (v1 != v2, NULL);

  s = GTS_SEGMENT (gts_object_new (GTS_OBJECT_CLASS (klass)));
  s->v1 = v1;
  s->v2 = v2;
  v1->segments = g_slist_prepend (v1->segments, s);
  v2->segments = g_slist_prepend (v2->segments, s);
  
  return s;
}
Esempio n. 24
0
static void segment_destroy (GtsObject * object)
{
  GtsSegment * segment = GTS_SEGMENT (object);
  GtsVertex * v1 = segment->v1;
  GtsVertex * v2 = segment->v2;

  v1->segments = g_slist_remove (v1->segments, segment);
  if (!GTS_OBJECT_DESTROYED (v1) &&
      !gts_allow_floating_vertices && v1->segments == NULL)
    gts_object_destroy (GTS_OBJECT (v1));

  v2->segments = g_slist_remove (v2->segments, segment);
  if (!GTS_OBJECT_DESTROYED (v2) &&
      !gts_allow_floating_vertices && v2->segments == NULL)
    gts_object_destroy (GTS_OBJECT (v2));

  (* GTS_OBJECT_CLASS (gts_segment_class ())->parent_class->destroy) (object);
}
Esempio n. 25
0
static gdouble region_area (GtsVertex * v, GtsFace * f)
{
  /* cf. Section 3.3 of [Meyer et al 2002] */
  
  if (gts_triangle_area (GTS_TRIANGLE (f)) == 0.0) return (0.0);

  if (triangle_obtuse (v, f)) {
    if (angle_obtuse (v, f))
      return (gts_triangle_area (GTS_TRIANGLE (f))/2.0);
    else
      return (gts_triangle_area (GTS_TRIANGLE (f))/4.0);
  } else {
    GtsEdge * e = gts_triangle_edge_opposite (GTS_TRIANGLE (f), v);

    return ((cotan (GTS_SEGMENT (e)->v1, v, GTS_SEGMENT (e)->v2)* 
             gts_point_distance2 (GTS_POINT (v), 
				  GTS_POINT (GTS_SEGMENT (e)->v2)) +
             cotan (GTS_SEGMENT (e)->v2, v, GTS_SEGMENT (e)->v1)* 
             gts_point_distance2 (GTS_POINT (v), 
                                  GTS_POINT (GTS_SEGMENT (e)->v1)))
            /8.0);
  }
}
Esempio n. 26
0
void 
pygts_edge_cleanup(GtsSurface *s)
{
  GSList *edges = NULL;
  GSList *i, *ii, *cur, *parents=NULL;
  PygtsEdge *edge;
  GtsEdge *e, *duplicate;

  g_return_if_fail(s != NULL);

  /* build list of edges */
  gts_surface_foreach_edge(s, (GtsFunc)build_list, &edges);

  /* remove degenerate and duplicate edges.
     Note: we could use gts_edges_merge() to remove the duplicates and then
     remove the degenerate edges but it is more efficient to do everything 
     at once (and it's more pedagogical too ...) */

  /* We want to control manually the destruction of edges */
  gts_allow_floating_edges = TRUE;

  i = edges;
  while(i) {
    e = (GtsEdge*)i->data;
    if(GTS_SEGMENT(e)->v1 == GTS_SEGMENT(e)->v2) {
      /* edge is degenerate */
      if( !g_hash_table_lookup(obj_table,GTS_OBJECT(e)) ) {
	/* destroy e */
	gts_object_destroy(GTS_OBJECT(e));
      }
    }
    else {
      if((duplicate = gts_edge_is_duplicate(e))) {

	/* Detach and save any parent triangles */
	if( (edge = PYGTS_EDGE(g_hash_table_lookup(obj_table,GTS_OBJECT(e))))
	    !=NULL ) {
	  ii = e->triangles;
	  while(ii!=NULL) {
	    cur = ii;
	    ii = g_slist_next(ii);
	    if(PYGTS_IS_PARENT_TRIANGLE(cur->data)) {
	      e->triangles = g_slist_remove_link(e->triangles, cur);
	      parents = g_slist_prepend(parents,cur->data);
	      g_slist_free_1(cur);
	    }
	  } 
	}

	/* replace e with its duplicate */
	gts_edge_replace(e, duplicate);

	/* Reattach the parent segments */
	if( edge != NULL ) {
	  ii = parents;
	  while(ii!=NULL) {
	    e->triangles = g_slist_prepend(e->triangles, ii->data);
	    ii = g_slist_next(ii);
	  }
	  g_slist_free(parents);
	  parents = NULL;
	}

	if( !g_hash_table_lookup(obj_table,GTS_OBJECT(e)) ) {
	  /* destroy e */
	  gts_object_destroy(GTS_OBJECT (e));
	}
      }
    }
    i = g_slist_next(i);
  }
  
  /* don't forget to reset to default */
  gts_allow_floating_edges = FALSE;

  /* free list of edges */
  g_slist_free (edges);
}
Esempio n. 27
0
/**
 * gts_triangle_set:
 * @triangle: a #GtsTriangle.
 * @e1: a #GtsEdge.
 * @e2: another #GtsEdge touching @e1.
 * @e3: another #GtsEdge touching both @e1 and @e2.
 *
 * Sets the edge of @triangle to @e1, @e2 and @e3 while checking that they
 * define a valid triangle.
 */
void gts_triangle_set (GtsTriangle * triangle,
                       GtsEdge * e1,
                       GtsEdge * e2,
                       GtsEdge * e3)
{
    g_return_if_fail (e1 != NULL);
    g_return_if_fail (e2 != NULL);
    g_return_if_fail (e3 != NULL);
    g_return_if_fail (e1 != e2 && e1 != e3 && e2 != e3);

    triangle->e1 = e1;
    triangle->e2 = e2;
    triangle->e3 = e3;

    if (GTS_SEGMENT (e1)->v1 == GTS_SEGMENT (e2)->v1)
        g_return_if_fail (gts_segment_connect (GTS_SEGMENT (e3),
                                               GTS_SEGMENT (e1)->v2,
                                               GTS_SEGMENT (e2)->v2));
    else if (GTS_SEGMENT (e1)->v2 == GTS_SEGMENT (e2)->v1)
        g_return_if_fail (gts_segment_connect (GTS_SEGMENT (e3),
                                               GTS_SEGMENT (e1)->v1,
                                               GTS_SEGMENT (e2)->v2));
    else if (GTS_SEGMENT (e1)->v2 == GTS_SEGMENT (e2)->v2)
        g_return_if_fail (gts_segment_connect (GTS_SEGMENT (e3),
                                               GTS_SEGMENT (e1)->v1,
                                               GTS_SEGMENT (e2)->v1));
    else if (GTS_SEGMENT (e1)->v1 == GTS_SEGMENT (e2)->v2)
        g_return_if_fail (gts_segment_connect (GTS_SEGMENT (e3),
                                               GTS_SEGMENT (e1)->v2,
                                               GTS_SEGMENT (e2)->v1));
    else
        return; //finetjul: g_assert_not_reached ();

    e1->triangles = g_slist_prepend (e1->triangles, triangle);
    e2->triangles = g_slist_prepend (e2->triangles, triangle);
    e3->triangles = g_slist_prepend (e3->triangles, triangle);
}
Esempio n. 28
0
static PyObject *
new_(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
  PyObject *o;
  PygtsObject *obj;
  GtsSegment *tmp;
  GtsObject *segment=NULL;
  PyObject *v1_=NULL,*v2_=NULL;
  PygtsVertex *v1,*v2;
  guint alloc_gtsobj = TRUE;
  guint N;

  /* Parse the args */
  if(kwds) {
    o = PyDict_GetItemString(kwds,"alloc_gtsobj");
    if(o==Py_False) {
      alloc_gtsobj = FALSE;
    }
    if(o!=NULL) {
      PyDict_DelItemString(kwds, "alloc_gtsobj");
    }
  }
  if(kwds) {
    Py_INCREF(Py_False);
    PyDict_SetItemString(kwds,"alloc_gtsobj", Py_False);
  }

  /* Allocate the gtsobj (if needed) */
  if( alloc_gtsobj ) {

    /* Parse the args */
    if( (N = PyTuple_Size(args)) < 2 ) {
      PyErr_SetString(PyExc_TypeError,"expected two Vertices");
      return NULL;
    }
    v1_ = PyTuple_GET_ITEM(args,0);
    v2_ = PyTuple_GET_ITEM(args,1);

    /* Convert to PygtsObjects */
    if(!pygts_vertex_check(v1_)) {
      PyErr_SetString(PyExc_TypeError,"expected two Vertices");
      return NULL;
    }
    if(!pygts_vertex_check(v2_)) {
      PyErr_SetString(PyExc_TypeError,"expected two Vertices");
      return NULL;
    }
    v1 = PYGTS_VERTEX(v1_);
    v2 = PYGTS_VERTEX(v2_);

    /* Error check */
    if(PYGTS_OBJECT(v1)->gtsobj == PYGTS_OBJECT(v2)->gtsobj) {
      PyErr_SetString(PyExc_ValueError,"Vertices are identical");
      return NULL;
    }

    /* Create the GtsSegment */
    segment = GTS_OBJECT(gts_segment_new(gts_segment_class(),
					 GTS_VERTEX(v1->gtsobj),
					 GTS_VERTEX(v2->gtsobj)));
    if( segment == NULL )  {
      PyErr_SetString(PyExc_MemoryError, "could not create Segment");
      return NULL;
    }

    /* Check for duplicate */
    tmp = gts_segment_is_duplicate(GTS_SEGMENT(segment));
    if( tmp != NULL ) {
      gts_object_destroy(segment);
      segment = GTS_OBJECT(tmp);
    }

    /* If corresponding PyObject found in object table, we are done */
    if( (obj=(PygtsObject*)g_hash_table_lookup(obj_table,segment)) != NULL ) {
      Py_INCREF(obj);
      return (PyObject*)obj;
    }
  }  

  /* Chain up */
  obj = PYGTS_OBJECT(PygtsObjectType.tp_new(type,args,kwds));

  if( alloc_gtsobj ) {
    obj->gtsobj = segment;
    pygts_object_register(PYGTS_OBJECT(obj));
  }

  return (PyObject*)obj;
}
Esempio n. 29
0
/* stripe - Turns the input surface into triangle strips and outputs a
   Geomview representation of the result. */
int main (int argc, char * argv[])
{
    GtsSurface * s;
    GSList * strips = NULL, * i;
    gboolean verbose = FALSE;
    int c = 0;
    GtsFile * fp;

    /* parse options using getopt */
    while (c != EOF) {
#ifdef HAVE_GETOPT_LONG
        static struct option long_options[] = {
            {"help", no_argument, NULL, 'h'},
            {"verbose", no_argument, NULL, 'v'}
        };
        int option_index = 0;
        switch ((c = getopt_long (argc, argv, "hv",
                                  long_options, &option_index))) {
#else /* not HAVE_GETOPT_LONG */
        switch ((c = getopt (argc, argv, "hv"))) {
#endif /* not HAVE_GETOPT_LONG */
        case 'v': /* verbose */
            verbose = TRUE;
            break;
        case 'h': /* help */
            fprintf (stderr,
                     "Usage: stripe [OPTION] < FILE\n"
                     "Turns the input surface into triangle strips and outputs a\n"
                     "Geomview representation of the result.\n"
                     "\n"
                     "  -v      --verbose  print statistics about the surface and strips\n"
                     "  -h      --help     display this help and exit\n"
                     "\n"
                     "Report bugs to %s\n",
                     GTS_MAINTAINER);
            return 0; /* success */
            break;
        case '?': /* wrong options */
            fprintf (stderr, "Try `stripe --help' for more information.\n");
            return 1; /* failure */
        }
    }

    /* read surface in */
    s = gts_surface_new (gts_surface_class (),
                         gts_face_class (),
                         gts_edge_class (),
                         gts_vertex_class ());
    fp = gts_file_new (stdin);
    if (gts_surface_read (s, fp)) {
        fputs ("stripe: file on standard input is not a valid GTS file\n",
               stderr);
        fprintf (stderr, "stdin:%d:%d: %s\n", fp->line, fp->pos, fp->error);
        return 1; /* failure */
    }
    gts_file_destroy (fp);

    if (verbose)
        gts_surface_print_stats (s, stderr);

    strips = gts_surface_strip (s);

    /* if verbose on print stats */
    if (verbose) {
        GtsRange l;

        gts_range_init (&l);
        i = strips;
        while (i) {
            gts_range_add_value (&l, g_slist_length (i->data));
            i = i->next;
        }
        gts_range_update (&l);
        fprintf (stderr, "# Strips: %d\n#   length : ", l.n);
        gts_range_print (&l, stderr);
        fputc ('\n', stderr);
    }

    puts ("LIST {\n");
    i = strips;
    while (i) {
        GList * j = i->data;
        GtsTriangle * oldt = NULL;
        GtsColor c;

        c.r = rand ()/(gdouble) RAND_MAX;
        c.g = rand ()/(gdouble) RAND_MAX;
        c.b = rand ()/(gdouble) RAND_MAX;
        while (j) {
            GtsTriangle * t = j->data;
            GtsPoint
            * p1 = GTS_POINT (GTS_SEGMENT (t->e1)->v1),
              * p2 = GTS_POINT (GTS_SEGMENT (t->e1)->v2),
                * p3 = GTS_POINT (gts_triangle_vertex (t));

            printf ("OFF 3 1 3\n%g %g %g\n%g %g %g\n%g %g %g\n3 0 1 2 %g %g %g\n",
                    p1->x, p1->y, p1->z,
                    p2->x, p2->y, p2->z,
                    p3->x, p3->y, p3->z,
                    c.r, c.g, c.b);
            if (oldt) {
                GtsSegment * cs = GTS_SEGMENT (gts_triangles_common_edge (t, oldt));
                GtsPoint
                * op1 = GTS_POINT (GTS_SEGMENT (oldt->e1)->v1),
                  * op2 = GTS_POINT (GTS_SEGMENT (oldt->e1)->v2),
                    * op3 = GTS_POINT (gts_triangle_vertex (oldt));

                printf ("VECT 1 3 0 3 0 %g %g %g %g %g %g %g %g %g\n",
                        (op1->x + op2->x + op3->x)/3.,
                        (op1->y + op2->y + op3->y)/3.,
                        (op1->z + op2->z + op3->z)/3.,
                        (GTS_POINT (cs->v1)->x + GTS_POINT (cs->v2)->x)/2.,
                        (GTS_POINT (cs->v1)->y + GTS_POINT (cs->v2)->y)/2.,
                        (GTS_POINT (cs->v1)->z + GTS_POINT (cs->v2)->z)/2.,
                        (p1->x + p2->x + p3->x)/3.,
                        (p1->y + p2->y + p3->y)/3.,
                        (p1->z + p2->z + p3->z)/3.);
            }
            oldt = t;
            j = j->next;
        }
        i = i->next;
    }
    puts ("}\n");

    return 0; /* success */
}
Esempio n. 30
0
static void gts_constraint_split (GtsConstraint * c, 
				  GtsSurface * s,
				  GtsFifo * fifo)
{
  GSList * i;
  GtsVertex * v1, * v2;
  GtsEdge * e;

  g_return_if_fail (c != NULL);
  g_return_if_fail (s != NULL);

  v1 = GTS_SEGMENT (c)->v1;
  v2 = GTS_SEGMENT (c)->v2;
  e = GTS_EDGE (c);

  i = e->triangles;
  while (i) {
    GtsFace * f = i->data;
    if (GTS_IS_FACE (f) && gts_face_has_parent_surface (f, s)) {
      GtsVertex * v = gts_triangle_vertex_opposite (GTS_TRIANGLE (f), e);
      if (gts_point_orientation (GTS_POINT (v1), 
				 GTS_POINT (v2), 
				 GTS_POINT (v)) == 0.) {
	GSList * j = e->triangles;
	GtsFace * f1 = NULL;
	GtsEdge * e1, * e2;

	/* replaces edges with constraints */
	gts_triangle_vertices_edges (GTS_TRIANGLE (f), e,
				     &v1, &v2, &v, &e, &e1, &e2);
	if (!GTS_IS_CONSTRAINT (e1)) {
	  GtsEdge * ne1 = 
	    gts_edge_new (GTS_EDGE_CLASS (GTS_OBJECT (c)->klass), v2, v);
	  gts_edge_replace (e1, ne1);
	  gts_object_destroy (GTS_OBJECT (e1));
	  e1 = ne1;
	  if (fifo) gts_fifo_push (fifo, e1);
	}
	if (!GTS_IS_CONSTRAINT (e2)) {
	  GtsEdge * ne2 = 
	    gts_edge_new (GTS_EDGE_CLASS (GTS_OBJECT (c)->klass), v, v1);
	  gts_edge_replace (e2, ne2);
	  gts_object_destroy (GTS_OBJECT (e2));
	  e2 = ne2;
	  if (fifo) gts_fifo_push (fifo, e2);
	}

	/* look for face opposite */
	while (j && !f1) {
	  if (GTS_IS_FACE (j->data) && 
	      gts_face_has_parent_surface (j->data, s))
	    f1 = j->data;
	  j = j->next;
	}
	if (f1) { /* c is not a boundary of s */
	  GtsEdge * e3, * e4, * e5;
	  GtsVertex * v3;
	  gts_triangle_vertices_edges (GTS_TRIANGLE (f1), e,
				       &v1, &v2, &v3, &e, &e3, &e4);
	  e5 = gts_edge_new (s->edge_class, v, v3);
	  gts_surface_add_face (s, gts_face_new (s->face_class, e5, e2, e3));
	  gts_surface_add_face (s, gts_face_new (s->face_class, e5, e4, e1));
	  gts_object_destroy (GTS_OBJECT (f1));
	}
	gts_object_destroy (GTS_OBJECT (f));
	return;
      }
    }
    i = i->next;
  }
}