pair<double, double> polygon_gravity_center(node *s, int n)
{//多边形s有n个顶点,下标从0到n-1,顶点按逆时针方向排列
 //返回多边形重心,pair.first是x坐标,pair.second是y坐标
	node p(0, 0);
	//数组o指代三角形重心,数组area指代三角形面积
	pair<double, double> o[MAX];
	double area[MAX];
	for(int i = 0; i < n; ++ i){
		if(i != n - 1){
			o[i] = triangle_gravity_center(p, s[i], s[i + 1]);
			area[i] = triangle_area(p, s[i], s[i + 1]);
		}
		else{
			o[i] = triangle_gravity_center(p, s[i], s[0]);
			area[i] = triangle_area(p, s[i], s[0]);
		}
	}
	double a_sum(0);
	pair<double, double> o_sum(0, 0);
	for(int i = 0; i < n; ++ i)
		a_sum += area[i];
	for(int i = 0; i < n; ++ i){
		o_sum.first += o[i].first * area[i];
		o_sum.second += o[i].second * area[i];
	}
	return(make_pair(o_sum.first / a_sum, o_sum.second / a_sum));
}
Exemplo n.º 2
0
// test wether point X is inside triangle ABC
static int winding_triangle(double A[2], double B[2], double C[2], double X[2])
{
	double v1 = triangle_area(A, B, X);
	double v2 = triangle_area(B, C, X);
	double v3 = triangle_area(C, A, X);
	int r = 0;
	if (v1 >= 0 && v2 >= 0 && v3 >= 0) r = 1;
	if (v1 < 0 && v2 < 0 && v3 < 0) r = -1;
	return r;
}
Exemplo n.º 3
0
static void tri_test(void)
{
  mesh* m;
  point pts[3];
  ment v[3];
  ment e;
  unsigned i;
  double A;
  double l[3];
  double s;
  m = mesh_new();
  pts[0] = point_new(-1,0,0);
  pts[1] = point_new( 1,0,0);
  pts[2] = point_new( 0,my_sqrt(3),0);
  for (i = 0; i < 3; ++i)
    v[i] = ment_new(m, VERTEX, 0);
  for (i = 0; i < 3; ++i)
    mesh_set_point(m, v[i], pts[i]);
  e = ment_new(m, TRIANGLE, v);
  A = triangle_area(ment_triangle(m, e));
  debug("area: %e\n", A);
  s = 0;
  for (i = 0; i < 3; ++i) {
    mesh_down(m, e, EDGE, i, v);
    l[i] = line_len(verts_line(m, v));
    debug("length: %e\n", l[i]);
    s += l[i] * l[i];
  }
  s /= 3;
  debug("condition bound: %e\n", A / s);
  debug("quality: %e\n", ment_quality(m, e));
  mesh_free(m);
}
Exemplo n.º 4
0
static void tet_test(void)
{
  mesh* m;
  point pts[4];
  ment v[4];
  ment e;
  unsigned i;
  double V;
  double A[4];
  double s;
  m = mesh_new();
  pts[0] = point_new(-1, 0, -1.0 / my_sqrt(2));
  pts[1] = point_new( 1, 0, -1.0 / my_sqrt(2));
  pts[2] = point_new( 0,-1,  1.0 / my_sqrt(2));
  pts[3] = point_new( 0, 1,  1.0 / my_sqrt(2));
  for (i = 0; i < 4; ++i)
    v[i] = ment_new(m, VERTEX, 0);
  for (i = 0; i < 4; ++i)
    mesh_set_point(m, v[i], pts[i]);
  e = ment_new(m, TET, v);
  V = tet_volume(ment_tet(m, e));
  debug("volume: %e\n", V);
  s = 0;
  for (i = 0; i < 4; ++i) {
    mesh_down(m, e, TRIANGLE, i, v);
    A[i] = triangle_area(verts_triangle(m, v));
    debug("area: %e\n", A[i]);
    s += A[i] * A[i];
  }
  s /= 4;
  s = my_pow(s, 3.0 / 4.0);
  debug("condition bound: %.10e\n", V / s);
  debug("quality: %e\n", ment_quality(m, e));
  mesh_free(m);
}
Exemplo n.º 5
0
/**
 * @brief Read triangles from an element file generated by Triangle.
 *
 * @param[in] fd An open file descriptor.
 * @param[in] fmt A format string, using the printf notations.
 * @param[in] mesh The mesh into which to put the nodes.
 */
