bool MOERTEL::Overlap::buildPoly(std::vector<double>& source_xi, std::vector<double>& source_eta, std::vector<double>& target_xi, std::vector<double>& target_eta, double *PE, double *N) { bool s_in, p_in; double point_s[2], point_p[2]; double eps = 1.0e-10; // GAH EPSILON int index = -1; bool ok; // Make sure they are empty target_xi.clear(); target_eta.clear(); // Find the first s inside the polygon for(unsigned int i = 0; i < source_xi.size(); i++){ // clip point s against this edge (PE = point on edge, N is outward normal of edge) point_s[0] = source_xi[i]; point_s[1] = source_eta[i]; s_in = Clip_TestPoint(N, PE, point_s, eps); // true if point is inside edge if(s_in){ // if point s is inside the clipedge index = i; // placeholder break; } } if(index < 0){ // There were no points found inside the clipedge return false; } // Note that we are at index i and s_in is true // Go to the end of the input poly data for(unsigned int i = static_cast<unsigned int>(index); i < source_xi.size(); i++){ if(i + 1 >= source_xi.size() - 1){ // p is at the beginning of the list point_p[0] = source_xi[0]; point_p[1] = source_eta[0]; } else { point_p[0] = source_xi[i + 1]; point_p[1] = source_eta[i + 1]; } p_in = Clip_TestPoint(N, PE, point_p, eps); // true if point is inside edge if(s_in && p_in){ // both s and p are in polygon // Store p in new polygon target_xi.push_back(point_p[0]); target_eta.push_back(point_p[1]); } else if(s_in && !p_in){ // s is in, and p is out double xi[2]; ok = Guarded_Clip_Intersect(N, PE, point_s, point_p, xi); if(!ok){ // Cannot find the intersection between edge and clip edge std::stringstream oss; oss << "***ERR*** MOERTEL::Overlap::buildPoly:\n" << "***ERR*** Cannot find the intersection between edge and clip edge\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } // Store i in new polygon target_xi.push_back(xi[0]); target_eta.push_back(xi[1]); } else if(!s_in && p_in){ // s is out, p is in double xi[2]; ok = Guarded_Clip_Intersect(N, PE, point_s, point_p, xi); if(!ok){ // Cannot find the intersection between edge and clip edge std::stringstream oss; oss << "***ERR*** MOERTEL::Overlap::buildPoly:\n" << "***ERR*** Cannot find the intersection between edge and clip edge\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } // Store i in new polygon target_xi.push_back(xi[0]); target_eta.push_back(xi[1]); // Store p in new polygon target_xi.push_back(point_p[0]); target_eta.push_back(point_p[1]); } // Do nothing if neither s nor p are inside clip edge // Advance s s_in = p_in; point_s[0] = point_p[0]; point_s[1] = point_p[1]; } // Note that here s_in, and point_s are set to the 0th point in the source data // We now need to march back up to index for(int i = 0; i < index; i++){ point_p[0] = source_xi[i + 1]; point_p[1] = source_eta[i + 1]; p_in = Clip_TestPoint(N, PE, point_p, eps); // true if point is inside edge if(s_in && p_in){ // both s and p are in polygon // Store p in new polygon target_xi.push_back(point_p[0]); target_eta.push_back(point_p[1]); } else if(s_in && !p_in){ // s is in, and p is out double xi[2]; ok = Guarded_Clip_Intersect(N, PE, point_s, point_p, xi); if(!ok){ // Cannot find the intersection between edge and clip edge std::stringstream oss; oss << "***ERR*** MOERTEL::Overlap::buildPoly:\n" << "***ERR*** Cannot find the intersection between edge and clip edge\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } // Store i in new polygon target_xi.push_back(xi[0]); target_eta.push_back(xi[1]); } else if(!s_in && p_in){ // s is out, p is in double xi[2]; ok = Guarded_Clip_Intersect(N, PE, point_s, point_p, xi); if(!ok){ // Cannot find the intersection between edge and clip edge std::stringstream oss; oss << "***ERR*** MOERTEL::Overlap::buildPoly:\n" << "***ERR*** Cannot find the intersection between edge and clip edge\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } // Store i in new polygon target_xi.push_back(xi[0]); target_eta.push_back(xi[1]); // Store p in new polygon target_xi.push_back(point_p[0]); target_eta.push_back(point_p[1]); } // Do nothing if neither s nor p are inside clip edge // Advance s s_in = p_in; point_s[0] = point_p[0]; point_s[1] = point_p[1]; } return true; // If we have not thrown an error or returned false, return the polygon }
/*----------------------------------------------------------------------* | perform clipping algorithm (private) mwgee 10/05| *----------------------------------------------------------------------*/ bool MOERTEL::Overlap::Clipelements() { if (!havemxi_ || !havesxi_ || !havelines_ || !havesxim_ || !havelinem_) { std::cout << "***ERR*** MOERTEL::Overlap::Clipelements:\n" << "***ERR*** initialization of Overlap class missing\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; exit(EXIT_FAILURE); } const int nmnode = mseg_.Nnode(); const int nsnode = sseg_.Nnode(); // put all mseg nodes in polygon for (int i=0; i<nmnode; ++i) AddPointtoPolygon(100+i,&mline_[i][0]); //for (int i=0; i<nmnode; ++i) // std::cout << "mline_[" << i << "][0] " << mline_[i][0] << " mline_[" << i << "][1] " << mline_[i][1] // << " mline_[" << i << "][2] " << mline_[i][2] << " mline_[" << i << "][3] " << mline_[i][3] << endl; //=========================================================================== // loop edges of slave segment and clip the master edges // add all intersection points that can be found for (int clipedge=0; clipedge<nsnode; ++clipedge) { // point on that clip edge (dim 2) double* PE = &sline_[clipedge][0]; // the outward normal to the clip edge (dim 2) double* N = &sn_[clipedge][0]; // loop edges of master segment and clip them against the clip edge // add all intersections for (int medge=0; medge<nmnode; ++medge) { bool ok; // start point of medge with id 100+medge double* P0 = &mline_[medge][0]; //int id0 = 100+medge; // end point of medge has id 100+(medge+1 < 3) double* P1 = &mline_[medge][2]; // find intersection between medge and clipedge // if there's an intersection, put it in the polygon // the id is 10*clipedge+medge double xi[2]; ok = Clip_Intersect(N,PE,P0,P1,xi); if (ok) { //std::cout << "OVERLAP Clipelements: adding intersection point " << 10*clipedge+medge << endl; AddPointtoPolygon(10*clipedge+medge,xi); } } // for (int medge=0; medge<3; ++medge) } // for (int clipedge=0; clipedge<3; ++clipedge) //=========================================================================== // loop all clipedges and clip all points incl intersections // that are in the polygon // throw away all points that are not inside { int np = SizePointPolygon(); std::vector<Teuchos::RCP<MOERTEL::Point> > point; PointView(point); int p; for (p=0; p<np; ++p) { bool ok = true; //std::cout << "OVERLAP Clipelements: now clipping point " << point[p]->Id() << endl; const double* P = point[p]->Xi(); for (int clipedge=0; clipedge<nsnode; ++clipedge) { // point on that clip edge (dim 2) double* PE = &sline_[clipedge][0]; // the outward normal to the clip edge (dim 2) double* N = &sn_[clipedge][0]; // clip point P against this edge ok = Clip_TestPoint(N,PE,P,1.0e-10); // leave point in if (ok) continue; // remove this point else { ok = false; break; } } // for (int clipedge=0; clipedge<3; ++clipedge) // if not found inside, remove point if (!ok) { //std::cout << "OVERLAP Clipelements: removing point " << point[p]->Id() << endl; RemovePointfromPolygon(point[p]->Id(),P); } } // for (int p=0; p<np; ++p) point.clear(); } //=========================================================================== // loop all slave nodes and clip against master element. // put those slave nodes that are inside master element into polygon // Note that this works in master segment coords and the node that is put in // is put in with slave segment coords as the polygon is completely in // slave segment coords // master point have ids 100,101,102 // slave points have ids 1000,1001,1002 // edge intersections have ids sedge*10+medge // try only to put slave points in if the polygon is not empty int np = SizePointPolygon(); if (np) { for (int i=0; i<nsnode; ++i) { bool ok = true; // get the slave point in master coords double* P = sxim_[i]; // loop master clip edges for (int clipedge=0; clipedge<nmnode; ++clipedge) { // point on master clipedge double* PE = &mlinem_[clipedge][0]; // the outward normal to the clip edge (dim 2) double* N = &mn_[clipedge][0]; // clip point P against this edge ok = Clip_TestPoint(N,PE,P,1.0e-5); // put point in if (ok) continue; else { ok = false; break; } } // for (int clipedge=0; clipedge<3; ++clipedge) // don't put point in if (!ok) continue; else { //std::cout << "OVERLAP Clipelements: inserting slave point " << 1000+i << " xi=" // << sxi_[i][0] << "/" << sxi_[i][1] << endl; AddPointtoPolygon(1000+i,sxi_[i]); } } // for (int i=0; i<3; ++i) } //=========================================================================== //=========================================================================== //=========================================================================== #if 0 // make printout of the polygon so far { int np = SizePointPolygon(); std::vector<Teuchos::RCP<MOERTEL::Point> > point; PointView(point); for (int p=0; p<np; ++p) { std::cout << "OVERLAP Clipelements: point " << setw(3) << point[p]->Id() << " xi " << point[p]->Xi()[0] << "/" << point[p]->Xi()[1] << endl; } point.clear(); } #endif //=========================================================================== // count how many corner nodes of mseg are in and how many // intersections there are np = SizePointPolygon(); //=========================================================================== // if there are no points, there is still the chance that all slave points // are inside the master element if (!np) { for (int i=0; i<3; ++i) { bool ok = true; // get the slave point in master coords double* P = sxim_[i]; for (int clipedge=0; clipedge<3; ++clipedge) { // point on master clipedge double* PE = &mlinem_[clipedge][0]; // the outward normal to the clip edge (dim 2) double* N = &mn_[clipedge][0]; // clip point P against this edge ok = Clip_TestPoint(N,PE,P,1.0e-5); // put point in if (ok) continue; else { ok = false; break; } } // for (int clipedge=0; clipedge<3; ++clipedge) // don't put point in if (!ok) continue; else { //std::cout << "OVERLAP Clipelements: inserting slave point " << 1000+i << " xi=" // << sxi_[i][0] << "/" << sxi_[i][1] << endl; AddPointtoPolygon(1000+i,sxi_[i]); } } // for (int i=0; i<3; ++i) //========================================================================= // check again how many points there are inside np = SizePointPolygon(); if (np>2); // all slave points are in master segment, just continue else if (np && np <= 2) { if (inter_.OutLevel()>8) std::cout << "MOERTEL: ***WRN*** MOERTEL::Overlap::Clipelements:\n" << "MOERTEL: ***WRN*** " << np << " slave nodes seem to be in master segment but no overlap detected\n" << "MOERTEL: ***WRN*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; return false; } else // with none or less then 3 points in we assume no overlap return false; } //=========================================================================== // maybe its a good idea to collapse intersections with nodes (that are in) // that are really close to each other if (p_.size()>3) CollapsePoints(p_,1.0e-5); #if 0 // make printout of the polygon so far { std::cout << "--------------------------------------------\n"; int np = SizePointPolygon(); std::vector<Teuchos::RCP<MOERTEL::Point> > point; PointView(point); for (int p=0; p<np; ++p) { std::cout << "OVERLAP Clipelements: point " << setw(3) << point[p]->Id() << " xi " << point[p]->Xi()[0] << "/" << point[p]->Xi()[1] << endl; } point.clear(); } #endif //=========================================================================== // check again np = SizePointPolygon(); if (np && np<3) { if (OutLevel()>8) std::cout << "MOERTEL: ***WRN*** MOERTEL::Overlap::Clipelements:\n" << "MOERTEL: ***WRN*** " << np << " nodes in polygon but could not detect overlap\n" << "MOERTEL: ***WRN*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; return false; } else if (!np) return false; //=========================================================================== // finish the polygon ConvexHull(p_); return true; }
bool MOERTEL::Overlap::ClipelementsSH() { if (!havemxi_ || !havesxi_ || !havelines_ || !havesxim_ || !havelinem_){ std::stringstream oss; oss << "***ERR*** MOERTEL::Overlap::Clipelements:\n" << "***ERR*** initialization of Overlap class missing\n" << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n"; throw ReportError(oss); } const int nmnode = mseg_.Nnode(); const int nsnode = sseg_.Nnode(); bool ok = true; double eps = 1.0e-10; // GAH EPSILON // I am reading http://cs.fit.edu/~wds/classes/graphics/Clip/clip/clip.html and // http://en.wikipedia.org/wiki/Sutherland–Hodgman_algorithm as I write this code. // I assume that the master segment is convex. It should be if this is a mesh. Secondly, the // slave segment is a square in its parametric space -1 <= \xi <= 1 and -1 <= \eta <= 1. It need // only be convex. // For the Sutherland-Hodgman algorithm, the slave segment is used for the clip polygon. // Start with an input list of polygon vertices, in the slave coordinate system. Note that these points // are ordered around the polygon, as i is the line number of the boundaries of the master seg. std::vector<double> s_poly_xi, s_poly_eta, t_poly_xi, t_poly_eta; // Put all the corners of the master segment into the polygon for (int i=0; i<nmnode; ++i) { // loop over the corners of the master seg s_poly_xi.push_back(mline_[i][0]); s_poly_eta.push_back(mline_[i][1]); } // Clip that poly against the slave poly one edge at a time for (int clipedge = 0; clipedge < nsnode; ++clipedge) { // point on that clip edge (dim 2) double* PE = &sline_[clipedge][0]; // the outward normal to the clip edge (dim 2) double* N = &sn_[clipedge][0]; ok = buildPoly(s_poly_xi, s_poly_eta, t_poly_xi, t_poly_eta, PE, N); if(!ok){ // there is no intersection between polys. However, it is possible that the // slave poly is completely contained within the master break; } // The target vectors now become the source vectors s_poly_xi = t_poly_xi; s_poly_eta = t_poly_eta; } // for (int clipedge=0; clipedge<3; ++clipedge) if(ok){ // We have a target polygon double xi[2]; // Compress the polygon by removing adjacent points less than epsilon apart for(unsigned int p = t_poly_xi.size() - 1; p >= 1; p--){ xi[0] = t_poly_xi[p] - t_poly_xi[p - 1]; xi[1] = t_poly_eta[p] - t_poly_eta[p - 1]; double dist = MOERTEL::length(xi, 2); if(dist <= eps){ // remove the point p t_poly_xi.erase(t_poly_xi.begin() + p); t_poly_eta.erase(t_poly_eta.begin() + p); } } // Check the last point too if(t_poly_xi.size() >= 2){ xi[0] = t_poly_xi[t_poly_xi.size() - 1] - t_poly_xi[0]; xi[1] = t_poly_eta[t_poly_xi.size() - 1] - t_poly_eta[0]; double dist = MOERTEL::length(xi, 2); if(dist <= eps){ // remove the point p t_poly_xi.erase(t_poly_xi.end() - 1); t_poly_eta.erase(t_poly_eta.end() - 1); } } // Do we still have a polygon? If not, just move on if(t_poly_xi.size() < 3){ return false; } // Store it in the polygon for (unsigned int p = 0; p < t_poly_xi.size(); ++p) { xi[0] = t_poly_xi[p]; xi[1] = t_poly_eta[p]; AddPointtoPolygon(p, xi); } #if 0 // make printout of the polygon so far { int np = SizePointPolygon(); std::vector<Teuchos::RCP<MOERTEL::Point> > point; PointView(point); std::cout << "Master is in slave" << std::endl; for (int p=0; p<np; ++p) { std::cout << "OVERLAP Clipelements: point " << std::setw(3) << point[p]->Id() << " xi " << point[p]->Xi()[0] << "/" << point[p]->Xi()[1] << std::endl; } point.clear(); } #endif return true; } //=========================================================================== // We come down here if there is no polygon from the above. This could mean that the slave segment is // completely inside the master segment. std::vector<int> s_node_id; for (int i=0; i<nsnode; ++i) { bool ok = true; // get the slave point in master coords double* P = sxim_[i]; // loop master clip edges for (int clipedge=0; clipedge<nmnode; ++clipedge) { // point on master clipedge double* PE = &mlinem_[clipedge][0]; // the outward normal to the clip edge (dim 2) double* N = &mn_[clipedge][0]; // clip point P against this edge // GAH - EPSILON clip test point ok = Clip_TestPoint(N,PE,P,1.0e-5); // put point in if (ok) continue; else { ok = false; break; } } // for (int clipedge=0; clipedge<3; ++clipedge) // We will be here, with ok == true only if the point is inside ALL clip edges // don't put point in if (!ok) continue; else { // Point is inside ALL clip edges s_node_id.push_back(i); } } // for (int i=0; i<3; ++i) if(s_node_id.size() < static_cast<unsigned int>(nsnode)){ // Slave poly does not lie within master either. // There is no overlap. Move on. /* The reasoning here is that zero of the master polygon was found in the slave (no nodes). If the slave is completely * within the master, then all 4 nodes need to cleanly show up inside the master. If they do not, chances are only * a corner or edge of the master is touched. */ return false; } // Slave is completely in master. Put the slave in the polygon for(unsigned int i = 0; i < s_node_id.size(); i++){ //std::cout << "OVERLAP Clipelements: inserting slave point " << 1000+i << " xi=" // << sxi_[i][0] << "/" << sxi_[i][1] << endl; AddPointtoPolygon(i,sxi_[i]); } #if 0 // make printout of the polygon so far { int np = SizePointPolygon(); std::vector<Teuchos::RCP<MOERTEL::Point> > point; PointView(point); std::cout << "Slave is in master" << std::endl; for (int p=0; p<np; ++p) { std::cout << "OVERLAP Clipelements: point " << std::setw(3) << point[p]->Id() << " xi " << point[p]->Xi()[0] << "/" << point[p]->Xi()[1] << std::endl; } point.clear(); } #endif return true; }