Exemple #1
0
/*----------------------------------------------------------------------*
 |  make a triangulization of a polygon (private)             mwgee 10/05|
 *----------------------------------------------------------------------*/
bool MOERTEL::Overlap::Triangulation()
{
  // we have a polygon that is in clockwise order at this moment

  // if more than 3 points, find a center point
  int np = SizePointPolygon();
  if (np<3)
  {
	std::cout << "***ERR*** MOERTEL::Overlap::Triangulization:\n"
         << "***ERR*** # point in polygon < 3 ... very strange!!!\n"
         << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
    exit(EXIT_FAILURE);
  }
  if (np>3) // we have to add a center point
  {
    double xi[2];
	std::vector<Teuchos::RCP<MOERTEL::Point> > points; PointView(points);

#if 1 // compute center point xi as centroid
    Centroid(xi,points,np);    
    //std::cout << "Centroid xi : " << xi[0] << " / " << xi[1] << endl; fflush(stdout);
#endif
    
#if 0 // compute center point as nodal avergage
    xi[0] = xi[1] = 0.0;
    for (int i=0; i<np; ++i)
    {
      const double* pxi = points[i]->Xi();
      xi[0] += pxi[0];
      xi[1] += pxi[1];
    }
    xi[0] /= np;
    xi[1] /= np;
    //std::cout << "Nodal    xi : " << xi[0] << " / " << xi[1] << endl << endl; fflush(stdout);
#endif
    
    // create a point -1 as center point and add it to the polygon
    AddPointtoPolygon(-1,xi);
    points.clear();
  } // if (np>3)
  
  np = SizePointPolygon();
  std::vector<Teuchos::RCP<MOERTEL::Point> >  points; PointView(points);

  // create a MOERTEL::Node for every point
  int dof[3]; dof[0] = dof[1] = dof[2] = -1;
  
  // find real world coords for all points
  // find real world normal for all points
  // note that the polygon is in slave segment parameter space and is
  // completely contained in the slave segment. we can therefore use
  // slave segment values to interpolate polgon point values
  for (int i=0; i<np; ++i)
  {
    double x[3]; x[0] = x[1] = x[2] = 0.0;
    double n[3]; n[0] = n[1] = n[2] = 0.0;
    double val[20];
    sseg_.EvaluateFunction(0,points[i]->Xi(),val,sseg_.Nnode(),NULL);
    MOERTEL::Node** snodes = sseg_.Nodes();
    for (int j=0; j<sseg_.Nnode(); ++j)
      for (int k=0; k<3; ++k)
      {
        x[k] += val[j]*snodes[j]->X()[k];
        n[k] += val[j]*snodes[j]->N()[k];
      }
    const double length = MOERTEL::length(n,3);
    for (int j=0; j<3; ++j) n[j] /= length;
    // create a node with this coords and normal;
    MOERTEL::Node* node = new MOERTEL::Node(points[i]->Id(),x,3,dof,false,OutLevel());
    node->SetN(n);
    // set node in point
    points[i]->SetNode(node);
#if 0
	std::cout << *points[i];
#endif
  }  

  // find projection values for all points in polygon on mseg
  {
    double mxi[2];
	double gap;
    MOERTEL::Projector projector(inter_.IsOneDimensional(),OutLevel());
    for (int i=0; i<np; ++i)
    {
	  Teuchos::RCP<MOERTEL::Node> node = points[i]->Node();
      projector.ProjectNodetoSegment_NodalNormal(*node,mseg_,mxi,gap);
      // create a projected node and set it in node
      MOERTEL::ProjectedNode* pnode = new MOERTEL::ProjectedNode(*node,mxi,&mseg_);
      node->SetProjectedNode(pnode);
	  node->SetGap(gap);
#if 0
	  std::cout << "-------------------------------------------------------\n";
      if (mseg_.Nnode()==3)
      {
        if (mxi[0]<=1. && mxi[1]<=abs(1.-mxi[0]) && mxi[0]>=0. && mxi[1]>=0.)
          std::cout << "OVERLAP: point " << points[i]->Id() << " is in mseg, mxi " << mxi[0] << " / " << mxi[1] << endl;
        else
          std::cout << "OVERLAP: point " << points[i]->Id() << " is NOT in mseg, mxi " << mxi[0] << " / " << mxi[1] << endl;
      }
      else if (mseg_.Nnode()==4)
      {
        if (mxi[0]<=1.001 && mxi[0]>=-1.001 && mxi[1]<=1.001 && mxi[1]>=-1.001)
          std::cout << "OVERLAP: point " << points[i]->Id() << " is in mseg, mxi " << mxi[0] << " / " << mxi[1] << endl;
        else
          std::cout << "OVERLAP: point " << points[i]->Id() << " is NOT in mseg, mxi " << mxi[0] << " / " << mxi[1] << endl;
      }
      else
      {
		std::cout << "***ERR*** MOERTEL::Overlap::Triangulization:\n"
             << "***ERR*** # nodes " << mseg_.Nnode() << " of master segment is unknown\n"
             << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
        exit(EXIT_FAILURE);
      }
	  std::cout << "-------------------------------------------------------\n";
#endif

    }
  }

  // if we plan to interpolate function values at the gaussian points we need the
  // function values at the points
  if (exactvalues_==false)
  {
    // every point has 3 values of the 3 shape functions of the elements:
    // max 4 values from function 0 from sseg
    // max 4 values from function 1 from sseg
    // max 4 values from function 0 from mseg
    for (int i=0; i<np; ++i)
    {
      double val[20];
      int nmval = mseg_.Nnode();
      int nsval = sseg_.Nnode();
      // evaluate function 0 from sseg
      sseg_.EvaluateFunction(0,points[i]->Xi(),val,nsval,NULL);
      points[i]->StoreFunctionValues(0,val,nsval);
      // evaluate function 1 from sseg
      sseg_.EvaluateFunction(1,points[i]->Xi(),val,nsval,NULL);
      points[i]->StoreFunctionValues(1,val,nsval);
      // evaluate function 0 from mseg
      mseg_.EvaluateFunction(0,points[i]->Node()->GetProjectedNode()->Xi(),val,nmval,NULL);
      points[i]->StoreFunctionValues(2,val,nmval);
    }
  }
  
  // create the triangle elements from polygon with centerpoint
  // In case of np==3, there is no centerpoint
  if (np>3)
  {
    // the polygon is in clockwise order, center point is points[0] and has
    // id = -1
    if (points[0]->Id() != -1)
    {
	  std::cout << "***ERR*** MOERTEL::Overlap::Triangulization:\n"
           << "***ERR*** points[0]->Id() is not -1\n"
           << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
      exit(EXIT_FAILURE);
    }
    int nodeid[3];
    MOERTEL::Segment_BiLinearTri* tmp;
    MOERTEL::Function_LinearTri* func = new Function_LinearTri(OutLevel());
    for (int i=2; i<np; ++i)
    {
      // there are np-1 triangles
      // triangle ids go from 0 to np-2
      // a triangle is defined by nodes 0, i, i-1
      // *this class takes ownership of triangle
      nodeid[0]   = points[0]->Id();
      nodeid[1]   = points[i]->Id();
      nodeid[2]   = points[i-1]->Id();
      tmp = new MOERTEL::Segment_BiLinearTri(i-2,3,nodeid,OutLevel());
      // set a linear shape function to this triangle
      tmp->SetFunction(0,func);
      // add triangle to the *this class
      AddSegment(tmp->Id(),tmp);
    }
    // add the last triangle defined by nodes 0, 1, np-1 separately
    // *this class takes ownership of triangle
    nodeid[0]   = points[0]->Id();
    nodeid[1]   = points[1]->Id();
    nodeid[2]   = points[np-1]->Id();
    tmp = new MOERTEL::Segment_BiLinearTri(np-2,3,nodeid,OutLevel());
    // set a linear shape function to this triangle
    tmp->SetFunction(0,func);
    // add triangle to the *this class
    AddSegment(tmp->Id(),tmp);
    if (func) delete func; func = NULL;
  }
  else if (np==3) // single triangle without centerpoint
  {
    int nodeid[3];
    MOERTEL::Segment_BiLinearTri* tmp;
    MOERTEL::Function_LinearTri* func = new Function_LinearTri(OutLevel());
    nodeid[0] = points[0]->Id();
    nodeid[1] = points[2]->Id();
    nodeid[2] = points[1]->Id();
    // *this class takes ownership of triangle
    tmp = new MOERTEL::Segment_BiLinearTri(0,3,nodeid,OutLevel());
    // set a linear shape function to this triangle
    tmp->SetFunction(0,func);
    // add triangle the *this class
    AddSegment(tmp->Id(),tmp);
    if (func) delete func; func = NULL;
  }
  else
  {
	std::cout << "***ERR*** MOERTEL::Overlap::Triangulization:\n"
         << "***ERR*** # point in polygon < 3 ... very strange!!!\n"
         << "***ERR*** file/line: " << __FILE__ << "/" << __LINE__ << "\n";
    exit(EXIT_FAILURE);
  }
  
  // create ptr topology between triangle and nodes in points
  std::vector<MOERTEL::Node*> nodes(np);
  for (int i=0; i<np; ++i) nodes[i] = points[i]->Node().get();
  
  // loop segments and set ptr to nodes in them
  std::map<int,Teuchos::RCP<MOERTEL::Segment> >::iterator curr;
  for (curr=s_.begin(); curr != s_.end(); ++curr)
    curr->second->GetPtrstoNodes(nodes);
  
  nodes.clear();
  
  points.clear();
  
  return true;
}
Exemple #2
0
/*----------------------------------------------------------------------*
 |  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 MoertelT::MOERTEL_TEMPLATE_CLASS_1A(OverlapT, IFace)::CollapsePoints(
    std::map<int, Teuchos::RCP<MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)>>& p,
    const double                                                           eps)
{
  // we don't want to collapse on a polygon that has just three or less points
  if (p.size() <= 3) return true;

  // # points
  int np = p.size();

  // get a view of all points
  std::vector<Teuchos::RCP<MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)>> points;
  PointView(p, points);

  // create a new std::map for collapsed points
  std::map<int, Teuchos::RCP<MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)>> pnew;

  // create  vector holding points to collapse
  std::vector<Teuchos::RCP<MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)>> collapse(
      points.size());

  // loop points and compare coords
  for (int i = 0; i < np; ++i) {
    if (points[i] == Teuchos::null) continue;

    // put point i into vector with collapse points
    // std::cout << "Adding " << i << " to collapse\n";
    collapse[0] = points[i];
    int count   = 1;

    for (int j = i + 1; j < np; ++j) {
      if (points[j] == Teuchos::null) continue;
      double xi1xi2[2];
      xi1xi2[0]   = points[j]->Xi()[0] - points[i]->Xi()[0];
      xi1xi2[1]   = points[j]->Xi()[1] - points[i]->Xi()[1];
      double dist = MOERTEL::length(xi1xi2, 2);
      // std::cout << "distance between " << i << " and " << j << " : " << dist
      // << std::endl;
      if (dist < eps) {
        // std::cout << "Adding " << j << " to collapse\n";
        // add point2 to collapse vector
        collapse[count] = points[j];
        ++count;
        points[j] = Teuchos::null;
      }
    }

    // loop all nodes in the collapse vector and put in the one with an
    // id above 100 (if there is any)
    bool foundit = false;
    // if (count>1)
    //  std::cout << "Collapsing " << count << " nodes\n";
    for (int j = 0; j < count; ++j) {
      if (collapse[j]->Id() >= 100) {
        AddPointtoPolygon(pnew, collapse[j]->Id(), collapse[j]->Xi());
        foundit = true;
        break;
      }
    }
    if (!foundit)  // there is no point with id >= 100
    {
      AddPointtoPolygon(pnew, collapse[0]->Id(), collapse[0]->Xi());
    }
  }  // for (int i=0; i<np; ++i)

  points.clear();

  // the new polygon is supposed to have at least three points, otherwise its
  // no better than the old uncollapsed one and we'd rather keep the old one
  // ^^^ this comment is inaccurate ^^^
  // soon after this method is called, there is a check for a degenerate overlap
  // by asking how many things are in p.  If p is less than three, the overlap
  // is skipped, otherwise the computation continues.  After that, an area
  // weighted sum is computed on the polygon.  If the area is 0, this generates
  // NaNs. By commenting out this if block, the check for degeneracy will work
  // as claimed in the comments.
  /* */
  if (pnew.size() < 3) {
    pnew.clear();
    collapse.clear();
    return true;
  }
  /* */

  p.clear();
  CopyPointPolygon(pnew, p);
  pnew.clear();

  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;
}
bool MoertelT::MOERTEL_TEMPLATE_CLASS_1A(OverlapT, IFace)::ConvexHull(
    std::map<int, Teuchos::RCP<MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)>>& p)
{
  // # points
  int np = p.size();

  // sort points by xi[0] coordinate
  std::vector<Teuchos::RCP<MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)>> points;
  PointView(p, points);
  std::vector<double> dlistx(np);
  std::vector<double> dlisty(np);
  std::vector<int>    list2(np);
  for (int i = 0; i < np; ++i) {
    dlistx[i] = points[i]->Xi()[0];
    list2[i]  = i;
  }
  MOERTEL::sort(&dlistx[0], np, &list2[0]);

  // get assoc. y-list
  for (int i = 0; i < np; ++i) dlisty[i] = points[list2[i]]->Xi()[1];

  // sort list again for those points where x is identical
  for (int i = 0; i < np - 1; ++i)
    if (dlistx[i] == dlistx[i + 1])
      if (dlisty[i] > dlisty[i + 1]) {
        MOERTEL::swap(dlistx[i], dlistx[i + 1]);
        MOERTEL::swap(dlisty[i], dlisty[i + 1]);
        MOERTEL::swap(list2[i], list2[i + 1]);
      }

  // create a new polygon and put points in in sorted order
  std::map<int, Teuchos::RCP<MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)>> newp;
  for (int i = 0; i < np; ++i) {
    Teuchos::RCP<MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)> tmp =
        Teuchos::rcp(new MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)(
            i, points[list2[i]]->Xi(), OutLevel()));
    newp.insert(
        std::pair<int, Teuchos::RCP<MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)>>(
            i, tmp));
  }

  // delete the old one
  p.clear();
  // copy new one over
  CopyPointPolygon(newp, p);
  // destroy the new one
  newp.clear();

  points.clear();

  std::map<int, Teuchos::RCP<MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)>>::
      iterator pcurr;

