bool PointProjectionTools::segmentIntersect(const CCVector2& A, const CCVector2& B, const CCVector2& C, const CCVector2& D)
{
	CCVector2 AB = B-A;
	CCVector2 AC = C-A;
	CCVector2 AD = D-A;
	PointCoordinateType cross_AB_AC = AB.cross(AC);
	PointCoordinateType cross_AB_AD = AB.cross(AD);
	
	//both C and D are on the same side of AB?
	if (cross_AB_AC * cross_AB_AD > 0)
	{
		//no intersection
		return false;
	}

	CCVector2 CD = D-C;
	CCVector2 CB = B-C;
	PointCoordinateType cross_CD_CA = -CD.cross(AC);
	PointCoordinateType cross_CD_CB = CD.cross(CB);

	//both A and B are on the same side of CD?
	if (cross_CD_CA * cross_CD_CB > 0)
	{
		//no intersection
		return false;
	}

	PointCoordinateType cross_AB_CD = AB.cross(CD);
	if (fabs(cross_AB_CD) != 0) //AB and CD are not parallel
	{
		//where do they intersect?
		//PointCoordinateType v = cross_AB_AC/cross_AB_CD;
		//assert(v >= 0 && v <= 1);

		return true;
	}
	else //AB and CD are parallel (therefore they are colinear - see above tests)
	{
		PointCoordinateType dAB = AB.norm();
		
		PointCoordinateType dot_AB_AC = AB.dot(AC);
		if (dot_AB_AC >= 0 && dot_AB_AC < dAB * AC.norm())
		{
			//C is between A and B
			return true;
		}

		PointCoordinateType dot_AB_AD = AB.dot(AD);
		if (dot_AB_AD >= 0 && dot_AB_AD < dAB * AD.norm())
		{
			//D is between A and B
			return true;
		}

		//otherwise there's an intersection only if B and C are on both sides!
		return (dot_AB_AC * dot_AB_AD < 0);
	}
}
예제 #2
0
/** Only if the point lies 'in front of' the segment! Returns -1.0 otherwise.
**/
PointCoordinateType ComputeSquareDistToEdge(const CCVector2& P, const CCVector2& A, const CCVector2& B)
{
	CCVector2 AP = P-A;
	CCVector2 AB = B-A;
	PointCoordinateType dot = AB.dot(AP); // = cos(PAB) * ||AP|| * ||AB||
	if (dot < 0)
	{
		//return AP.norm2();
		return -1.0;
	}
	else
	{
		PointCoordinateType squareLengthAB = AB.norm2();
		if (dot > squareLengthAB)
		{
			//return (P-B).norm2();
			return -1.0;
		}
		else
		{
			CCVector2 HP = AP - AB * (dot / squareLengthAB);
			return HP.norm2();
		}
	}
}
/** \return The nearest point distance (or -1 if no point was found!)
**/
static PointCoordinateType FindNearestCandidate(	unsigned& minIndex,
													const VertexIterator& itA,
													const VertexIterator& itB,
													const std::vector<Vertex2D>& points,
													const std::vector<HullPointFlags>& pointFlags,
													PointCoordinateType minSquareEdgeLength,
													PointCoordinateType maxSquareEdgeLength,
													bool allowLongerChunks = false)
{
	//look for the nearest point in the input set
	PointCoordinateType minDist2 = -1;
	CCVector2 AB = **itB - **itA;
	PointCoordinateType squareLengthAB = AB.norm2();
	unsigned pointCount = static_cast<unsigned>(points.size());
	for (unsigned i = 0; i < pointCount; ++i)
	{
		const Vertex2D& P = points[i];
		if (pointFlags[P.index] != POINT_NOT_USED)
			continue;

		//skip the edge vertices!
		if (P.index == (*itA)->index || P.index == (*itB)->index)
			continue;

		//we only consider 'inner' points
		CCVector2 AP = P - **itA;
		if (AB.x * AP.y - AB.y * AP.x < 0)
		{
			continue;
		}

		PointCoordinateType dot = AB.dot(AP); // = cos(PAB) * ||AP|| * ||AB||
		if (dot >= 0 && dot <= squareLengthAB)
		{
			CCVector2 HP = AP - AB * (dot / squareLengthAB);
			PointCoordinateType dist2 = HP.norm2();
			if (minDist2 < 0 || dist2 < minDist2)
			{
				//the 'nearest' point must also be a valid candidate
				//(i.e. at least one of the created edges is smaller than the original one
				//and we don't create too small edges!)
				PointCoordinateType squareLengthAP = AP.norm2();
				PointCoordinateType squareLengthBP = (P - **itB).norm2();
				if (	squareLengthAP >= minSquareEdgeLength
					&&	squareLengthBP >= minSquareEdgeLength
					&&	(allowLongerChunks || (squareLengthAP < squareLengthAB || squareLengthBP < squareLengthAB))
					)
				{
					minDist2 = dist2;
					minIndex = i;
				}
			}
		}
	}
	return (minDist2 < 0 ? minDist2 : minDist2/squareLengthAB);
}
예제 #4
0
//! Returns true if the AB and CD segments intersect each other
bool Intersect(const CCVector2& A, const CCVector2& B, const CCVector2& C, const CCVector2& D)
{
	if (cross(A,B,C) * cross(A,B,D) >= 0) //both points are on the same side? No intersection
		return false;

	CCVector2 AB = B-A;
	CCVector2 AC = C-A;
	CCVector2 CD = D-C;

	PointCoordinateType q = CD.y * AB.x - CD.x * AB.y;
	if (fabs(q) > ZERO_TOLERANCE) //AB and CD are not parallel
	{
		//where do they interest?
		PointCoordinateType p = AC.x * AB.y - AC.y * AB.x;
		PointCoordinateType v = p/q;
		if (v <= 0 || v >= 1) //not CD!
			return false;

		//test further with AB
		p = CD.y * AC.x - CD.x * AC.y;
		v= p/q;
		return (v > 0 && v < 1); //not AB?
	}
	else //AB and CD are parallel
	{
		PointCoordinateType dAB = AB.norm();
		PointCoordinateType dAC = AC.norm();
		PointCoordinateType dot = AB.dot(AC) / (dAB * dAC);
		if (fabs(dot) < 0.999)
		{
			//not colinear
			return false;
		}
		else
		{
			//colinear --> do they actually intersect?
			return (dAC < dAB || (D-A).norm() < dAB);
		}
	}
}