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)); }
// 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; }
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); }
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); }
/** * @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(); }
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 ); }
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]); } }
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; }
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; }
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; }
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; }
INLINE Real element_size(Few<Vector<2>, 2> b) { return triangle_area(b); }
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); }
/** * @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)); }
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); }
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; }
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); }
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; }
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; }
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; }
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; }
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; }
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); }
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; }
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; }
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; }
int main(int argc, char *argv[]) { auto area = triangle_area(10, 20); std::cout << "area " << area << std::endl; return 0; }