Esempio n. 1
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. 2
0
static PyObject*
triangles(PygtsVertex *self, PyObject *args)
{
  GSList *triangles, *t;
  PygtsTriangle *triangle;
  guint i,N;
  PyObject *tuple;

  SELF_CHECK

  triangles = gts_vertex_triangles(PYGTS_VERTEX_AS_GTS_VERTEX(self),NULL);
  N = g_slist_length(triangles);

  /* Create the tuple */
  if( (tuple=PyTuple_New(N)) == NULL) {
    PyErr_SetString(PyExc_MemoryError,"could not create tuple");
    return NULL;
  }

  /* Put PygtsVertex objects into the tuple */
  t = triangles;
  for(i=0;i<N;i++) {

    if( (triangle = pygts_triangle_new(GTS_TRIANGLE(t->data))) == NULL ) {
      Py_DECREF(tuple);
      return NULL;
    }

    PyTuple_SET_ITEM(tuple, i, (PyObject*)triangle);
    
    t = g_slist_next(t);
  }

  return tuple;
}
Esempio n. 3
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. 4
0
static GtsSurface * happrox_list (GSList * points,
				  gboolean keep_enclosing,
				  gboolean closed,
				  CostFunc cost_func,
				  gpointer cost_data,
				  GtsStopFunc stop_func,
				  gpointer stop_data)
{
  GtsSurface * s = gts_surface_new (gts_surface_class (),
				    GTS_FACE_CLASS (list_face_class ()),
				    gts_edge_class (),
				    gts_vertex_class ());
  GtsTriangle * t;
  GtsVertex * w1, * w2, * w3;
  GtsListFace * f;

  /* creates enclosing triangle */
  t = gts_triangle_enclosing (gts_triangle_class (), points, 10.);
  gts_triangle_vertices (t, &w1, &w2, &w3);
  GTS_POINT (w1)->z = GTS_POINT (w2)->z = GTS_POINT (w3)->z = 
    keep_enclosing ? -10. : -1e30;

  f = GTS_LIST_FACE (gts_face_new (s->face_class, t->e1, t->e2, t->e3));
  gts_surface_add_face (s, GTS_FACE (f));
  f->points = points;

  /* refine surface */
  surface_hf_refine (s, cost_func, cost_data, stop_func, stop_data);

  /* destroy unused vertices */
  gts_surface_foreach_face (s, (GtsFunc) destroy_unused, NULL);
  
  /* destroy enclosing triangle */
  if (!keep_enclosing) {
    gts_allow_floating_vertices = TRUE;
    gts_object_destroy (GTS_OBJECT (w1));
    gts_object_destroy (GTS_OBJECT (w2));
    gts_object_destroy (GTS_OBJECT (w3));
    gts_allow_floating_vertices = FALSE;
  }
  else if (closed) {
    GSList * l = gts_surface_boundary (s);
    GtsFace * f;

    g_assert (g_slist_length (l) == 3);
    f = gts_face_new (s->face_class, l->data, l->next->data, l->next->next->data);
    gts_surface_add_face (s, f);
    if (!gts_face_is_compatible (f, s))
      gts_triangle_revert (GTS_TRIANGLE (f));
    g_slist_free (l);
    gts_object_destroy (GTS_OBJECT (t));
  }
  else
    gts_object_destroy (GTS_OBJECT (t));

  return s;
}
Esempio n. 5
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. 6
0
/**
 * gts_triangle_new:
 * @klass: a #GtsTriangleClass.
 * @e1: a #GtsEdge.
 * @e2: another #GtsEdge touching @e1.
 * @e3: another #GtsEdge touching both @e1 and @e2.
 *
 * Returns: a new #GtsTriangle having @e1, @e2 and @e3 as edges.
 */
