Click here to Skip to main content
15,894,740 members
Articles / Programming Languages / C#

Mars Mission (1) : surface landing

Rate me:
Please Sign up or sign in to vote.
4.96/5 (45 votes)
20 Nov 2010CPOL32 min read 113.4K   869   71  
strategy/action game defending the solar system : collision detection while flying around the surface
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using Debugger;

namespace Mars_Mission
{
	public class classCave
	{
		public static int intStandardCaveCellDepth = classLandscape.intLandscapeCellWidth;
		public classCaveCell[] cCells;
		static double dblMaxAngleDeviationPerCell = Math.PI * .12;
		static public Random rnd;
		public classLandscapeCell LandscapeCell;
		static public bool bolActive;

		public classCaveCell cFurthestVisibleCellMovingUp;
		public classCaveCell cFurthestVisibleCellMovingDown;


		System.Windows.Forms.PictureBox picViewscreen;
		//Bitmap bmpCells;

		public classCave(ref Random RND, ref classLandscapeCell cLandscapeCell, int intAverageDepth)
		{
			rnd = RND;
			LandscapeCell = cLandscapeCell;
			picViewscreen = classLandscape.picViewscreen;
			int intDepth = (int)(rnd.NextDouble() * 100000) % (int)((double)intAverageDepth * .75) + (int)((double)intAverageDepth * .5);
			generateCave(intDepth);
		}

		/// <summary>
		/// returns an array of points to draw a polygon.  polygon appears on screen with ptPerspectiveGame of the game world located at ptPerspectiveOnScreen.
		/// dblZoom of the classLandscape is used to resize the polygon.
		/// </summary>
		/// <param name="cCellPersepective">cave cell where ptPerspectiveGame can be found</param>
		/// <param name="ptPerspectiveGame">point of view of the object at this location in the game world</param>
		/// <param name="ptPerspectiveOnScreen">location on screen where the perspective game world location is positioned</param>
		/// <returns></returns>
		public Point[] getPolygonPoints(ref classCaveCell cCellPersepective, classMath.classDoubleCartesian ptPerspectiveGame, Point ptPerspectiveOnScreen)
		{ return getPolygonPoints(ref cCellPersepective, ptPerspectiveGame, ptPerspectiveOnScreen, 100000); }
		public Point[] getPolygonPoints(ref classCaveCell cCellPersepective, classMath.classDoubleCartesian ptPerspectiveGame, Point ptPerspectiveOnScreen, int intMaxCellVisible)
		{
			cFurthestVisibleCellMovingUp = cCellPersepective;
			cFurthestVisibleCellMovingDown = cCellPersepective;

			bool bolContinue = true;
			classMath.classDoubleLine linViewLine = new classMath.classDoubleLine();
			classMath.classDoubleCartesian ptIntersection = new classMath.classDoubleCartesian();
			linViewLine.pt1 = ptPerspectiveGame;
			do // look up
			{
				classMath.classDoubleLine[] linTests = new classMath.classDoubleLine[0];
				if (cFurthestVisibleCellMovingUp.intMyIndex > 0)
				{
					cFurthestVisibleCellMovingUp = cFurthestVisibleCellMovingUp.cPreviousCell;
					linViewLine.pt2 = cFurthestVisibleCellMovingUp.ptCenter;

					Array.Resize<classMath.classDoubleLine>(ref linTests, linTests.Length + 2);
					linTests[linTests.Length - 2] = new classMath.classDoubleLine(cFurthestVisibleCellMovingUp.cLeftWall.ptMine, cFurthestVisibleCellMovingUp.cNextCell.cLeftWall.ptMine);
					linTests[linTests.Length - 1] = new classMath.classDoubleLine(cFurthestVisibleCellMovingUp.cRightWall.ptMine, cFurthestVisibleCellMovingUp.cNextCell.cRightWall.ptMine);

					for (int intTestLines = 0; intTestLines < linTests.Length; intTestLines++)
					{
						if (classMath.LinesIntersect(linTests[intTestLines], linViewLine, ref ptIntersection))
						{
							bolContinue = false;
							break;
						}
					}
				}
				else
					bolContinue = false;
			} while (bolContinue);

			bolContinue = true;
			cFurthestVisibleCellMovingDown = cCellPersepective;
			do // look down
			{
				classMath.classDoubleLine[] linTests = new classMath.classDoubleLine[0];
				if (cFurthestVisibleCellMovingDown.intMyIndex < cCells.Length - 2)
				{
					cFurthestVisibleCellMovingDown = cFurthestVisibleCellMovingDown.cNextCell;
					linViewLine.pt2 = cFurthestVisibleCellMovingDown.ptCenter;

					Array.Resize<classMath.classDoubleLine>(ref linTests, linTests.Length + 2);
					linTests[linTests.Length - 2] = new classMath.classDoubleLine(cFurthestVisibleCellMovingDown.cLeftWall.ptMine, cFurthestVisibleCellMovingDown.cLeftWall.ptNext);
					linTests[linTests.Length - 1] = new classMath.classDoubleLine(cFurthestVisibleCellMovingDown.cRightWall.ptMine, cFurthestVisibleCellMovingDown.cRightWall.ptNext);

					for (int intTestLines = 0; intTestLines < linTests.Length; intTestLines++)
					{
						if (classMath.LinesIntersect(linTests[intTestLines], linViewLine, ref ptIntersection))
						{
							bolContinue = false;
							break;
						}
					}
				}
				else
					bolContinue = false;
			} while (bolContinue);

			/// move along right wall 
			/// from cCellPerspective to cFurthestDown
			/// then cross from right to left of cFurthestdown
			/// move along left wall
			/// from cFurthest down to cFurthestUp
			/// then cross from left to right of cFurthestUp
			/// move along right wall
			/// from cFurthestUp to cCellPerspective
			/// 
			int intNumCaves = cFurthestVisibleCellMovingDown.intMyIndex - cFurthestVisibleCellMovingUp.intMyIndex;

			if (intNumCaves > intMaxCellVisible)
			{
				if (cFurthestVisibleCellMovingDown.intMyIndex - cCellPersepective.intMyIndex > intMaxCellVisible / 2
					&& cCellPersepective.intMyIndex - cFurthestVisibleCellMovingUp.intMyIndex > intMaxCellVisible / 2)
				{ // shorten cells up & down
					cFurthestVisibleCellMovingUp = cCellPersepective;
					for (int intCellCounter = 0; intCellCounter < intMaxCellVisible / 2; intCellCounter++)
						cFurthestVisibleCellMovingUp = cFurthestVisibleCellMovingUp.cPreviousCell;

					cFurthestVisibleCellMovingDown = cCellPersepective;
					for (int intCellCounter = 0; intCellCounter < intMaxCellVisible / 2; intCellCounter++)
						cFurthestVisibleCellMovingDown = cFurthestVisibleCellMovingDown.cNextCell;
				}
				else if (cFurthestVisibleCellMovingDown.intMyIndex - cCellPersepective.intMyIndex > intMaxCellVisible / 2)
				{ // shorten cells down
					int intMaxNumCellsDown = intMaxCellVisible - (cCellPersepective.intMyIndex - cFurthestVisibleCellMovingUp.intMyIndex);
					cFurthestVisibleCellMovingDown = cCellPersepective;
					for (int intCellCounter = 0; intCellCounter < intMaxNumCellsDown; intCellCounter++)
						cFurthestVisibleCellMovingDown = cFurthestVisibleCellMovingDown.cNextCell;
				}
				else
				{  // shorten cells up
					int intMaxCellsUp = intMaxCellVisible - (cFurthestVisibleCellMovingDown.intMyIndex - cCellPersepective.intMyIndex);
					cFurthestVisibleCellMovingUp = cCellPersepective;
					for (int intCellCounter = 0; intCellCounter < intMaxCellsUp; intCellCounter++)
						cFurthestVisibleCellMovingUp = cFurthestVisibleCellMovingUp.cPreviousCell;
				}
				intNumCaves = cFurthestVisibleCellMovingDown.intMyIndex - cFurthestVisibleCellMovingUp.intMyIndex;
			}

			classCaveCell cThisCell = cFurthestVisibleCellMovingUp;
			classMath.classDoubleCartesian[] ptOrderedGamePoints = new classMath.classDoubleCartesian[2 * (intNumCaves + 1)+3];
			int intPointCounter = 0;

			while (cThisCell != cFurthestVisibleCellMovingDown.cNextCell)
			{
				ptOrderedGamePoints[intPointCounter++] = cThisCell.cRightWall.ptMine;
				cThisCell = cThisCell.cNextCell;
			}

			ptOrderedGamePoints[intPointCounter++] = cThisCell.cRightWall.ptMine;
			ptOrderedGamePoints[intPointCounter++] = cThisCell.cLeftWall.ptMine;

			while (cThisCell != cFurthestVisibleCellMovingUp)
			{
				cThisCell = cThisCell.cPreviousCell;
				ptOrderedGamePoints[intPointCounter++] = cThisCell.cLeftWall.ptMine;
			}

			ptOrderedGamePoints[intPointCounter++] = cThisCell.cRightWall.ptMine;

			Point[] ptRetVal = new Point[ptOrderedGamePoints.Length];

			classMath.classRadialCoor cRadEquivalent = new classMath.classRadialCoor();
			for (intPointCounter = 0; intPointCounter < ptRetVal.Length; intPointCounter++)
			{
				cRadEquivalent.angle = classMath.arcTan(ptOrderedGamePoints[intPointCounter], ptPerspectiveGame);
				cRadEquivalent.radius = classMath.distanceBetweenTwoPoints(ptPerspectiveGame, ptOrderedGamePoints[intPointCounter]);
				cRadEquivalent.radius *= classLandscape.dblZoom;
				ptRetVal[intPointCounter].X = (int)(ptPerspectiveOnScreen.X + cRadEquivalent.radius * Math.Cos(cRadEquivalent.angle));
				ptRetVal[intPointCounter].Y = (int)(ptPerspectiveOnScreen.Y + cRadEquivalent.radius * Math.Sin(cRadEquivalent.angle));
			}

			return ptRetVal;
		}

