static void testAxialSymmetry(BGraph *graph, BNode *root_node, BNode *node1, BNode *node2, BArc *arc1, BArc *arc2, float axis[3], float limit, int group) { const float limit_sq = limit * limit; float nor[3], vec[3], p[3]; sub_v3_v3v3(p, node1->p, root_node->p); cross_v3_v3v3(nor, p, axis); sub_v3_v3v3(p, root_node->p, node2->p); cross_v3_v3v3(vec, p, axis); add_v3_v3(vec, nor); cross_v3_v3v3(nor, vec, axis); if (fabsf(nor[0]) > fabsf(nor[1]) && fabsf(nor[0]) > fabsf(nor[2]) && nor[0] < 0) { negate_v3(nor); } else if (fabsf(nor[1]) > fabsf(nor[0]) && fabsf(nor[1]) > fabsf(nor[2]) && nor[1] < 0) { negate_v3(nor); } else if (fabsf(nor[2]) > fabsf(nor[1]) && fabsf(nor[2]) > fabsf(nor[0]) && nor[2] < 0) { negate_v3(nor); } /* mirror node2 along axis */ copy_v3_v3(p, node2->p); BLI_mirrorAlongAxis(p, root_node->p, nor); /* check if it's within limit before continuing */ if (len_squared_v3v3(node1->p, p) <= limit_sq) { /* mark node as symmetric physically */ copy_v3_v3(root_node->symmetry_axis, nor); root_node->symmetry_flag |= SYM_PHYSICAL; root_node->symmetry_flag |= SYM_AXIAL; /* flag side on arcs */ flagAxialSymmetry(root_node, node1, arc1, group); flagAxialSymmetry(root_node, node2, arc2, group); if (graph->axial_symmetry) { graph->axial_symmetry(root_node, node1, node2, arc1, arc2); } } else { /* NOT SYMMETRIC */ } }
static void testRadialSymmetry(BGraph *graph, BNode* root_node, RadialArc* ring, int total, float axis[3], float limit, int group) { int symmetric = 1; int i; /* sort ring by angle */ for (i = 0; i < total - 1; i++) { float minAngle = FLT_MAX; int minIndex = -1; int j; for (j = i + 1; j < total; j++) { float angle = dot_v3v3(ring[i].n, ring[j].n); /* map negative values to 1..2 */ if (angle < 0) { angle = 1 - angle; } if (angle < minAngle) { minIndex = j; minAngle = angle; } } /* swap if needed */ if (minIndex != i + 1) { RadialArc tmp; tmp = ring[i + 1]; ring[i + 1] = ring[minIndex]; ring[minIndex] = tmp; } } for (i = 0; i < total && symmetric; i++) { BNode *node1, *node2; float tangent[3]; float normal[3]; float p[3]; int j = (i + 1) % total; /* next arc in the circular list */ add_v3_v3v3(tangent, ring[i].n, ring[j].n); cross_v3_v3v3(normal, tangent, axis); node1 = BLI_otherNode(ring[i].arc, root_node); node2 = BLI_otherNode(ring[j].arc, root_node); copy_v3_v3(p, node2->p); BLI_mirrorAlongAxis(p, root_node->p, normal); /* check if it's within limit before continuing */ if (len_v3v3(node1->p, p) > limit) { symmetric = 0; } } if (symmetric) { /* mark node as symmetric physically */ copy_v3_v3(root_node->symmetry_axis, axis); root_node->symmetry_flag |= SYM_PHYSICAL; root_node->symmetry_flag |= SYM_RADIAL; /* FLAG SYMMETRY GROUP */ for (i = 0; i < total; i++) { ring[i].arc->symmetry_group = group; ring[i].arc->symmetry_flag = SYM_SIDE_RADIAL + i; } if (graph->radial_symmetry) { graph->radial_symmetry(root_node, ring, total); } } }