static void
mesh_read_triangles(FILE* fd, const char* fmt, mesh_t* mesh)
{
    size_t i = 0;
    int ret = -1;
    int node1 = -1;
    int node2 = -1;
    int node3 = -1;

    mesh->triangle = smalloc(mesh->nb_triangles * sizeof(triangle_t));

    for (i = 0; i < mesh->nb_triangles && !feof(fd); ++i) {
        /* TRIANGLE: triangle index - node - node - node
         * FREEFEM: node - node - node
         */
        ret = fscanf(fd, fmt, &node1, &node2, &node3);

        /* we didn't read everything, something is wrong */
        if (ret < 3) {
            die("read_elements: fscanf failed at %lu.", i);
        }

        mesh->triangle[i].A = &(mesh->node[node1 - 1]);
        mesh->triangle[i].B = &(mesh->node[node2 - 1]);
        mesh->triangle[i].C = &(mesh->node[node3 - 1]);
        mesh->triangle[i].area = triangle_area(mesh->triangle[i]);
    }

    debug("read %lu triangles.", i);
}
void CThinshellElementFEM::_initElements(
    const CMeMaterialProperty &mtl,
    const Vector3d &p0, const Vector3d &p1, const Vector3d &p2, const Vector3d &p3,
    const double& thickness)
{
    //compute volume for each triangle, each truss edge
    m_area0 = fabs(triangle_area(p0, p1, p2));
    m_area1 = fabs(triangle_area(p0, p1, p3));
    m_thickness = thickness;

    //construct the world/local transform matrix for the two triangles
    double3x3 rot;
    Vector3d N0, N1;
    const Vector3d q1=p1-p0, q2=p2-p0, q3=p3-p0;
    getReferencePlanesForTrianglePair(q1, q2, q3, N0, N1, rot, m_len0);
    const Vector3d qq1(m_len0, 0, 0);
    const Vector3d qq2 = rot*q2;
    const Vector3d qq3 = rot*q3;
    m_qq2 = qq2;
    m_qq3 = qq3;
    const double DELTA = m_len0*HEIGHT_DELTA;
    const Vector3d qq4 = rot*(q2+DELTA*N0);
    const Vector3d qq5 = rot*(q3+DELTA*N1);

    //derivitive pF/pX
    copyVectorsToColumns(qq1, qq2, qq4, m_XInv0);
    copyVectorsToColumns(qq1, qq3, qq5, m_XInv1);
    m_XInv0.Invert();
    m_XInv1.Invert();

    //stiffness related comp.
    double3x3 jac[6];
    double3x3 *ppJacobian[6]= {jac, jac+1, jac+2, jac+3, jac+4, jac+5};
    const double E = mtl.getYoung()*m_thickness;
    computeStiffnessMat(m_XInv0, -E*m_area0, ppJacobian);
    computeStiffnessMat(m_XInv1, -E*m_area1, ppJacobian+3);
    m_A11 = jac[0].x[0];
    m_A12 = jac[1].x[0];
    m_A22 = jac[2].x[0];
    m_B11 = jac[3].x[0];
    m_B12 = jac[4].x[0];
    m_B22 = jac[5].x[0];

    m_strain0.ZeroMatrix();
    m_strain1.ZeroMatrix();
}
Exemplo n.º 7
0
gdouble element_area( const Element *element )
{
    g_return_val_if_fail( element != NULL, 0.0 );

    HalfEdge *he = element->adjacent_halfedge;
    Point2 *p1 = NODE_POSITION(he->origin);
    Point2 *p2 = NODE_POSITION(he->next->origin);
    Point2 *p3 = NODE_POSITION(he->next->next->origin);

    return triangle_area( p1, p2, p3 );
}
Exemplo n.º 8
0
static void polygon2_compute_area(polygon2_t* poly)
{
  // Compute the area using the fan algorithm.
  poly->area = 0.0;
  int I = poly->ordering[0];
  for (int j = 1; j < poly->num_vertices - 1; ++j)
  {
    // Form a triangle from vertex 0, vertex j, and vertex j+1.
    int J = poly->ordering[j];
    int K = poly->ordering[j+1];
    poly->area += triangle_area(&poly->vertices[I], &poly->vertices[J], &poly->vertices[K]);
  }
}
Exemplo n.º 9
0
int main(void)
{
  double base, height, area;

  printf("Enter the base and height: ");
  scanf("%lf %lf", &base, &height);

  area = triangle_area(base, height);

  printf("Triangle area is: %g\n", area);

  return 0;
}
Exemplo n.º 10
0
int main()
{
    float a1, a2, c1, c2, k1, k2;
    char h;
    
    a1 = triangle_area(3, 8);
    a2 = triangle_area(14, 2);
    printf("%.2f, %.2f",a1, a2);
    
    c1 = fahrenheit2celsius(32);
    c2 = fahrenheit2celsius(212);
    printf("\n%.2f, %.2f",c1, c2);
    
    k1 = fahrenheit2kelvin(32);
    k2 = fahrenheit2kelvin(212);
    printf("\n%.2f, %.2f", k1, k2);
    
    displayHello();
    
    
    
    getchar();getchar();
    return 0;
}
Exemplo n.º 11
0
Arquivo: mxmath.c Projeto: asir6/Colt
double triangle_compactness(const Vec3 *v1, const Vec3 *v2, const Vec3 *v3)
{

	Vec3 temp1, temp2, temp3;
	double l1, l2, l3;

	mxv_sub( temp1.elt, v2->elt, v1->elt, 3 );
	mxv_sub( temp2.elt, v3->elt, v2->elt, 3 );
	mxv_sub( temp3.elt, v1->elt, v3->elt, 3 );
    l1 = mxv_len2( temp1.elt, 3 );
    l2 = mxv_len2( temp2.elt, 3 );
    l3 = mxv_len2( temp3.elt, 3 );

	return FOUR_ROOT3 * triangle_area(v1, v2, v3) / (l1+l2+l3);

} /* end function triangle_compactness */
/* Triangle print */
static int triangle_print(struct seq_file *m, void *v)
{
	int area;

	seq_printf(m, "Triangle: \n");
	if (triangle_impossible == 1) {
		seq_printf(m, "Impossible\n");
	} else {
		/* points */
		seq_printf(m, "A(x=%d, y=%d), ", given_triangle.A.x, given_triangle.A.y);
		seq_printf(m, "B(x=%d, y=%d), ", given_triangle.B.x, given_triangle.B.y);
		seq_printf(m, "C(x=%d, y=%d)\n", given_triangle.C.x, given_triangle.C.y);
		/* sides */
		seq_printf(m, "a=%d, ", given_triangle.side_a);
		seq_printf(m, "b=%d, ", given_triangle.side_b);
		seq_printf(m, "c=%d\n", given_triangle.side_c);
		/* perimeter */
		seq_printf(m, "perimeter=%d\n", given_triangle.side_a + 
			given_triangle.side_b + given_triangle.side_c);
		/* area */
		area = triangle_area(&given_triangle);
		seq_printf(m, "area=%d\n", area);
		/* height */
		seq_printf(m, "ha=%d, ", (area * 2) / given_triangle.side_a);
		seq_printf(m, "hb=%d, ", (area * 2) / given_triangle.side_b);
		seq_printf(m, "hc=%d\n", (area * 2) / given_triangle.side_b);
		/* median */
		seq_printf(m, "ma=%d, ", triangle_median(given_triangle.side_b, 
			given_triangle.side_c, given_triangle.side_a));
		seq_printf(m, "mb=%d, ", triangle_median(given_triangle.side_a, 
			given_triangle.side_c, given_triangle.side_b));
		seq_printf(m, "mc=%d\n", triangle_median(given_triangle.side_a, 
			given_triangle.side_b, given_triangle.side_c));

		/* TODO: angles... */
	}

	return 0;
}
Exemplo n.º 13
0
double MeshData::mesh_area(void)
{
    double      s;
    int         i1, i2, i3;
    double      *p1, *p2, *p3;

    int         i;

    s = 0;
    for(i=0; i<ele_num; i++) {
        i1 = ele_arr[i*3+0];
        i2 = ele_arr[i*3+1];
        i3 = ele_arr[i*3+2];

        p1 = vex_arr+i1*3;
        p2 = vex_arr+i2*3;
        p3 = vex_arr+i3*3;

        s += triangle_area(p1, p2, p3);
    }

    return s;
}
Exemplo n.º 14
0
INLINE Real element_size(Few<Vector<2>, 2> b) { return triangle_area(b); }
Exemplo n.º 15
0
void polygon2_clip(polygon2_t* poly, polygon2_t* other)
{
  // This implementation is based on that shown in Chapter 7.6.1 of 
  // Joseph O'Rourke's _Computational_Geometry_In_C_.

  int a = 0, b = 0, aa = 0, ba = 0;
  int n = poly->num_vertices, m = other->num_vertices;
  polygon2_inout_t inflag = UNKNOWN;
  static point2_t origin = {.x = 0.0, .y = 0.0};
  point2_t p0; // First point.

  // We'll store the coordinates of the vertices of the 
  // clipped polygon here.
  real_slist_t* xlist = real_slist_new();
  real_slist_t* ylist = real_slist_new();

  do
  {
    // Computations of key variables.
    int a1 = (a + n - 1) % n;
    int b1 = (b + m - 1) % m;

    int aa = poly->ordering[a];
    int aa1 = poly->ordering[a1];
    int bb = poly->ordering[b];
    int bb1 = poly->ordering[b1];

    point2_t* Pa = &poly->vertices[aa];
    point2_t* Pa1 = &poly->vertices[aa1];
    point2_t* Qb = &other->vertices[bb];
    point2_t* Qb1 = &other->vertices[bb1];

    point2_t A, B;
    A.x = Pa1->x - Pa->x;
    A.y = Pa1->y - Pa->y;
    B.x = Qb1->x - Qb->x;
    B.y = Qb1->y - Qb->y;

    int cross = SIGN(triangle_area(&origin, &A, &B));
    int aHB   = SIGN(triangle_area(Qb1, Qb, Pa));
    int bHA   = SIGN(triangle_area(Pa1, Pa, Qb));

    // If A and B intersect, update inflag.
    point2_t p;
    char code = seg_set_int(Pa1, Pa, Qb1, Qb, &p);
    if ((code == '1') || (code == 'v')) 
    {
      if ((inflag == UNKNOWN) && (real_slist_empty(xlist)))
      {
        aa = ba = 0;
        p0.x = p.x;
        p0.y = p.y;
        real_slist_append(xlist, p0.x);
        real_slist_append(ylist, p0.y);
      }
      inflag = in_out(&p, inflag, aHB, bHA, xlist, ylist);
    }

    // Advance rules.
    else if (cross >= 0)
    {
      if (bHA > 0)
        a = advance(a, &aa, n, (inflag == PIN), Pa, xlist, ylist);
      else
        b = advance(b, &ba, m, (inflag == QIN), Qb, xlist, ylist);
    }
    else // if (cross < 0)
    {
      if (aHB > 0)
        b = advance(b, &ba, m, (inflag == QIN), Qb, xlist, ylist);
      else
        a = advance(a, &aa, n, (inflag == PIN), Pa, xlist, ylist);
    }
  }
  while (((aa < n) || (ba < m)) && (aa < 2*n) && (ba < 2*m));

  // Replace this polygon with its clipped version.
  ASSERT(xlist->size > 0);
  ASSERT(xlist->size == ylist->size);
  if (xlist->size > poly->num_vertices)
    poly->vertices = polymec_realloc(poly->vertices, sizeof(point2_t)*xlist->size);
  poly->num_vertices = xlist->size;
  for (int i = 0; i < xlist->size; ++i)
  {
    // FIXME: Verify!
    poly->vertices[i].x = real_slist_pop(xlist, NULL);
    poly->vertices[i].y = real_slist_pop(ylist, NULL);
  }
  polygon2_compute_area(poly);

  // Clean up.
  real_slist_free(xlist);
  real_slist_free(ylist);
}
Exemplo n.º 16
0
/**
* @brief judge the point D whether is inside the triangle.
*
* @param A one point of triangle.
* @param B one point of triangle.
* @param C one point of triangle.
* @param D one point to judge whether it is inside the triangle.
*
* @return return 0 means not inside the triangle, else return 1 means inside in 
* the triangle, otherwise return -1 means some error occur, such as invalid 
* triangle.
*/
int point_inside_triangle_use_areasum(POINT A, POINT B, POINT C, POINT D) {
	if (!triangle_verification(A, B, C)) { return -1; }
	return (triangle_area(A, B, C) >= triangle_area(A, B, D) 
		+ triangle_area(B, C, D) + triangle_area(C, A, D));
}
Exemplo n.º 17
0
static int getAspectRatio(std::vector<MElement *> &elements,
                          std::vector<std::vector<MEdge> > &boundaries)
{

  double area3D = 0.0;
  for(unsigned int i = 0; i <elements.size(); ++i){
    MElement *t = elements[i];
    std::vector<MVertex *> v(3);
    for(int k = 0; k < 3; k++) v[k] = t->getVertex(k);
    double p0[3] = {v[0]->x(), v[0]->y(), v[0]->z()};
    double p1[3] = {v[1]->x(), v[1]->y(), v[1]->z()};
    double p2[3] = {v[2]->x(), v[2]->y(), v[2]->z()};
    double a_3D = fabs(triangle_area(p0, p1, p2));
    area3D += a_3D;
  }

  double tot_length = 0.0;
  for(unsigned int i = 0; i <boundaries.size(); ++i){
    std::vector<MEdge> iBound = boundaries[i];
    double iLength = 0.0;
    for( unsigned int j = 0; j <iBound.size(); ++j){
      MVertex *v0 = iBound[j].getVertex(0);
      MVertex *v1 = iBound[j].getVertex(1);
      const double length = sqrt((v0->x() - v1->x()) * (v0->x() - v1->x()) +
                                 (v0->y() - v1->y()) * (v0->y() - v1->y()) +
                                 (v0->z() - v1->z()) * (v0->z() - v1->z()));
      iLength += length;
    }
    tot_length += iLength;
  }
  int AR = 1;
  if (boundaries.size() > 0){
    tot_length /= boundaries.size();
    AR = (int) ceil(2*3.14*area3D/(tot_length*tot_length));
  }

  //compute AR also with Bounding box
  std::set<MVertex*> vs;
  for(unsigned int i = 0; i < elements.size(); i++){
    MElement *e = elements[i];
    for(int j = 0; j < e->getNumVertices(); j++){
      vs.insert(e->getVertex(j));
    }
  }
  SBoundingBox3d bb;
  std::vector<SPoint3> vertices;
  for (std::set<MVertex* >::iterator it = vs.begin(); it != vs.end(); it++){
    SPoint3 pt((*it)->x(),(*it)->y(), (*it)->z());
    vertices.push_back(pt);
    bb += pt;
  }
  double H = norm(SVector3(bb.max(), bb.min()));

  //SOrientedBoundingBox obbox =  SOrientedBoundingBox::buildOBB(vertices);
  //double H = obbox.getMaxSize();

  double D = H;
  if (boundaries.size()  > 0 ) D = 10e4;
  for (unsigned int i = 0; i < boundaries.size(); i++){
    std::set<MVertex*> vb;
    std::vector<MEdge> iBound = boundaries[i];
    for (unsigned int j = 0; j < iBound.size(); j++){
      MEdge e = iBound[j];
      vb.insert(e.getVertex(0));
      vb.insert(e.getVertex(1));
    }
    std::vector<SPoint3> vBounds;
    SBoundingBox3d bb;
    for (std::set<MVertex* >::iterator it = vb.begin(); it != vb.end(); it++){
      SPoint3 pt((*it)->x(),(*it)->y(), (*it)->z());
      vBounds.push_back(pt);
      bb +=pt;
    }
    double iD = norm(SVector3(bb.max(), bb.min()));
    D = std::min(D, iD);

    //SOrientedBoundingBox obboxD = SOrientedBoundingBox::buildOBB(vBounds);
    //D = std::max(D, obboxD.getMaxSize());
  }
  int AR2 = (int)ceil(H/D);

  return std::max(AR, AR2);
}
Exemplo n.º 18
0
int intersect_prop ( double xa, double ya, double xb, double yb, double xc, 
  double yc, double xd, double yd )