		public static int intMoveCounter = 0;

		public classCollisionResult moveCaveScape(ref classCollisionDetectionObject cCDO)
		{
			intMoveCounter = (intMoveCounter + 1) % 20;

			if (cCDO.ptSurface.X == cCDO.ptEnd.X && cCDO.ptSurface.Y == cCDO.ptEnd.Y)
			{
				classCollisionResult cRetVal = new classCollisionResult();
				cRetVal.eCollision = enuCollisionResult.no_Collision;
				if (cCDO.eLoc == enuLocation.Cave)
				{
					cRetVal.cCavescaveCellWall = cCDO.cCaveCell.cLeftWall;
					cRetVal.eLoc = enuLocation.Cave;
				}
				return cRetVal;
			}
		
			classCaveCell cCellStart = cCDO.cCaveCell == null ? cCells[0] : cCDO.cCaveCell;
			classCaveCell cFindEndUp = cCellStart;
			classCaveCell cFindEndDown = cCellStart;
			classCaveCell cCellEnd = cCellStart;
			classMath.classRadialCoor cRadMotion = new classMath.classRadialCoor(classMath.arcTan(cCDO.ptEnd, cCDO.ptSurface), classMath.distanceBetweenTwoPoints(cCDO.ptEnd, cCDO.ptSurface));

			classCollisionResult cNearestCollision = new classCollisionResult();
			cNearestCollision.cLandscapeCell = LandscapeCell;
			cNearestCollision.eLoc = cCDO.ptEnd.Y > cCells[0].ptCenter.Y ? enuLocation.Cave : enuLocation.Surface;
			cNearestCollision.cCavescaveCellWall = cCellEnd.cLeftWall;

			bool bolContinue = true;
			int intMaxCellMove = (int)Math.Ceiling(cRadMotion.radius / classLandscape.LandscapeCellWidth) + 5;
			if (cCDO.ptEnd.Y < cCells[0].ptCenter.Y)
			{
				cCellEnd = cCells[0];
			}
			else
			{
				if (cCDO.cCaveCell == null)
					cCDO.cCaveCell = cCells[0];
				do
				{
					if ((cFindEndDown  == null 
							|| Math.Abs ( cFindEndDown.intMyIndex - cCDO.cCaveCell.intMyIndex) >= intMaxCellMove
							|| cFindEndDown.intMyIndex == cCells.Length -2)
						&& (cFindEndUp == null
							|| Math.Abs(cFindEndUp.intMyIndex - cCDO.cCaveCell.intMyIndex) >= intMaxCellMove))
					{/// if we have gone to the limits of our search -> determine direction of motion & set cEnd/cStart accordingly
						if (Math.Abs(cRadMotion.angle - cCDO.cCaveCell.angle) < Math.PI / 2)
						{ // moving "down" towards next cells
							cCellStart = cCDO.cCaveCell;
							for (int intCellCounter = 0; intCellCounter < intMaxCellMove && cCellStart.cPreviousCell != null; intCellCounter++)
								cCellStart = cCellStart.cPreviousCell;
							cCellEnd = cCDO.cCaveCell;
							for (int intCellCounter = 0; intCellCounter < intMaxCellMove && cCellEnd.cNextCell != null && cCellEnd.intMyIndex < cCells.Length -2; intCellCounter++)
								cCellEnd = cCellEnd.cNextCell;
						}
						else
						{ // moving "up" towards previous cells
							cCellStart = cCDO.cCaveCell;
							for (int intCellCounter = 0; intCellCounter < intMaxCellMove && cCellStart.cNextCell != null && cCellStart.intMyIndex < cCells.Length - 2; intCellCounter++)
								cCellStart = cCellStart.cNextCell;
							cCellEnd = cCDO.cCaveCell;
							for (int intCellCounter = 0; intCellCounter < intMaxCellMove && cCellEnd.cPreviousCell != null; intCellCounter++)
								cCellEnd = cCellEnd.cPreviousCell;
						}
						bolContinue = false;
					}
					else if (cFindEndDown != null 
						&& (cFindEndDown.pointIsInsideMe(cCDO.ptEnd)))
					{
						cCellEnd = cFindEndDown;
						bolContinue = false;
					}
					else if (cFindEndUp != null 
							&& (cFindEndUp.pointIsInsideMe(cCDO.ptEnd)))
					{
						cCellEnd = cFindEndUp;
						bolContinue = false;
					}
					else
					{
						if (cFindEndUp == null && (cFindEndDown == null || cFindEndDown.intMyIndex == cCells.Length-2))
						{
							// end-point is outside the cave
							/// must define the limits of test using the start cell as reference
							/// given the intended travelling distance f(start - end)
							/// calculate the maximum number of cells by dividing distance/intAverageCellDepth
							/// move away from start cell in either direction
							/// calculate the direction of motion given the angle b/w start-end relative to the angle of start cell
							/// given the direction of motion ("up" towards previous or "down" towards next)
							/// set cellStart & cellEnd equal to the appropriate limits counted away from original start-cell
							if (Math.Abs(cRadMotion.angle - cCDO.cCaveCell.angle) < Math.PI / 2)
							{ // moving "down" towards next cells
								cCellStart = cCDO.cCaveCell;
								for (int intCellCounter = 0; intCellCounter < intMaxCellMove && cCellStart.cPreviousCell != null; intCellCounter++)
									cCellStart = cCellStart.cPreviousCell;
								cCellEnd = cCDO.cCaveCell;
								for (int intCellCounter = 0; intCellCounter < intMaxCellMove && cCellEnd.cNextCell != null; intCellCounter++)
									cCellEnd = cCellEnd.cNextCell;
							}
							else
							{ // moving "up" towards previous cells
								cCellStart = cCDO.cCaveCell;
								for (int intCellCounter = 0; intCellCounter < intMaxCellMove && cCellStart.cNextCell != null && cCellStart.intMyIndex < cCells.Length -2; intCellCounter++)
									cCellStart = cCellStart.cNextCell;
								cCellEnd = cCDO.cCaveCell;
								for (int intCellCounter = 0; intCellCounter < intMaxCellMove && cCellEnd.cPreviousCell != null; intCellCounter++)
									cCellEnd = cCellEnd.cPreviousCell;
							}
							bolContinue = false;
						}
						else
						{
							if (cFindEndUp != null)
								cFindEndUp = cFindEndUp.cPreviousCell;
							if (cFindEndDown != null && cFindEndDown.intMyIndex < cCells.Length -2)
								cFindEndDown = cFindEndDown.cNextCell;
						}
					}
				} while (bolContinue);
			}

			bool bolMovingDownwards = (cCellEnd.intMyIndex > cCellStart.intMyIndex);
			if (Math.Abs(cCellEnd.intMyIndex - cCellStart.intMyIndex) < intMaxCellMove)
			{
				if (bolMovingDownwards)
				{
					if (cCellEnd.intMyIndex < cCells.Length - 2)
						cCellEnd = cCellEnd.cNextCell;
					if (cCellStart.intMyIndex >0)
						cCellStart = cCellStart.cPreviousCell;
				}
				else
				{
					if (cCellEnd.intMyIndex > 0)
						cCellEnd = cCellEnd.cPreviousCell;
					if (cCellStart.intMyIndex < cCells.Length - 2)
						cCellStart = cCellStart.cNextCell;
				}
			}

			while (cCellEnd.intMyIndex > cCells.Length - 2)
				cCellEnd = cCellEnd.cPreviousCell;
		
			/// rotate system around end point such that the new test-system has the start-end points on horizontal line with end point on the left
			classMath.classDoubleRectangle cRecMotion = new classMath.classDoubleRectangle();
			cRecMotion.X = cCDO.ptEnd.X;
			cRecMotion.Y = cCDO.ptEnd.Y - cCDO.radius;
			cRecMotion.Width = classMath.distanceBetweenTwoPoints(cCDO.ptEnd, cCDO.ptSurface);
			cRecMotion.Height = 2 * cCDO.radius;
			classMath.classDoubleCartesian dptRecMotion_TL = new classMath.classDoubleCartesian(cRecMotion.Left, cRecMotion.Top);
			classMath.classDoubleCartesian dptRecMotion_TR = new classMath.classDoubleCartesian(cRecMotion.Right, cRecMotion.Top);
			classMath.classDoubleCartesian dptRecMotion_BL = new classMath.classDoubleCartesian(cRecMotion.Left, cRecMotion.Bottom);
			classMath.classDoubleCartesian dptRecMotion_BR = new classMath.classDoubleCartesian(cRecMotion.Right, cRecMotion.Bottom);
			classMath.classDoubleCartesian dptRecMotion_Start = new classMath.classDoubleCartesian(cRecMotion.Right, cCDO.ptEnd.Y);

			classMath.classDoubleCartesian dptIntersection = new classMath.classDoubleCartesian();

			classCaveCell cThisCell = cCellStart;
			classCaveCell cQuitCell = bolMovingDownwards ? cCellEnd.cNextCell : cCellEnd.cPreviousCell;

			classMath.classDoubleCartesian dptThis_Left, dptThis_Right;
			double dblInfinity = Math.Pow(2, 60);
			cNearestCollision.dblDistance = cRadMotion.radius;

			Bitmap bmpDebug = null;
			classMath.classDoubleCartesian dptCommonPointOfRotation = cCDO.ptEnd.Copy();
			Point ptDebugEndRef = new Point();
			if (classLandscape.frmMain.DrawDebug)
			{
				/// debug images
				/// draw rectangle of motion & start/end circles
				bmpDebug = new Bitmap(test_Draw_Landscape___wo_bmp_II.formDebug.picDebug.Width, test_Draw_Landscape___wo_bmp_II.formDebug.picDebug.Height);
				ptDebugEndRef = new Point((int)(bmpDebug.Width * .25), (int)(bmpDebug.Height * .5));
				using (Graphics g = Graphics.FromImage(bmpDebug))
				{
					g.FillRectangle(classPensAndBrushes.brBlack, new Rectangle(0, 0, bmpDebug.Width, bmpDebug.Height));
					Point ptRecTL = classLandscape.getPointScreen(dptRecMotion_TL, cCDO.ptEnd, ptDebugEndRef);
					Point ptRecTR = classLandscape.getPointScreen(dptRecMotion_TR, cCDO.ptEnd, ptDebugEndRef);
					Point ptRecBR = classLandscape.getPointScreen(dptRecMotion_BR, cCDO.ptEnd, ptDebugEndRef);
					Point ptRecBL = classLandscape.getPointScreen(dptRecMotion_BL, cCDO.ptEnd, ptDebugEndRef);
					g.DrawRectangle(classPensAndBrushes.pBlue1, new Rectangle(ptRecTL.X, ptRecTL.Y, ptRecTR.X - ptRecTL.X, ptRecBR.Y - ptRecTR.Y));
					Point ptStartCenter = classLandscape.getPointScreen(dptRecMotion_Start, cCDO.ptEnd, ptDebugEndRef);
					g.DrawEllipse(classPensAndBrushes.pGreen1, new Rectangle(ptStartCenter.X - (int)(cCDO.radius * classLandscape.dblZoom), ptStartCenter.Y - (int)(cCDO.radius * classLandscape.dblZoom), (int)(2 * cCDO.radius * classLandscape.dblZoom), (int)(2 * cCDO.radius * classLandscape.dblZoom)));
					g.DrawEllipse(classPensAndBrushes.pPurple1, new Rectangle(ptDebugEndRef.X - (int)(cCDO.radius * classLandscape.dblZoom), ptDebugEndRef.Y - (int)(cCDO.radius * classLandscape.dblZoom), (int)(2 * cCDO.radius * classLandscape.dblZoom), (int)(2 * cCDO.radius * classLandscape.dblZoom)));

					/// draw cavescape
					classMath.classDoubleCartesian dptDebugLast_Left = getRotatedPoint_Left(ref cCDO, cThisCell, cRadMotion, !bolMovingDownwards);
					classMath.classDoubleCartesian dptDebugLast_Right = getRotatedPoint_Right(ref cCDO, cThisCell, cRadMotion, !bolMovingDownwards);

					Point ptDebugLast_Left = classLandscape.getPointScreen(dptDebugLast_Left, cCDO.ptEnd, ptDebugEndRef);
					Point ptDebugLast_Right = classLandscape.getPointScreen(dptDebugLast_Right, cCDO.ptEnd, ptDebugEndRef);

					classMath.classDoubleCartesian dptDebugThis_Right, dptDebugThis_Left;
					Point ptDebugThis_Left, ptDebugThis_Right;

					classCaveCell cDebugCell = cThisCell;
					do
					{
							dptDebugThis_Left = getRotatedPoint_Left(ref cCDO, cDebugCell, cRadMotion, bolMovingDownwards);
							dptDebugThis_Right = getRotatedPoint_Right(ref cCDO, cDebugCell, cRadMotion, bolMovingDownwards);

							ptDebugThis_Left = classLandscape.getPointScreen(dptDebugThis_Left, cCDO.ptEnd, ptDebugEndRef);
							ptDebugThis_Right = classLandscape.getPointScreen(dptDebugThis_Right, cCDO.ptEnd, ptDebugEndRef);
							g.DrawLine(classPensAndBrushes.pWhite1, ptDebugLast_Left, ptDebugThis_Left);
							g.DrawLine(classPensAndBrushes.pWhite1, ptDebugLast_Right, ptDebugThis_Right);

							if (classLandscape.frmMain.drawPoints)
							{
								int intRadius = 2;
								g.DrawEllipse(classPensAndBrushes.pWhite1, new Rectangle(ptDebugThis_Left.X - intRadius, ptDebugThis_Left.Y - intRadius, 2 * intRadius, 2 * intRadius));
								g.DrawEllipse(classPensAndBrushes.pWhite1, new Rectangle(ptDebugLast_Left.X - intRadius, ptDebugLast_Left.Y - intRadius, 2 * intRadius, 2 * intRadius));
								g.DrawEllipse(classPensAndBrushes.pWhite1, new Rectangle(ptDebugThis_Right.X - intRadius, ptDebugThis_Right.Y - intRadius, 2 * intRadius, 2 * intRadius));
								g.DrawEllipse(classPensAndBrushes.pWhite1, new Rectangle(ptDebugLast_Right.X - intRadius, ptDebugLast_Right.Y - intRadius, 2 * intRadius, 2 * intRadius));
							}

							ptDebugLast_Left = ptDebugThis_Left;
							ptDebugLast_Right = ptDebugThis_Right;
							dptDebugLast_Left = dptDebugThis_Left;
							dptDebugLast_Right = dptDebugThis_Right;
							if (cDebugCell.cBottomWall != null)
							{
								classMath.classDoubleCartesian dptBottomLeft = classMath.RotateAboutCommonPoint(cCDO.ptEnd, cDebugCell.cBottomWall.ptBottomLeft, -cRadMotion.angle + Math.PI);
								classMath.classDoubleCartesian dptBottomRight = classMath.RotateAboutCommonPoint(cCDO.ptEnd, cDebugCell.cBottomWall.ptBottomRight, -cRadMotion.angle + Math.PI);
								Point ptBottomLeft = classLandscape.getPointScreen(dptBottomLeft, cCDO.ptEnd, ptDebugEndRef);
								Point ptBottomRight = classLandscape.getPointScreen(dptBottomRight, cCDO.ptEnd, ptDebugEndRef);
								g.DrawLine(classPensAndBrushes.pWhite1, ptBottomLeft, ptBottomRight);
							}
						cDebugCell = bolMovingDownwards ? cDebugCell.cNextCell : cDebugCell.cPreviousCell;
					} while (cDebugCell != cQuitCell);
					//bmpDebug.Save("c:\\temp\\marsmission\\cavespace.bmp");
				}
			}

			classMath.classDoubleCartesian dptLast_Left = getRotatedPoint_Left(ref cCDO, cThisCell, cRadMotion, !bolMovingDownwards);
			classMath.classDoubleCartesian dptLast_Right = getRotatedPoint_Right(ref cCDO, cThisCell, cRadMotion, !bolMovingDownwards);
			//int intCollisionCounter = 0;
			do
			{
				dptThis_Left = getRotatedPoint_Left(ref cCDO, cThisCell, cRadMotion, bolMovingDownwards);
				dptThis_Right = getRotatedPoint_Right(ref cCDO, cThisCell, cRadMotion, bolMovingDownwards);

				classMath.classDoubleCartesian dptTop = dptThis_Left;
				classMath.classDoubleCartesian dptBottom = dptThis_Right;

				for (enuLeftRight eLeftRight = enuLeftRight.Left; eLeftRight < enuLeftRight._numLeftRight; eLeftRight++)
				{
					if (eLeftRight == enuLeftRight.Bottom && cThisCell.cBottomWall == null)
					{
						/// there is no bottom wall and we're trying to do a bottom wall						
						/// therefore -> ignore
					}
					else
					{
						classCollisionResult cThisCollision = new classCollisionResult();
						classCollisionResult cThisCircleCollision = new classCollisionResult();
						switch (eLeftRight)
						{
							case enuLeftRight.Left:
								cThisCircleCollision.cCavescaveCellWall
									= cThisCollision.cCavescaveCellWall
									= cThisCell.cLeftWall;

								if (dptThis_Left.Y > dptLast_Left.Y)
								{
									dptBottom = dptThis_Left;
									dptTop = dptLast_Left;
								}
								else
								{
									dptBottom = dptLast_Left;
									dptTop = dptThis_Left;
								}
								break;

							case enuLeftRight.Right:
								cThisCircleCollision.cCavescaveCellWall
									= cThisCollision.cCavescaveCellWall
									= cThisCell.cRightWall;
								if (dptThis_Right.Y > dptLast_Right.Y)
								{
									dptBottom = dptThis_Right;
									dptTop = dptLast_Right;
								}
								else
								{
									dptBottom = dptLast_Right;
									dptTop = dptThis_Right;
								}
								break;

							case enuLeftRight.Bottom:
								cThisCircleCollision.cCavescaveCellWall
									= cThisCollision.cCavescaveCellWall
									= cThisCell.cBottomWall;
								classMath.classDoubleCartesian dptBottomLeft = classMath.RotateAboutCommonPoint(cCDO.ptEnd, cThisCell.cBottomWall.ptBottomLeft, -cRadMotion.angle + Math.PI);
								classMath.classDoubleCartesian dptBottomRight = classMath.RotateAboutCommonPoint(cCDO.ptEnd, cThisCell.cBottomWall.ptBottomRight, -cRadMotion.angle + Math.PI);

								if (dptBottomLeft.Y > dptBottomRight.Y)
								{
									dptBottom = dptBottomLeft;
									dptTop = dptBottomRight;
								}
								else
								{
									dptBottom = dptBottomRight;
									dptTop = dptBottomLeft;
								}
								break;
						}

						double dblAngleTangent = classMath.arcTan(dptTop, dptBottom);
						double dblAngleNormal = dblAngleTangent - Math.PI / 2;

						if (classMath.LinesIntersect(dptTop, dptBottom,
													 dptRecMotion_TL, dptRecMotion_TR,
													 ref dptIntersection)
						 || classMath.LinesIntersect(dptTop, dptBottom,
													 dptRecMotion_TR, dptRecMotion_BR,
													 ref dptIntersection)
						 || classMath.LinesIntersect(dptTop, dptBottom,
													 dptRecMotion_BR, dptRecMotion_BL,
													 ref dptIntersection)
						 || classMath.LinesIntersect(dptTop, dptBottom,
													 dptRecMotion_BL, dptRecMotion_TL,
													 ref dptIntersection)
						 || (classMath.PointIsInsideRectangle(dptBottom, cRecMotion) && classMath.PointIsInsideRectangle(dptTop, cRecMotion)))
						{
							cThisCollision.eLoc = enuLocation.Cave;
							cThisCollision.dblDistance = dblInfinity;

							// dptIntersectionTangent is the point at which a line going through ptLast & ptThis extending towards infinity
							// meets the left side of a circle inside the rectangular path of motion 
							classMath.classDoubleCartesian dptIntersectionTangent = new classMath.classDoubleCartesian(); // angle of tangent is same as angle of line 
							classMath.classDoubleCartesian ptContact = null;// point on circle at furthest motion

							if (dptTop.Y == dptBottom.Y)
							{ // horizontal line -> collision with point furthest to right AND inside rectangular path of motion
								if (classMath.PointIsInsideRectangle(dptTop, cRecMotion) && classMath.PointIsInsideRectangle(dptBottom, cRecMotion))
								{
									// both points are inside rectangle 
									ptContact = new classMath.classDoubleCartesian(dptBottom.X > dptTop.X ? dptBottom.X : dptTop.X, dptRecMotion_Start.Y);
								}
								else if (classMath.PointIsInsideRectangle(dptTop, cRecMotion))
								{
									ptContact = dptTop;
								}
								else if (classMath.PointIsInsideRectangle(dptBottom, cRecMotion))
								{
									ptContact = dptBottom;
								}
								else
								{
									ptContact = null;
								}
							}
							else if (dptTop.X == dptBottom.X)
							{ // vertical line -> 
								//		if the line traverses dptRecMotion_Start.y
								//			->  collision with line at (dptBottom.x, dptRecMotion_Start.y)
								//		else 
								//			->  collision with point closes to center inside rectangle
								if (dptTop.Y < dptRecMotion_Start.Y
									&& dptBottom.Y > dptRecMotion_Start.Y)
								{ // traverses horizontal center line of rectangle
									ptContact = new classMath.classDoubleCartesian(dptBottom.X, dptRecMotion_Start.Y);
								}
								else
								{
									if (Math.Abs(dptBottom.Y - dptRecMotion_Start.Y) < Math.Abs(dptTop.Y - dptRecMotion_Start.Y))
									{
										ptContact = dptBottom;
									}
									else
									{
										ptContact = dptTop;
									}
								}
							}
							else
							{
								double dblDeltaY = cCDO.radius * Math.Sin(dblAngleNormal);
								dptIntersectionTangent.Y = dptRecMotion_Start.Y + dblDeltaY;
								// find point on line at y = dptIntersectionTangent
								classMath.classDoubleCartesian ptLeftInfinity = new classMath.classDoubleCartesian(-dblInfinity, dptIntersectionTangent.Y);
								classMath.classDoubleCartesian ptRightInfinity = new classMath.classDoubleCartesian(dblInfinity, dptIntersectionTangent.Y);
								classMath.LinesIntersect(ptLeftInfinity, ptRightInfinity, dptTop, dptBottom, ref dptIntersectionTangent);
								if (dptIntersection.X >= dptRecMotion_Start.X)
								{ // contact at start position
									ptContact = null;
									cThisCollision.dblDistance = 0;
								}
								else if (dptIntersectionTangent.Y >= (dptBottom.Y < dptTop.Y ? dptBottom.Y : dptTop.Y)
								   && dptIntersectionTangent.Y <= (dptBottom.Y > dptTop.Y ? dptBottom.Y : dptTop.Y)
								   && dptIntersectionTangent.X >= (dptBottom.X < dptTop.X ? dptBottom.X : dptTop.X)
								   && dptIntersectionTangent.X <= (dptBottom.X > dptTop.X ? dptBottom.X : dptTop.X)
								   && classMath.PointIsInsideRectangle(dptIntersectionTangent, cRecMotion))
								{
									double dblDeltaXWithdptIntersectionTangent = Math.Abs(cCDO.radius * Math.Cos(dblAngleNormal));
									cThisCollision.dblDistance = dptRecMotion_Start.X - dptIntersectionTangent.X - dblDeltaXWithdptIntersectionTangent;
									if (cThisCollision.dblDistance < 0)
										cThisCollision.dblDistance = 0;
									cThisCollision.dblAngleNormalToPointOfContact = cThisCollision.cCavescaveCellWall.dblNormal;
									goto TestNearestCollision;
								}
								else
								{
									if (classMath.PointIsInsideRectangle(dptTop, cRecMotion) && classMath.PointIsInsideRectangle(dptBottom, cRecMotion))
									{
										// both points are inside rectangle 
										if (classMath.distanceBetweenTwoPoints(dptBottom, dptRecMotion_Start) < classMath.distanceBetweenTwoPoints(dptTop, dptRecMotion_Start))
										{
											ptContact = dptBottom;
										}
										else
										{
											ptContact = dptTop;
										}
									}
									else if (classMath.PointIsInsideRectangle(dptTop, cRecMotion))
									{
										ptContact = dptTop;
									}
									else if (classMath.PointIsInsideRectangle(dptBottom, cRecMotion))
									{
										ptContact = dptBottom;
									}
									else
									{
										ptContact = null;
										cThisCollision.dblDistance = 0;
									}
								}
							}
							// given point ptContact -> place object the furthest to the left inside rectangle AND to the right of ptContact
							// calculate deltaY from dptRecMotion_Start.Y to ptContact.Y
							if (ptContact != null)
							{
								double dblDeltaY = ptContact.Y - dptRecMotion_Start.Y;
								double dblNormalizedDeltaY = dblDeltaY / cCDO.radius;
								cThisCollision.dblAngleNormalToPointOfContact = Math.Asin(dblNormalizedDeltaY);
								double dblDeltaX = Math.Abs(cCDO.radius * Math.Cos(cThisCollision.dblAngleNormalToPointOfContact));
								cThisCollision.dblDistance = dptRecMotion_Start.X - ptContact.X - dblDeltaX;
							}
						TestNearestCollision:

							int intMinDistance = 5;
							if (Math.Abs(cThisCollision.dblDistance) < intMinDistance)
							{
								cThisCollision.dblDistance = 0;
							}
							if (cThisCollision.dblDistance < cNearestCollision.dblDistance && cThisCollision.dblDistance >= 0)
							{
								cThisCollision.eCollision = enuCollisionResult.crash;
								cThisCollision.ptEnd = new classMath.classDoubleCartesian(cCDO.ptSurface.X + cThisCollision.dblDistance * Math.Cos(cRadMotion.angle), cCDO.ptSurface.Y + cThisCollision.dblDistance * Math.Sin(cRadMotion.angle));

								cNearestCollision = cThisCollision;
							}
						}

						classMath.classDoubleCartesian dptIntersectionWithCircle = new classMath.classDoubleCartesian();
						if (classMath.LineIntersectsCircle(cCDO.ptEnd, cCDO.radius, dptTop, dptBottom, ref dptIntersectionWithCircle))
						{
							//given point ptContact -> place object the furthest to the left inside rectangle AND to the right of ptContact
							//calculate deltaY from dptRecMotion_Start.Y to ptContact.Y
							cThisCircleCollision.eLoc = enuLocation.Cave;
							cThisCircleCollision.dblDistance = cRadMotion.radius;
							double dblDistanceIntended = classMath.distanceBetweenTwoPoints(cCDO.ptEnd, cCDO.ptSurface);
							double dblDistanceRejected = 0;
							/// line is tangent to circle at new end point
							/// normal line goes through center
							double dblDistanceBetweenCircleCenterAndIntersection = classMath.distanceBetweenTwoPoints(dptIntersectionWithCircle, cCDO.ptEnd);
							double dblAngleBetweenCircleCenterandIntersection = classMath.arcTan(cCDO.ptEnd, dptIntersectionWithCircle);

							dblDistanceRejected = Math.Abs(dblDistanceBetweenCircleCenterAndIntersection * Math.Cos(dblAngleBetweenCircleCenterandIntersection));
							if (dblDistanceRejected >= dblDistanceIntended)
								dblDistanceRejected = dblDistanceIntended;

							cThisCircleCollision.dblAngleNormalToPointOfContact = cThisCircleCollision.cCavescaveCellWall.dblNormal; //classMath.cleanAngle(dblAngleBetweenCircleCenterandIntersection + cRadMotion.angle);

							cThisCircleCollision.dblDistance = dblDistanceIntended - dblDistanceRejected;
							
							int intMin = 5;
							if (Math.Abs(cThisCircleCollision.dblDistance) < intMin)
							{
								cThisCircleCollision.dblDistance = 0;
							}
							if (cThisCircleCollision.dblDistance < cNearestCollision.dblDistance)
							{
								cNearestCollision = cThisCircleCollision;
								cThisCircleCollision.eCollision = enuCollisionResult.crash;
							}
						}
					}
				}
				dptLast_Left = dptThis_Left;
				dptLast_Right = dptThis_Right;
				cThisCell = bolMovingDownwards ? cThisCell.cNextCell : cThisCell.cPreviousCell;
			} while (cThisCell != cQuitCell);

			if (cNearestCollision.dblDistance < cRadMotion.radius)
			{
				cCDO.ptEnd.X = cCDO.ptSurface.X + cNearestCollision.dblDistance * Math.Cos(cRadMotion.angle);
				cCDO.ptEnd.Y = cCDO.ptSurface.Y + cNearestCollision.dblDistance * Math.Sin(cRadMotion.angle);
			}
			if (classLandscape.frmMain.DrawDebug)
			{
				classMath.classDoubleCartesian dptEnd = new classMath.classDoubleCartesian(dptRecMotion_Start.X - cNearestCollision.dblDistance, dptRecMotion_Start.Y);
				Point ptEndCenter = classLandscape.getPointScreen(dptEnd, dptCommonPointOfRotation, ptDebugEndRef);

				using (Graphics g = Graphics.FromImage(bmpDebug))
					g.DrawEllipse(classPensAndBrushes.pRed1, new Rectangle(ptEndCenter.X - (int)(cCDO.radius * classLandscape.dblZoom), ptEndCenter.Y - (int)(cCDO.radius * classLandscape.dblZoom), (int)(2 * cCDO.radius * classLandscape.dblZoom), (int)(2 * cCDO.radius * classLandscape.dblZoom)));

				test_Draw_Landscape___wo_bmp_II.formDebug.picDebug.Image = bmpDebug;
				test_Draw_Landscape___wo_bmp_II.formDebug.picDebug.Refresh();
			}

			if (cCDO.ptEnd.Y > cCells[0].ptCenter.Y)
			{
				cCDO.cCaveCell = cNearestCollision.cCavescaveCellWall.cMyCaveCell;
				cCDO.eLoc = enuLocation.Cave;
				cNearestCollision.ptEnd = cCDO.ptEnd;
				setCaveCell(ref cCDO);

			}
			else
			{
				cCDO.cCaveCell = null;
				cCDO.eLoc = enuLocation.Surface;
				cNearestCollision.ptEnd = cCDO.ptEnd;
			}

			if (cCDO.eLoc == enuLocation.Cave)
			{
				classCaveCell.classCaveCellWall.intCounter = 0;
				cCDO.cCaveCell.cLeftWall.Push(ref cCDO.ptSurface, cCDO.radius);
				classCaveCell.classCaveCellWall.intCounter = 0;
				cCDO.cCaveCell.cRightWall.Push(ref cCDO.ptSurface, cCDO.radius);
				if (cCDO.cCaveCell.cBottomWall != null)
				{
					cCDO.cCaveCell.cBottomWall.Push(ref cCDO.ptSurface, cCDO.radius);
				}
				setCaveCell(ref cCDO);
			}
			return cNearestCollision;
		}

