/* * By using the associative property of the barycenter, we can get the barycenter of 2 triangles as the barrycenter of the barycenters of each triangle; */ PersCamera Triangle::getPersCamParamsBarycentricTwo(cv::Mat equi_image, Vec9f triangle3D1, Vec9f triangle3D2){ EquiTrans equi; //First convert the triangle to get spheric coordinates of vertices //cv::Vec6f triangle1 = triangle2SphericSacht(equi_image.rows, equi_image.cols,1,triangle3D1); cv::Vec6f triangle1 = convToSphericTriangle(triangle3D1); //cv::Vec6f triangle2 = triangle2SphericSacht(equi_image.rows, equi_image.cols,1,triangle3D2); cv::Vec6f triangle2 = convToSphericTriangle(triangle3D2); //Get the 3 Vertices as points Point2f p1,p2,p3,q1,q2,q3; //Centers for each triangle Point2f center, center1, center2; //First vertice p1.x = triangle1[0]; p1.y = triangle1[1]; q1.x = triangle2[0]; q1.y = triangle2[1]; //Second vertice p2.x = triangle1[2]; p2.y = triangle1[3]; q2.x = triangle2[2]; q2.y = triangle2[3]; //Third vertice p3.x = triangle1[4]; p3.y = triangle1[5]; q3.x = triangle2[4]; q3.y = triangle2[5]; /********************************************************************************/ //Horizontal /*******************************************************************************/ // Get the maximum angular difference between the points in terms of theta (horizontal) // in order to make correct viewing direction we have to make sure that the points are all // in correct order and interval. We take the first point as anchor and cheick the angular // distance with the other points double t1_thetad1_2, t1_thetad1_3, t1_thetad2_3, t2_thetad1_2, t2_thetad1_3, t2_thetad2_3, t1_max_thetad, t2_max_thetad; t1_thetad1_2 = abs(p2.x - p1.x); t2_thetad1_2 = abs(q2.x - q1.x); t1_thetad1_3 = abs(p3.x - p1.x); t2_thetad1_2 = abs(q2.x - q1.x); t1_thetad2_3 = abs(p3.x - p2.x); t2_thetad2_3 = abs(q3.x - q2.x); t1_max_thetad = max(t1_thetad1_2, max(t1_thetad1_3,t1_thetad2_3)); t2_max_thetad = max(t2_thetad1_2, max(t2_thetad1_3,t2_thetad2_3)); /***************************************************************************************/ //Vertical /**************************************************************************************/ //Get the angular phi difference between points double t1_phid1_2, t1_phid1_3, t1_phid2_3, t2_phid1_2, t2_phid1_3, t2_phid2_3, t1_max_phid,t2_max_phid; //Triangle1 t1_phid1_2 = abs(p2.y - p1.y); t1_phid1_3 = abs(p3.y - p1.y); t1_phid2_3 = abs(p3.y - p2.y); //t1_max_phid = max(t1_phid1_2, max(t1_phid1_3,t1_phid2_3)); //Triangle2 t2_phid1_2 = abs(p2.y - p1.y); t2_phid1_3 = abs(p3.y - p1.y); t2_phid2_3 = abs(p3.y - p2.y); //t2_max_phid = max(t2_phid1_2, max(t2_phid1_3,t2_phid2_3)); //Make sure there are no loopings in the point angle calculations //If the angle is larger than PI then we have to shift the point to the other side // depending on the sign of p1, we either add or remove 2PI //For first Triangle if(abs(t1_thetad1_2) > M_PI) { p2.y += (p1.y/abs(p1.y))*2*M_PI; triangle1[3] = p2.y; } if(abs(t1_thetad1_3) > M_PI){ p3.y += (p1.y/abs(p1.y))*2*M_PI; triangle1[5] = p3.y; } //For Second Triangle if(abs(t2_thetad1_2) > M_PI) { q2.y += (q1.y/abs(q1.y))*2*M_PI; triangle2[3] = q2.y; } if(abs(t2_thetad1_3) > M_PI){ q3.y += (q1.y/abs(q1.y))*2*M_PI; triangle2[5] = q3.y; } //Recalculate the new maxes and mins t1_phid1_2 = abs(p2.y - p1.y); t1_phid1_3 = abs(p3.y - p1.y); t1_phid2_3 = abs(p3.y - p2.y); t1_max_phid = max(t1_phid1_2, max(t1_phid1_3,t1_phid2_3)); //Triangle2 t2_phid1_2 = abs(p2.y - p1.y); t2_phid1_3 = abs(p3.y - p1.y); t2_phid2_3 = abs(p3.y - p2.y); t2_max_phid = max(t2_phid1_2, max(t2_phid1_3,t2_phid2_3)); //Get barycenters for each triangle center1 = triangleCenter(triangle1); center2 = triangleCenter(triangle2); //Get the barycenter of the centers center.x = (center1.x + center2.x)/2; center.y = (center1.y + center2.y)/2; //Set Viewing direction as the barycenter of the triangles ViewDirection vd; vd.pan = center.y; vd.tilt = center.x; //Calculate the field of view as the difference between the barycenters to which we add the radius // of the circumcircles double bary_theta = abs(center1.x - center2.x); double bary_phi = abs(center2.y - center2.y); //Get pan and tilt angles by finding max angle distance and adding to barycenter difference double v_angle, h_angle; h_angle = bary_phi + t1_max_phid + t2_max_phid; v_angle = bary_theta + t1_max_thetad + t2_max_thetad; //Finally make the Perspective camera PersCamera cam; cam.setCamera(equi_image, h_angle, v_angle, vd); return cam; }
/* what is constant: variant==CHANGE_RATIO_KEEP_COM_CONSTANT: - length of longest edge (WF 030726: Incorrect. The smallest edge of the original triangle will be the longest edge of the new triangle. Intended?) - center of mass - triangle normal variant==CHANGE_RATIO_KEEP_LONGEST_EDGE_CONSTANT: - length of longest edge - vertices adjacent to longest edge - triangle normal */ int changeRatio(double *ratio, TriangleSet *mesh, int trId, int variant, BOOL doNotChange, TinyVector *resultVectors) { double s, r, a, b, c; double alpha, beta, gamma; double h, p; double lengths[3], dsav; TinyVector v[3]; int i, j; int vIds[3], index[3], isav, index2[3]; TinyVector n1, n2, sp, com; double scaleFactor; double comX, comY; double rvA[2], rvB[2], rvC[2]; TinyVector newVertices[3]; BOOL edgeACisShortest; normalizeRatios(ratio); if(!validTriangleEdgeLengths(ratio[0], ratio[1], ratio[2])) return -1; a = ratio[0]; b = ratio[1]; c = ratio[2]; // ---------------------------------------------------------- // Calculate properties of the "ratio triangle". // Triangle is supposed lie with A in origin, c on x-axis // ---------------------------------------------------------- /* half of triangle border length */ s = (a + b + c) / 2; /* radius of inner circle */ r = sqrt(((s - a) * (s - b) * (s - c)) / s); /* angles */ alpha = 2 * atan(r / (s - a)); beta = 2 * atan(r / (s - b)); gamma = 2 * atan(r / (s - c)); h = sin(alpha) * b; p = cos(alpha) * b; /* Retrieve vertices of triangle to be changed */ for(i = 0; i < 3; i++) { vIds[i] = mesh->getTriangleVertex(trId, i); v[i] = mesh->getVertex(vIds[i]); } // Original edge lengths lengths[0] = tv_abs(v[0] - v[1]); lengths[1] = tv_abs(v[1] - v[2]); lengths[2] = tv_abs(v[2] - v[0]); for(i = 0; i < 3; i++) index[i] = i; // Sort original edge lenghts in ascending order for(i = 0; i < 2; i++) { for(j = i + 1; j < 3; j++) { if(lengths[i] > lengths[j]) { dsav = lengths[i]; lengths[i] = lengths[j]; lengths[j] = dsav; isav = index[i]; index[i] = index[j]; index[j] = isav; } } } /* For constructing the new start triangle from the ratio triangle, sort vertices so that edge from first to second (c) is longest, second to third (a) is shortest edge. This configuration matches the ratio triple configuration. a < b < c (e.g. 1:1.5:2). */ if((index[2] == 1) && (index[0] == 0)) { /* 2->1->0 */ index2[0] = 2; index2[1] = 1; index2[2] = 0; } else if((index[2] == 0) && (index[0] == 1)) { /* 0->1->2 */ index2[0] = 0; index2[1] = 1; index2[2] = 2; } else if((index[2] == 1) && (index[0] == 2)) { /* 1->2->0 */ index2[0] = 1; index2[1] = 2; index2[2] = 0; } else if((index[2] == 2) && (index[0] == 1)) { /* 0->2->1 */ index2[0] = 0; index2[1] = 2; index2[2] = 1; } else if((index[2] == 0) && (index[0] == 2)) { /* 1->0->2 */ index2[0] = 1; index2[1] = 0; index2[2] = 2; } else if((index[2] == 2) && (index[0] == 0)) { /* 2->0->1 */ index2[0] = 2; index2[1] = 0; index2[2] = 1; } n1 = v[index2[1]] - v[index2[0]]; lotPointLine(v[index2[2]], v[index2[1]], v[index2[0]] - v[index2[1]], &sp); n2 = v[index2[2]] - sp; n1.normalize(); n2.normalize(); // WF 030801: Largest edge length value and maximum of ratio. // This means the longest edge of the original triangle // will be the longest edge of the new triangle. scaleFactor = lengths[index[2]] / ratio[2]; //scaleFactor=lengths[index[0]] / ratio[2]; // maintains smallest edge of original. //scaleFactor=lengths[index[0]]; if(variant == CHANGE_RATIO_KEEP_COM_CONSTANT) { /* calculate center of mass of "ratio-triangle" */ comX = (c + p) / 3; comY = h / 3; /* center of mass of real triangle remains the same */ /* PRECONDITION: edge AB (aka edge c) must be longest, BC (aka edge a) shortest !! */ /* c is longest,a shortest */ rvA[0] = -comX; rvA[1] = -comY; rvB[0] = c - comX; rvB[1] = -comY; rvC[0] = p - comX; rvC[1] = h - comY; com = triangleCenter(trId, mesh); /* New vertices A,B,C */ newVertices[0] = com + n1 * scaleFactor * rvA[0] + n2 * scaleFactor * rvA[1]; newVertices[1] = com + n1 * scaleFactor * rvB[0] + n2 * scaleFactor * rvB[1]; newVertices[2] = com + n1 * scaleFactor * rvC[0] + n2 * scaleFactor * rvC[1]; /* replace vertices in mesh with new ones */ for(i = 0; i < 3; i++) { if(!doNotChange) { mesh->setVertex(vIds[index2[i]], newVertices[i]); } } for(i = 0; i < 3; i++) { resultVectors[index2[i]] = newVertices[i]; } } /* CHANGE_RATIO_KEEP_COM_CONSTANT */ else if(variant == CHANGE_RATIO_KEEP_LONGEST_EDGE_CONSTANT) { com = triangleCenter(trId, mesh); newVertices[2] = v[index2[0]] + n1 * p * scaleFactor + n2 * h * scaleFactor; if(!doNotChange) { mesh->setVertex(vIds[index2[2]], newVertices[2]); } resultVectors[index2[2]] = newVertices[2]; for(i = 0; i < 2; i++) resultVectors[i] = v[index2[i]]; } /* CHANGE_RATIO_KEEP_LONGEST_EDGE_CONSTANT */ else return -1; com = triangleCenter(trId, mesh); triangleEdgeLengths(trId, mesh, lengths); double lengthsNew[3]; lengthsNew[0] = tv_abs(resultVectors[0] - resultVectors[1]); lengthsNew[1] = tv_abs(resultVectors[1] - resultVectors[2]); lengthsNew[2] = tv_abs(resultVectors[2] - resultVectors[0]); TinyVector newCom = triangleCenter(resultVectors[0], resultVectors[1], resultVectors[2]); return 0; }
/* * Get the perpective camera that includes a triangle by using the barycenter as point and the * radius of the circumcircle */ PersCamera Triangle::getPersCamParamsBarycentric(cv::Mat equi_image, Vec9f vertices){ EquiTrans equi; //First convert the triangle to get spheric coordinates of vertices //cv::Vec6f triangle = triangle2SphericSacht(equi_image.rows, equi_image.cols,1,vertices); cv::Vec6f triangle = convToSphericTriangle(vertices); //Get the 3 Vertices as points in 3D then convert to angular position //Point3f p3d1,p3d2,p3d3; Point2f p1,p2,p3; //First vertice //p3d1.x = triangle[0]; //p3d1.y = triangle[1]; //p3d1.z = triangle[2]; //Second vertice //p3d2.x = triangle[3]; //p3d2.y = triangle[4]; //p3d2.z = triangle[5]; //Theturn cam;ird vertice //p3d3.x = triangle[6]; //p3d3.y = triangle[7]; //p3d3.z = triangle[8]; //double x=0.0,y=0.0; //equi.convSpherePointToAngles(p3d1, &x,&y); ///equi.convSpherePointToAngles(p3d2, &x,&y); //p2.x = x; //p2.y = y; //equi.convSpherePointToAngles(p3d3, &x,&y); //p3.x = x; //p3.y = y; p1.x = triangle[0]; p1.y = triangle[1]; p2.x = triangle[2]; p2.y = triangle[3]; p3.x = triangle[4]; p3.y = triangle[5]; // Horizontal // Get the maximum angular difference between the points in terms of theta (horizontal) // in order to make correct viewing direction we have to make sure that the points are all // in correct order and interval. We take the first point as anchor and cheick the angular // distance with the other points double thetad1_2, thetad1_3, thetad2_3, max_thetad; thetad1_2 = abs(p2.x - p1.x); thetad1_3 = abs(p3.x - p1.x); thetad2_3 = abs(p3.x - p2.x); max_thetad = max(thetad1_2, max(thetad1_3,thetad2_3)); //Get the angular phi difference between points double phid1_2, phid1_3, phid2_3, max_phid; phid1_2 = abs(p2.y - p1.y); phid1_3 = abs(p3.y - p1.y); phid2_3 = abs(p3.y - p2.y); //max_phid = max(phid1_2, max(phid1_3,phid2_3)); //If the angle is larger than PI then we have to shift the point to the other side // depending on the sign of p1, we either add or remove 2PI if(abs(thetad1_2) > M_PI) { p2.y += (p1.y/abs(p1.y))*2*M_PI; triangle[3] = p2.y; } if(abs(thetad1_3) > M_PI){ p3.y += (p1.y/abs(p1.y))*2*M_PI; triangle[5] = p3.y; } //Recalculate the angular phi difference between points phid1_2 = abs(p2.y - p1.y); phid1_3 = abs(p3.y - p1.y); phid2_3 = abs(p3.y - p2.y); max_phid = max(phid1_2, max(phid1_3,phid2_3)); //Get the barycenter cv::Point2f center = triangleCenter(triangle); //Get pan and tilt angles by finding max angle distance double v_angle, h_angle; h_angle = max_phid; v_angle = max_thetad; cout << "getPersCamParamsBarycentric: Cam image: (" << h_angle << "," << v_angle << ")" << endl; //Set Viewing direction as the barycenter of the triangle ViewDirection vd; vd.pan = center.y; vd.tilt = center.x; //vd.pan = 0.164793; //vd.tilt = -0.276993; cout << "getPersCamParamsBarycentric: Viewing Direction: (" << vd.pan << "," << vd.tilt << ")" << endl; //Finally make the Perspective camera PersCamera cam; if(h_angle!=h_angle || v_angle!=v_angle){ h_angle = v_angle = 0; } else{ cam.setCamera(equi_image, h_angle, v_angle, vd); } return cam; }