/******************************************************************************/
/*
  Purpose:

    INTERSECT_PROP is TRUE if lines VA:VB and VC:VD have a proper intersection.

  Licensing:

    This code is distributed under the GNU LGPL license.

  Modified:

    04 May 2014

  Author:

    Original C version by Joseph ORourke.
    This C version by John Burkardt.

  Reference:

    Joseph ORourke,
    Computational Geometry in C,
    Cambridge, 1998,
    ISBN: 0521649765,
    LC: QA448.D38.

  Parameters:

    Input, double XA, YA, XB, YB, XC, YC, XD, YD, the X and Y 
    coordinates of the four vertices.

    Output, int INTERSECT_PROP, the result of the test.
*/
{
  double t1;
  double t2;
  double t3;
  double t4;
  int value;
  int value1;
  int value2;
  int value3;
  int value4;

  if ( collinear ( xa, ya, xb, yb, xc, yc ) )
  {
    value = 0;
  }
  else if ( collinear ( xa, ya, xb, yb, xd, yd ) )
  {
    value = 0;
  }
  else if ( collinear ( xc, yc, xd, yd, xa, ya ) )
  {
    value = 0;
  }
  else if ( collinear ( xc, yc, xd, yd, xb, yb ) )
  {
    value = 0;
  }
  else
  {
    t1 = triangle_area ( xa, ya, xb, yb, xc, yc );
    t2 = triangle_area ( xa, ya, xb, yb, xd, yd );
    t3 = triangle_area ( xc, yc, xd, yd, xa, ya );
    t4 = triangle_area ( xc, yc, xd, yd, xb, yb );

    value1 = ( 0.0 < t1 );
    value2 = ( 0.0 < t2 );
    value3 = ( 0.0 < t3 );
    value4 = ( 0.0 < t4 );

    value = ( l4_xor ( value1, value2 ) ) && ( l4_xor ( value3, value4 ) );
  }
  return value;
}
Exemplo n.º 19
0
float QuadDice::quad_area(const float3& a, const float3& b, const float3& c, const float3& d)
{
	return triangle_area(a, b, d) + triangle_area(a, d, c);
}
Exemplo n.º 20
0
template <typename PointInT, typename PointOutT> void
pcl::ROPSEstimation <PointInT, PointOutT>::computeLRF (const PointInT& point, const std::set <unsigned int>& local_triangles, Eigen::Matrix3f& lrf_matrix) const
{
  const unsigned int number_of_triangles = static_cast <unsigned int> (local_triangles.size ());

  std::vector<Eigen::Matrix3f, Eigen::aligned_allocator<Eigen::Matrix3f> > scatter_matrices (number_of_triangles);
  std::vector <float> triangle_area (number_of_triangles);
  std::vector <float> distance_weight (number_of_triangles);

  float total_area = 0.0f;
  const float coeff = 1.0f / 12.0f;
  const float coeff_1_div_3 = 1.0f / 3.0f;

  Eigen::Vector3f feature_point (point.x, point.y, point.z);

  std::set <unsigned int>::const_iterator it;
  unsigned int i_triangle = 0;
  for (it = local_triangles.begin (), i_triangle = 0; it != local_triangles.end (); it++, i_triangle++)
  {
    Eigen::Vector3f pt[3];
    for (unsigned int i_vertex = 0; i_vertex < 3; i_vertex++)
    {
      const unsigned int index = triangles_[*it].vertices[i_vertex];
      pt[i_vertex] (0) = surface_->points[index].x;
      pt[i_vertex] (1) = surface_->points[index].y;
      pt[i_vertex] (2) = surface_->points[index].z;
    }

    const float curr_area = ((pt[1] - pt[0]).cross (pt[2] - pt[0])).norm ();
    triangle_area[i_triangle] = curr_area;
    total_area += curr_area;

    distance_weight[i_triangle] = pow (support_radius_ - (feature_point - (pt[0] + pt[1] + pt[2]) * coeff_1_div_3).norm (), 2.0f);

    Eigen::Matrix3f curr_scatter_matrix;
    curr_scatter_matrix.setZero ();
    for (unsigned int i_pt = 0; i_pt < 3; i_pt++)
    {
      Eigen::Vector3f vec = pt[i_pt] - feature_point;
      curr_scatter_matrix += vec * (vec.transpose ());
      for (unsigned int j_pt = 0; j_pt < 3; j_pt++)
        curr_scatter_matrix += vec * ((pt[j_pt] - feature_point).transpose ());
    }
    scatter_matrices[i_triangle] = coeff * curr_scatter_matrix;
  }

  if (std::abs (total_area) < std::numeric_limits <float>::epsilon ())
    total_area = 1.0f / total_area;
  else
    total_area = 1.0f;

  Eigen::Matrix3f overall_scatter_matrix;
  overall_scatter_matrix.setZero ();
  std::vector<float> total_weight (number_of_triangles);
  const float denominator = 1.0f / 6.0f;
  for (unsigned int i_triangle = 0; i_triangle < number_of_triangles; i_triangle++)
  {
    float factor = distance_weight[i_triangle] * triangle_area[i_triangle] * total_area;
    overall_scatter_matrix += factor * scatter_matrices[i_triangle];
    total_weight[i_triangle] = factor * denominator;
  }

  Eigen::Vector3f v1, v2, v3;
  computeEigenVectors (overall_scatter_matrix, v1, v2, v3);

  float h1 = 0.0f;
  float h3 = 0.0f;
  for (it = local_triangles.begin (), i_triangle = 0; it != local_triangles.end (); it++, i_triangle++)
  {
    Eigen::Vector3f pt[3];
    for (unsigned int i_vertex = 0; i_vertex < 3; i_vertex++)
    {
      const unsigned int index = triangles_[*it].vertices[i_vertex];
      pt[i_vertex] (0) = surface_->points[index].x;
      pt[i_vertex] (1) = surface_->points[index].y;
      pt[i_vertex] (2) = surface_->points[index].z;
    }

    float factor1 = 0.0f;
    float factor3 = 0.0f;
    for (unsigned int i_pt = 0; i_pt < 3; i_pt++)
    {
      Eigen::Vector3f vec = pt[i_pt] - feature_point;
      factor1 += vec.dot (v1);
      factor3 += vec.dot (v3);
    }
    h1 += total_weight[i_triangle] * factor1;
    h3 += total_weight[i_triangle] * factor3;
  }

  if (h1 < 0.0f) v1 = -v1;
  if (h3 < 0.0f) v3 = -v3;

  v2 = v3.cross (v1);

  lrf_matrix.row (0) = v1;
  lrf_matrix.row (1) = v2;
  lrf_matrix.row (2) = v3;
}
Exemplo n.º 21
0
double qmTet(const double &x1, const double &y1, const double &z1,
             const double &x2, const double &y2, const double &z2,
             const double &x3, const double &y3, const double &z3,
             const double &x4, const double &y4, const double &z4,
             const qualityMeasure4Tet &cr, double *volume)
{
  switch(cr){
  case QMTET_ONE:
    return 1.0;
  case QMTET_3:
    {
      double mat[3][3];
      mat[0][0] = x2 - x1;
      mat[0][1] = x3 - x1;
      mat[0][2] = x4 - x1;
      mat[1][0] = y2 - y1;
      mat[1][1] = y3 - y1;
      mat[1][2] = y4 - y1;
      mat[2][0] = z2 - z1;
      mat[2][1] = z3 - z1;
      mat[2][2] = z4 - z1;
      *volume = fabs(det3x3(mat)) / 6.;
      double l = ((x2 - x1) * (x2 - x1) +
                  (y2 - y1) * (y2 - y1) +
                  (z2 - z1) * (z2 - z1));
      l += ((x3 - x1) * (x3 - x1) + (y3 - y1) * (y3 - y1) + (z3 - z1) * (z3 - z1));
      l += ((x4 - x1) * (x4 - x1) + (y4 - y1) * (y4 - y1) + (z4 - z1) * (z4 - z1));
      l += ((x3 - x2) * (x3 - x2) + (y3 - y2) * (y3 - y2) + (z3 - z2) * (z3 - z2));
      l += ((x4 - x2) * (x4 - x2) + (y4 - y2) * (y4 - y2) + (z4 - z2) * (z4 - z2));
      l += ((x3 - x4) * (x3 - x4) + (y3 - y4) * (y3 - y4) + (z3 - z4) * (z3 - z4));
      return 12. * pow(3 * fabs(*volume), 2. / 3.) / l;
    }
  case QMTET_2:
    {
      double mat[3][3];
      mat[0][0] = x2 - x1;
      mat[0][1] = x3 - x1;
      mat[0][2] = x4 - x1;
      mat[1][0] = y2 - y1;
      mat[1][1] = y3 - y1;
      mat[1][2] = y4 - y1;
      mat[2][0] = z2 - z1;
      mat[2][1] = z3 - z1;
      mat[2][2] = z4 - z1;
      *volume = fabs(det3x3(mat)) / 6.;
      double p0[3] = {x1, y1, z1};
      double p1[3] = {x2, y2, z2};
      double p2[3] = {x3, y3, z3};
      double p3[3] = {x4, y4, z4};
      double s1 = fabs(triangle_area(p0, p1, p2));
      double s2 = fabs(triangle_area(p0, p2, p3));
      double s3 = fabs(triangle_area(p0, p1, p3));
      double s4 = fabs(triangle_area(p1, p2, p3));
      double rhoin = 3. * fabs(*volume) / (s1 + s2 + s3 + s4);
      double l = sqrt((x2 - x1) * (x2 - x1) +
                      (y2 - y1) * (y2 - y1) +
                      (z2 - z1) * (z2 - z1));
      l = std::max(l, sqrt((x3 - x1) * (x3 - x1) + (y3 - y1) * (y3 - y1) +
                           (z3 - z1) * (z3 - z1)));
      l = std::max(l, sqrt((x4 - x1) * (x4 - x1) + (y4 - y1) * (y4 - y1) +
                           (z4 - z1) * (z4 - z1)));
      l = std::max(l, sqrt((x3 - x2) * (x3 - x2) + (y3 - y2) * (y3 - y2) +
                           (z3 - z2) * (z3 - z2)));
      l = std::max(l, sqrt((x4 - x2) * (x4 - x2) + (y4 - y2) * (y4 - y2) +
                           (z4 - z2) * (z4 - z2)));
      l = std::max(l, sqrt((x3 - x4) * (x3 - x4) + (y3 - y4) * (y3 - y4) +
                           (z3 - z4) * (z3 - z4)));
      return 2. * sqrt(6.) * rhoin / l;
    }
    break;
  case QMTET_COND:
    {
      /// condition number is defined as (see Knupp & Freitag in IJNME) 
      double INVW[3][3] = {{1,-1./sqrt(3.),-1./sqrt(6.)},{0,2/sqrt(3.),-1./sqrt(6.)},{0,0,sqrt(1.5)}};
      double A[3][3] = {{x2-x1,y2-y1,z2-z1},{x3-x1,y3-y1,z3-z1},{x4-x1,y4-y1,z4-z1}};
      double S[3][3],INVS[3][3];
      matmat(A,INVW,S);
      *volume = inv3x3(S,INVS) * 0.70710678118654762;//2/sqrt(2);
      double normS = norm2 (S);
      double normINVS = norm2 (INVS);
      return normS * normINVS;      
    }
  default:
    Msg::Error("Unknown quality measure");
    return 0.;
  }
}
int main(void){
	printf("%f", triangle_area(3, 4));
	return 0;
}
Exemplo n.º 23
0
double *polygon_sample ( int nv, double v[], int n, int *seed )