		classMath.classDoubleCartesian getRotatedPoint_Left(ref classCollisionDetectionObject cCDO, classCaveCell cThisCell, classMath.classRadialCoor cRadMotion, bool bolMovingDownwards)
		{
			return bolMovingDownwards
								 ? classMath.RotateAboutCommonPoint(cCDO.ptEnd, cThisCell.cLeftWall.ptNext, -cRadMotion.angle +  Math.PI )
								 : classMath.RotateAboutCommonPoint(cCDO.ptEnd, cThisCell.cLeftWall.ptMine, -cRadMotion.angle + Math.PI);
		}

		classMath.classDoubleCartesian getRotatedPoint_Right(ref classCollisionDetectionObject cCDO, classCaveCell cThisCell, classMath.classRadialCoor cRadMotion, bool bolMovingDownwards)
		{
			return bolMovingDownwards
								 ? classMath.RotateAboutCommonPoint(cCDO.ptEnd, cThisCell.cRightWall.ptNext, -cRadMotion.angle + Math.PI)
								 : classMath.RotateAboutCommonPoint(cCDO.ptEnd, cThisCell.cRightWall.ptMine, -cRadMotion.angle + Math.PI);
		}
		
		/// <summary>
		/// tests if the ptSurface of this object is find in this object's current caveCell.
		/// if the ptSurface is not inside the specified cell then the caveCell is reset to match ptSurface
		/// </summary>
		/// <param name="cCDO">reference to a collision detection object class</param>
		public void setCaveCell(ref classCollisionDetectionObject cCDO)
		{
			int intMaxSearch = 15; 
			if (!cCDO.cCaveCell.pointIsInsideMe(cCDO.ptSurface))
			{
				classCaveCell cFindUp = cCDO.cCaveCell.cPreviousCell;
				classCaveCell cFindDown = cCDO.cCaveCell.cNextCell;

				for (int intFindCell = 0; intFindCell < intMaxSearch; intFindCell++)
				{
					if (cFindUp != null)
						if (cFindUp.pointIsInsideMe(cCDO.ptSurface))
						{
							cCDO.cCaveCell = cFindUp;
							return;
						}
						else
							cFindUp = cFindUp.cPreviousCell;
					if (cFindDown != null)
						if (cFindDown.pointIsInsideMe(cCDO.ptSurface))
						{
							cCDO.cCaveCell = cFindDown;
							return;
						}
						else
							cFindDown = cFindDown.cNextCell;
				}
			}

		}