#if 0
  // printout the polygon
  std::cout << "Input polygon:\n";
  for (pcurr=p.begin(); pcurr != p.end(); ++pcurr)
    if (pcurr->second != Teuchos::null)
      std::cout << *(pcurr->second);
#endif

  //===========================================================================
  // build the upper hull
  std::map<int, Teuchos::RCP<MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)>> upper;
  PointView(p, points);
  // put in the first 2 points
  AddPointtoPolygon(upper, 0, points[0]->Xi());  // std::cout << *points[0];
  AddPointtoPolygon(upper, 1, points[1]->Xi());  // std::cout << *points[1];
  //---------------------------------------------------------------------------
  for (int i = 2; i < np; ++i) {
    // add point[i] to upper
    AddPointtoPolygon(upper, i, points[i]->Xi());  // std::cout << *points[i];

    // find whether we still have a convex hull
    while (upper.size() > 2 && !MakeRightTurnUpper(i, upper))
      RemovePointBefore(i, upper);
#if 0
  // printout the current upper hull
  std::map<int,MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)*>::iterator pcurr;
  for (pcurr=upper.begin(); pcurr != upper.end(); ++pcurr)
    if (pcurr->second)
      std::cout << *(pcurr->second);
#endif
  }  // for (int i=2; i<np; ++i)

  //===========================================================================
  // build the lower hull
  std::map<int, Teuchos::RCP<MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)>> lower;
  // put in the first 2 points
  AddPointtoPolygon(
      lower, np - 1, points[np - 1]->Xi());  // std::cout << *points[np-1];
  AddPointtoPolygon(
      lower, np - 2, points[np - 2]->Xi());  // std::cout << *points[np-2];
  //---------------------------------------------------------------------------
  for (int i = np - 3; i >= 0; --i) {
    // add point[i] to lower
    AddPointtoPolygon(lower, i, points[i]->Xi());  // std::cout << *points[i];

    // find whether we still have a convex hull
    while (lower.size() > 2 && !MakeRightTurnLower(i, lower))
      RemovePointAfter(i, lower);
#if 0
  // printout the current lower hull
  std::map<int,Teuchos::RCP<MoertelT::MOERTEL_TEMPLATE_CLASS(PointT) > >::iterator pcurr;
  for (pcurr=lower.begin(); pcurr != lower.end(); ++pcurr)
    if (pcurr->second)
      std::cout << *(pcurr->second);
#endif
  }  // for (int i=np-3; i>=0; --i)

  //===========================================================================
  points.clear();

  //===========================================================================
  // join upper and lower hull
  // note not to put in duplicate start and end point
  std::map<int, Teuchos::RCP<MoertelT::MOERTEL_TEMPLATE_CLASS(PointT)>> finalp;

  // put upper hull in
  int i = 0;
  for (pcurr = upper.begin(); pcurr != upper.end(); ++pcurr) {
    // std::cout << *(pcurr->second);
    AddPointtoPolygon(finalp, i, pcurr->second->Xi());
    ++i;
  }

  // put lower hull in, skip first and last point
  pcurr = lower.end();
  --pcurr;
  --pcurr;
  for (; pcurr != lower.begin(); --pcurr) {
    // std::cout << *(pcurr->second);
    AddPointtoPolygon(finalp, i, pcurr->second->Xi());
    ++i;
  }

#if 0
  // printout the polygon
  std::cout << "--------------------------------------------\n";
  std::cout << "Final polygon:\n";
  for (pcurr=finalp.begin(); pcurr != finalp.end(); ++pcurr)
    if (pcurr->second != Teuchos::null)
      std::cout << *(pcurr->second);
#endif

  // compare size of convex hull polygon newp to size of p, all
  // nodes must be part of the convex hull
  if (finalp.size() != p.size()) {
    if (OutLevel() > 8)
      std::cout << "MOERTEL: ***WRN*** MOERTEL::Overlap::ConvexHull:\n"
                << "MOERTEL: ***WRN*** size of convex hull " << finalp.size()
                << " not # nodes " << p.size() << std::endl
                << "MOERTEL: ***WRN*** file/line: " << __FILE__ << "/"
                << __LINE__ << "\n";
  }

  // copy the polygon over to the input map p
  p.clear();
  upper.clear();
  lower.clear();
  CopyPointPolygon(finalp, p);
  finalp.clear();

  return true;
}