/// <summary> /// This will create an intersection if two nodes overlap on the road. Only good if the roads only overlap once. /// </summary> /// <param name="bRoad"></param> /// <param name="tRoad"></param> private static void UnitTest_IntersectionHelper(GSDRoad bRoad, GSDRoad tRoad, GSDRoadIntersection.iStopTypeEnum iStopType, GSDRoadIntersection.RoadTypeEnum rType) { GSDSplineN tInter1 = null; GSDSplineN tInter2 = null; foreach (GSDSplineN tNode in bRoad.GSDSpline.mNodes) { foreach (GSDSplineN xNode in tRoad.GSDSpline.mNodes) { if (GSDRootUtil.IsApproximately(Vector3.Distance(tNode.transform.position, xNode.transform.position), 0f, 0.05f)) { tInter1 = tNode; tInter2 = xNode; break; } } } if (tInter1 != null && tInter2 != null) { GameObject tInter = GSD.Roads.GSDIntersections.CreateIntersection(tInter1, tInter2); GSDRoadIntersection GSDRI = tInter.GetComponent <GSDRoadIntersection>(); GSDRI.iStopType = iStopType; GSDRI.rType = rType; } }
/// <summary> /// Creates intersections where this road intersects with other roads. /// </summary> /// <param name="tRoad">The primary road to create intersections for.</param> /// <param name="iStopType">Stop signs, traffic lights #1 (US) or traffic lights #2 (Euro). Defaults to none.</param> /// <param name="rType">Intersection type: No turn lane, left turn lane or both turn lanes. Defaults to no turn lane.</param> public static void CreateIntersections_ProgrammaticallyForRoad(GSDRoad tRoad, GSDRoadIntersection.iStopTypeEnum iStopType = GSDRoadIntersection.iStopTypeEnum.None, GSDRoadIntersection.RoadTypeEnum rType = GSDRoadIntersection.RoadTypeEnum.NoTurnLane) { /* * General logic: * 20m increments to gather collection of which roads intersect * 2m increments to find actual intersection point * each 2m, primary road checks all intersecting array for an intersection. * find intersection point * if any intersections already within 75m or 100m, dont create intersection here * check if nodes within 50m, if more than one just grab closest, and move it to intersecting point * if no node within 50m, add * create intersection with above two nodes */ Object[] GSDRoadObjs = Object.FindObjectsOfType <GSDRoad>(); //20m increments to gather collection of which roads intersect List <GSDRoad> xRoads = new List <GSDRoad>(); foreach (GSDRoad xRoad in GSDRoadObjs) { if (tRoad != xRoad) { float EarlyDistanceCheckMeters = 10f; float EarlyDistanceCheckThreshold = 50f; bool EarlyDistanceFound = false; float tRoadMod = EarlyDistanceCheckMeters / tRoad.GSDSpline.distance; float xRoadMod = EarlyDistanceCheckMeters / xRoad.GSDSpline.distance; Vector3 tVect1 = default(Vector3); Vector3 tVect2 = default(Vector3); for (float i = 0f; i < 1.0000001f; i += tRoadMod) { tVect1 = tRoad.GSDSpline.GetSplineValue(i); for (float x = 0f; x < 1.000001f; x += xRoadMod) { tVect2 = xRoad.GSDSpline.GetSplineValue(x); if (Vector3.Distance(tVect1, tVect2) < EarlyDistanceCheckThreshold) { if (!xRoads.Contains(xRoad)) { xRoads.Add(xRoad); } EarlyDistanceFound = true; break; } } if (EarlyDistanceFound) { break; } } } } //See if any end point nodes are on top of each other already since T might not intersect all the time.: List <KeyValuePair <GSDSplineN, GSDSplineN> > tKVP = new List <KeyValuePair <GSDSplineN, GSDSplineN> >(); foreach (GSDRoad xRoad in xRoads) { foreach (GSDSplineN IntersectionNode1 in tRoad.GSDSpline.mNodes) { if (IntersectionNode1.bIsIntersection || !IntersectionNode1.IsLegitimate()) { continue; } foreach (GSDSplineN IntersectionNode2 in xRoad.GSDSpline.mNodes) { if (IntersectionNode2.bIsIntersection || !IntersectionNode2.IsLegitimate()) { continue; } if (IntersectionNode1.transform.position == IntersectionNode2.transform.position) { //Only do T intersections and let the next algorithm handle the +, since T might not intersect all the time. if (IntersectionNode1.bIsEndPoint || IntersectionNode2.bIsEndPoint) { tKVP.Add(new KeyValuePair <GSDSplineN, GSDSplineN>(IntersectionNode1, IntersectionNode2)); } } } } } foreach (KeyValuePair <GSDSplineN, GSDSplineN> KVP in tKVP) { //Now create the f*****g intersection: GameObject tInter = GSD.Roads.GSDIntersections.CreateIntersection(KVP.Key, KVP.Value); GSDRoadIntersection GSDRI_JustCreated = tInter.GetComponent <GSDRoadIntersection>(); GSDRI_JustCreated.iStopType = iStopType; GSDRI_JustCreated.rType = rType; } //Main algorithm: 2m increments to find actual intersection point: foreach (GSDRoad xRoad in xRoads) { if (tRoad != xRoad) { //Debug.Log("Checking road: " + xRoad.transform.name); float DistanceCheckMeters = 2f; bool EarlyDistanceFound = false; float tRoadMod = DistanceCheckMeters / tRoad.GSDSpline.distance; float xRoadMod = DistanceCheckMeters / xRoad.GSDSpline.distance; Vector3 tVect = default(Vector3); Vector2 iVect1 = default(Vector2); Vector2 iVect2 = default(Vector2); Vector2 xVect1 = default(Vector2); Vector2 xVect2 = default(Vector2); Vector2 IntersectPoint2D = default(Vector2); float i2 = 0f; for (float i = 0f; i < 1.0000001f; i += tRoadMod) { i2 = (i + tRoadMod); if (i2 > 1f) { i2 = 1f; } tVect = tRoad.GSDSpline.GetSplineValue(i); iVect1 = new Vector2(tVect.x, tVect.z); tVect = tRoad.GSDSpline.GetSplineValue(i2); iVect2 = new Vector2(tVect.x, tVect.z); float x2 = 0f; for (float x = 0f; x < 1.000001f; x += xRoadMod) { x2 = (x + xRoadMod); if (x2 > 1f) { x2 = 1f; } tVect = xRoad.GSDSpline.GetSplineValue(x); xVect1 = new Vector2(tVect.x, tVect.z); tVect = xRoad.GSDSpline.GetSplineValue(x2); xVect2 = new Vector2(tVect.x, tVect.z); //Now see if these two lines intersect: if (GSD.GSDRootUtil.Intersects2D(ref iVect1, ref iVect2, ref xVect1, ref xVect2, out IntersectPoint2D)) { //Get height of intersection on primary road: float tHeight = 0f; float hParam = tRoad.GSDSpline.GetClosestParam(new Vector3(IntersectPoint2D.x, 0f, IntersectPoint2D.y)); Vector3 hVect = tRoad.GSDSpline.GetSplineValue(hParam); tHeight = hVect.y; //if any intersections already within 75m or 100m, dont create intersection here Object[] AllInterectionObjects = Object.FindObjectsOfType <GSDRoadIntersection>(); foreach (GSDRoadIntersection GSDRI in AllInterectionObjects) { if (Vector2.Distance(new Vector2(GSDRI.transform.position.x, GSDRI.transform.position.z), IntersectPoint2D) < 100f) { goto NoIntersectionCreation; } } GSDSplineN IntersectionNode1 = null; GSDSplineN IntersectionNode2 = null; Vector3 IntersectionPoint3D = new Vector3(IntersectPoint2D.x, tHeight, IntersectPoint2D.y); //Debug.Log("Instersect found road: " + xRoad.transform.name + " at point: " + IntersectionPoint3D.ToString()); //Check primary road if any nodes are nearby and usable for intersection foreach (GSDSplineN tNode in tRoad.GSDSpline.mNodes) { if (tNode.IsLegitimate()) { if (Vector2.Distance(new Vector2(tNode.transform.position.x, tNode.transform.position.z), IntersectPoint2D) < 30f) { IntersectionNode1 = tNode; IntersectionNode1.transform.position = IntersectionPoint3D; IntersectionNode1.pos = IntersectionPoint3D; break; } } } //Check secondary road if any nodes are nearby and usable for intersection foreach (GSDSplineN tNode in xRoad.GSDSpline.mNodes) { if (tNode.IsLegitimate()) { if (Vector2.Distance(new Vector2(tNode.transform.position.x, tNode.transform.position.z), IntersectPoint2D) < 30f) { IntersectionNode2 = tNode; IntersectionNode2.transform.position = IntersectionPoint3D; IntersectionNode2.pos = IntersectionPoint3D; break; } } } //Check if any of the nodes are null. If so, need to insert node. And maybe update it. if (IntersectionNode1 == null) { IntersectionNode1 = InsertNode_Programmatically(tRoad, IntersectionPoint3D); } if (IntersectionNode2 == null) { IntersectionNode2 = InsertNode_Programmatically(xRoad, IntersectionPoint3D); } //Now create the f*****g intersection: GameObject tInter = GSD.Roads.GSDIntersections.CreateIntersection(IntersectionNode1, IntersectionNode2); GSDRoadIntersection GSDRI_JustCreated = tInter.GetComponent <GSDRoadIntersection>(); GSDRI_JustCreated.iStopType = iStopType; GSDRI_JustCreated.rType = rType; } NoIntersectionCreation: //Gibberish to get rid of warnings: int xxx = 1; if (xxx == 1) { xxx = 2; } } if (EarlyDistanceFound) { break; } } } } }