		enum enuLeftRight {Left =0, Right, Bottom, _numLeftRight};
		/// <summary>
		/// assumes point of view is set to the center of the screen and uses the same dblZoom as classLandscape
		/// </summary>
		/// <param name="cCDO"></param>
		/// <returns></returns>
		public Bitmap getViewScreen(ref classCollisionDetectionObject cCDO) { return getViewScreen(ref cCDO, false); }
		public Bitmap getViewScreen(ref classCollisionDetectionObject cCDO, bool bolWithLandscape)
		{
			if (picViewscreen.Width < 10 || picViewscreen.Height < 10)
				return null;
			Bitmap bmpRetVal = bolWithLandscape 
				? LandscapeCell.cLandscape.getViewScreen(cCDO.ptSurface, true) 
				: new Bitmap(picViewscreen.Width, picViewscreen.Height);

			using (Graphics g = Graphics.FromImage(bmpRetVal))
			{
				if (!bolWithLandscape)
					g.FillRectangle(LandscapeCell.cLandscape.brMyDirt, new Rectangle(0, 0, bmpRetVal.Width, bmpRetVal.Height));

				Point[] ptPolygon = getPolygonPoints(ref cCDO.cCaveCell, cCDO.ptSurface, classLandscape.ptCenterScreen);
				g.FillPolygon(LandscapeCell.cLandscape.brMyCave, ptPolygon);

				if (classLandscape.frmMain.drawPoints)
				{
					int intRadius = 2;
					for (int intPointCounter = 0; intPointCounter < ptPolygon.Length; intPointCounter++)
					{
						g.DrawEllipse(classPensAndBrushes.pWhite1, new Rectangle(ptPolygon[intPointCounter].X -intRadius, ptPolygon[intPointCounter].Y - intRadius, intRadius*2, intRadius*2));
					}
				}

			}

			return bmpRetVal;
		}

	

