Beispiel #1
0
int main()
{
	scanf("%d", &N);

	GenerateConvexPolygon(N);

	return 0;
}
int ConvexPolygonClipping(const MeshPolygon* clippedPolygon,
								  const MeshPolygon* clippingWindow,
								  Queue* queue)
{
	if(NULL == clippedPolygon || NULL == clippingWindow || NULL == queue)
	{
		return WRONG_PARAM;
	}
	int allPointCountForClipping = 0;
	const Point* pointListForClipingWindow  = GetPolygonPointList(clippingWindow);
	const int pointCountForClippingWindow  = GetPolygonPointCount(clippingWindow);
	allPointCountForClipping += pointCountForClippingWindow;
	int clipingWindowPointInClippedWindowCount[3] = {0};
	for (int i = 0; i < pointCountForClippingWindow; ++i)
	{
		int checkResult = PointInPolygon(clippedPolygon, pointListForClipingWindow[i].x, pointListForClipingWindow[i].z);
		++clipingWindowPointInClippedWindowCount[checkResult + 1];
	}

	//裁剪多边形的顶点都位于被裁剪多边形的内部或者边上
	//目前无法裁剪这种情况
	if (0 == clipingWindowPointInClippedWindowCount[0])
	{
		return CLIPPING_WINDOW_ALL_IN_CLIPPED_POLYGON;
	}


	const Point* pointListForClippedPolygon = GetPolygonPointList(clippedPolygon);
	const int pointCountForClippedPolygon = GetPolygonPointCount(clippedPolygon);
	int clippedPolygonointInClippedWindowCount[3] = {0};
	for (int i = 0; i < pointCountForClippedPolygon; ++i)
	{
		int checkResult = PointInPolygon(clippingWindow, pointListForClippedPolygon[i].x, pointListForClippedPolygon[i].z);
		++clippedPolygonointInClippedWindowCount[checkResult + 1];
	}

	allPointCountForClipping += pointCountForClippedPolygon;
	//被裁剪的多边形的顶点全部为与裁剪多边形内或边上
	//不需要参见
	if (0 == clippedPolygonointInClippedWindowCount[0])
	{
		return ALL_POINT_IN_CLIPPING_WINDOW;
	}


	//两多边形不相交 不需要裁剪
	if (0 == clipingWindowPointInClippedWindowCount[2] && 0 == clippedPolygonointInClippedWindowCount[2])
	{
		return NOT_NEED_CLIPPING;
	}
	ClippingInterPoint* pointChainForClippingWindow = CreateClippingWindowData(clippedPolygon, clippingWindow);
	ClippingInterPoint* pointChainForClippedPolygon = CreateClippedPolygonData(clippedPolygon, clippingWindow);

	//查找交点并将交点插入正确的位置
	const Vector* const pNormalOfClippedPolygon = GetPolygonNormal(clippedPolygon);
	Rect checkRect;
	for (int indexOfClippingWindow = 0; indexOfClippingWindow < pointCountForClippingWindow; ++indexOfClippingWindow)
	{
		int nextIndexOfClippingWindow = indexOfClippingWindow + 1 == pointCountForClippingWindow ? 0 : indexOfClippingWindow + 1;

		for (int indexOfclippedPolygon = 0; indexOfclippedPolygon < pointCountForClippedPolygon; ++indexOfclippedPolygon)
		{
			int nextIndexOfClippedPolygon = indexOfclippedPolygon + 1 == pointCountForClippedPolygon ? 0 : indexOfclippedPolygon + 1;

			ClippingInterPoint* const pBeginPointOfClippinWindow = &pointChainForClippingWindow[indexOfClippingWindow];
			ClippingInterPoint* const pEndPointOfClippinWindow = &pointChainForClippingWindow[nextIndexOfClippingWindow];

			ClippingInterPoint* const pBeginPointOfClippedPolygon = &pointChainForClippedPolygon[indexOfclippedPolygon];
			ClippingInterPoint* const pEndPointOfClippedPolygon = &pointChainForClippedPolygon[nextIndexOfClippedPolygon];
			Vector toBeginPoint = {pBeginPointOfClippinWindow->point.x - pBeginPointOfClippedPolygon->point.x,
									0.0f,
									pBeginPointOfClippinWindow->point.z - pBeginPointOfClippedPolygon->point.z};
			Vector toEndPoint = {pEndPointOfClippinWindow->point.x - pBeginPointOfClippedPolygon->point.x,
								0.0f,
								pEndPointOfClippinWindow->point.z - pBeginPointOfClippedPolygon->point.z};

			float cosofToBeginPoint = VectorDotProduct(&toBeginPoint, &pNormalOfClippedPolygon[indexOfclippedPolygon]);					
			float cosofToEndPoint = VectorDotProduct(&toEndPoint, &pNormalOfClippedPolygon[indexOfclippedPolygon]);	
			bool beginPointIsSpecial = (FloatEqualZero(cosofToBeginPoint) && cosofToEndPoint > 0.0f);
			bool endPointIsSpecial = (FloatEqualZero(cosofToEndPoint) &&  cosofToBeginPoint> 0.0f);
			if (beginPointIsSpecial || endPointIsSpecial)
			{
				//特殊点,即交点在被裁减的多边形的边上,且同在内侧
				ClippingInterPoint* pTempPoint = beginPointIsSpecial ? pBeginPointOfClippinWindow : pEndPointOfClippinWindow;
				pTempPoint->pointType = INTER_POINT_TYPE_CLIPPING_WINDOW_POINT_AN_INSERCTION_POINT;
				ClippingInterPoint* pCurrentPositon = &pointChainForClippedPolygon[indexOfclippedPolygon];
				ClippingInterPoint* pNextPosition = pCurrentPositon->next2ClippedPolygon;
				ClippingInterPoint* pEndPosition = &pointChainForClippedPolygon[nextIndexOfClippedPolygon];
				pTempPoint->tValueForClippedPolygon = GetTValue(&pBeginPointOfClippedPolygon->point, &pEndPointOfClippedPolygon->point, &pTempPoint->point);

				while (true)
				{
					if( pTempPoint->tValueForClippedPolygon < pCurrentPositon->tValueForClippedPolygon)
					{
						ClippingInterPoint* pLastPosition = pCurrentPositon->prev2ClippedPolygon;
						pLastPosition->next2ClippedPolygon = pTempPoint;
						pCurrentPositon->prev2ClippedPolygon = pTempPoint;
						pTempPoint->prev2ClippedPolygon = pLastPosition;
						pTempPoint->next2ClippedPolygon = pCurrentPositon;
						break;
					}
					else if (pEndPosition == pNextPosition)
					{
						pCurrentPositon->next2ClippedPolygon = pTempPoint;
						pNextPosition->prev2ClippedPolygon = pTempPoint;
						pTempPoint->prev2ClippedPolygon = pCurrentPositon;
						pTempPoint->next2ClippedPolygon = pNextPosition;
						break;
					}
					pCurrentPositon = pNextPosition;
					pNextPosition = pCurrentPositon->next2ClippedPolygon;
				}
				continue;
			}

			if (FloatEqualZero(cosofToBeginPoint) && cosofToEndPoint < 0.0f)
			{
				//特殊点,即交点在被裁减的多边形的边上,且同在外侧
				//直接抛弃,不处理
				continue;
			}
			if (FloatEqualZero(cosofToEndPoint) && cosofToBeginPoint < 0.0f)
			{
				//特殊点,即交点在被裁减的多边形的边上,且同在外侧
				//直接抛弃,不处理
				continue;
			}

			//如果两点在边的同一侧,即没有交点,直接跳过
			if (cosofToBeginPoint > 0.0f && cosofToEndPoint > 0.0f)
			{
				continue;
			}
			if (cosofToBeginPoint < 0.0f && cosofToEndPoint < 0.0f)
			{
				continue;
			}	

			//如果有交点,则求交点并将交点插入正确的位置
			//两相交线段求交点
			//从而可以求出p的坐标 具体算法可以参考图形学算法
			float tValue =cosofToBeginPoint;
			tValue /= (cosofToBeginPoint - cosofToEndPoint);
			float insertionX = pBeginPointOfClippinWindow->point.x + tValue * (pEndPointOfClippinWindow->point.x - pBeginPointOfClippinWindow->point.x);
			float insertionZ = pBeginPointOfClippinWindow->point.z + tValue * (pEndPointOfClippinWindow->point.z - pBeginPointOfClippinWindow->point.z);
			
			//检查点是否在线段的延长线上
			Point point = {insertionX, insertionZ};
			Point a = pBeginPointOfClippedPolygon->point;
			Point b = pEndPointOfClippedPolygon->point;
			MakeRectByPoint(&checkRect, &a, &b);
			if(true != InRect(&checkRect, &point))
			{
				continue;
			}
			
			a = pBeginPointOfClippinWindow->point;
			b = pEndPointOfClippinWindow->point;
			MakeRectByPoint(&checkRect, &a, &b);
			if(true != InRect(&checkRect, &point))
			{
				continue;
			}
			
			ClippingInterPoint* pTempPoint = (ClippingInterPoint*)malloc(sizeof(ClippingInterPoint));
			++allPointCountForClipping;
			pTempPoint->point = point;
			pTempPoint->tValueForClippingWindow = tValue;
			pTempPoint->tValueForClippedPolygon = GetTValue(&pBeginPointOfClippedPolygon->point, &pEndPointOfClippedPolygon->point, &point);

			//通过遍历链表查找正确的位置插入生成点
			ClippingInterPoint* pCurrentPositon = &pointChainForClippingWindow[indexOfClippingWindow];
			ClippingInterPoint* pNextPosition = pCurrentPositon->next2ClippingdWindow;
			ClippingInterPoint* pEndPosition = &pointChainForClippingWindow[nextIndexOfClippingWindow];
			bool pointIsAdd = false;
			while(true)
			{
				if (IsSamePoint(&pTempPoint->point, &pCurrentPositon->point))
				{
					//检查该点以否已经添加,如果已经添加则退出循环
					//防止重复添加导致在后面在裁剪的时候死循环
					pointIsAdd = true;
					break;
				}
				if( pTempPoint->tValueForClippingWindow < pCurrentPositon->tValueForClippingWindow)
				{
					ClippingInterPoint* pLastPosition = pCurrentPositon->prev2ClippingdWindow;
					pLastPosition->next2ClippingdWindow = pTempPoint;
					pCurrentPositon->prev2ClippingdWindow = pTempPoint;
					pTempPoint->prev2ClippingdWindow = pLastPosition;
					pTempPoint->next2ClippingdWindow = pCurrentPositon;
					break;
				}
				else if (pEndPosition == pNextPosition)
				{
					pCurrentPositon->next2ClippingdWindow = pTempPoint;
					pNextPosition->prev2ClippingdWindow = pTempPoint;
					pTempPoint->prev2ClippingdWindow = pCurrentPositon;
					pTempPoint->next2ClippingdWindow = pNextPosition;
					break;
				}
				pCurrentPositon = pNextPosition;
				pNextPosition = pCurrentPositon->next2ClippingdWindow;
			}
			if (true == pointIsAdd)
			{
				free(pTempPoint);
				continue;
			}
			
			//通过遍历链表查找正确的位置插入生成点
			pCurrentPositon = &pointChainForClippedPolygon[indexOfclippedPolygon];
			pNextPosition = pCurrentPositon->next2ClippedPolygon;
			pEndPosition = &pointChainForClippedPolygon[nextIndexOfClippedPolygon];
			while (true)
			{
				if( pTempPoint->tValueForClippedPolygon < pCurrentPositon->tValueForClippedPolygon)
				{
					ClippingInterPoint* pLastPosition = pCurrentPositon->prev2ClippedPolygon;
					pLastPosition->next2ClippedPolygon = pTempPoint;
					pCurrentPositon->prev2ClippedPolygon = pTempPoint;
					pTempPoint->prev2ClippedPolygon = pLastPosition;
					pTempPoint->next2ClippedPolygon = pCurrentPositon;
					break;
				}
				else if (pEndPosition == pNextPosition)
				{
					pCurrentPositon->next2ClippedPolygon = pTempPoint;
					pNextPosition->prev2ClippedPolygon = pTempPoint;
					pTempPoint->prev2ClippedPolygon = pCurrentPositon;
					pTempPoint->next2ClippedPolygon = pNextPosition;
					break;
				}
				pCurrentPositon = pNextPosition;
				pNextPosition = pCurrentPositon->next2ClippedPolygon;
			}

			if (cosofToBeginPoint < 0.0f && cosofToEndPoint > 0.0f)
			{
				pTempPoint->pointType = INTER_POINT_TYPE_INTERSECTION_POINT_FOR_IN;
			}
			else if(cosofToBeginPoint > 0.0f && cosofToEndPoint < 0.0f)
			{
				pTempPoint->pointType = INTER_POINT_TYPE_INTERSECTION_POINT_FOR_OUT;
			}
			else
			{
				assert(0);
			}
		}
	}

	//完成链表构建
	//开始生成convex polygon

	//首先检查是否有足够的空间容纳结果
	int* bufferForPolygonConverCount = (int*)malloc(sizeof(int*) * allPointCountForClipping);
	GenerateConvexPolygon(pointChainForClippedPolygon, pointCountForClippedPolygon, NULL, bufferForPolygonConverCount, allPointCountForClipping);

	//完成链表构建
	//开始生成convex polygon

	for (int i = 0; i < pointCountForClippedPolygon; ++i)
	{
		pointChainForClippedPolygon[i].state = PROCESS_STATE_UNPROCESSED;
		int checkResult = PointInPolygon(clippingWindow, pointChainForClippedPolygon[i].point.x, pointChainForClippedPolygon[i].point.z);
		if (checkResult >= 0)
		{
			pointChainForClippedPolygon[i].state = PROCESS_STATE_NO_NEED_PROCESS;
		}

	}

	GenerateConvexPolygon(pointChainForClippedPolygon, pointCountForClippedPolygon, queue, bufferForPolygonConverCount, allPointCountForClipping);

	//释放分配的内存
	ClippingInterPoint* pCurrent = &pointChainForClippedPolygon[0];
	ClippingInterPoint* pNext = pCurrent->next2ClippedPolygon;
	while (pNext != &pointChainForClippedPolygon[0])
	{
		if (INTER_POINT_TYPE_INTERSECTION_POINT_FOR_IN == pNext->pointType || INTER_POINT_TYPE_INTERSECTION_POINT_FOR_OUT == pNext->pointType)
		{
			pCurrent = pNext;
			pNext = pNext->next2ClippedPolygon;
			free(pCurrent);
		}
		else
		{
			pNext = pNext->next2ClippedPolygon;
		}
	}
	Queue* checkQueue = CreateQueue(GetDataCountFromQueue(queue));
	while (MeshPolygon* checkPolygon = (MeshPolygon*)PopDataFromQueue(queue))
	{
		if (true != IsSamePolygon(checkPolygon, clippedPolygon))
		{
			PushDataToQueue(checkQueue, (void*)checkPolygon);
		}
	}
	ShiftQueueData(queue, checkQueue);
	ReleaseQueue(checkQueue);
	free(bufferForPolygonConverCount);
	free(pointChainForClippedPolygon);
	free(pointChainForClippingWindow);
	return 0;
}