private Vector3 getOutgoingVectorForOneWayIntersection(Intersection intersection, Road connectedRoad) { float roadEndWidth = connectedRoad.GetRoadWidth(); float roadEndLength = roadEndWidth / 2; return(IntersectionMath.getOutgoingVector(intersection, connectedRoad).normalized *roadEndWidth / 2); }
private Vector3 CoordinateForRoadWithAbstractRoadInfos(Intersection intersection, Road connectedRoad, RightOrLeft rtlt, AbstractWayInfo[] infos) { infos = AbstractWayInfo.sortAbstractWayInfos(infos); // convert the road to an abstract way info AbstractWayInfo info = new AbstractWayInfo(IntersectionMath.getOutgoingVector(intersection, connectedRoad).normalized, connectedRoad.GetRoadWidth()); // TODO : CHECK FOR nonexistent index int index = 0; for (int i = 0; i < infos.Length; i++) { if (infos[i] == info) { index = i; } } Vector3[] vertices = MeshVerticesForAbstractWayInfos(infos); switch (rtlt) { case RightOrLeft.LEFT: return(vertices[index - 1 < 0 ? infos.Length - 1 : index - 1]); case RightOrLeft.RIGHT: return(vertices[index]); } Debug.LogError("Semantics Error, please check"); return(Vector3.zero); }
private GameObject buildTwoWayIntersection(Intersection intersection, Road road1, Road road2) { // create a four way intersection instead of a two way intersection if the angle is less than 90 switch (GetTwoWayIntersectionType(intersection)) { case TwoWayIntersectionType.SKEW: case TwoWayIntersectionType.TRANSITION: AbstractWayInfo[] infos = AbstractWayInfosForTwoWayIntersection(intersection, road1, road2); return(buildMultiwayIntersectionWithVectors(intersection, infos)); case TwoWayIntersectionType.SMOOTH: // only when angle > 90 Vector3 vec1 = IntersectionMath.getOutgoingVector(intersection, road1).normalized; Vector3 vec2 = IntersectionMath.getOutgoingVector(intersection, road2).normalized; float roadWidth1 = road1.GetRoadWidth(); float roadWidth2 = road2.GetRoadWidth(); Vector3 vec1Norm = Quaternion.Euler(new Vector3(0, 90, 0)) * vec1 * roadWidth1 / 2; Vector3 vec2Norm = Quaternion.Euler(new Vector3(0, -90, 0)) * vec2 * roadWidth2 / 2; // check the intersection, if there's its inner, if there isn't, its outer Vector3 refPoint; GameObject inner; GameObject outer; if (Math3d.LineLineIntersection(out refPoint, vec1Norm, vec1, vec2Norm, vec2)) { // we intersected, its inner inner = buildInner(vec1Norm, vec2Norm, refPoint, intersection.position, intersection.customization); outer = buildOuter(-vec1Norm, -vec2Norm, 4, intersection.position, intersection.customization); } else { // we are outer outer = buildOuter(vec1Norm, vec2Norm, 4, intersection.position, intersection.customization); // get the real intersection // we need to * a const since the Math scirpt only considers line to be that long inner = buildInner(-vec1Norm, -vec2Norm, refPoint, intersection.position, intersection.customization); } // add rigidbody to enable selection return(createParentIntersectionWithChildIntersections("Two way intersection", intersection.customization, inner, outer)); } Debug.LogError("Semantics Error, please check"); return(null); }
private AbstractWayInfo[] AbstractWayInfosForMultiwayIntersection(Intersection intersection, Road[] connectedRoads) { // convert roads to vectos Vector3[] vectors = connectedRoads.Select(rd => IntersectionMath.getOutgoingVector(intersection, rd)).ToArray(); float[] widths = connectedRoads.Select(rd => rd.GetRoadWidth()).ToArray(); AbstractWayInfo[] infos; // handle when connectedRoads.Length == 3 << build a four-way intersection instead if (connectedRoads.Length == 3) { // find the vector whose direction is of greatest difference to other two Vector3 maxVector = vectors[0]; float maxRoadWidth = widths[0]; float maxAngles = 0; for (int i = 0; i < 3; i++) { float accum = 0; for (int j = 0; j < 3; j++) { float zeroTo180Angle = Vector3.Angle(vectors[i], vectors[j]); float distance = zeroTo180Angle > 90 ? 180 - zeroTo180Angle : zeroTo180Angle; accum += distance; } if (accum > maxAngles) { maxVector = vectors[i]; maxRoadWidth = widths[i]; maxAngles = accum; } } Vector3[] resultingVectors = { vectors[0], vectors[1], vectors[2], -maxVector }; float[] resultingWidths = { widths[0], widths[1], widths[2], maxRoadWidth }; infos = AbstractWayInfo.InfosWithDirectionsAndWidths(resultingVectors, resultingWidths); } else { infos = AbstractWayInfo.InfosWithDirectionsAndWidths(vectors, widths); } return(infos); }
// returns the maximum value of AbstractCarPosition.offset so that the car is not rushing into the intersection public float stoppingDistanceForCurrentDrive(AbstractCarPosition carPosition) { /** * * toIntersection ref intersection * * toLeftEdge * \===================================================| ^ * \|< STOPPING DISTANCE > | width(refIntersection) * \ ------------------------------------------------| x * \ | width(toIntersection) * \===============================================| v * toRightEdge * * * */ Intersection toIntersection = carPosition.referenceRoad.otherIntersection(carPosition.referenceIntersection); Vector3 toLeftEdge = builder.coordinateForRoadAtIntersection(toIntersection, carPosition.referenceRoad, IntersectionBuilder.RightOrLeft.LEFT); Vector3 toRightEdge = builder.coordinateForRoadAtIntersection(toIntersection, carPosition.referenceRoad, IntersectionBuilder.RightOrLeft.RIGHT); // get the proportion int totalNumberOfLanes = carPosition.referenceRoad.GetNumberOfLanesInDirectionWithReferenceIntersection(toIntersection) + carPosition.referenceRoad.GetNumberOfLanesInDirectionWithReferenceIntersection(carPosition .referenceIntersection); Vector3 stoppingLocation = Vector3.Lerp(toLeftEdge, toRightEdge, 1f / 2 - (1f / 2 + carPosition.laneNumber) / totalNumberOfLanes) * (1f / 2); // project the stopping location onto the outgoing vector Vector3 stoppingCompensation = Vector3.Project(stoppingLocation, IntersectionMath.getOutgoingVector(toIntersection, carPosition.referenceRoad)); float stoppingDistance = carPosition.referenceRoad.GetRoadLength() - stoppingCompensation.magnitude; return(stoppingDistance); }
public float startingDistanceForCurrentDrive(AbstractCarPosition carPosition) { /** * * refIntersection toIntersection * * fromLeftEdge * \===================================================| ^ * \ | width(toIntersection) * \ ------------------------------------------------| x * < >\ | width(refIntersection) * | \===============================================| v * | fromRightEdge * | * +--> startingDistance * */ Intersection toIntersection = carPosition.referenceRoad.otherIntersection(carPosition.referenceIntersection); Vector3 fromLeftEdge = builder.coordinateForRoadAtIntersection(carPosition.referenceIntersection, carPosition.referenceRoad, IntersectionBuilder.RightOrLeft.LEFT); Vector3 fromRightEdge = builder.coordinateForRoadAtIntersection(carPosition.referenceIntersection, carPosition.referenceRoad, IntersectionBuilder.RightOrLeft.RIGHT); // get the proportion int totalNumberOfLanes = carPosition.referenceRoad.GetNumberOfLanesInDirectionWithReferenceIntersection(toIntersection) + carPosition.referenceRoad.GetNumberOfLanesInDirectionWithReferenceIntersection(carPosition .referenceIntersection); Vector3 startingLocation = Vector3.Lerp(fromLeftEdge, fromRightEdge, 1f / 2 + (1f / 2 + carPosition.laneNumber) / totalNumberOfLanes) * (1f / 2); // project the stopping location onto the outgoing vector Vector3 startignCompensation = Vector3.Project(startingLocation, IntersectionMath.getOutgoingVector(carPosition.referenceIntersection, carPosition.referenceRoad)); float startingDistance = startignCompensation.magnitude; return(startingDistance); }
private AbstractWayInfo[] AbstractWayInfosForTwoWayIntersection(Intersection intersection, Road road1, Road road2) { Vector3 vec1 = IntersectionMath.getOutgoingVector(intersection, road1).normalized; Vector3 vec2 = IntersectionMath.getOutgoingVector(intersection, road2).normalized; // create a four way intersection instead of a two way intersection if the angle is less than 90 Vector3[] vecs = null; float[] roadWidths = null; switch (GetTwoWayIntersectionType(intersection)) { case TwoWayIntersectionType.SKEW: vecs = new[] { vec1, vec2, -vec1, -vec2 }; roadWidths = new[] { road1.GetRoadWidth(), road2.GetRoadWidth(), road1.GetRoadWidth(), road2.GetRoadWidth() }; break; case TwoWayIntersectionType.TRANSITION: // create a halfway rotation Quaternion rotation = Quaternion.Euler(Quaternion.FromToRotation(vec1, vec2).eulerAngles / 2); // this is the virtual directional vector Vector3 newVec = rotation * vec1; // this is the virtual road width, set it to be the average of the two float newWidth = road1.GetRoadWidth() + road2.GetRoadWidth() / 2; vecs = new[] { vec1, vec2, newVec, -newVec }; roadWidths = new[] { road1.GetRoadWidth(), road2.GetRoadWidth(), newWidth, newWidth }; break; case TwoWayIntersectionType.SMOOTH: Debug.LogError("Code Error, this method is to be called without smooth transition"); break; } // zip vecs and roadWidths into abstract road infos AbstractWayInfo[] infos = AbstractWayInfo.InfosWithDirectionsAndWidths(vecs, roadWidths); return(infos); }
/** * @brief the detailed type for a two-way intersection * * @param intersection the intersection to inspect type * */ public TwoWayIntersectionType GetTwoWayIntersectionType(Intersection intersection) { Debug.Assert(intersection.getConnectedRoads().Length == 2); Road road1 = intersection.getConnectedRoads()[0]; Road road2 = intersection.getConnectedRoads()[1]; Vector3 vec1 = IntersectionMath.getOutgoingVector(intersection, road1).normalized; Vector3 vec2 = IntersectionMath.getOutgoingVector(intersection, road2).normalized; // create a four way intersection instead of a two way intersection if the angle is less than 90 if (Vector3.Angle(vec1, vec2) < 90) { return(TwoWayIntersectionType.SKEW); } else //force a four way intersection if two roads are of different width if (Mathf.Approximately(road1.GetRoadWidth(), road2.GetRoadWidth()) == false) { return(TwoWayIntersectionType.TRANSITION); } else { return(TwoWayIntersectionType.SMOOTH); } }