		classCaveCell getNearestCenter(classMath.classDoubleCartesian pt)
		{
			return new classCaveCell();
		}

		Point convertGameWorldPointToBmpCellLocationPoints(classMath.classDoubleCartesian ptGameWorld)
		{
			double dblRatio = 100;
			return new Point((int)(ptGameWorld.X / dblRatio), (int)(ptGameWorld.Y / dblRatio));
		}

		void generateCave(int intDepth)
		{
			classMath.classDoubleCartesian.bolClassLock = false;

			cCells = new classCaveCell[intDepth];
			// generate all cells

			for (int intCellCounter = 0; intCellCounter < cCells.Length; intCellCounter++)
			{
				cCells[intCellCounter] = new classCaveCell();
				cCells[intCellCounter].intMyIndex = intCellCounter;
				cCells[intCellCounter].cLeftWall = new classCaveCell.classCaveCellWall();
				cCells[intCellCounter].cLeftWall.cMyCaveCell = cCells[intCellCounter];
				cCells[intCellCounter].cRightWall = new classCaveCell.classCaveCellWall();
				cCells[intCellCounter].cRightWall.cMyCaveCell = cCells[intCellCounter];
				cCells[intCellCounter].cCave = this;
			}

			// connect all cells
			for (int intCellCounter = 0; intCellCounter < cCells.Length; intCellCounter++)
			{
				if (intCellCounter > 0)
					cCells[intCellCounter].cPreviousCell = cCells[intCellCounter - 1];
				if (intCellCounter < cCells.Length - 1)
					cCells[intCellCounter].cNextCell = cCells[intCellCounter + 1];
			}

			Point ptTL = convertGameWorldPointToBmpCellLocationPoints(LandscapeCell.ptLeft);
			Point ptBR = convertGameWorldPointToBmpCellLocationPoints(LandscapeCell.ptRight);

			cCells[0].cCave = this;
			cCells[0].cLeftWall.ptMine= LandscapeCell.ptLeft;
			cCells[0].cRightWall.ptMine = LandscapeCell.ptRight;
			cCells[0].ptCenter = classMath.findCenterOfLine(cCells[0].cLeftWall.ptMine, cCells[0].cRightWall.ptMine);
			cCells[0].eBottomType = enuLandscapeCellType.empty;
			cCells[0].eLeftType
				= cCells[0].eRightType
				= enuLandscapeCellType.caveMouth;
			cCells[0].cCave = this;
			cCells[0].dblDepth = 0;
			cCells[0].dblWidth = classLandscape.intLandscapeCellWidth;
			cCells[0].angle = Math.PI / 2;
			cCells[0].intMyIndex = 0;

			classMath.classDoubleCartesian ptIntersection = new classMath.classDoubleCartesian();
			int intNumInRow = 0;
			int intSizeChangeSign = 1;
			int intMinDepthCellCounter = 20;
			double dblMinDepth = cCells[0].ptCenter.Y + intMinDepthCellCounter * classLandscape.LandscapeCellWidth;
			double dblMinWidth = 1.25 * classLandscape.LandscapeCellWidth;

			for (int intCellCounter = 1; intCellCounter < cCells.Length; intCellCounter++)
			{
				classCaveCell cThisCell = cCells[intCellCounter];
				intNumInRow--;
				if (intCellCounter > cCells.Length - 10)
				{
					intSizeChangeSign = -1;
					int intSizeChangeNeeded = (int)cThisCell.cPreviousCell.dblWidth - classLandscape.intLandscapeCellWidth;
					int intNumCellsLeft = cCells.Length - intCellCounter;
					int intMinChange = intSizeChangeNeeded / (intNumCellsLeft + 2);

					cThisCell.dblWidth = cThisCell.cPreviousCell.dblWidth
										- intMinChange
										- (int)(rnd.NextDouble() * intMinChange);
					if (cThisCell.intMyIndex < cCells.Length -1)
					{
						if (cThisCell.dblWidth < dblMinWidth)
							cThisCell.dblWidth = dblMinWidth;
					}
					else
						cThisCell.dblWidth = dblMinWidth / 2;					
				}
				else
				{
					if (intNumInRow <= 0)
					{
						if (cThisCell.cPreviousCell.dblWidth == dblMinWidth)
							intSizeChangeSign = 1;
						else
						{
							intSizeChangeSign *= -1;
						}
						intNumInRow = (int)(rnd.NextDouble() * 1000) % 20 + 5;
					}

					cThisCell.dblWidth = (rnd.NextDouble() * .75) * intSizeChangeSign * classLandscape.LandscapeCellWidth + cThisCell.cPreviousCell.dblWidth; // (.5 prev-width) < new width < (1.5 prev-width)
					if (cThisCell.dblWidth < dblMinWidth)
					{
						cThisCell.dblWidth = dblMinWidth;
					} 
				}

				do
				{
					cThisCell.dblDepth = intStandardCaveCellDepth;//(int)((double)intStandardCaveCellDepth * (rnd.NextDouble() * 2.0 - 1.0) + 2.0 * (double)intStandardCaveCellDepth);
				
					if ((cThisCell.intMyIndex > intMinDepthCellCounter
						&& cThisCell.cPreviousCell.cLeftWall.ptMine.Y < dblMinDepth
						&& cThisCell.cPreviousCell.angle > 1.5 * Math.PI)
						|| (cThisCell.intMyIndex < intMinDepthCellCounter
							&& cThisCell.cPreviousCell.angle >1.5 * Math.PI))
					{
						cThisCell.angle = classMath.cleanAngle(cThisCell.cPreviousCell.angle + rnd.NextDouble() * classCave.dblMaxAngleDeviationPerCell);
						if (cThisCell.dblWidth > dblMinWidth)
						{
							cThisCell.dblWidth *= .9;
							if (cThisCell.dblWidth < dblMinWidth)
								cThisCell.dblWidth = dblMinWidth;
						}
					}
					else if ((cThisCell.intMyIndex > intMinDepthCellCounter
						&& cThisCell.cPreviousCell.cRightWall.ptMine.Y < dblMinDepth
						&& cThisCell.cPreviousCell.angle >  Math.PI)
						|| (cThisCell.intMyIndex < intMinDepthCellCounter
							&& cThisCell.cPreviousCell.angle > Math.PI))
					{
						cThisCell.angle = classMath.cleanAngle(cThisCell.cPreviousCell.angle - rnd.NextDouble() * classCave.dblMaxAngleDeviationPerCell);
						if (cThisCell.dblWidth > dblMinWidth)
						{
							cThisCell.dblWidth *= .9;
							if (cThisCell.dblWidth < dblMinWidth)
								cThisCell.dblWidth = dblMinWidth;
						}
					}
					else
						cThisCell.angle = classMath.cleanAngle(cThisCell.cPreviousCell.angle + rnd.NextDouble() * classCave.dblMaxAngleDeviationPerCell * 2.0 - classCave.dblMaxAngleDeviationPerCell);
					
					cThisCell.ptCenter = new classMath.classDoubleCartesian(cThisCell.cPreviousCell.ptCenter.X + cThisCell.dblDepth * Math.Cos(cThisCell.cPreviousCell.angle),
																			cThisCell.cPreviousCell.ptCenter.Y + cThisCell.dblDepth * Math.Sin(cThisCell.cPreviousCell.angle));
					
					cThisCell.cLeftWall.ptMine = new classMath.classDoubleCartesian(cThisCell.ptCenter.X + cThisCell.dblWidth / 2.0 * Math.Cos(cThisCell.angle + Math.PI / 2.0),
																		            cThisCell.ptCenter.Y + cThisCell.dblWidth / 2.0 * Math.Sin(cThisCell.angle + Math.PI / 2.0));

					
					cThisCell.cRightWall.ptMine = new classMath.classDoubleCartesian(cThisCell.ptCenter.X + cThisCell.dblWidth / 2.0 * Math.Cos(cThisCell.angle - Math.PI / 2.0),
																					 cThisCell.ptCenter.Y + cThisCell.dblWidth / 2.0 * Math.Sin(cThisCell.angle - Math.PI / 2.0));

				} while 
					(
					classMath.LinesIntersect(cThisCell.cLeftWall.ptMine, cThisCell.cRightWall.ptMine, cThisCell.cPreviousCell.cLeftWall.ptMine, cThisCell.cPreviousCell.cRightWall.ptMine, ref ptIntersection)					
					);
				/*
				 //stretch limits of bmpCellLoc
				Point ptBmpCellLoc_Left = convertGameWorldPointToBmpCellLocationPoints(cThisCell.ptLeft);
				if (ptBmpCellLoc_Left.X < ptTL.X)
					ptTL.X = ptBmpCellLoc_Left.X;
				if (ptBmpCellLoc_Left.X > ptBR.X)
					ptBR.X = ptBmpCellLoc_Left.X;
				if (ptBmpCellLoc_Left.Y < ptTL.Y)
					ptTL.Y = ptBmpCellLoc_Left.Y;
				if (ptBmpCellLoc_Left.Y > ptBR.Y)
					ptBR.Y = ptBmpCellLoc_Left.Y;

				Point ptBmpCellLoc_Right = convertGameWorldPointToBmpCellLocationPoints(cThisCell.ptRight);
				if (ptBmpCellLoc_Right.X < ptTL.X)
					ptTL.X = ptBmpCellLoc_Right.X;
				if (ptBmpCellLoc_Right.X > ptBR.X)
					ptBR.X = ptBmpCellLoc_Right.X;
				if (ptBmpCellLoc_Right.Y < ptTL.Y)
					ptTL.Y = ptBmpCellLoc_Right.Y;
				if (ptBmpCellLoc_Right.Y > ptBR.Y)
					ptBR.Y = ptBmpCellLoc_Right.Y;
				//*/

				cThisCell.eLeftType
					= cThisCell.eRightType
					= cThisCell.eBottomType
					= enuLandscapeCellType.empty;
			}

			// create cell walls
			for (int intCellCounter = 0; intCellCounter < cCells.Length; intCellCounter++)
			{
				classCaveCell cThisCaveCell = cCells[intCellCounter];
				
				if (intCellCounter < cCells.Length -1)
				{
					cThisCaveCell.cRightWall.cMyCaveCell = cThisCaveCell;
					cThisCaveCell.cRightWall.ptNext = cThisCaveCell.cNextCell.cRightWall.ptMine;
					cThisCaveCell.cRightWall.dblNormal =classMath.cleanAngle( classMath.arcTan(cThisCaveCell.cRightWall.ptNext, cThisCaveCell.cRightWall.ptMine) + Math.PI / 2);

					cThisCaveCell.cLeftWall.cMyCaveCell = cThisCaveCell;
					cThisCaveCell.cLeftWall.ptNext = cThisCaveCell.cNextCell.cLeftWall.ptMine;
					cThisCaveCell.cLeftWall.dblNormal = classMath.cleanAngle(classMath.arcTan(cThisCaveCell.cLeftWall.ptNext, cThisCaveCell.cLeftWall.ptMine) - Math.PI / 2);
				}
				if (intCellCounter == cCells.Length - 2)
				{
					cThisCaveCell.cBottomWall = new classCaveCell.classCaveCellWall();
					cThisCaveCell.cBottomWall.cMyCaveCell = cThisCaveCell;
					cThisCaveCell.cBottomWall.ptBottomLeft = cThisCaveCell.cLeftWall.ptNext;
					cThisCaveCell.cBottomWall.ptBottomRight = cThisCaveCell.cRightWall.ptNext;
					cThisCaveCell.cBottomWall.dblNormal = classMath.cleanAngle(classMath.arcTan(cThisCaveCell.cBottomWall.ptBottomRight , cThisCaveCell.cBottomWall.ptBottomLeft) - Math.PI / 2);
				}
			}

			
			// set each wall's push-toward wall
			for (int intCellCounter = 1; intCellCounter < cCells.Length; intCellCounter++)
			{
				classCaveCell cThisCell = cCells[intCellCounter];
				if (intCellCounter < cCells.Length - 1)
				{
					{					// test left walls push towards each other
						double dblAngleAwayFromThisTowardsPrevious = cThisCell.cPreviousCell.cLeftWall.dblNormal + Math.PI / 2;
						double dblAngleAwayFromThisTowardsNext = cThisCell.cLeftWall.dblNormal - Math.PI / 2;
						classMath.classDoubleCartesian dptPrev_Standard = new classMath.classDoubleCartesian(cThisCell.cLeftWall.ptMine.X + classLandscape.LandscapeCellWidth * Math.Cos(dblAngleAwayFromThisTowardsPrevious),
																											 cThisCell.cLeftWall.ptMine.Y + classLandscape.LandscapeCellWidth * Math.Sin(dblAngleAwayFromThisTowardsPrevious));
						classMath.classDoubleCartesian dptPrev_Alt = new classMath.classDoubleCartesian(dptPrev_Standard.X + classLandscape.LandscapeCellWidth * Math.Cos(cThisCell.cPreviousCell.cLeftWall.dblNormal),
																										dptPrev_Standard.Y + classLandscape.LandscapeCellWidth * Math.Sin(cThisCell.cPreviousCell.cLeftWall.dblNormal));
						
						classMath.classDoubleCartesian dptNext_Standard = new classMath.classDoubleCartesian(cThisCell.cLeftWall.ptMine.X + classLandscape.LandscapeCellWidth * Math.Cos(dblAngleAwayFromThisTowardsNext),
																											 cThisCell.cLeftWall.ptMine.Y + classLandscape.LandscapeCellWidth * Math.Sin(dblAngleAwayFromThisTowardsNext));
						classMath.classDoubleCartesian dptNext_Alt = new classMath.classDoubleCartesian(dptNext_Standard.X + classLandscape.LandscapeCellWidth * Math.Cos(cThisCell.cLeftWall.dblNormal),
																										dptNext_Standard.Y + classLandscape.LandscapeCellWidth * Math.Sin(cThisCell.cLeftWall.dblNormal));

						if (classMath.LinesIntersect(dptPrev_Standard, dptPrev_Alt, dptNext_Standard, dptNext_Alt, ref ptIntersection))
						{
							/// walls push towards each other
							cThisCell.cLeftWall.cCellWallIPushTowards = cThisCell.cPreviousCell.cLeftWall;
							if (cThisCell.cPreviousCell.cLeftWall.cCellWallIPushTowards != null)
							{
								System.Windows.Forms.MessageBox.Show("Problem : generateCave -> setting left wall push -> previous wall was already set");
							}
							else
								cThisCell.cPreviousCell.cLeftWall.cCellWallIPushTowards = cThisCell.cLeftWall;
						}
					}

					{					// test Right walls push towards each other
						double dblAngleAwayFromThisTowardsPrevious = cThisCell.cPreviousCell.cRightWall.dblNormal - Math.PI / 2;
						double dblAngleAwayFromThisTowardsNext = cThisCell.cRightWall.dblNormal + Math.PI / 2;
						classMath.classDoubleCartesian dptPrev_Standard = new classMath.classDoubleCartesian(cThisCell.cRightWall.ptMine.X + classLandscape.LandscapeCellWidth * Math.Cos(dblAngleAwayFromThisTowardsPrevious),
																											 cThisCell.cRightWall.ptMine.Y + classLandscape.LandscapeCellWidth * Math.Sin(dblAngleAwayFromThisTowardsPrevious));
						classMath.classDoubleCartesian dptPrev_Alt = new classMath.classDoubleCartesian(dptPrev_Standard.X + classLandscape.LandscapeCellWidth * Math.Cos(cThisCell.cPreviousCell.cRightWall.dblNormal),
																										dptPrev_Standard.Y + classLandscape.LandscapeCellWidth * Math.Sin(cThisCell.cPreviousCell.cRightWall.dblNormal));

						classMath.classDoubleCartesian dptNext_Standard = new classMath.classDoubleCartesian(cThisCell.cRightWall.ptMine.X + classLandscape.LandscapeCellWidth * Math.Cos(dblAngleAwayFromThisTowardsNext),
																											 cThisCell.cRightWall.ptMine.Y + classLandscape.LandscapeCellWidth * Math.Sin(dblAngleAwayFromThisTowardsNext));
						classMath.classDoubleCartesian dptNext_Alt = new classMath.classDoubleCartesian(dptNext_Standard.X + classLandscape.LandscapeCellWidth * Math.Cos(cThisCell.cNextCell.cRightWall.dblNormal),
																										dptNext_Standard.Y + classLandscape.LandscapeCellWidth * Math.Sin(cThisCell.cNextCell.cRightWall.dblNormal));

						if (classMath.LinesIntersect(dptPrev_Standard, dptPrev_Alt, dptNext_Standard, dptNext_Alt, ref ptIntersection))
						{
							/// walls push towards each other
							cThisCell.cRightWall.cCellWallIPushTowards = cThisCell.cPreviousCell.cRightWall;
							if (cThisCell.cPreviousCell.cRightWall.cCellWallIPushTowards != null)
							{
								System.Windows.Forms.MessageBox.Show("Problem : generateCave -> setting Right wall push -> previous wall was already set");
							}
							else
								cThisCell.cPreviousCell.cRightWall.cCellWallIPushTowards = cThisCell.cRightWall;
						}
					}
				}
				else
				{ // bottom cell
					
				}
			}

			/* /// draw bmpCellLoc
			Size szBmpCells = new Size(ptBR.X - ptTL.X, ptBR.Y - ptTL.Y);
			bmpCells = new Bitmap(szBmpCells.Width, szBmpCells.Height);
			using (Graphics g = Graphics.FromImage(bmpCells))
			{
				g.FillRectangle(classPensAndBrushes.brWhite, new Rectangle(0, 0, bmpCells.Width, bmpCells.Height));
				long lngColorincrement = classMath.convertBaseNtoInt(new int[] { 0, 256, 256, 256 }, 256) / cCells.Length;
				
				for (int intCellCounter = 0; intCellCounter <  cCells.Length - 1; intCellCounter++)
				//	for (int intCellCounter = 0; intCellCounter < 73; intCellCounter++)
				{
					int[] intColorCode = classMath.convertIntegerToBaseN(lngColorincrement * intCellCounter, 256, 4);
					using (SolidBrush brCell = new SolidBrush(Color.FromArgb(255, intColorCode[1], intColorCode[2], intColorCode[3])))
					{
						Point[] ptPolygon = new Point[4];
						ptPolygon[0] = convertGameWorldPointToBmpCellLocationPoints(cCells[intCellCounter].ptLeft);
						ptPolygon[1] = convertGameWorldPointToBmpCellLocationPoints(cCells[intCellCounter].ptRight);
						ptPolygon[2] = convertGameWorldPointToBmpCellLocationPoints(cCells[intCellCounter + 1].ptRight);
						ptPolygon[3] = convertGameWorldPointToBmpCellLocationPoints(cCells[intCellCounter + 1].ptLeft);

						for (int intPointcounter = 0; intPointcounter < ptPolygon.Length; intPointcounter++)
						{
							ptPolygon[intPointcounter].X -= ptTL.X;
							ptPolygon[intPointcounter].Y -= ptTL.Y;
						}

						g.FillPolygon(brCell, ptPolygon);
					}
				}
			}
			bmpCells.Save("c:\\temp\\Caves\\Caves_(" + LandscapeCell.intMyIndex.ToString() + ").bmp");
			//*/
			classMath.classDoubleCartesian.bolClassLock = true;
		}
	}