/******************************************************************************/
/*
  Purpose:

    POLYGON_SAMPLE uniformly samples a polygon.

  Licensing:

    This code is distributed under the GNU LGPL license.

  Modified:

    07 May 2014

  Author:

    John Burkardt

  Parameters:

    Input, int NV, the number of vertices.

    Input, double V[2*NV], the vertices of the polygon, listed in
    counterclockwise order.

    Input, int N, the number of points to create.

    Input/output, int *SEED, a seed for the random
    number generator.

    Output, double POLYGON_SAMPLE[2*N], the points.
*/
{
  double *area_cumulative;
  double area_polygon;
  double *area_relative;
  double *area_triangle;
  double area_percent;
  int i;
  int ip1;
  int j;
  int k;
  double *r;
  double *s;
  int *triangles;
  double *x;
  double *y;
/*
  Triangulate the polygon.
*/
  x = ( double * ) malloc ( nv * sizeof ( double ) );
  y = ( double * ) malloc ( nv * sizeof ( double ) );
  for ( i = 0; i < nv; i++ )
  {
    x[i] = v[0+i*2];
    y[i] = v[1+i*2];
  }

  triangles = polygon_triangulate ( nv, x, y );
/*
  Determine the areas of each triangle.
*/
  area_triangle = ( double * ) malloc ( ( nv - 2 ) * sizeof ( double ) );

  for ( i = 0; i < nv - 2; i++ )
  {
    area_triangle[i] = triangle_area ( 
      v[0+triangles[0+i*3]*2], v[1+triangles[0+i*3]*2], 
      v[0+triangles[1+i*3]*2], v[1+triangles[1+i*3]*2], 
      v[0+triangles[2+i*3]*2], v[1+triangles[2+i*3]*2] );
  }
/*
  Normalize the areas.
*/
  area_polygon = r8vec_sum ( nv - 2, area_triangle );

  area_relative = ( double * ) malloc ( ( nv - 2 ) * sizeof ( double ) );
  for ( i = 0; i < nv - 2; i++ )
  {
    area_relative[i] = area_triangle[i] / area_polygon;
  }
/*
  Replace each area by the sum of itself and all previous ones.
*/
  area_cumulative = ( double * ) malloc ( ( nv - 2 ) * sizeof ( double ) );
  area_cumulative[0] = area_relative[0];
  for ( i = 1; i < nv - 2; i++ )
  {
    area_cumulative[i] = area_relative[i] + area_cumulative[i-1];
  }

  s = ( double * ) malloc ( 2 * n * sizeof ( double ) );

  for ( j = 0; j < n; j++ )
  {
/*
  Choose triangle I at random, based on areas.
*/
    area_percent = r8_uniform_01 ( seed );

    for ( k = 0; k < nv - 2; k++ )
    {
      i = k;

      if ( area_percent <= area_cumulative[k] )
      {
        break;
      }
    }
/*
  Now choose a point at random in triangle I.
*/
    r = r8vec_uniform_01_new ( 2, seed );

    if ( 1.0 < r[0] + r[1] )
    {
      r[0] = 1.0 - r[0];
      r[1] = 1.0 - r[1];
    }

    s[0+j*2] = ( 1.0 - r[0] - r[1] ) * v[0+triangles[0+i*3]*2]
                     + r[0]          * v[0+triangles[1+i*3]*2]
                            + r[1]   * v[0+triangles[2+i*3]*2];

    s[1+j*2] = ( 1.0 - r[0] - r[1] ) * v[1+triangles[0+i*3]*2]
                     + r[0]          * v[1+triangles[1+i*3]*2]
                            + r[1]   * v[1+triangles[2+i*3]*2];
    free ( r );
  }

  free ( area_cumulative );
  free ( area_relative );
  free ( area_triangle );
  free ( triangles );
  free ( x );
  free ( y );

  return s;
}
Exemplo n.º 24
0
bool line_3D::intersects_triangle(triangle_3D triangle, double &a, double &b, double &c, double &t)
  {
    point_3D vector1,vector2,vector3,normal;
    point_3D center;
    double bounding_sphere_radius;
    double distance_ca, distance_cb, distance_cc;

    // compute the triangle bounding sphere:

    center.x = (triangle.a.x + triangle.b.x + triangle.c.x) / 3.0;
    center.y = (triangle.a.y + triangle.b.y + triangle.c.y) / 3.0;
    center.z = (triangle.a.z + triangle.b.z + triangle.c.z) / 3.0;

    distance_ca = point_distance(center,triangle.a);
    distance_cb = point_distance(center,triangle.b);
    distance_cc = point_distance(center,triangle.c);

    bounding_sphere_radius = distance_ca;

    if (distance_cb > bounding_sphere_radius)
      bounding_sphere_radius = distance_cb;

    if (distance_cc > bounding_sphere_radius)
      bounding_sphere_radius = distance_cc;

    a = 0.0;
    b = 0.0;
    c = 0.0;

    substract_vectors(triangle.a,triangle.b,vector1);
    substract_vectors(triangle.a,triangle.c,vector2);

    cross_product(vector1,vector2,normal);

    /*
     Compute general plane equation in form
     qa * x + qb * y + qc * z + d = 0:
     */

    double qa = normal.x;
    double qb = normal.y;
    double qc = normal.z;
    double d = -1 * (qa * triangle.a.x + qb * triangle.a.y + qc * triangle.a.z);

    /* Solve for t: */

    double denominator = (qa * this->q0 + qb * this->q1 + qc * this->q2);

    if (denominator == 0)
      return false;

    t = (-qa * this->c0 - qb * this->c1 - qc * this->c2 - d) / denominator;

    /* t now contains parameter value for the intersection */

    if (t < 0.0)
      return false;

    point_3D intersection;

    this->get_point(t,intersection);  // intersection in 3D space

    if (point_distance(intersection,center) > bounding_sphere_radius)
      return false;

    // vectors from the intersection to each triangle vertex:

    substract_vectors(triangle.a,intersection,vector1);
    substract_vectors(triangle.b,intersection,vector2);
    substract_vectors(triangle.c,intersection,vector3);

    point_3D normal1, normal2, normal3;

    // now multiply the vectors to get their normals:

    cross_product(vector1,vector2,normal1);
    cross_product(vector2,vector3,normal2);
    cross_product(vector3,vector1,normal3);

    // if one of the vectors points in other direction than the others, the point is not inside the triangle:

    if (dot_product(normal1,normal2) <= 0 || dot_product(normal2,normal3) <= 0)
      return false;

    // now compute the barycentric coordinates:

    triangle_3D helper_triangle;
    double total_area;

    total_area = triangle_area(triangle);

    helper_triangle.a = intersection;
    helper_triangle.b = triangle.b;
    helper_triangle.c = triangle.c;
    a = triangle_area(helper_triangle) / total_area;

    helper_triangle.a = triangle.a;
    helper_triangle.b = intersection;
    helper_triangle.c = triangle.c;
    b = triangle_area(helper_triangle) / total_area;

    helper_triangle.a = triangle.a;
    helper_triangle.b = triangle.b;
    helper_triangle.c = intersection;
    c = triangle_area(helper_triangle) / total_area;

    return true;
  }