GtsTriangle * gts_triangle_new (GtsTriangleClass * klass,
                                GtsEdge * e1,
                                GtsEdge * e2,
                                GtsEdge * e3)
{
    GtsTriangle * t;

    t = GTS_TRIANGLE (gts_object_new (GTS_OBJECT_CLASS (klass)));
    gts_triangle_set (t, e1, e2, e3);

    return t;
}
Esempio n. 7
0
static void mark_as_hole (GtsFace * f, GtsSurface * s)
{
  GtsEdge * e1, * e2, * e3;

  if (GTS_OBJECT (f)->reserved == f)
    return;

  GTS_OBJECT (f)->reserved = f;
  e1 = GTS_TRIANGLE (f)->e1;
  e2 = GTS_TRIANGLE (f)->e2;
  e3 = GTS_TRIANGLE (f)->e3;

  if (!GTS_IS_CONSTRAINT (e1)) {
    GSList * i = e1->triangles;
    while (i) {
      GtsFace * f1 = i->data;
      if (f1 != f && GTS_IS_FACE (f1) && gts_face_has_parent_surface (f1, s))
	mark_as_hole (f1, s);
      i = i->next;
    }
  }
  if (!GTS_IS_CONSTRAINT (e2)) {
    GSList * i = e2->triangles;
    while (i) {
      GtsFace * f1 = i->data;
      if (f1 != f && GTS_IS_FACE (f1) && gts_face_has_parent_surface (f1, s))
	mark_as_hole (f1, s);
      i = i->next;
    }
  }
  if (!GTS_IS_CONSTRAINT (e3)) {
    GSList * i = e3->triangles;
    while (i) {
      GtsFace * f1 = i->data;
      if (f1 != f && GTS_IS_FACE (f1) && gts_face_has_parent_surface (f1, s))
	mark_as_hole (f1, s);
      i = i->next;
    }
  }
}
Esempio n. 8
0
static void edge_mark_as_hole (GtsEdge * e, GtsSurface * s)
{
  GSList * i = e->triangles;

  while (i) {
    GtsFace * f = i->data;
    if (GTS_IS_FACE (f) && 
	gts_face_has_parent_surface (f, s) &&
	triangle_is_hole (GTS_TRIANGLE (f)))
      mark_as_hole (f, s);
    i = i->next;
  }
}
Esempio n. 9
0
static gdouble interpolated_value (GtsSurface * s, FttVector * p)
{
  GtsPoint q;
  GtsFace * t;

  q.x = p->x; q.y = p->y;
  t = gts_point_locate (&q, s, NULL);
  if (t == NULL) {
    g_warning ("cannot locate point (%g,%g)", p->x, p->y);
    return 0.;
  }
  gts_triangle_interpolate_height (GTS_TRIANGLE (t), &q);
  return q.z;
}
Esempio n. 10
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. 11
0
static void triangle_destroy (GtsObject * object)
{
    GtsTriangle * triangle = GTS_TRIANGLE (object);
    GtsEdge * e1 = triangle->e1;
    GtsEdge * e2 = triangle->e2;
    GtsEdge * e3 = triangle->e3;

    e1->triangles = g_slist_remove (e1->triangles, triangle);
    if (!GTS_OBJECT_DESTROYED (e1) &&
            !gts_allow_floating_edges && e1->triangles == NULL)
        gts_object_destroy (GTS_OBJECT (e1));

    e2->triangles = g_slist_remove (e2->triangles, triangle);
    if (!GTS_OBJECT_DESTROYED (e2) &&
            !gts_allow_floating_edges && e2->triangles == NULL)
        gts_object_destroy (GTS_OBJECT (e2));

    e3->triangles = g_slist_remove (e3->triangles, triangle);
    if (!GTS_OBJECT_DESTROYED (e3) &&
            !gts_allow_floating_edges && e3->triangles == NULL)
        gts_object_destroy (GTS_OBJECT (e3));

    (* GTS_OBJECT_CLASS (gts_triangle_class ())->parent_class->destroy) (object);
}
Esempio n. 12
0
static void list_face_cost_init (ListFace * f)
{
  triangle_plane (GTS_TRIANGLE (f), f->p);
}
Esempio n. 13
0
static gboolean face_is_marked (GtsObject * o)
{
  if (o->reserved == o || gts_triangle_is_duplicate (GTS_TRIANGLE (o)))
    return TRUE;
  return FALSE;
}
Esempio n. 14
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;
  }
}
Esempio n. 15
0
/** 
 * gts_vertex_principal_directions:
 * @v: a #GtsVertex.  
 * @s: a #GtsSurface.
 * @Kh: mean curvature normal (a #GtsVector).
 * @Kg: Gaussian curvature (a gdouble).
 * @e1: first principal curvature direction (direction of largest curvature).
 * @e2: second principal curvature direction.
 *
 * Computes the principal curvature directions at a point given @Kh
 * and @Kg, the mean curvature normal and Gaussian curvatures at that
 * point, computed with gts_vertex_mean_curvature_normal() and
 * gts_vertex_gaussian_curvature(), respectively. 
 *
 * Note that this computation is very approximate and tends to be
 * unstable.  Smoothing of the surface or the principal directions may
 * be necessary to achieve reasonable results.  
 */
