bool SeparateTriTri_coplanar ( Triangle3d const & A, Triangle3d const & B, Plane3d & out, real epsilon )
{
	if(!TestCoplanar(A,B,epsilon))
	{
		return false;
	}

	// ----------
	// Test if triangle B is outside any of A's edge-planes

	{
		for(int i = 0; i < 3; i++)
		{
			Plane3d P = Plane3d( A.getCorner(i), A.getEdgeDir(i).cross( A.getNormal() ) );

			ContainmentResult test = Containment3d::TestTriPlane( B, P, epsilon );

			if( (test == CR_Outside) || (test == CR_TouchingOutside) || (test == CR_Boundary) ) 
			{
				out = P;
				return true;
			}
		}
	}
	
	// ----------
	// Test if triangle A is outside any of B's edge-planes

	{
		for(int i = 0; i < 3; i++)
		{
			Plane3d P = Plane3d( B.getCorner(i), B.getEdgeDir(i).cross( B.getNormal() ) );

			ContainmentResult test = Containment3d::TestTriPlane( A, P, epsilon );

			if( (test == CR_Outside) || (test == CR_TouchingOutside) || (test == CR_Boundary) ) 
			{
				out = P;
				return true;
			}
		}
	}

	// ----------

	return false;
}
bool TestTriTri_proj ( Triangle3d const & inTriA,
                       Triangle3d const & inTriB,
                       Vector const & direction,
                       real epsilon )
{
	Triangle3d triA = inTriA;
	Triangle3d triB = inTriB;

	if(!triA.isFacing(direction)) triA.flip();
	if(!triB.isFacing(direction)) triB.flip();

	int i;

	// ----------

	for(i = 0; i < 3; i++)
	{
		Plane3d P = Plane3d( triA.getCorner(i), triA.getEdgeDir(i).cross( direction ) );

		ContainmentResult test = Containment3d::TestTriPlane( triB, P, epsilon );

		if( Containment::isNonContainment(test) ) return false;
	}
	
	// ----------

	for(i = 0; i < 3; i++)
	{
		Plane3d P = Plane3d( triB.getCorner(i), triB.getEdgeDir(i).cross( direction ) );

		ContainmentResult test = Containment3d::TestTriPlane( triA, P, epsilon );

		if( Containment::isNonContainment(test) ) return false;
	}

	// ----------

	return true;
}
Plane3d OrientedBox::getFacePlane ( int whichFace ) const
{
	switch(whichFace)
	{
	case 0: return Plane3d( m_center + m_axisX * m_extentX,  m_axisX );
	case 1: return Plane3d( m_center + m_axisY * m_extentY,  m_axisY );
	case 2: return Plane3d( m_center + m_axisZ * m_extentZ,  m_axisZ );
	case 3: return Plane3d( m_center - m_axisX * m_extentX, -m_axisX );
	case 4: return Plane3d( m_center - m_axisY * m_extentY, -m_axisY );
	case 5: return Plane3d( m_center - m_axisZ * m_extentZ, -m_axisZ );

	default:
		DEBUG_FATAL(true,("OrientedBox::getFacePlane - invalid face\n"));
		return Plane3d(Vector::zero,Vector::zero);
	}
}
Plane3d Prism::base_plane() const {
    return Plane3d(base_vertices_[0]->point(), direction_);
}
Plane3d Prism::top_plane() const {
    return Plane3d(top_vertices_[0]->point(), direction_);
}
 inline
 Plane3d
 Circle3d::plane() const {
     return Plane3d(centerPoint(), normalVector());
 }
Plane3d          Triangle3d::getPlane        ( void ) const 
{ 
    return Plane3d(getCornerA(),getNormal()); 
}
Plane3d Facet::supporting_plane() const {
    Point3d p = vertices_[0]->point();
    return Plane3d(p, normal_);
}
Plane3d Circle::getPlane ( void ) const
{
	return Plane3d(m_center,Vector::unitY);
}