Exemplo n.º 25
0
bool EdgeCollapser::collapse_edge_introduces_normal_inversion( size_t source_vertex,
        size_t destination_vertex,
        size_t edge_index,
        const Vec3d& vertex_new_position )
{

    // Get the set of triangles which are going to be deleted
    std::vector< size_t >& triangles_incident_to_edge = m_surf.m_mesh.m_edge_to_triangle_map[edge_index];

    // Get the set of triangles which move because of this motion
    std::vector<size_t> moving_triangles;
    for ( size_t i = 0; i < m_surf.m_mesh.m_vertex_to_triangle_map[source_vertex].size(); ++i )
    {
        moving_triangles.push_back( m_surf.m_mesh.m_vertex_to_triangle_map[source_vertex][i] );
    }
    for ( size_t i = 0; i < m_surf.m_mesh.m_vertex_to_triangle_map[destination_vertex].size(); ++i )
    {
        moving_triangles.push_back( m_surf.m_mesh.m_vertex_to_triangle_map[destination_vertex][i] );
    }

    //
    // check for normal inversion
    //

    for ( size_t i = 0; i < moving_triangles.size(); ++i )
    {

        // Disregard triangles which will end up being deleted - those triangles incident to the collapsing edge.
        bool triangle_will_be_deleted = false;
        for ( size_t j = 0; j < triangles_incident_to_edge.size(); ++j )
        {
            if ( moving_triangles[i] == triangles_incident_to_edge[j] )
            {
                triangle_will_be_deleted = true;
                break;
            }
        }

        if ( triangle_will_be_deleted ) {
            continue;
        }

        const Vec3st& current_triangle = m_surf.m_mesh.get_triangle( moving_triangles[i] );
        Vec3d old_normal = m_surf.get_triangle_normal( current_triangle );

        Vec3d new_normal;

        double new_area;
        if ( current_triangle[0] == source_vertex || current_triangle[0] == destination_vertex )
        {
            new_normal = triangle_normal( vertex_new_position, m_surf.get_position(current_triangle[1]), m_surf.get_position(current_triangle[2]) );
            new_area = triangle_area( vertex_new_position, m_surf.get_position(current_triangle[1]), m_surf.get_position(current_triangle[2]) );
        }
        else if ( current_triangle[1] == source_vertex || current_triangle[1] == destination_vertex )
        {
            new_normal = triangle_normal( m_surf.get_position(current_triangle[0]), vertex_new_position, m_surf.get_position(current_triangle[2]) );
            new_area = triangle_area( m_surf.get_position(current_triangle[0]), vertex_new_position, m_surf.get_position(current_triangle[2]) );
        }
        else
        {
            assert( current_triangle[2] == source_vertex || current_triangle[2] == destination_vertex );
            new_normal = triangle_normal( m_surf.get_position(current_triangle[0]), m_surf.get_position(current_triangle[1]), vertex_new_position );
            new_area = triangle_area( m_surf.get_position(current_triangle[0]), m_surf.get_position(current_triangle[1]), vertex_new_position );
        }

        if ( dot( new_normal, old_normal ) < 1e-5 )
        {
            if ( m_surf.m_verbose ) {
                std::cout << "collapse edge introduces normal inversion" << std::endl;
            }

            g_stats.add_to_int( "EdgeCollapser:collapse_normal_inversion", 1 );

            return true;
        }

        if ( new_area < m_surf.m_min_triangle_area )
        {
            if ( m_surf.m_verbose ) {
                std::cout << "collapse edge introduces tiny triangle area" << std::endl;
            }

            g_stats.add_to_int( "EdgeCollapser:collapse_degenerate_triangle", 1 );

            return true;
        }

    }

    return false;

}
Exemplo n.º 26
0
void CThinshell2Element::init(const int isstatic, 
		const int nodeid,						//the center vertex id
		const Vector3d *p,						//vertex position buffer
		const Vector3d *wpnorm,					//weighted polygon normal array
		const int *surfpoly,					//buffer of the whole surface polygons
		const int nv_per_elm,					//number of vertices for each surface polygon
		const int *polyfanid,					//the polyfan around the center vertex, input IDs only
		const int n1RingPoly,					//valence of the center vertex, also length of poylfanid
		const double& thickness)
{
	double plyvolume[MAX_NODE_VALENCE+1], edgevolume[MAX_NODE_VALENCE+1];
	int i, k;

	m_n1RingPoly = n1RingPoly;
	m_nCenterID = nodeid;
	for (i=0; i<n1RingPoly; i++) m_n1RingPolyID[i]=polyfanid[i];

	//Find all the fan polygons, store in tri buffer
	set<int> nodeset; nodeset.clear();
	for (i=0; i<n1RingPoly; i++){
		const int plyid = polyfanid[i];
		const int *ppoly = &surfpoly[plyid*nv_per_elm];
		_searchNodeInPolygon(nodeid, ppoly, nv_per_elm, nodeset);
		if (nv_per_elm==3){
			Vector3i tri(ppoly[0], ppoly[1], ppoly[2]);
			plyvolume[i] = triangle_area(p[tri.x], p[tri.y], p[tri.z]);
		}
		else{
			ASSERT0(nv_per_elm==4);
			Vector4i tri(ppoly[0], ppoly[1], ppoly[2], ppoly[3]);
			plyvolume[i] = quad_area(p[tri.x], p[tri.y], p[tri.z], p[tri.w]);
		}
	}

	//use the fan polygons to find the truss vertices
	set<int>::iterator itr = nodeset.begin();
	k = 0;
	while(itr!=nodeset.end()){
		m_nNodeID[k] = *itr;
		itr++, k++;
	}
	m_nRod = k;
	assert(m_nRod>0);
	if (m_nRod>MAX_NODE_VALENCE){
		printf("ALERT: node valence buffer is too small, increase to %d!!\n", m_nRod);
		m_nRod = MAX_NODE_VALENCE;
	}

	//find truss edge volume
	for (i=0; i<m_n1RingPoly; i++) plyvolume[i]*= thickness/nv_per_elm;
	for (i=0; i<m_nRod; i++) edgevolume[i]=0;
	for (i=0; i<m_n1RingPoly; i++){
		const double vol = plyvolume[i];
		const int plyid = polyfanid[i];
		const int *ppoly = &surfpoly[plyid*nv_per_elm];
		for (int j=0; j<nv_per_elm; j++){
			const int id = ppoly[j];
			for (k=0; k<m_nRod; k++){ 
				if (m_nNodeID[k]==id) 
					break;
			}
			if (k<m_nRod)
				edgevolume[k]+=vol;
		}
	}

	_initShearElements(isstatic, p, wpnorm, edgevolume);
}
Exemplo n.º 27
0
int in_cone ( int im1, int ip1, int n, int prev[], int next[], double x[], 
  double y[] )