void gts_vertex_principal_directions (GtsVertex * v, GtsSurface * s,
                                      GtsVector Kh, gdouble Kg,
				      GtsVector e1, GtsVector e2)
{
  GtsVector N;
  gdouble normKh;
  GSList * i, * j;
  GtsVector basis1, basis2, d, eig;
  gdouble ve2, vdotN;
  gdouble aterm_da, bterm_da, cterm_da, const_da;
  gdouble aterm_db, bterm_db, cterm_db, const_db;
  gdouble a, b, c;
  gdouble K1, K2;
  gdouble *weights, *kappas, *d1s, *d2s;
  gint edge_count;
  gdouble err_e1, err_e2;
  int e;

  /* compute unit normal */
  normKh = sqrt (gts_vector_scalar (Kh, Kh));

  if (normKh > 0.0) {
    N[0] = Kh[0] / normKh;
    N[1] = Kh[1] / normKh;
    N[2] = Kh[2] / normKh;
  } else {
    /* This vertex is a point of zero mean curvature (flat or saddle
     * point).  Compute a normal by averaging the adjacent triangles
     */
    N[0] = N[1] = N[2] = 0.0;
    i = gts_vertex_faces (v, s, NULL);
    while (i) {
      gdouble x, y, z;
      gts_triangle_normal (GTS_TRIANGLE ((GtsFace *) i->data),
                           &x, &y, &z);
      N[0] += x;
      N[1] += y;
      N[2] += z;

      i = i->next;
    }
    g_return_if_fail (gts_vector_norm (N) > 0.0);
    gts_vector_normalize (N);
  }
    

  /* construct a basis from N: */
  /* set basis1 to any component not the largest of N */
  basis1[0] =  basis1[1] =  basis1[2] = 0.0;
  if (fabs (N[0]) > fabs (N[1]))
    basis1[1] = 1.0;
  else
    basis1[0] = 1.0;
    
  /* make basis2 orthogonal to N */
  gts_vector_cross (basis2, N, basis1);
  gts_vector_normalize (basis2);

  /* make basis1 orthogonal to N and basis2 */
  gts_vector_cross (basis1, N, basis2);
  gts_vector_normalize (basis1);
  
  aterm_da = bterm_da = cterm_da = const_da = 0.0;
  aterm_db = bterm_db = cterm_db = const_db = 0.0;

  weights = g_malloc (sizeof (gdouble)*g_slist_length (v->segments));
  kappas = g_malloc (sizeof (gdouble)*g_slist_length (v->segments));
  d1s = g_malloc (sizeof (gdouble)*g_slist_length (v->segments));
  d2s = g_malloc (sizeof (gdouble)*g_slist_length (v->segments));
  edge_count = 0;

  i = v->segments;
  while (i) {
    GtsEdge * e;
    GtsFace * f1, * f2;
    gdouble weight, kappa, d1, d2;
    GtsVector vec_edge;

    if (! GTS_IS_EDGE (i->data)) {
      i = i->next;
      continue;
    }

    e = i->data;

    /* since this vertex passed the tests in
     * gts_vertex_mean_curvature_normal(), this should be true. */
    g_assert (gts_edge_face_number (e, s) == 2);

    /* identify the two triangles bordering e in s */
    f1 = f2 = NULL;
    j = e->triangles;
    while (j) {
      if ((! GTS_IS_FACE (j->data)) || 
          (! gts_face_has_parent_surface (GTS_FACE (j->data), s))) {
        j = j->next;
        continue;
      }
      if (f1 == NULL)
        f1 = GTS_FACE (j->data);
      else {
        f2 = GTS_FACE (j->data);
        break;
      }
      j = j->next;
    }
    g_assert (f2 != NULL);

    /* We are solving for the values of the curvature tensor 
     *     B = [ a b ; b c ].  
     * The computations here are from section 5 of [Meyer et al 2002].  
     *
     * The first step is to calculate the linear equations governing
     * the values of (a,b,c).  These can be computed by setting the
     * derivatives of the error E to zero (section 5.3).
     * 
     * Since a + c = norm(Kh), we only compute the linear equations
     * for dE/da and dE/db.  (NB: [Meyer et al 2002] has the
     * equation a + b = norm(Kh), but I'm almost positive this is
     * incorrect.)
     *
     * Note that the w_ij (defined in section 5.2) are all scaled by
     * (1/8*A_mixed).  We drop this uniform scale factor because the
     * solution of the linear equations doesn't rely on it.
     *
     * The terms of the linear equations are xterm_dy with x in
     * {a,b,c} and y in {a,b}.  There are also const_dy terms that are
     * the constant factors in the equations.  
     */

    /* find the vector from v along edge e */
    gts_vector_init (vec_edge, GTS_POINT (v), 
                     GTS_POINT ((GTS_SEGMENT (e)->v1 == v) ? 
                                GTS_SEGMENT (e)->v2 : GTS_SEGMENT (e)->v1));
    ve2 = gts_vector_scalar (vec_edge, vec_edge);
    vdotN = gts_vector_scalar (vec_edge, N);

    /* section 5.2 - There is a typo in the computation of kappa.  The
     * edges should be x_j-x_i.
     */
    kappa = 2.0 * vdotN / ve2;

    /* section 5.2 */

    /* I don't like performing a minimization where some of the
     * weights can be negative (as can be the case if f1 or f2 are
     * obtuse).  To ensure all-positive weights, we check for
     * obtuseness and use values similar to those in region_area(). */
    weight = 0.0;
    if (! triangle_obtuse(v, f1)) {
      weight += ve2 * 
        cotan (gts_triangle_vertex_opposite (GTS_TRIANGLE (f1), e), 
               GTS_SEGMENT (e)->v1, GTS_SEGMENT (e)->v2) / 8.0;
    } else {
      if (angle_obtuse (v, f1)) {
        weight += ve2 * gts_triangle_area (GTS_TRIANGLE (f1)) / 4.0;
      } else {
        weight += ve2 * gts_triangle_area (GTS_TRIANGLE (f1)) / 8.0;
      }
    }

    if (! triangle_obtuse(v, f2)) {
      weight += ve2 * 
        cotan (gts_triangle_vertex_opposite (GTS_TRIANGLE (f2), e), 
               GTS_SEGMENT (e)->v1, GTS_SEGMENT (e)->v2) / 8.0;
    } else {
      if (angle_obtuse (v, f2)) {
        weight += ve2 * gts_triangle_area (GTS_TRIANGLE (f2)) / 4.0;
      } else {
        weight += ve2 * gts_triangle_area (GTS_TRIANGLE (f2)) / 8.0;
      }
    }

    /* projection of edge perpendicular to N (section 5.3) */
    d[0] = vec_edge[0] - vdotN * N[0];
    d[1] = vec_edge[1] - vdotN * N[1];
    d[2] = vec_edge[2] - vdotN * N[2];
    gts_vector_normalize (d);
    
    /* not explicit in the paper, but necessary.  Move d to 2D basis. */
    d1 = gts_vector_scalar (d, basis1);
    d2 = gts_vector_scalar (d, basis2);

    /* store off the curvature, direction of edge, and weights for later use */
    weights[edge_count] = weight;
    kappas[edge_count] = kappa;
    d1s[edge_count] = d1;
    d2s[edge_count] = d2;
    edge_count++;

    /* Finally, update the linear equations */
    aterm_da += weight * d1 * d1 * d1 * d1;
    bterm_da += weight * d1 * d1 * 2 * d1 * d2;
    cterm_da += weight * d1 * d1 * d2 * d2;
    const_da += weight * d1 * d1 * (- kappa);

    aterm_db += weight * d1 * d2 * d1 * d1;
    bterm_db += weight * d1 * d2 * 2 * d1 * d2;
    cterm_db += weight * d1 * d2 * d2 * d2;
    const_db += weight * d1 * d2 * (- kappa);

    i = i->next;
  }

  /* now use the identity (Section 5.3) a + c = |Kh| = 2 * kappa_h */
  aterm_da -= cterm_da;
  const_da += cterm_da * normKh;

  aterm_db -= cterm_db;
  const_db += cterm_db * normKh;
  
  /* check for solvability of the linear system */
  if (((aterm_da * bterm_db - aterm_db * bterm_da) != 0.0) &&
      ((const_da != 0.0) || (const_db != 0.0))) {
    linsolve (aterm_da, bterm_da, -const_da,
              aterm_db, bterm_db, -const_db,
              &a, &b);

    c = normKh - a;

    eigenvector (a, b, c, eig);
  } else {
    /* region of v is planar */
    eig[0] = 1.0;
    eig[1] = 0.0;
  }

  /* Although the eigenvectors of B are good estimates of the
   * principal directions, it seems that which one is attached to
   * which curvature direction is a bit arbitrary.  This may be a bug
   * in my implementation, or just a side-effect of the inaccuracy of
   * B due to the discrete nature of the sampling.
   *
   * To overcome this behavior, we'll evaluate which assignment best
   * matches the given eigenvectors by comparing the curvature
   * estimates computed above and the curvatures calculated from the
   * discrete differential operators.  */

  gts_vertex_principal_curvatures (0.5 * normKh, Kg, &K1, &K2);
  
  err_e1 = err_e2 = 0.0;
  /* loop through the values previously saved */
  for (e = 0; e < edge_count; e++) {
    gdouble weight, kappa, d1, d2;
    gdouble temp1, temp2;
    gdouble delta;

    weight = weights[e];
    kappa = kappas[e];
    d1 = d1s[e];
    d2 = d2s[e];

    temp1 = fabs (eig[0] * d1 + eig[1] * d2);
    temp1 = temp1 * temp1;
    temp2 = fabs (eig[1] * d1 - eig[0] * d2);
    temp2 = temp2 * temp2;

    /* err_e1 is for K1 associated with e1 */
    delta = K1 * temp1 + K2 * temp2 - kappa;
    err_e1 += weight * delta * delta;

    /* err_e2 is for K1 associated with e2 */
    delta = K2 * temp1 + K1 * temp2 - kappa;
    err_e2 += weight * delta * delta;
  }
  g_free (weights);
  g_free (kappas);
  g_free (d1s);
  g_free (d2s);

  /* rotate eig by a right angle if that would decrease the error */
  if (err_e2 < err_e1) {
    gdouble temp = eig[0];

    eig[0] = eig[1];
    eig[1] = -temp;
  }

  e1[0] = eig[0] * basis1[0] + eig[1] * basis2[0];
  e1[1] = eig[0] * basis1[1] + eig[1] * basis2[1];
  e1[2] = eig[0] * basis1[2] + eig[1] * basis2[2];
  gts_vector_normalize (e1);

  /* make N,e1,e2 a right handed coordinate sytem */
  gts_vector_cross (e2, N, e1);
  gts_vector_normalize (e2);
}
Esempio n. 16
0
static PyObject *
new_(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
  PyObject *o;
  PygtsObject *obj;
  guint alloc_gtsobj = TRUE;
  PyObject *o1_,*o2_,*o3_;
  GtsVertex *v1=NULL, *v2=NULL, *v3=NULL;
  GtsEdge *e1=NULL,*e2=NULL,*e3=NULL,*e;
  GtsSegment *s1,*s2,*s3;
  gboolean flag=FALSE;  /* Flag when the args are gts.Point objects */
  GtsFace *f;
  GtsTriangle *t;
  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)) < 3 ) {
      PyErr_SetString(PyExc_TypeError,"expected three Edges or three Vertices");
      return NULL;
    }
    o1_ = PyTuple_GET_ITEM(args,0);
    o2_ = PyTuple_GET_ITEM(args,1);
    o3_ = PyTuple_GET_ITEM(args,2);

    /* Convert to PygtsObjects */
    if( pygts_edge_check(o1_) ) {
      e1 = PYGTS_EDGE_AS_GTS_EDGE(o1_);
    }
    else {
      if( pygts_vertex_check(o1_) ) {
	v1 = PYGTS_VERTEX_AS_GTS_VERTEX(o1_);
	flag = TRUE;
      }
    }

    if( pygts_edge_check(o2_) ) {
      e2 = PYGTS_EDGE_AS_GTS_EDGE(o2_);
    }
    else {
      if( pygts_vertex_check(o2_) ) {
	v2 = PYGTS_VERTEX_AS_GTS_VERTEX(o2_);
	flag = TRUE;
      }
    }

    if( pygts_edge_check(o3_) ) {
      e3 = PYGTS_EDGE_AS_GTS_EDGE(o3_);
    }
    else {
      if(pygts_vertex_check(o3_)) {
	v3 = PYGTS_VERTEX_AS_GTS_VERTEX(o3_);
	flag = TRUE;
      }
    }
    
    /* Check for three edges or three vertices */
    if( !((e1!=NULL && e2!=NULL && e3!=NULL) ||
	  (v1!=NULL && v2!=NULL && v3!=NULL)) ) {
      PyErr_SetString(PyExc_TypeError,
		      "three Edge or three Vertex objects expected");
      return NULL;
    }

    if(flag) {

      /* Create gts edges */
      if( (e1 = gts_edge_new(gts_edge_class(),v1,v2)) == NULL ) {
	PyErr_SetString(PyExc_MemoryError, "could not create Edge");
	return NULL;
      }
      if( (e2 = gts_edge_new(gts_edge_class(),v2,v3)) == NULL ) {
	PyErr_SetString(PyExc_MemoryError, "could not create Edge");
	gts_object_destroy(GTS_OBJECT(e1));
	return NULL;
      }
      if( (e3 = gts_edge_new(gts_edge_class(),v3,v1)) == NULL ) {
	PyErr_SetString(PyExc_MemoryError, "could not create Edge");
	gts_object_destroy(GTS_OBJECT(e1));
	gts_object_destroy(GTS_OBJECT(e2));
	return NULL;
      }
      
      /* Check for duplicates */
      if( (e = gts_edge_is_duplicate(e1)) != NULL ) {
	gts_object_destroy(GTS_OBJECT(e1));
	e1 = e;
      }
      if( (e = gts_edge_is_duplicate(e2)) != NULL ) {
	gts_object_destroy(GTS_OBJECT(e2));
	e2 = e;
      }
      if( (e = gts_edge_is_duplicate(e3)) != NULL ) {
	gts_object_destroy(GTS_OBJECT(e3));
	e3 = e;
      }
    }
  
    /* Check that edges connect */
    s1 = GTS_SEGMENT(e1);
    s2 = GTS_SEGMENT(e2);
    s3 = GTS_SEGMENT(e3);
    if( !((s1->v1==s3->v2 && s1->v2==s2->v1 && s2->v2==s3->v1) ||
	  (s1->v1==s3->v2 && s1->v2==s2->v2 && s2->v1==s3->v1) ||
	  (s1->v1==s3->v1 && s1->v2==s2->v1 && s2->v2==s3->v2) ||
	  (s1->v2==s3->v2 && s1->v1==s2->v1 && s2->v2==s3->v1) ||
	  (s1->v1==s3->v1 && s1->v2==s2->v2 && s2->v1==s3->v2) ||
	  (s1->v2==s3->v2 && s1->v1==s2->v2 && s2->v1==s3->v1) ||
	  (s1->v2==s3->v1 && s1->v1==s2->v1 && s2->v2==s3->v2) ||
	  (s1->v2==s3->v1 && s1->v1==s2->v2 && s2->v1==s3->v2)) ) {
      PyErr_SetString(PyExc_RuntimeError, "Edges in face must connect");
      if(!g_hash_table_lookup(obj_table,GTS_OBJECT(e1))) {
	gts_object_destroy(GTS_OBJECT(e1));
      }
      if(!g_hash_table_lookup(obj_table,GTS_OBJECT(e1))) {
	gts_object_destroy(GTS_OBJECT(e2));
      }
      if(!g_hash_table_lookup(obj_table,GTS_OBJECT(e1))) {
	gts_object_destroy(GTS_OBJECT(e3));
      }
      return NULL;
    }

    /* Create the GtsFace */
    if( (f = gts_face_new(gts_face_class(),e1,e2,e3)) == NULL )  {
      PyErr_SetString(PyExc_MemoryError, "could not create Face");
      if(!g_hash_table_lookup(obj_table,GTS_OBJECT(e1))) {
	gts_object_destroy(GTS_OBJECT(e1));
      }
      if(!g_hash_table_lookup(obj_table,GTS_OBJECT(e1))) {
	gts_object_destroy(GTS_OBJECT(e2));
      }
      if(!g_hash_table_lookup(obj_table,GTS_OBJECT(e1))) {
	gts_object_destroy(GTS_OBJECT(e3));
      }
      return NULL;
    }

    /* Check for duplicate */
    t = gts_triangle_is_duplicate(GTS_TRIANGLE(f));
    if( t != NULL ) {
      gts_object_destroy(GTS_OBJECT(f));
      if(!GTS_IS_FACE(t)) {
	PyErr_SetString(PyExc_TypeError, "expected a Face (internal error)");
      }
      f = GTS_FACE(t);
    }

    /* If corresponding PyObject found in object table, we are done */
    if( (obj=(PygtsObject*)g_hash_table_lookup(obj_table,GTS_OBJECT(f))) != NULL ) {
      Py_INCREF(obj);
      return (PyObject*)obj;
    }
  }
  
  /* Chain up */
  obj = PYGTS_OBJECT(PygtsTriangleType.tp_new(type,args,kwds));

  if( alloc_gtsobj ) {

    obj->gtsobj = GTS_OBJECT(f);

    /* Create the parent GtsSurface */
    if( (obj->gtsobj_parent = parent(GTS_FACE(obj->gtsobj))) == NULL ) {
      gts_object_destroy(obj->gtsobj);
      obj->gtsobj = NULL;
      return NULL;
    }

    pygts_object_register(PYGTS_OBJECT(obj));
  }

  return (PyObject*)obj;
}