// // Draw catenary curve between conductor attachment points // from the current tower to the previous tower. // void vtRoute::_DrawCat(FPoint3 pt0, FPoint3 pt1, double catenary, int iNumSegs, vtMesh *pWireMesh) { FPoint3 diff = pt1-pt0; FPoint3 ptNew; int i; double xz = sqrt(diff.z*diff.z+diff.x*diff.x); // distance in the xz plane double y = diff.y; FPoint3 step = diff / (float) iNumSegs; // Calculate the parabolic constants. double parabolicConst = (xz / 2) - (y * (catenary / xz)); FPoint3 ptCur(0,0,0); double dist=0; vtHeightField3d *pHeightField = m_pTheTerrain->GetHeightField(); float ground; // Iterate along the xz-plane for (i = 0; i < iNumSegs-1; i++) { ptCur.x += step.x; ptCur.z += step.z; dist = sqrt(ptCur.x*ptCur.x + ptCur.z*ptCur.z); ptCur.y = (float) ((dist / (2*catenary)) * (dist - (2*parabolicConst))); ptNew = pt0 + ptCur; pHeightField->FindAltitudeAtPoint(ptNew, ground); ground += 0.5; if (ptNew.y < ground) ptNew.y = ground; pWireMesh->AddVertex(ptNew); } }
//变角度线扫描法——改进后的线扫描法 void findCircleParameter::revisedScanLineMethod(Mat imgOrg, Point2i& center, int& radius, int threshold, int N) { Mat src, gray; src = imgOrg.clone(); cvtColor(src, gray, CV_BGR2GRAY); vector<Point> points; vector<double> distance; Size imgSize = src.size(); int x, y; double theta = 0; for (int n = 0; n < 2 * N; n++, theta = PI*n / (2 * N)) { //if (n == N||n==0) continue; int min1, min2; min1 = min2 = 255; int max1, max2; max1 = max2 = 0; int radius = 0; Point ptMax1(0, 0), ptMax2(0, 0); Point ptMin1(0, 0), ptMin2(0, 0); int flag = 0; double minVal, maxVal; if (0 == n) { for (int i = 0; i < imgSize.height; i++) { minMaxLoc(gray.row(i), &minVal, &maxVal, &ptMin1, &ptMax1); if ((maxVal - minVal)>threshold) { flag++; ptMax1.y = i; //cout << "horizontal top:" << endl; //cout << "ptMax1=(" << ptMax1.x << ", " << ptMax1.y << ")" << endl; points.push_back(ptMax1); goto top_label; } } top_label: #ifdef _SHOW_POINTS_ circle(src, ptMax1, 5, Scalar(0, 255, 255), -1); imshow("src", src); waitKey(); #endif for (int i = imgSize.height - 1; i >= 0; i--) { minMaxLoc(gray.row(i), &minVal, &maxVal, &ptMin2, &ptMax2); if ((maxVal - minVal) > threshold) { flag++; ptMax2.y = i; //cout << "horizontal bottom:" << endl; //cout << "ptMax2=(" << ptMax2.x << ", " << ptMax2.y << ")" << endl; //src.row(i) = Scalar(0, 0, 255); //src.row(i + 1) = Scalar(0, 0, 255); points.push_back(ptMax2); goto bottom_label; } } bottom_label: #ifdef _SHOW_POINTS_ circle(src, ptMax2, 5, Scalar(0, 255, 255), -1); line(src, ptMax1, ptMax2, Scalar(192, 192, 0), 2); imshow("src", src); waitKey(); #endif if (flag == 2) { distance.push_back(sqrt(pow(ptMax1.x - ptMax2.x, 2) + pow(ptMax1.y - ptMax2.y, 2))); } else if (flag == 1) { points.pop_back(); } } else if (0 < n&&n < N) { for (int i = 0; i < imgSize.width; i++) { for (int j = 0; j <= i; j++) { x = j; y = -tan(theta)*(x - i); Point ptCur(x, y); if (!ptCur.inside(Rect(0, 0, imgSize.width, imgSize.height))) { continue; } uchar I = gray.at<uchar>(ptCur); if (I > max1) { max1 = I; ptMax1 = ptCur; } if (I < min1) { min1 = I; } if (abs(max1 - min1) > threshold) { flag++; //cout << "jump outer1" << endl; //cout << "ptMax1=(" << ptMax1.x << ", " << ptMax1.y << ")" << endl; points.push_back(ptMax1); /* Point start, end; for (int k = 0; k <= i; k++) { x = k; y = -tan(theta)*(x - i); if (k == 0) { start = Point(x, y); } else if (k == i) { end = Point(x, y); } } line(src, start, end, Scalar(0, 0, 255), 2);*/ goto outer1; } } } outer1: #ifdef _SHOW_POINTS_ circle(src, ptMax1, 5, Scalar(0, 255, 255), -1); imshow("src", src); waitKey(); #endif for (int i = imgSize.width - 1; i >= 0; i--) { for (int j = i; j < imgSize.width; j++) { x = j; y = imgSize.height - 1 - tan(theta)*(x - i); Point ptCur(x, y); if (!ptCur.inside(Rect(0, 0, imgSize.width, imgSize.height))) { continue; } uchar I = gray.at<uchar>(ptCur); if (I > max2) { max2 = I; ptMax2 = ptCur; } if (I < min2) { min2 = I; } if (abs(max2 - min2) > threshold) { flag++; //cout << "jump outer2" << endl; //cout << "ptMax2=(" << ptMax2.x << ", " << ptMax2.y << ")" << endl; points.push_back(ptMax2); //Point start, end; //for (int k = i; k < imgSize.width; k++) //{ // x = k; // y = imgSize.height - 1 - tan(theta)*(x - i); // if (k == i) // { // start = Point(x, y); // } // else if (k == imgSize.width-1) // { // end = Point(x, y); // } //} //line(src, start, end, Scalar(0, 0, 255), 2); goto outer2; } } } outer2: ; #ifdef _SHOW_POINTS_ circle(src, ptMax2, 5, Scalar(0, 255, 255), -1); line(src, ptMax1, ptMax2, Scalar(192, 192, 0), 2); imshow("src", src); waitKey(); #endif if (flag == 2) { distance.push_back(sqrt(pow(ptMax1.x - ptMax2.x, 2) + pow(ptMax1.y - ptMax2.y, 2))); } else if (flag == 1) { points.pop_back(); } } else if (N == n) { for (int i = 0; i < imgSize.width; i++) { minMaxLoc(gray.col(i), &minVal, &maxVal, &ptMin1, &ptMax1); if ((maxVal - minVal)>threshold) { flag++; ptMax1.x = i; //cout << "vertical left:" << endl; //cout << "ptMax1=(" << ptMax1.x << ", " << ptMax1.y << ")" << endl; //src.col(i) = Scalar(0, 0, 255); //src.col(i - 1) = Scalar(0, 0, 255); points.push_back(ptMax1); goto left_label; } } left_label: #ifdef _SHOW_POINTS_ circle(src, ptMax1, 5, Scalar(0, 255, 255), -1); imshow("src", src); waitKey(); #endif for (int i = gray.cols - 1; i >= 0; i--) { minMaxLoc(gray.col(i), &minVal, &maxVal, &ptMin2, &ptMax2); if ((maxVal - minVal) > threshold) { flag++; ptMax2.x = i; //cout << "vertical right:" << endl; //cout << "ptMax1=(" << ptMax2.x << ", " << ptMax2.y << ")" << endl; points.push_back(ptMax2); //src.col(i) = Scalar(0, 0, 255); //src.col(i + 1) = Scalar(0, 0, 255); goto right_label; } } right_label: #ifdef _SHOW_POINTS_ circle(src, ptMax2, 5, Scalar(0, 255, 255), -1); line(src, ptMax1, ptMax2, Scalar(192, 192, 0), 2); imshow("src", src); waitKey(); #endif if (flag == 2) { distance.push_back(sqrt(pow(ptMax1.x - ptMax2.x, 2) + pow(ptMax1.y - ptMax2.y, 2))); } else if (flag == 1) { points.pop_back(); } } else if (N < n&&n < 2 * N) { for (int i = 0; i < imgSize.width; i++) { for (int j = 0; j <= i; j++) { x = j; y = imgSize.height - 1 - tan(theta)*(x - i); Point ptCur(x, y); if (!ptCur.inside(Rect(0, 0, imgSize.width, imgSize.height))) { continue; } uchar I = gray.at<uchar>(ptCur); if (I > max1) { max1 = I; ptMax1 = ptCur; } if (I < min1) { min1 = I; } if (abs(max1 - min1) > threshold) { flag++; //cout << "jump outer3" << endl; //cout << "ptMax1=(" << ptMax1.x << ", " << ptMax1.y << ")" << endl; points.push_back(ptMax1); //Point start, end; //for (int k = 0; k <= i; k++) //{ // x = k; // y = imgSize.height - 1 - tan(theta)*(x - i); // if (k == 0) // { // start = Point(x, y); // } // else if (k == i) // { // end = Point(x, y); // } //} //line(src, start, end, Scalar(0, 0, 255), 2); goto outer3; } } } outer3: #ifdef _SHOW_POINTS_ circle(src, ptMax1, 5, Scalar(0, 255, 255), -1); imshow("src", src); waitKey(); #endif for (int i = imgSize.width - 1 / 2; i >= 0; i--) { for (int j = i; j < imgSize.width; j++) { x = j; y = -tan(theta)*(x - i); Point ptCur(x, y); if (!ptCur.inside(Rect(0, 0, imgSize.width, imgSize.height))) { continue; } uchar I = gray.at<uchar>(ptCur); if (I > max2) { max2 = I; ptMax2 = ptCur; } if (I < min2) { min2 = I; } if (abs(max2 - min2) > threshold) { flag++; //cout << "jump outer4" << endl; //cout << "ptMax2=(" << ptMax2.x << ", " << ptMax2.y << ")" << endl; points.push_back(ptMax2); /* Point start, end; for (int k = i; k < imgSize.width; k++) { x = k; y = -tan(theta)*(x - i); if (k == i) { start = Point(x, y); } else if (k == imgSize.width - 1) { end = Point(x, y); } } line(src, start, end, Scalar(0, 0, 255), 2);*/ goto outer4; } } } outer4: ; #ifdef _SHOW_POINTS_ circle(src, ptMax2, 5, Scalar(0, 255, 255), -1); line(src, ptMax1, ptMax2, Scalar(192, 192, 0), 2); imshow("src", src); waitKey(); #endif if (flag == 2) { distance.push_back(sqrt(pow(ptMax1.x - ptMax2.x, 2) + pow(ptMax1.y - ptMax2.y, 2))); } else if (flag == 1) { points.pop_back(); } } else { cout << "The value of n is error!" << endl; break; } } //vector<Point>::iterator itero = points.begin(); //ofstream of("points.txt", ios::trunc | ios::out); //while (itero != points.end()) //{ // of << (*itero).x << ", " << (*itero).y << endl; // itero++; //} //of.close(); //find out validate points double mean = 0; vector<double>::iterator iter = distance.begin(); while (iter != distance.end()) { mean += *iter; iter++; } mean /= distance.size(); vector<Point> validPoints; for (int i = 0; i < distance.size(); i++) { if (distance.at(i) < mean) { validPoints.push_back(points.at(2 * i)); validPoints.push_back(points.at(2 * i + 1)); } } //figure out the center and radius of the circle with Kasa method if (!CircleFitByKasa(validPoints, center, radius)) { cout << "Revisied LineScan Method Failed, Because the Circle Fit Method failed!" << endl; return; } //#ifdef _DEBUG_ cout << "Use the Revised ScanLine Method:" << endl << "\tThe center is (" << center.x << ", " << center.y << ")" << endl << "\tThe radius is " << radius << endl; circle(src, center, radius, Scalar(0, 0, 255), src.cols / 300); circle(src, center, 5, Scalar(0, 255, 255), -1); //namedWindow("Revised ScanLine Method Result", CV_WINDOW_AUTOSIZE); //imshow("Revised ScanLine Method Result", src); imshow(win_name, src); //imwrite("Revised_Scan_ret.tiff", src); //waitKey(); //#endif }