Advertisement

Lines...the're evil aren't they?

Started by January 06, 2003 07:20 PM
2 comments, last by MattS423 22 years, 1 month ago
ok, i'm trying to clip a line to the screen, but itn't not wroking very well...take a look
    
int ClipLine(int &x1, int &y1, int &x2, int &y2)
{

#define CLIP_CODE_C	0x0000

#define CLIP_CODE_N	0x0008

#define CLIP_CODE_S	0x0004

#define CLIP_CODE_E	0x0002

#define CLIP_CODE_W	0x0001

#define CLIP_CODE_NE	0x000a

#define CLIP_CODE_SE	0x0006

#define CLIP_CODE_NW	0x0009

#define CLIP_CODE_SW	0x0005


	int ClippedX1; // init. varibles to clip line to

	int ClippedY1;
	int ClippedX2;
	int ClippedY2;

	//init. clip codes

	int Point1Code = 0;
	int Point2Code = 0;

	//figrue out these codes

	
	//point 1 y value

	if(y1 < ClipMinY)
		Point1Code |= CLIP_CODE_N;
	
	else if(y1 > ClipMaxY)
		Point1Code |= CLIP_CODE_S;

	//point 1 x value

	if(x1 < ClipMinX)
		Point1Code |= CLIP_CODE_W;
	
	else if(x1 > ClipMaxX)
		Point1Code |= CLIP_CODE_E;

	//point 2 y value

	if(y2 < ClipMinY)
		Point2Code |= CLIP_CODE_N;

	else if(y2 > ClipMaxY)
		Point2Code |= CLIP_CODE_S;

	//point 2 x value


	if(x2 < ClipMinX)
		Point2Code |= CLIP_CODE_W;

	else if(x2 > ClipMaxX)
		Point2Code |= CLIP_CODE_E;

	//trival rejection

	if((Point1Code & Point2Code))	//if both points are off screen

		return 2;					//in the same manner

									//(both north, south, east or west)


	if((Point1Code == 0 && Point2Code == 0))
		return 1; //they are both on screen


	//ok, now we know that one of the two points needs to be clipped.

	//do point one first, then point two, clipping them to the

	//predefined clipping thing

	
	switch(Point1Code)
	{
	case CLIP_CODE_C:
		//it's inside the clipper

		break;

	case CLIP_CODE_N:
		//it's above the clipper.  Bring it down.

		 ClippedY1 = ClipMinY; //known B/C of geometry

		 ClippedX1 = x1 + 0.5 + (ClipMinY-y1)*(x2-x1)/(y2-y1);
		break;

	case CLIP_CODE_S:
		ClippedY1 = ClipMaxY; //known because of geometry

		ClippedX1 = x1 + 0.5 + (ClipMaxY-y1)*(x2-x1)/(y2-y1);
		break;

	case CLIP_CODE_W:
		ClippedX1 = ClipMinX;
		ClippedY1 =  y1 + 0.5 + (ClipMinX-x1)*(y2-y1)/(x2-x1); 
		break;

	case CLIP_CODE_E:
		ClippedX1 = ClipMaxX;
		ClippedY1 =  y1 + 0.5 + (ClipMaxX-x1)*(y2-y1)/(x2-x1);
		break;

	//ok, if we're still in this switch-case thing by now,then

	//there is more than one line intersection, in which case we'll

	//need to calculate both intersections. (How fun!)

		//remember you're still in a switch statement


	case CLIP_CODE_NE:
		//calculate the north HLine intersection

		
		ClippedY1 = ClipMinY; //easy enough

		ClippedX1 = x1 + 0.5 + (ClipMinY-y1)*(x2-x1)/(y2-y1);

		//ok, now if that worked, we don't need to clip it again.

		//if it didn't, we should.


		if(ClippedX1 < ClipMinX || ClippedX1 > ClipMaxX)
		{
			//there is a east VLine intersection

			ClippedX1 = ClipMaxX;
			ClippedY1 =  y1 + 0.5 + (ClipMaxX-x1)*(y2-y1)/(x2-x1);
		}

		break; //end CLIP_CODE_NE


	case CLIP_CODE_SE:
		//South HLine intersection

		ClippedY1 = ClipMaxY; //known because of geometry

		ClippedX1 = x1 + 0.5 + (ClipMaxY-y1)*(x2-x1)/(y2-y1);

		//if it works, great. if not, nuts.


		if(ClippedX1 < ClipMinX || ClippedX1 > ClipMaxX)
		{
			//east VLine intersection

			ClippedX1 = ClipMaxX;
			ClippedY1 =  y1 + 0.5 + (ClipMaxX-x1)*(y2-y1)/(x2-x1);
		}

		break;

	case CLIP_CODE_NW:

		// North HLine intersection

		ClippedY1 = ClipMinY; //easy enough

		ClippedX1 = x1 + 0.5 + (ClipMinY-y1)*(x2-x1)/(y2-y1);
		
		if(ClippedX1 < ClipMinX || ClippedX1 > ClipMaxX)
		{
			//west VLine intersection

			ClippedX1 = ClipMinX;
			ClippedY1 =  y1 + 0.5 + (ClipMinX-x1)*(y2-y1)/(x2-x1); 
		}

		break;

	case CLIP_CODE_SW:
		//south HLine intersection

		ClippedY1 = ClipMaxY; //known because of geometry

		ClippedX1 = x1 + 0.5 + (ClipMaxY-y1)*(x2-x1)/(y2-y1);

		if(ClippedX1 < ClipMinX || ClippedX1 > ClipMaxX)
		{
			//west VLine intersection

			ClippedX1 = ClipMinX;
			ClippedY1 =  y1 + 0.5 + (ClipMinX-x1)*(y2-y1)/(x2-x1);

		}
		break;

	default: break;
	
	}//end point1


	//now roll right into point2

	//(ya!!)


	//determine the clip point for point2

	//(this will look alot like the thing above for point1)


	switch(Point2Code)
	{
	case CLIP_CODE_C:
		break;

	case CLIP_CODE_N:
		ClippedY2 = ClipMinY;
		ClippedX2 = x2 + (ClipMinY - y2)*(x1-x2)/(y1/y2);
		break;
		
	case CLIP_CODE_S:
		ClippedY2 = ClipMaxY;
		ClippedX2 = x2 + (ClipMinY - y2)*(x1-x2)/(y1/y2);
		break;

	case CLIP_CODE_W:
		ClippedX2 = ClipMinX;
		ClippedY2 = y2 + (ClipMinX - x2)*(y1-y2)/(x1-x2); 
		break;
		
	case CLIP_CODE_E:
		ClippedX2 = ClipMaxY;
		ClippedY2 =  y2 + (ClipMaxX - x2)*(y1-y2)/(x1-x2);
		break;

		//ok, now for the hard part..


	case CLIP_CODE_NE:
		//north HLine intersection

		ClippedY2 = ClipMinY;
		ClippedX2 = x2 + (ClipMinY - y2)*(x1-x2)/(y1/y2);
		
		//IF

		if(ClippedX2 < ClipMinX || ClippedX2 > ClipMaxX)
		{
			//east VLine intersection

			ClippedX2 = ClipMaxY;
			ClippedY2 =  y2 + (ClipMaxX - x2)*(y1-y2)/(x1-x2);
			
		}
		break;

	case CLIP_CODE_SE:
		//south HLine intersection

		ClippedY2 = ClipMaxY;
		ClippedX2 = x2 + (ClipMinY - y2)*(x1-x2)/(y1/y2);

		if(ClippedX2 < ClipMinX || ClippedX2 > ClipMaxX)
		{
			//east VLine intersection

			ClippedX2 = ClipMaxY;
			ClippedY2 =  y2 + (ClipMaxX - x2)*(y1-y2)/(x1-x2);

		}
		break;

	case CLIP_CODE_NW:
		//north HLine intersection

		ClippedY2 = ClipMinY;
		ClippedX2 = x2 + (ClipMinY - y2)*(x1-x2)/(y1/y2);

		if(ClippedX2 < ClipMinX || ClippedX2 > ClipMaxX)
		{
			//west VLine intersection

			ClippedX2 = ClipMinX;
			ClippedY2 = y2 + (ClipMinX - x2)*(y1-y2)/(x1-x2); 

		}
		break;

	case CLIP_CODE_SW:
		//south HLine

		ClippedY2 = ClipMaxY;
		ClippedX2 = x2 + (ClipMinY - y2)*(x1-x2)/(y1/y2);
		
		if(ClippedX2 < ClipMinX || ClippedX2 > ClipMaxX)
		{
			//west VLine

			ClippedX2 = ClipMinX;
			ClippedY2 = y2 + (ClipMinX - x2)*(y1-y2)/(x1-x2); 

		}
		
		break;



	default: break;
	}//end switch

	

	//well that was relitively painless...now do a bounds check


	if( (ClippedX1 < ClipMinX) || (ClippedX1 > ClipMaxX) ||
		(ClippedY1 < ClipMinY) || (ClippedY1 > ClipMaxY) ||
		(ClippedX2 < ClipMinX) || (ClippedX2 > ClipMaxX) ||
		(ClippedY2 < ClipMinY) || (ClippedY2 > ClipMaxY) )
	{
		//oops.  there are still points outside the clipping region

		//give up

		return 0;
	}

//restore varibles


	x1 = ClippedX1;
	y1 = ClippedY1;
	x2 = ClippedX2;
	y2 = ClippedY2;
	
	return 1;
}//end Clipline()


    
whats wrong? [edited by - MattS423 on January 6, 2003 8:21:27 PM]
Programmers of the world, UNTIE!
Seems a very convoluted way to do a very simple task. Many of the conditions could be eliminated by simply breaking it into a left/right and top/bottom clipping and insuring the order for the two parts. Just swap the points, toggle a flag and if the flag is set at the end do one more swap, i.e. an even number of swaps means you are in the same order as you started.
Keys to success: Ability, ambition and opportunity.
Advertisement
Thats a good idea...

I tried to find an article on GameDev for this, but i couldn''t find one. anybody konw of anything?

also, that monster up there should do SOMETHING, right?
it compiles, runs, and then causes somekind of error, and the program just exits....strange, isn''t it?

well, thanks for your help
Programmers of the world, UNTIE!
quote:
Original post by MattS423
also, that monster up there should do SOMETHING, right?
it compiles, runs, and then causes somekind of error, and the program just exits....strange, isn''t it?



The error should give you a clue about what is wrong.

I used my old friend google to do a search on "line clipping," and here is what my friend said:

#1 link:

http://www.cs.brown.edu/courses/cs123/lectures/Clipping.pdf

link with Java demonstration of the algorithm from the #1 link:

http://graphics.lcs.mit.edu/classes/6.837/F99/assignment2/CohenSutherland.html

Link with 3 different algorithms:

http://www.cis.ohio-state.edu/~hwshen/681/0118.pdf





Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net

This topic is closed to new replies.

Advertisement