static PyObject *M_Geometry_area_tri(PyObject *UNUSED(self), PyObject* args) { VectorObject *vec1, *vec2, *vec3; if(!PyArg_ParseTuple(args, "O!O!O!:area_tri", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3)) { return NULL; } if(vec1->size != vec2->size || vec1->size != vec3->size) { PyErr_SetString(PyExc_ValueError, "vectors must be of the same size"); return NULL; } if(BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec3) == -1) return NULL; if (vec1->size == 3) { return PyFloat_FromDouble(area_tri_v3(vec1->vec, vec2->vec, vec3->vec)); } else if (vec1->size == 2) { return PyFloat_FromDouble(area_tri_v2(vec1->vec, vec2->vec, vec3->vec)); } else { PyErr_SetString(PyExc_ValueError, "only 2D,3D vectors are supported"); return NULL; } }
static void occ_face(const OccFace *face, float co[3], float normal[3], float *area) { ObjectInstanceRen *obi; VlakRen *vlr; float v1[3], v2[3], v3[3], v4[3]; obi = &R.objectinstance[face->obi]; vlr = RE_findOrAddVlak(obi->obr, face->facenr); if (co) { if (vlr->v4) mid_v3_v3v3(co, vlr->v1->co, vlr->v3->co); else cent_tri_v3(co, vlr->v1->co, vlr->v2->co, vlr->v3->co); if (obi->flag & R_TRANSFORMED) mul_m4_v3(obi->mat, co); } if (normal) { normal[0] = -vlr->n[0]; normal[1] = -vlr->n[1]; normal[2] = -vlr->n[2]; if (obi->flag & R_TRANSFORMED) mul_m3_v3(obi->nmat, normal); } if (area) { copy_v3_v3(v1, vlr->v1->co); copy_v3_v3(v2, vlr->v2->co); copy_v3_v3(v3, vlr->v3->co); if (vlr->v4) copy_v3_v3(v4, vlr->v4->co); if (obi->flag & R_TRANSFORMED) { mul_m4_v3(obi->mat, v1); mul_m4_v3(obi->mat, v2); mul_m4_v3(obi->mat, v3); if (vlr->v4) mul_m4_v3(obi->mat, v4); } /* todo: correct area for instances */ if (vlr->v4) *area = area_quad_v3(v1, v2, v3, v4); else *area = area_tri_v3(v1, v2, v3); } }
static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3) { float t1, t2, t3, len1, len2, len3, area; float *varea = sys->varea, *v1, *v2, *v3; int obtuse = 0; v1 = sys->verts[i1]; v2 = sys->verts[i2]; v3 = sys->verts[i3]; t1 = cotangent_tri_weight_v3(v1, v2, v3); t2 = cotangent_tri_weight_v3(v2, v3, v1); t3 = cotangent_tri_weight_v3(v3, v1, v2); if (angle_v3v3v3(v2, v1, v3) > DEG2RADF(90.0f)) obtuse = 1; else if (angle_v3v3v3(v1, v2, v3) > DEG2RADF(90.0f)) obtuse = 2; else if (angle_v3v3v3(v1, v3, v2) > DEG2RADF(90.0f)) obtuse = 3; if (obtuse > 0) { area = area_tri_v3(v1, v2, v3); varea[i1] += (obtuse == 1) ? area : area * 0.5f; varea[i2] += (obtuse == 2) ? area : area * 0.5f; varea[i3] += (obtuse == 3) ? area : area * 0.5f; } else { len1 = len_v3v3(v2, v3); len2 = len_v3v3(v1, v3); len3 = len_v3v3(v1, v2); t1 *= len1 * len1; t2 *= len2 * len2; t3 *= len3 * len3; varea[i1] += (t2 + t3) * 0.25f; varea[i2] += (t1 + t3) * 0.25f; varea[i3] += (t1 + t2) * 0.25f; } }
// With A, B and P indicating the three vertices of a given triangle, returns: // 1 if points A and B are in the same position in the 3D space; // 2 if the distance between point P and line segment AB is zero; and // zero otherwise. int BlenderFileLoader::testDegenerateTriangle(float v1[3], float v2[3], float v3[3]) { const float eps = 1.0e-6; const float eps_sq = eps * eps; #if 0 float area = area_tri_v3(v1, v2, v3); bool verbose = (area < 1.0e-6); #endif if (equals_v3v3(v1, v2) || equals_v3v3(v2, v3) || equals_v3v3(v1, v3)) { #if 0 if (verbose && G.debug & G_DEBUG_FREESTYLE) { printf("BlenderFileLoader::testDegenerateTriangle = 1\n"); } #endif return 1; } if (dist_squared_to_line_segment_v3(v1, v2, v3) < eps_sq || dist_squared_to_line_segment_v3(v2, v1, v3) < eps_sq || dist_squared_to_line_segment_v3(v3, v1, v2) < eps_sq) { #if 0 if (verbose && G.debug & G_DEBUG_FREESTYLE) { printf("BlenderFileLoader::testDegenerateTriangle = 2\n"); } #endif return 2; } #if 0 if (verbose && G.debug & G_DEBUG_FREESTYLE) { printf("BlenderFileLoader::testDegenerateTriangle = 0\n"); } #endif return 0; }
static void init_laplacian_matrix(LaplacianSystem *sys) { float *v1, *v2, *v3, *v4; float w1, w2, w3, w4; float areaf; int i, j; unsigned int idv1, idv2, idv3, idv4, idv[4]; bool has_4_vert; for (i = 0; i < sys->numEdges; i++) { idv1 = sys->medges[i].v1; idv2 = sys->medges[i].v2; v1 = sys->vertexCos[idv1]; v2 = sys->vertexCos[idv2]; sys->numNeEd[idv1] = sys->numNeEd[idv1] + 1; sys->numNeEd[idv2] = sys->numNeEd[idv2] + 1; w1 = len_v3v3(v1, v2); if (w1 < sys->min_area) { sys->zerola[idv1] = 1; sys->zerola[idv2] = 1; } else { w1 = 1.0f / w1; } sys->eweights[i] = w1; } for (i = 0; i < sys->numFaces; i++) { has_4_vert = ((&sys->mfaces[i])->v4) ? 1 : 0; idv1 = sys->mfaces[i].v1; idv2 = sys->mfaces[i].v2; idv3 = sys->mfaces[i].v3; idv4 = has_4_vert ? sys->mfaces[i].v4 : 0; sys->numNeFa[idv1] += 1; sys->numNeFa[idv2] += 1; sys->numNeFa[idv3] += 1; if (has_4_vert) sys->numNeFa[idv4] += 1; v1 = sys->vertexCos[idv1]; v2 = sys->vertexCos[idv2]; v3 = sys->vertexCos[idv3]; v4 = has_4_vert ? sys->vertexCos[idv4] : NULL; if (has_4_vert) { areaf = area_quad_v3(v1, v2, v3, sys->vertexCos[sys->mfaces[i].v4]); } else { areaf = area_tri_v3(v1, v2, v3); } if (fabsf(areaf) < sys->min_area) { sys->zerola[idv1] = 1; sys->zerola[idv2] = 1; sys->zerola[idv3] = 1; if (has_4_vert) sys->zerola[idv4] = 1; } if (has_4_vert) { sys->ring_areas[idv1] += average_area_quad_v3(v1, v2, v3, v4); sys->ring_areas[idv2] += average_area_quad_v3(v2, v3, v4, v1); sys->ring_areas[idv3] += average_area_quad_v3(v3, v4, v1, v2); sys->ring_areas[idv4] += average_area_quad_v3(v4, v1, v2, v3); } else { sys->ring_areas[idv1] += areaf; sys->ring_areas[idv2] += areaf; sys->ring_areas[idv3] += areaf; } if (has_4_vert) { idv[0] = idv1; idv[1] = idv2; idv[2] = idv3; idv[3] = idv4; for (j = 0; j < 4; j++) { idv1 = idv[j]; idv2 = idv[(j + 1) % 4]; idv3 = idv[(j + 2) % 4]; idv4 = idv[(j + 3) % 4]; v1 = sys->vertexCos[idv1]; v2 = sys->vertexCos[idv2]; v3 = sys->vertexCos[idv3]; v4 = sys->vertexCos[idv4]; w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2); w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3); w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1); sys->vweights[idv1] += (w2 + w3 + w4) / 4.0f; } } else { w1 = cotangent_tri_weight_v3(v1, v2, v3) / 2.0f; w2 = cotangent_tri_weight_v3(v2, v3, v1) / 2.0f; w3 = cotangent_tri_weight_v3(v3, v1, v2) / 2.0f; sys->fweights[i][0] = sys->fweights[i][0] + w1; sys->fweights[i][1] = sys->fweights[i][1] + w2; sys->fweights[i][2] = sys->fweights[i][2] + w3; sys->vweights[idv1] = sys->vweights[idv1] + w2 + w3; sys->vweights[idv2] = sys->vweights[idv2] + w1 + w3; sys->vweights[idv3] = sys->vweights[idv3] + w1 + w2; } } for (i = 0; i < sys->numEdges; i++) { idv1 = sys->medges[i].v1; idv2 = sys->medges[i].v2; /* if is boundary, apply scale-dependent umbrella operator only with neighboors in boundary */ if (sys->numNeEd[idv1] != sys->numNeFa[idv1] && sys->numNeEd[idv2] != sys->numNeFa[idv2]) { sys->vlengths[idv1] += sys->eweights[i]; sys->vlengths[idv2] += sys->eweights[i]; } } }
static float average_area_quad_v3(float *v1, float *v2, float *v3, float *v4) { float areaq; areaq = area_tri_v3(v1, v2, v3) + area_tri_v3(v1, v2, v4) + area_tri_v3(v1, v3, v4); return areaq / 2.0f; }
static void init_laplacian_matrix(LaplacianSystem *sys) { float *v1, *v2; float w1, w2, w3; float areaf; int i; unsigned int idv1, idv2; for (i = 0; i < sys->numEdges; i++) { idv1 = sys->medges[i].v1; idv2 = sys->medges[i].v2; v1 = sys->vertexCos[idv1]; v2 = sys->vertexCos[idv2]; sys->numNeEd[idv1] = sys->numNeEd[idv1] + 1; sys->numNeEd[idv2] = sys->numNeEd[idv2] + 1; w1 = len_v3v3(v1, v2); if (w1 < sys->min_area) { sys->zerola[idv1] = 1; sys->zerola[idv2] = 1; } else { w1 = 1.0f / w1; } sys->eweights[i] = w1; } for (i = 0; i < sys->numPolys; i++) { const MPoly *mp = &sys->mpoly[i]; const MLoop *l_next = &sys->mloop[mp->loopstart]; const MLoop *l_term = l_next + mp->totloop; const MLoop *l_prev = l_term - 2; const MLoop *l_curr = l_term - 1; for (; l_next != l_term; l_prev = l_curr, l_curr = l_next, l_next++) { const float *v_prev = sys->vertexCos[l_prev->v]; const float *v_curr = sys->vertexCos[l_curr->v]; const float *v_next = sys->vertexCos[l_next->v]; const unsigned int l_curr_index = l_curr - sys->mloop; sys->numNeFa[l_curr->v] += 1; areaf = area_tri_v3(v_prev, v_curr, v_next); if (areaf < sys->min_area) { sys->zerola[l_curr->v] = 1; } sys->ring_areas[l_prev->v] += areaf; sys->ring_areas[l_curr->v] += areaf; sys->ring_areas[l_next->v] += areaf; w1 = cotangent_tri_weight_v3(v_curr, v_next, v_prev) / 2.0f; w2 = cotangent_tri_weight_v3(v_next, v_prev, v_curr) / 2.0f; w3 = cotangent_tri_weight_v3(v_prev, v_curr, v_next) / 2.0f; sys->fweights[l_curr_index][0] += w1; sys->fweights[l_curr_index][1] += w2; sys->fweights[l_curr_index][2] += w3; sys->vweights[l_curr->v] += w2 + w3; sys->vweights[l_next->v] += w1 + w3; sys->vweights[l_prev->v] += w1 + w2; } } for (i = 0; i < sys->numEdges; i++) { idv1 = sys->medges[i].v1; idv2 = sys->medges[i].v2; /* if is boundary, apply scale-dependent umbrella operator only with neighboors in boundary */ if (sys->numNeEd[idv1] != sys->numNeFa[idv1] && sys->numNeEd[idv2] != sys->numNeFa[idv2]) { sys->vlengths[idv1] += sys->eweights[i]; sys->vlengths[idv2] += sys->eweights[i]; } } }