	public class classCaveCell
	{
		public double angle;
		public double dblWidth;
		public double dblDepth;
		public enuLandscapeCellType eLeftType;
		public enuLandscapeCellType eRightType;
		public enuLandscapeCellType eBottomType;
		public int intMyIndex;
		public classCave cCave;

		public classMath.classDoubleCartesian ptCenter;

		public classCaveCellWall cLeftWall;
		public classCaveCellWall cRightWall;
		public classCaveCellWall cBottomWall;

		public classCaveCell cNextCell;
		public classCaveCell cPreviousCell;
		public bool bolVisible;
		classMath.classDoubleCartesian[] dptPoly;

		public classCaveCell()
		{

		}

		public bool pointIsInsideMe(classMath.classDoubleCartesian ptLoc)
		{
			if (intMyIndex < cCave.cCells.Length - 1)
			{
				if (dptPoly == null)
				{
					dptPoly = new classMath.classDoubleCartesian[4];
					dptPoly[0] = cLeftWall.ptMine.Copy();
					dptPoly[1] = cLeftWall.ptNext.Copy();
					dptPoly[2] = cRightWall.ptNext.Copy();
					dptPoly[3] = cRightWall.ptMine.Copy();
				}

				for (int intPtCounter = 0; intPtCounter < dptPoly.Length; intPtCounter++)
				{
					double dblDifference = dptPoly[intPtCounter].X - ptLoc.X;
					if (Math.Abs(dblDifference) > cCave.LandscapeCell.cLandscape.dblRealWidth / 2)
					{
						if (dblDifference > 0)
							dptPoly[intPtCounter].X -= cCave.LandscapeCell.cLandscape.dblRealWidth;
						else
							dptPoly[intPtCounter].X += cCave.LandscapeCell.cLandscape.dblRealWidth;
					}
				}

				return classMath.PointInPolygon(ptLoc, dptPoly);
			}
			else
				return false;
		}

