Esempio n. 1
0
//=============================================================================
//		NGeometryUtilities::ClipLineToRectangle : Clip a line to a rectangle.
//-----------------------------------------------------------------------------
//		Note : Clips using Cohen-Sutherland.
//-----------------------------------------------------------------------------
template<class T> NGeometryComparison NGeometryUtilities::ClipLineToRectangle(	const              NRectangleT<T> &theRect,
																				const std::vector< NPointT<T> >   &theInput,
																					  std::vector< NPointT<T> >   &theOutput)
{	T						dx, dy, minX, maxX, minY, maxY;
	NBitfield				code0, code1, codeOut;
	NPointT<T>				p0, p1, pointOut;
	NGeometryComparison		theResult;



	// Get the state we need
	p0 = theInput[0];
	p1 = theInput[1];

	code0 = GetClipCode(theRect, p0);
	code1 = GetClipCode(theRect, p1);



	// Both points are outside
	if ((code0 & code1) != 0)
		{
		theOutput.clear();
		return(kNGeometryOutside);
		}



	// Both points are inside
	else if ((code0 | code1) == 0)
		{
		theOutput = theInput;
		return(kNGeometryInside);
		}



	// Intersection
	//
	// We pick an exterior point, then clip the segment to an edge.
	if (code0 != 0)
		{
		codeOut  = code0;
		pointOut = p0;
		}
	else
		{
		codeOut  = code1;
		pointOut = p1;
		}

	dx = p1.x - p0.x;
	dy = p1.y - p0.y;
		
	minX = theRect.GetMinX();
	maxX = theRect.GetMaxX();
		
	minY = theRect.GetMinY();
	maxY = theRect.GetMaxY();



	// Split line at top of rectangle
	if (codeOut & kNGeometryClipTop)
		{
		pointOut.x = p0.x + (dx * ((maxY - p0.y) / dy));
		pointOut.y = maxY;
		}
			
	// Split line at bottom of rectangle
	else if (codeOut & kNGeometryClipBottom)
		{
		pointOut.x = p0.x + (dx * ((minY - p0.y) / dy));
		pointOut.y = minY;
		}
		
	// Split line at right edge of rectangle
	else if (codeOut & kNGeometryClipRight)
		{
		pointOut.x = maxX;
		pointOut.y = p0.y + (dy * ((maxX - p0.x) / dx));
		}
			
	// Split line at left edge of rectangle
	else if (codeOut & kNGeometryClipLeft)
		{
		pointOut.x = minX;
		pointOut.y = p0.y + (dy * ((minX - p0.x) / dx));
		}
		
	else
		NN_LOG("Invalid codeOut: %d", codeOut);



	// Clip the new segment
	if (codeOut == code0)
		theResult = ClipLineToRectangle(theRect, vector(pointOut, p1), theOutput);
	else
		theResult = ClipLineToRectangle(theRect, vector(p0, pointOut), theOutput);



	// Update the result
	//
	// Since we know we had an intersection with one of the rectangle edges,
	// a result of inside is actually an intersection.
	//
		// A result of outside indicates the line intersected an edge but didn't
	// encroach on the rectangle itself so that result remains.
	if (theResult == kNGeometryInside)
		theResult = kNGeometryIntersects;

	return(theResult);
}
Esempio n. 2
0
static int ClipLine(const AbsRectangle &clipping,
			core::position2d<s32> &p0,
			core::position2d<s32> &p1,
			const core::position2d<s32>& p0_in,
			const core::position2d<s32>& p1_in)
{
	u32 code0;
	u32 code1;
	u32 code;

	p0 = p0_in;
	p1 = p1_in;

	code0 = GetClipCode( clipping, p0 );
	code1 = GetClipCode( clipping, p1 );

	// trivial accepted
	while ( code0 | code1 )
	{
		s32 x=0;
		s32 y=0;

		// trivial reject
		if ( code0 & code1 )
			return 0;

		if ( code0 )
		{
			// clip first point
			code = code0;
		}
		else
		{
			// clip last point
			code = code1;
		}

		if ( (code & CLIPCODE_BOTTOM) == CLIPCODE_BOTTOM )
		{
			// clip bottom viewport
			y = clipping.y1;
			x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y );
		}
		else
		if ( (code & CLIPCODE_TOP) == CLIPCODE_TOP )
		{
			// clip to viewport
			y = clipping.y0;
			x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y );
		}
		else
		if ( (code & CLIPCODE_RIGHT) == CLIPCODE_RIGHT )
		{
			// clip right viewport
			x = clipping.x1;
			y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X );
		}
		else
		if ( (code & CLIPCODE_LEFT) == CLIPCODE_LEFT )
		{
			// clip left viewport
			x = clipping.x0;
			y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X );
		}

		if ( code == code0 )
		{
			// modify first point
			p0.X = x;
			p0.Y = y;
			code0 = GetClipCode( clipping, p0 );
		}
		else
		{
			// modify second point
			p1.X = x;
			p1.Y = y;
			code1 = GetClipCode( clipping, p1 );
		}
	}

	return 1;
}