/** * Generate all the critical points based on the position of the viewpoint and end points * @param viewpoint the oject of the view point * @param endPoints the list of the end points that need to connected with the view point */ private void GenerateLinesCast(GameObject viewpoint, OBSTACLE.Obstacle endPoints) { for (int i = 0; i < endPoints.obstaclePoints.Length; i++) { Vector2 direction = endPoints.obstaclePoints[i] - viewpoint.transform.position; if (bPartiallyView) { if (HelpFunction.isInsideClockRangeOfTwoVector(startDirection, endDirection, direction)) { GenerateLineCast(viewpoint, endPoints, direction, i); } } else { GenerateLineCast(viewpoint, endPoints, direction, i); } } if (rangeEffect) { // compute the intersection point with the obstacle for (int i = 0; i < endPoints.obstaclePoints.Length; i++) { Vector2 intersection1; Vector2 intersection2; if (HelpFunction.FindLineCircleIntersections(viewpoint.transform.position, range, endPoints.obstaclePoints[i], endPoints.obstaclePoints[(i + 1) % endPoints.obstaclePoints.Length], out intersection1, out intersection2) != 0) { GenerateRangeIntersectionPoint(intersection1, endPoints.index); GenerateRangeIntersectionPoint(intersection2, endPoints.index); } } } }
public static int isConcave(OBSTACLE.Obstacle obstacle) { return(isConcave(obstacle.obstaclePoints)); }
/// <summary> /// Triangularization /// 1.Find a splitable point /// 2.split to get new polygon /// 3.repeat until all the polygon are convex /// /// Find a splitable point /// 1.Is the vertex a splitable point:whether the vertex is outside the polygon that surrounded by the rest of the vertex /// 2.random connect to a non-adjacent vertex /// </summary> public static List <OBSTACLE.Obstacle> triangularization(OBSTACLE.Obstacle obstacle) { int len = obstacle.obstaclePoints.Length; if (len <= 3) { List <OBSTACLE.Obstacle> newObstacleList = new List <OBSTACLE.Obstacle>(); newObstacleList.Add(obstacle); return(newObstacleList); } int searchIndex = isConcave(obstacle); List <int> covexIndex = new List <int>(); if (searchIndex == -1) { List <OBSTACLE.Obstacle> newObstacleList = new List <OBSTACLE.Obstacle>(); newObstacleList.Add(obstacle); return(newObstacleList); } //Find splitable point int canFragementIndex = -1;//the index of splitable point for (int i = 0; i < len; i++) { List <Vector3> polygon = new List <Vector3>(obstacle.obstaclePoints); polygon.RemoveAt(i); if (!IsPointInsidePolygon(obstacle.obstaclePoints[i], polygon) && IsFragementIndex(i, obstacle.obstaclePoints.ToList())) { canFragementIndex = i; break; } } if (canFragementIndex < 0) { throw new Exception("Invalid Argument"); } //split to a triangle and a polygon List <Vector3> tTriangles = new List <Vector3>(3); int next = (canFragementIndex == len - 1) ? 0 : canFragementIndex + 1; int prev = (canFragementIndex == 0) ? len - 1 : canFragementIndex - 1; tTriangles.Add(obstacle.obstaclePoints[prev]); tTriangles.Add(obstacle.obstaclePoints[canFragementIndex]); tTriangles.Add(obstacle.obstaclePoints[next]); //delete the point List <Vector3> tempObstclePoints = obstacle.obstaclePoints.ToList(); tempObstclePoints.RemoveAt(canFragementIndex); obstacle.obstaclePoints = tempObstclePoints.ToArray(); // Recursion splitting List <OBSTACLE.Obstacle> leaveTriangles = triangularization(obstacle); OBSTACLE.Obstacle newObstacle = new OBSTACLE.Obstacle(); newObstacle.obstaclePoints = tTriangles.ToArray(); leaveTriangles.Add(newObstacle); return(leaveTriangles); }
private void GenerateLineCast(GameObject viewpoint, OBSTACLE.Obstacle endPoints, Vector2 direction, int endPointIndex) { HitPoint hitPoint = new HitPoint(); RaycastHit2D[] rayCastHits2D; rayCastHits2D = Physics2D.RaycastAll(viewpoint.transform.position, direction); if (rayCastHits2D.Length > 0) { if (!HelpFunction.Vector2Equal(endPoints.obstaclePoints[endPointIndex], rayCastHits2D[0].point)) { if ((rayCastHits2D[0].point - new Vector2(viewpoint.transform.position.x, viewpoint.transform.position.y)).magnitude > new Vector2(endPoints.obstaclePoints[endPointIndex].x - viewpoint.transform.position.x, endPoints.obstaclePoints[endPointIndex].y - viewpoint.transform.position.y).magnitude) { // force to add the critical point if ((endPoints.obstaclePoints[endPointIndex] - viewpoint.transform.position).magnitude < range) { addPointToCriticalList(new HitPoint(endPoints.obstaclePoints[endPointIndex], endPoints.index)); } } } foreach (RaycastHit2D rayCastHit2D in rayCastHits2D) { Vector2 temp = new Vector2(rayCastHit2D.point.x - viewpoint.transform.position.x , rayCastHit2D.point.y - viewpoint.transform.position.y); // if the hit result is the same position as obstacle position if (HelpFunction.Vector2Equal(rayCastHit2D.point, endPoints.obstaclePoints[endPointIndex])) { // If the hit point is out of the range if (temp.magnitude > range) { hitPoint.location = new Vector2(viewpoint.transform.position.x, viewpoint.transform.position.y) + direction.normalized * range; hitPoint.obstacleIndex = endPoints.index; addPointToCriticalList(hitPoint); } else { // If the neighbour endpoints of the hitting result are both in the one side, keep the hitting result Vector3 prev = endPoints.obstaclePoints[(endPointIndex + endPoints.obstaclePoints.Length - 1) % endPoints.obstaclePoints.Length]; Vector3 next = endPoints.obstaclePoints[(endPointIndex + 1) % endPoints.obstaclePoints.Length]; if (AreSameSide(new Vector2(rayCastHit2D.point.x - viewpoint.transform.position.x, rayCastHit2D.point.y - viewpoint.transform.position.y) , prev - viewpoint.transform.position, next - viewpoint.transform.position)) { addPointToCriticalList(new HitPoint(rayCastHit2D.point, endPoints.index)); if (!bMesh) { GenerateVisibilityEffectWithLine(viewpoint, rayCastHit2D.point); } continue; } else { hitPoint.location = rayCastHit2D.point; hitPoint.obstacleIndex = endPoints.index; addPointToCriticalList(hitPoint); break; } } } else { hitPoint.location = rayCastHit2D.point; // find the index of obstacle in the hit point foreach (OBSTACLE.Obstacle obstacle in ObstaclesLine) { if (HelpFunction.isInObstacle(hitPoint.location, obstacle.obstaclePoints)) { hitPoint.obstacleIndex = obstacle.index; break; } } if (temp.magnitude > range) { hitPoint.location = new Vector2(viewpoint.transform.position.x, viewpoint.transform.position.y) + direction.normalized * range; } addPointToCriticalList(hitPoint); break; } } if (!bMesh) { GenerateVisibilityEffectWithLine(viewpoint, hitPoint.location); } } }