		public class classCaveCellWall
		{
			public classCaveCellWall()
			{
				_ptMine.bolLock
					= ptNext.bolLock
					= false;
			}

			public classCaveCell cMyCaveCell;
			public classMath.classDoubleCartesian _ptMine = new classMath.classDoubleCartesian();
			public classMath.classDoubleCartesian ptMine
			{
				get { return _ptMine; }
				set
				{
					_ptMine = value;
				}
			}

			public classMath.classDoubleCartesian _ptNext = new classMath.classDoubleCartesian();
			public classMath.classDoubleCartesian ptNext
			{
				get { return _ptNext; }
				set
				{
					_ptNext = value;
				}
			}
			classMath.classDoubleCartesian _ptBottomLeft;
			public classMath.classDoubleCartesian ptBottomLeft
			{
				get { return _ptBottomLeft; }
				set
				{
					_ptBottomLeft = value;
				}
			}

			classMath.classDoubleCartesian _ptBottomRight;
			public classMath.classDoubleCartesian ptBottomRight
			{
				get { return _ptBottomRight; }
				set
				{
					_ptBottomRight = value;
				}
			}
			public classCaveCellWall cCellWallIPushTowards;

			public static double dblStandardPush = classLandscape.LandscapeCellWidth / 1000.0;
			public static int intCounter;
			classMath.classDoubleCartesian dptIntersection;
			public void Push(ref classMath.classDoubleCartesian ptLoc, double dblRadiusObject) { Push(ref ptLoc, dblRadiusObject, false); }
			public void Push(ref classMath.classDoubleCartesian ptLoc, double dblRadiusObject, bool bolForceWedge)
			{

				//double dblDistanceToLeft = classMath.distanceBetweenTwoPoints(ptLoc, ptMine);
				//double dblDistanceToRight = classMath.distanceBetweenTwoPoints(ptLoc, ptNext);
				//if ((ptLoc.X + dblRadiusObject <= (ptMine.X < ptNext.X ? ptMine.X : ptNext.X)
				//        || ptLoc.X - dblRadiusObject >= (ptMine.X > ptNext.X ? ptMine.X : ptNext.X)
				//        || ptLoc.Y + dblRadiusObject <= (ptMine.Y < ptNext.Y ? ptMine.Y : ptNext.Y))
				//    && dblDistanceToLeft > dblRadiusObject
				//    && dblDistanceToRight > dblRadiusObject)
				//{
				//    return;
				//}

				intCounter++;
				if (intCounter > 3)
				{
					WedgeObject(ref ptLoc, dblRadiusObject);
					return;
				}


				// create a second pt in Normal direction 

				//// find point of intersection b/w this line normal to landscape and landscape
				dptIntersection = dptIntersection = new classMath.classDoubleCartesian();
				if (this == cMyCaveCell.cBottomWall)
					classMath.LineIntersectsCircle(ptLoc, dblRadiusObject, ptBottomLeft, ptBottomRight, ref dptIntersection);
				else
					classMath.LineIntersectsCircle(ptLoc, dblRadiusObject, ptMine, ptNext, ref dptIntersection);

				// calculate distance between the dptIntersection and ptLoc
				double dblDistance = Math.Floor(classMath.distanceBetweenTwoPoints(ptLoc, dptIntersection));

				/// calculate height of line at that location X
				//double dblYatX = dblM * ptTemp.X + dblB;
				dblStandardPush = 0.05 * classLandscape.LandscapeCellWidth;
				if (dblDistance <= dblRadiusObject)
				{
					if (bolForceWedge)
					{
						WedgeObject(ref ptLoc, dblRadiusObject);
					}
					else
					{
						classMath.classDoubleCartesian ptNew = new classMath.classDoubleCartesian();
						ptNew.X = dptIntersection.X + (dblRadiusObject + dblStandardPush) * Math.Cos(dblNormal);
						ptNew.Y = dptIntersection.Y + (dblRadiusObject + dblStandardPush) * Math.Sin(dblNormal);

						if (ptNew.Y > ptLoc.Y)
							classLandscape.frmMain.Refresh();

						ptLoc = ptNew;
						if (cCellWallIPushTowards != null)
						{
							cCellWallIPushTowards.Push(ref ptLoc, dblRadiusObject, true);
						}
					}
				}
			}

