public void test4() { IntersectionChecker i = new IntersectionChecker(); Edge road = new Edge(new Node(20, 155), new Node(75, 200), RoadTypes.STREET); i.fixRoad(road); RoadVisualizer.placeRoad(road, "0"); }
//TESTING public void test() { RoadVisualizer.placeRoad(new Edge(new Node(100, 100), new Node(125, 125), RoadTypes.HIGHWAY), "0"); RoadVisualizer.placeRoad(new Edge(new Node(125, 125), new Node(180, 150), RoadTypes.HIGHWAY), "1"); RoadVisualizer.placeRoad(PositionLegalizer.legalizeRoad(new Edge(new Node(180, 150), new Node(200, 250), RoadTypes.HIGHWAY)), "2"); RoadVisualizer.placeRoad(new Edge(new Node(200, 250), new Node(200, 550), RoadTypes.HIGHWAY), "3"); RoadVisualizer.placeRoad(new Edge(new Node(200, 550), new Node(200, 750), RoadTypes.HIGHWAY), "4"); RoadVisualizer.placeRoad(new Edge(new Node(125, 125), new Node(125, 175), RoadTypes.STREET), "5"); RoadVisualizer.placeRoad(new Edge(new Node(125, 175), new Node(80, 225), RoadTypes.STREET), "6"); RoadVisualizer.placeRoad(new Edge(new Node(125, 175), new Node(180, 150), RoadTypes.STREET), "7"); }
public void generateRoadMap() { resetRoads(); // Generate the first roads foreach (Edge road in globalGoals.generateFirstRoads(Approach.RANDOM)) { q.push(road, road.getTime()); } while (q.size > 0) { Edge roadToBuild = q.pop(); //check with localconstraints roadToBuild = localConstraints.validateRoad(roadToBuild); if (roadToBuild != null) { if (CityGeneratorUI.DebugMode) { Debug.Log("roadToBuild was valid"); } //add it to the roads array roads.Add(roadToBuild); //visualize it and give it the correct index RoadVisualizer.placeRoad(roadToBuild, (roads.Count - 1).ToString()); foreach (Edge road in globalGoals.generateNewRoads(roadToBuild)) { q.push(road, road.getTime()); } } else { if (CityGeneratorUI.DebugMode) { Debug.Log("roadToBuild was not valid"); } } } //construct the list of nodes with all their references constructNodeGraph(); CityGenerator.nrOfRoads = roads.Count; PreviewRoads.NrRoads = roads.Count; //reset the nr of roads visualized roadBuilt = true; }
/// <summary> /// Checks if the road intersects with other roads within a certain distance from the road (in the direction the road is facing) /// </summary> /// <returns><c>true</c>, if intersection was found and also changes fixedRoad, <c>false</c> otherwise.</returns> /// <param name="road">Road.</param> /// <param name="dist">Distance over which the intersection should be checked</param> private bool checkIntersection(Edge road, float dist) { //set up variables needed for boxcastall int layerMask = 1 << LayerMask.NameToLayer("Edge"); Vector3 halfExtends = new Vector3(0.1f, 100, ((posN1 - posN2).magnitude) / 2); Vector3 roadCenter = Vector3.Lerp(posN1, posN2, 0.5f); Vector3 direction = posN2 - posN1; Vector2 roadOrientation = new Vector2(direction.x, direction.z); //get the intersections with roads RaycastHit[] intersections = Physics.BoxCastAll(roadCenter, halfExtends, direction, Quaternion.LookRotation(direction), dist, layerMask); //no intersections, good! if (intersections.Length == 0) { //Debug.Log ("Road did not intersect"); return(false); } else { float closestRoadDistance = float.MaxValue; //just set it to the first value GameObject closestRoad = null; Vector2 closestIntersection = Vector2.zero; //first we check which road is closest foreach (RaycastHit hit in intersections) { //Debug.Log (road.getRoadType().ToString() + " intersects with: " + hit.collider.gameObject.name + " which has N1 at: " + hit.transform.GetChild (0).localPosition + " and posN1 is: " + posN1); //Debug.Log (road.getRoadType().ToString() + " intersects with: " + hit.collider.gameObject.name + " which has N2 at: " + hit.transform.GetChild (1).localPosition + " and posN1 is: " + posN1); //Debug.Log (hit.collider.gameObject.name + " shares N1: " + CoordinateHelper.areEqual (hit.transform.GetChild (0).localPosition, posN1)); //Debug.Log (hit.collider.gameObject.name + " shares N2: " + CoordinateHelper.areEqual (hit.transform.GetChild (1).localPosition, posN1)); //consider the case where roads have the same endpoints, i.e., they overlap exactly if ((CoordinateHelper.areEqual(hit.transform.GetChild(1).localPosition, posN1) && CoordinateHelper.areEqual(hit.transform.GetChild(0).localPosition, posN2)) || (CoordinateHelper.areEqual(hit.transform.GetChild(1).localPosition, posN2) && CoordinateHelper.areEqual(hit.transform.GetChild(0).localPosition, posN1))) { //in this case the road cannot be placed if (CityGeneratorUI.DebugMode) { Debug.Log("Intersection checker: roads overlapped exactly"); } fixedRoad = null; return(true); } else { //only consider road segments that are not a predecessor if (!CoordinateHelper.areEqual(hit.transform.GetChild(1).localPosition, posN1)) { //also dont consider roads that branch out from the same point if (!CoordinateHelper.areEqual(hit.transform.GetChild(0).localPosition, posN1)) { //these are the roads that have no endpoints in common with the current road. //check if the angle is valid Vector2 otherRoadOrientation = new Vector2(hit.transform.forward.x, hit.transform.forward.z); //check if the two roads have enough "space" between them. if (isValidAngle(roadOrientation.normalized, otherRoadOrientation.normalized)) { //find the road that is intersected with first Vector2 intersectionPoint = lineIntersectionPoint( road.n1.pos, road.n2.pos, CoordinateHelper.threeDtoTwoD(hit.transform.GetChild(0).localPosition), CoordinateHelper.threeDtoTwoD(hit.transform.GetChild(1).localPosition)); float distance = (road.n1.pos - intersectionPoint).magnitude; if (distance < closestRoadDistance) { //Debug.Log ("Road: " + hit.collider.gameObject.name + " has distance: " + (posN1 - hit.collider.transform.position).magnitude + " to n1"); closestRoad = hit.collider.gameObject; closestIntersection = intersectionPoint; closestRoadDistance = distance; } } else { //return that the road is invalid fixedRoad = null; return(true); } } else { if (CityGeneratorUI.DebugMode) { Debug.Log("Roads have same start point"); } //there is another road branching out from the same point.. check their angle Vector2 sameBranchRoadOrientation = new Vector2(hit.transform.forward.x, hit.transform.forward.z); if (Vector2.Angle(roadOrientation.normalized, sameBranchRoadOrientation.normalized) > CityGenerator.minRoadAngle) { //this is fine } else { //when this happens we cannot place this road fixedRoad = null; return(true); } } } else { //just to be sure, we dont want to make sharp turns if (CityGeneratorUI.DebugMode) { Debug.Log("Roads have same start point"); } //there is another road branching out from the same point.. check their angle Vector2 sameBranchRoadOrientation = new Vector2(hit.transform.forward.x, hit.transform.forward.z); if (Vector2.Angle(roadOrientation.normalized, sameBranchRoadOrientation.normalized) < 180 - CityGenerator.minRoadAngle) { //this is fine } else { //when this happens we cannot place this road fixedRoad = null; return(true); } } } } //no legitimate intersection was found if (closestRoad == null) { //return that no intersection was found return(false); } else { //Now we want to see if the angle between the roads is large enough. Vector2 closestRoadOrientation = new Vector2(closestRoad.transform.forward.x, closestRoad.transform.forward.z); //we want to make sure the angle is large enough if (isValidAngle(roadOrientation.normalized, closestRoadOrientation.normalized)) { //now we also need to update the roads list in the roadmapgenerator //set up all involved nodes Node roadToReplaceN1 = new Node(closestRoad.transform.GetChild(0).localPosition.x, closestRoad.transform.GetChild(0).localPosition.z); Node intersectionNode = new Node(closestIntersection); Node roadToReplaceN2 = new Node(closestRoad.transform.GetChild(1).localPosition.x, closestRoad.transform.GetChild(1).localPosition.z); //check if after splitting the new road segments are long enough if ((intersectionNode.pos - roadToReplaceN1.pos).magnitude > CityGenerator.minRoadLengthAfterSplit) { if ((intersectionNode.pos - roadToReplaceN2.pos).magnitude > CityGenerator.minRoadLengthAfterSplit) { fixedRoad.n2 = intersectionNode; //also check if the fixed road is long enough, do this before generating intersections! if (CoordinateHelper.validRoadLength(fixedRoad)) { //if the width of the closest road equals the highwaywidth, we create new highways RoadTypes roadType = (closestRoad.transform.localScale.x == CityGenerator.highwayWidth) ? RoadTypes.HIGHWAY : RoadTypes.STREET; //create new road segments for the road that is going to be split Edge splitRoad1 = new Edge(roadToReplaceN1, intersectionNode, roadType); Edge splitRoad2 = new Edge(intersectionNode, roadToReplaceN2, roadType); //get a reference to the road that is going to be split Edge roadToReplace = RoadMapGenerator.getRoad(roadToReplaceN1, roadToReplaceN2); //the road segments which will replace closestRoad List <Edge> replacementRoads = new List <Edge> (); replacementRoads.Add(splitRoad1); replacementRoads.Add(splitRoad2); if (CityGeneratorUI.DebugMode) { Debug.Log(closestRoad.name + " was split by road starting at" + road.n1 + " and ending at " + road.n2); } //physically change the road RoadVisualizer.replaceRoad(closestRoad, replacementRoads); //now replace the roads in the road list (logically) RoadMapGenerator.replaceRoad(roadToReplace, replacementRoads); } } else { //we cannot fix this intersection fixedRoad = null; return(true); } } else { //we cannot fix this intersection fixedRoad = null; return(true); } return(true); } else { //the road intersects with a road while the angle between them is too small //so we cannot place this road fixedRoad = null; return(true); } } } }