/******************************************************************************/
/*
  Purpose:

    IN_CONE is TRUE if the diagonal VERTEX(IM1):VERTEX(IP1) is strictly internal.

  Licensing:

    This code is distributed under the GNU LGPL license.

  Modified:

    05 May 2014

  Author:

    Original C version by Joseph ORourke.
    This C version by John Burkardt.

  Reference:

    Joseph ORourke,
    Computational Geometry in C,
    Cambridge, 1998,
    ISBN: 0521649765,
    LC: QA448.D38.

  Parameters:

    Input, int IM1, IP1, the indices of two vertices.

    Input, int N, the number of vertices.

    Input, int PREV[N], the previous neighbor of each vertex.

    Input, int NEXT[N], the next neighbor of each vertex.

    Input, double X[N], Y[N], the coordinates of each vertex.

    Output, int IN_CONE, the value of the test.
*/
{
  int i;
  int im2;
  double t1;
  double t2;
  double t3;
  double t4;
  double t5;
  int value;

  im2 = prev[im1];
  i = next[im1];

  t1 = triangle_area ( x[im1], y[im1], x[i], y[i], x[im2], y[im2] );

  if ( 0.0 <= t1 )
  {
    t2 = triangle_area ( x[im1], y[im1], x[ip1], y[ip1], x[im2], y[im2] );
    t3 = triangle_area ( x[ip1], y[ip1], x[im1], y[im1], x[i], y[i] );
    value = ( ( 0.0 < t2 ) && ( 0.0 < t3 ) );
  }
  else
  {
    t4 = triangle_area ( x[im1], y[im1], x[ip1], y[ip1], x[i], y[i] );
    t5 = triangle_area ( x[ip1], y[ip1], x[im1], y[im1], x[im2], y[im2] );
    value = ! ( ( 0.0 <= t4 ) && ( 0.0 <= t5 ) );
  }
  return value;
}
Exemplo n.º 28
0
bool EdgeFlipper::flip_edge( size_t edge, 
                            size_t tri0, 
                            size_t tri1, 
                            size_t third_vertex_0, 
                            size_t third_vertex_1 )
{     
    NonDestructiveTriMesh& m_mesh = m_surf.m_mesh;
    const std::vector<Vec3d>& xs = m_surf.get_positions();
    
    Vec2st& edge_vertices = m_mesh.m_edges[edge];
    
    // Find the vertices which will form the new edge
    Vec2st new_edge( third_vertex_0, third_vertex_1);
    
    // --------------
    
    // Control volume change
    double vol = fabs( signed_volume( xs[edge_vertices[0]], 
                                     xs[edge_vertices[1]], 
                                     xs[new_edge[0]], 
                                     xs[new_edge[1]] ) ); 
    
    if ( vol > m_surf.m_max_volume_change )
    {
        if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: volume change = " << vol << std::endl; }
        return false;
    }
    
    // --------------
    
    // Prevent non-manifold surfaces if we're not allowing them
    if ( false == m_surf.m_allow_non_manifold )
    {
        for ( size_t i = 0; i < m_mesh.m_vertex_to_edge_map[ third_vertex_0 ].size(); ++i )
        {
            if ( ( m_mesh.m_edges[ m_mesh.m_vertex_to_edge_map[third_vertex_0][i] ][0] == third_vertex_1 ) ||
                ( m_mesh.m_edges[ m_mesh.m_vertex_to_edge_map[third_vertex_0][i] ][1] == third_vertex_1 ) )
            {
                // edge already exists
                if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: edge exists" << std::endl;             }            
                return false;
            }
        }
    }
    
    // --------------
    
    // Don't flip edge on a degenerate tet
    if ( third_vertex_0 == third_vertex_1 )
    {
        if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: degenerate tet" << std::endl; }
        return false;
    }
    
    // --------------
    
    // Create the new triangles
    // new edge winding order == winding order of old triangle0 == winding order of new triangle0
    
    size_t new_triangle_third_vertex_0, new_triangle_third_vertex_1;
    if ( m_mesh.oriented( m_mesh.m_edges[edge][0], m_mesh.m_edges[edge][1], m_mesh.get_triangle(tri0) ) ) 
    {
		assert( m_mesh.oriented( m_mesh.m_edges[edge][1], m_mesh.m_edges[edge][0], m_mesh.get_triangle(tri1) ) );
        new_triangle_third_vertex_0 = m_mesh.m_edges[edge][1];
        new_triangle_third_vertex_1 = m_mesh.m_edges[edge][0];
    }
    else
    {
		assert( m_mesh.oriented( m_mesh.m_edges[edge][0], m_mesh.m_edges[edge][1], m_mesh.get_triangle(tri1) ) );
		assert( m_mesh.oriented( m_mesh.m_edges[edge][1], m_mesh.m_edges[edge][0], m_mesh.get_triangle(tri0) ) );
        new_triangle_third_vertex_0 = m_mesh.m_edges[edge][0];
        new_triangle_third_vertex_1 = m_mesh.m_edges[edge][1];
    }
    
    Vec3st new_triangle0( new_edge[0], new_edge[1], new_triangle_third_vertex_0 );
    Vec3st new_triangle1( new_edge[1], new_edge[0], new_triangle_third_vertex_1 );
    
    if ( m_surf.m_verbose )
    {
        std::cout << "flip --- new triangle 0: " << new_triangle0 << std::endl;
        std::cout << "flip --- new triangle 1: " << new_triangle1 << std::endl;
    }
    
    // --------------
    
    // if both triangle normals agree before flipping, make sure they agree after flipping
    if ( dot( m_surf.get_triangle_normal(tri0), m_surf.get_triangle_normal(tri1) ) > 0.0 ) 
    {
        if ( dot( m_surf.get_triangle_normal(new_triangle0), m_surf.get_triangle_normal(new_triangle1) ) < 0.0 )
        {
            if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: normal inversion" << std::endl; }
            return false;
        }
        
        if ( dot( m_surf.get_triangle_normal(new_triangle0), m_surf.get_triangle_normal(tri0) ) < 0.0 )
        {
            if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: normal inversion" << std::endl; }
            return false;
        }
        
        if ( dot( m_surf.get_triangle_normal(new_triangle1), m_surf.get_triangle_normal(tri1) ) < 0.0 )
        {
            if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: normal inversion" << std::endl; }
            return false;
        }
        
        if ( dot( m_surf.get_triangle_normal(new_triangle0), m_surf.get_triangle_normal(tri1) ) < 0.0 )
        {
            if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: normal inversion" << std::endl; }
            return false;
        }
        
        if ( dot( m_surf.get_triangle_normal(new_triangle1), m_surf.get_triangle_normal(tri0) ) < 0.0 )
        {
            if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: normal inversion" << std::endl; }
            return false;
        }
    }
    
    // --------------
    
    // Prevent intersection
    if ( m_surf.m_collision_safety && flip_introduces_collision( edge, new_edge, new_triangle0, new_triangle1 ) )
    {
        if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: intersection" << std::endl; }
        return false;
    }
    
    // --------------
    
    // Prevent degenerate triangles
    if ( triangle_area( xs[new_triangle0[0]], xs[new_triangle0[1]], xs[new_triangle0[2]] ) < m_surf.m_min_triangle_area )
    {
        if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: area too small" << std::endl;    }
        return false;
    }
    
    if ( triangle_area( xs[new_triangle1[0]], xs[new_triangle1[1]], xs[new_triangle1[2]] ) < m_surf.m_min_triangle_area )
    {
        if ( m_surf.m_verbose ) {std::cout << "edge flip rejected: area too small" << std::endl; }
        return false;
    }
    
    
    // --------------
    
    // Control change in area
    
    double old_area = m_surf.get_triangle_area( tri0 ) + m_surf.get_triangle_area( tri1 );
    double new_area = triangle_area( xs[new_triangle0[0]], xs[new_triangle0[1]], xs[new_triangle0[2]] ) 
    + triangle_area( xs[new_triangle1[0]], xs[new_triangle1[1]], xs[new_triangle1[2]] );
    
    if ( fabs( old_area - new_area ) > 0.1 * old_area )
    {
        if ( m_surf.m_verbose ) {std::cout << "edge flip rejected: area change too great" << std::endl; }
        return false;
    }
    
    // --------------
    
    // Don't flip unless both vertices are on a smooth patch
    if ( ( m_surf.classify_vertex( edge_vertices[0] ) > 1 ) || ( m_surf.classify_vertex( edge_vertices[1] ) > 1 ) )
    {
        if ( m_surf.m_verbose ) {std::cout << "edge flip rejected: vertices not on smooth patch" << std::endl;  }
        return false;
    }        
    
    
    // --------------
    
    // Don't introduce a large or small angle
    
    double min_angle = min_triangle_angle( xs[new_triangle0[0]], xs[new_triangle0[1]], xs[new_triangle0[2]] );
    min_angle = min( min_angle, min_triangle_angle( xs[new_triangle1[0]], xs[new_triangle1[1]], xs[new_triangle1[2]] ) );
    
    if ( rad2deg(min_angle) < m_surf.m_min_triangle_angle )
    {
        return false;
    }
    
    double max_angle = max_triangle_angle( xs[new_triangle0[0]], xs[new_triangle0[1]], xs[new_triangle0[2]] );
    max_angle = max( max_angle, max_triangle_angle( xs[new_triangle1[0]], xs[new_triangle1[1]], xs[new_triangle1[2]] ) );
    
    if ( rad2deg(max_angle) > m_surf.m_max_triangle_angle )
    {
        return false;
    }
    
    // --------------
    
    PreEdgeFlipInfo pre_info( edge, tri0, tri1 );

    for ( size_t i = 0; i < m_observers.size(); ++i )
    {
        if ( false == m_observers[i]->operationOK(m_surf, pre_info) )
        {
            return false;
        }
    }
    
    // --------------
    
    // Okay, now do the actual operation
       
    Vec3st old_tri0 = m_mesh.get_triangle(tri0);
    Vec3st old_tri1 = m_mesh.get_triangle(tri1);
    
    m_surf.remove_triangle( tri0 );
    m_surf.remove_triangle( tri1 );
    
    size_t new_triangle_index_0 = m_surf.add_triangle( new_triangle0 );
    size_t new_triangle_index_1 = m_surf.add_triangle( new_triangle1 );
        
    if ( m_surf.m_collision_safety )
    {
        if ( m_surf.m_collision_pipeline.check_triangle_vs_all_triangles_for_intersection( new_triangle_index_0 ) )
        {
            std::cout << "missed an intersection.  New triangles: " << new_triangle0 << ", " << new_triangle1 << std::endl;
            std::cout << "old triangles: " << old_tri0 << ", " << old_tri1 << std::endl;
            assert(0);
        }
        
        if ( m_surf.m_collision_pipeline.check_triangle_vs_all_triangles_for_intersection( new_triangle_index_1 ) )
        {
            std::cout << "missed an intersection.  New triangles: " << new_triangle0 << ", " << new_triangle1 << std::endl;
            std::cout << "old triangles: " << old_tri0 << ", " << old_tri1 << std::endl;      
            assert(0);
        }
    }
    
    m_surf.m_dirty_triangles.push_back( new_triangle_index_0 );
    m_surf.m_dirty_triangles.push_back( new_triangle_index_1 );   
    
    if ( m_surf.m_verbose ) { std::cout << "edge flip: ok" << std::endl; }
    
    PostEdgeFlipInfo post_info( pre_info, new_triangle_index_0, new_triangle_index_1 );
    
    for ( size_t i = 0; i < m_observers.size(); ++i )
    {
        m_observers[i]->operationOccurred(m_surf, post_info);
    }

    
    return true;
    
}
Exemplo n.º 29
0
int test_element( int argc, char *argv[] )
{
    Element *e = element_new();
    g_return_val_if_fail( e->adjacent_halfedge == NULL , 1 );
    element_free( e );

    Point2 p1, p2, p3;
    point2_set( &p1, 0.0, 1.0 );
    point2_set( &p2, 0.0, 0.0 );
    point2_set( &p3, sqrt( 3.0 ), 0.0 );

    gdouble a1, a2, a3;
    triangle_angles( &p1, &p2, &p3, &a1, &a2, &a3 );
    g_return_val_if_fail( fabs( a1 - G_PI/3.0) < SMALL_NUMBER, 1 );
    g_return_val_if_fail( fabs( a2 - G_PI/2.0) < SMALL_NUMBER, 1 );
    g_return_val_if_fail( fabs( a3 - G_PI/6.0) < SMALL_NUMBER, 1 );

    a1 = triangle_circumcircle_radius( &p1, &p2, &p3 );
    g_return_val_if_fail( fabs( a1 - 1.0 ) < SMALL_NUMBER, 1 );

    a1 = triangle_circumcircle_radius_edge_length( 1.0, sqrt( 3.0 ), 2.0 );
    g_return_val_if_fail( fabs( a1 - 1.0 ) < SMALL_NUMBER, 1 );

    Point2 p;
    triangle_circumcenter_coordinates( &p1, &p2, &p3, &p );
    g_return_val_if_fail( fabs( p.x - sqrt( 3.0 )/2.0 ) < SMALL_NUMBER, 1 );
    g_return_val_if_fail( fabs( p.y - 1.0/2.0 ) < SMALL_NUMBER, 1 );

    a1 = triangle_area( &p1, &p2, &p3 );
    g_return_val_if_fail( fabs( a1 - sqrt( 3.0 )/2.0 ) < SMALL_NUMBER, 1 );


    Mesh *mesh = mesh_new();
    Node *n1 = mesh_add_node( mesh, 0.0, 1.0 );
    Node *n2 = mesh_add_node( mesh, 0.0, 0.0 );
    Node *n3 = mesh_add_node( mesh, sqrt(3.0), 0.0 );
    Edge *e1 = mesh_add_edge( mesh, n1, n2 );
    Edge *e2 = mesh_add_edge( mesh, n2, n3 );
    Edge *e3 = mesh_add_edge( mesh, n3, n1 );
    Element *el = mesh_add_element( mesh, &e1->he[0], &e2->he[0], &e3->he[0] );

    gdouble l1, l2, l3;
    element_edge_lengths( el, &l1, &l2, &l3 );
    g_return_val_if_fail( fabs( l1 - 1.0) < SMALL_NUMBER, 1);
    g_return_val_if_fail( fabs( l2 - sqrt(3.0)) < SMALL_NUMBER, 1);
    g_return_val_if_fail( fabs( l3 - 2.0) < SMALL_NUMBER, 1);

    HalfEdge *he = element_min_edge( el, &l1 );
    g_return_val_if_fail( he->edge == e1, 1 );
    g_return_val_if_fail( fabs( l1 - 1.0) < SMALL_NUMBER, 1);

    l1 = element_min_edge_length( el );
    g_return_val_if_fail( fabs( l1 - 1.0) < SMALL_NUMBER, 1);

    he = element_max_edge( el, &l1 );
    g_return_val_if_fail( he->edge == e3, 1 );
    g_return_val_if_fail( fabs( l1 - 2.0) < SMALL_NUMBER, 1);

    l1 = element_max_edge_length( el );
    g_return_val_if_fail( fabs( l1 - 2.0) < SMALL_NUMBER, 1);

    element_angles( el, &a1, &a2, &a3 );
    g_return_val_if_fail( fabs( a1 - G_PI/3.0) < SMALL_NUMBER, 1);
    g_return_val_if_fail( fabs( a2 - G_PI/2.0) < SMALL_NUMBER, 1);
    g_return_val_if_fail( fabs( a3 - G_PI/6.0) < SMALL_NUMBER, 1);

    a1 = element_maximum_angle( el );
    g_return_val_if_fail( fabs( a1 - G_PI/2.0) < SMALL_NUMBER, 1);

    a1 = element_minimum_angle( el );
    g_return_val_if_fail( fabs( a1 - G_PI/6.0) < SMALL_NUMBER, 1);

    element_circumcenter_coordinates( el, &p );
    g_return_val_if_fail( fabs( p.x - sqrt( 3.0 )/2.0 ) < SMALL_NUMBER, 1);
    g_return_val_if_fail( fabs( p.y - 1.0/2.0 ) < SMALL_NUMBER, 1);

    point2_set( NODE_POSITION( n3 ), 3.0, 0.0 );
    a1 = element_area( el );
    g_return_val_if_fail( fabs( a1 - 3.0/2.0) < SMALL_NUMBER, 1);

    return 0;
}
Exemplo n.º 30
0
int main(int argc, char *argv[]) {
  auto area = triangle_area(10, 20);
  std::cout << "area " << area << std::endl;
  return 0;
}