			void WedgeObject(ref classMath.classDoubleCartesian ptLoc, double dblRadiusObject)
			{
				/// code copied from landscape fails here

				//dblRadiusObject *= 1.05;
				//classMath.classDoubleCartesian ptCommon = ptMine;
				//double dblAngleNeaghbour = classMath.cleanAngle(cellLeft.dblNormal - Math.PI / 2);
				//double dblMyAngle = classMath.cleanAngle(dblNormal + Math.PI / 2);

				//if (dblNormal > 1.5 * Math.PI)
				//{
				//    ptCommon = ptNext;
				//    dblAngleNeaghbour = classMath.cleanAngle(cellRight.dblNormal + Math.PI / 2);
				//    dblMyAngle = classMath.cleanAngle(dblNormal - Math.PI / 2);
				//}

				//double dblAngleCenterLine = (dblMyAngle + dblAngleNeaghbour) / 2;
				//double dblTangentToCircle = Math.Abs(dblMyAngle - dblAngleCenterLine);

				//double dblNormalToCircle = dblTangentToCircle + Math.PI / 2;
				//double dblASideofWedgeTriangle = dblRadiusObject * Math.Abs(Math.Sin(dblNormalToCircle) / Math.Tan(dblTangentToCircle));

				//double dblASideOfCircleTriangle = dblRadiusObject * Math.Abs(Math.Cos(dblNormalToCircle));

				//double dblTotalDistance = dblASideOfCircleTriangle + dblASideofWedgeTriangle;
				//ptLoc.X = ptCommon.X + dblTotalDistance * Math.Cos(dblAngleCenterLine);
				//ptLoc.Y = ptCommon.Y + dblTotalDistance * Math.Sin(dblAngleCenterLine);

			}
			public double dblNormal;
		}
	}

	//public class classCaveCoordinate
	//{
	//    public double Shift;
	//    public double Depth;
	//}
}
//public classMath.classDoubleCartesian ConvertPoint_CaveToCartesian(classCaveCoordinate ptCaveLoc)
//{
//    classMath.classDoubleCartesian ptRetVal = new classMath.classDoubleCartesian();
//    if (ptCaveLoc == null)
//        return null;
//    int intCellIndex = (int)Math.Floor(ptCaveLoc.Depth / classLandscape.LandscapeCellWidth);
//    if (intCellIndex >= 0 && intCellIndex < cCells.Length)
//    {
//        classCaveCell cThisCell = cCells[intCellIndex];
//        double dblDepthFromCenter = ptCaveLoc.Depth - intCellIndex * classLandscape.LandscapeCellWidth;
//        classMath.classDoubleCartesian ptReference = new classMath.classDoubleCartesian(cThisCell.ptCenter.X + dblDepthFromCenter * Math.Cos(cThisCell.angle),
//                                                                                        cThisCell.ptCenter.Y + dblDepthFromCenter * Math.Sin(cThisCell.angle));
//        int intSign = ptCaveLoc.Shift > 0 ? -1: 1;

//        ptRetVal.X = ptReference.X + Math.Abs(ptCaveLoc.Shift) * Math.Cos(cThisCell.angle + intSign * Math.PI / 2);
//        ptRetVal.Y = ptReference.Y + Math.Abs(ptCaveLoc.Shift) * Math.Sin(cThisCell.angle + intSign * Math.PI / 2);
//        classLandscape.frmMain.Text += "to Cartesian -> (" + ptRetVal.X.ToString("f2") + ", " + ptRetVal.Y.ToString("f2") + ")";
//        return ptRetVal;
//    }
//    else
//        System.Windows.Forms.MessageBox.Show("Error : ConvertPoint_CaveToCartesian -> cave cell does not exist");
//    return null;
//}

//public classCaveCoordinate ConvertPoint_CartesianToCave(classMath.classDoubleCartesian ptCartesianLoc, int intApproximateCellIndex)
//{
//    int intSearchVariance = 2;

//    classCaveCell cThisCell = cCells[intApproximateCellIndex];

//    for (int intShiftUpCounter = 0; intShiftUpCounter < intSearchVariance && cThisCell.cPreviousCell != null; intShiftUpCounter++)
//        cThisCell = cThisCell.cPreviousCell;

//    int intSearchCounter = 0;
//    classMath.classDoubleCartesian ptAlternate = new classMath.classDoubleCartesian();
//    classMath.classDoubleCartesian ptIntersection = new classMath.classDoubleCartesian();
//    classMath.classDoubleRectangle recTestZone = new classMath.classDoubleRectangle();
//    while (intSearchCounter < 2 * intSearchVariance)
//    {
//        classMath.classDoubleCartesian[] ptPolygon = { cThisCell.cLeftWall.ptMine, cThisCell.cLeftWall.ptNext, cThisCell.cRightWall.ptNext, cThisCell.cRightWall.ptMine, cThisCell.cLeftWall.ptMine };
//        if (classMath.PointInPolygon(ptCartesianLoc, ptPolygon))
//        {
//            ptAlternate.X = ptCartesianLoc.X + classLandscape.LandscapeCellWidth * Math.Cos(cThisCell.angle+Math.PI/2);
//            ptAlternate.Y = ptCartesianLoc.Y + classLandscape.LandscapeCellWidth * Math.Sin(cThisCell.angle+Math.PI/2);
//            classMath.LinesIntersect(ptCartesianLoc, ptAlternate, cThisCell.ptCenter, cThisCell.cNextCell.ptCenter, ref ptIntersection);
//            double dblAngleBetweenIntersectionAndPoint = classMath.arcTan(ptCartesianLoc, ptIntersection);
//            double dblDeltaTheta = classMath.cleanAngle(dblAngleBetweenIntersectionAndPoint - cThisCell.angle);
//            double dblAbsoluteX = classMath.distanceBetweenTwoPoints(ptIntersection, ptCartesianLoc);

//            classCaveCoordinate ptRetVal = new classCaveCoordinate();
//            ptRetVal.Shift = dblAbsoluteX * ((dblDeltaTheta > Math.PI) ? 1 : -1);
//            ptRetVal.Depth = (cThisCell.intMyIndex) * classLandscape.LandscapeCellWidth + classMath.distanceBetweenTwoPoints(cThisCell.ptCenter, ptIntersection);
//            classLandscape.frmMain.Text = "Cartesian (" + ptCartesianLoc.X.ToString("f2") + ", " + ptCartesianLoc.Y.ToString("f2") + ") to cave[" + cThisCell.intMyIndex.ToString() + "] (" + ptRetVal.Shift.ToString("f2") + ", " + ptRetVal.Depth.ToString("f2") + ") :::";
//            return ptRetVal;
//        }
//        intSearchCounter++;
//        cThisCell = cThisCell.cNextCell;
//    }
//    return null;
//}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO unemployable
Canada Canada
Christ Kennedy grew up in the suburbs of Montreal and is a bilingual Quebecois with a bachelor’s degree in computer engineering from McGill University. He is unemployable and currently living in Moncton, N.B. writing his next novel.

Comments and Discussions