private void walkToNextSegment(SegmentNodeConnection target, HashSet <SegmentNodeConnection> processed) { var node = target.Node; var trafficNode = node as TrafficNode; trafficNode.VisitedAsLine = true; if (node.Segments.Count() != 2) { return; // stop walking } var other = node.Segments.FirstOrDefault(s => s != target); walkToNextNode(other, processed); var incomingSegment = target.Segment.Description as TrafficSegmentDescription; var outgoingSegment = other.Segment.Description as TrafficSegmentDescription; if (TrafficSegmentDescription.CanMerge(incomingSegment, outgoingSegment)) { trafficNode.IsDeletionPossible = true; } var dot = fixTangents(target, other); if (dot < Math.Cos(Math.PI / 180 * 175)) { trafficNode.IsAlmostStraight = true; } }
//http://www.ryanjuckett.com/programming/biarc-interpolation/ public static void Biarc(SegmentNodeConnection start, SegmentNodeConnection end, out Arc arc1, out Arc arc2) { var t1 = start.Tangent; var t2 = end.Tangent; Biarc(t2d(start.Node.Position), t2d(t1).normalized, t2d(end.Node.Position), t2d(-t2).normalized, out arc1, out arc2); }
private void disconnect(SegmentNodeConnection connection) { if (connection == null) { return; //already disconnected } var segments = connection.Node.SegmentList; lock (segments) { bool isStart = connection.Segment.Start == connection; connection.Node.NotifiyOfDisconnect(connection); segments.Remove(connection); connection.Segment.NotifyOfDisconnect(isStart); if (isStart) { connection.Segment.Start = null; } else { connection.Segment.End = null; } } Remove(connection.Segment); }
public static Vector3 GetPosition(this SegmentNodeConnection con, Vector3 additionalOffset) { var off = con.Offset + additionalOffset; var tangent = con.Tangent; return(con.Node.Position + tangent * off.z + Vector3.Cross(tangent, Vector3.up) * off.x + Vector3.up * off.y); }
private void walkToNextNode(SegmentNodeConnection con, HashSet <SegmentNodeConnection> processed) { var segment = con.Segment; SegmentNodeConnection target; if (segment.Start == con) { target = segment.End; } else { target = segment.Start; } if (target != null && processed.Add(target)) { walkToNextSegment(target, processed); } }
public Segment MergeSegments(Node node) { if (node.SegmentList.Count != 2) { throw new InvalidOperationException("can only merge 2 segements"); } var a = node.SegmentList[0]; var b = node.SegmentList[1]; var segA = a.Segment; var segB = b.Segment; Segment segment; bool isAStart = segA.Start == a; bool isBStart = segB.Start == b; if (isAStart == isBStart) { throw new InvalidOperationException("can only merge nodes if the roads follow the same direction"); } SegmentNodeConnection otherA = isAStart ? segA.End : segA.Start; SegmentNodeConnection otherB = isBStart ? segB.End : segB.Start; if (!isAStart) { segment = CreateSegment(otherA.Node, otherB.Node, segA.Description); segment.Start.Tangent = otherA.Tangent; segment.End.Tangent = otherB.Tangent; } else { segment = CreateSegment(otherB.Node, otherA.Node, segA.Description); segment.Start.Tangent = otherB.Tangent; segment.End.Tangent = otherA.Tangent; } Remove(node); return(segment); }
private static bool getOffsets(Node node, SegmentNodeConnection con1, SegmentNodeConnection con2, out float offsetA, out float offsetB) { var wA = con1.Segment.GetWidth(); var wB = con2.Segment.GetWidth(); var o = node.Position.GetXZ(); var dA = con1.Tangent.GetXZ(); var dB = con2.Tangent.GetXZ(); var dot = Vector3.Dot(dA, dB); if (dot < -0.75) { offsetA = float.PositiveInfinity; offsetB = float.PositiveInfinity; return(false); } return(VectorMath2D.IntersectsLineLine(o, dA, wA, o, dB, wB, out offsetA, out offsetB)); }
private double fixTangents(SegmentNodeConnection a, SegmentNodeConnection b) { var targetLen = (a.Segment.Start?.Node.Position - a.Segment.End?.Node.Position)?.sqrMagnitude; var otherLen = (b.Segment.Start?.Node.Position - b.Segment.End?.Node.Position)?.sqrMagnitude; if (targetLen.HasValue && otherLen.HasValue) { var dot = Vector3.Dot(a.Tangent, b.Tangent); if (dot < -Math.Cos(Math.PI / 4)) { var t = (a.Tangent * targetLen.Value - b.Tangent * otherLen.Value).normalized; a.Tangent = t; b.Tangent = -t; } return(dot); } return(0); }
public static Vector3 GetPosition(this SegmentNodeConnection con) { return(GetPosition(con, Vector3.zero)); }
public static void SetHeading(this SegmentNodeConnection connnection, Vector3 heading) => connnection.Tangent = connnection.Segment.Start == connnection ? -heading : heading;
public static Vector3 GetHeading(this SegmentNodeConnection connnection) => connnection.Segment.Start == connnection ? -connnection.Tangent : connnection.Tangent;
internal void NotifyOfTangentChanged(SegmentNodeConnection segmentNodeConnection) { OnTangentChanged(segmentNodeConnection); }
internal void NotifyOfOffsetChanged(SegmentNodeConnection segmentNodeConnection) { OnOffsetChanged(segmentNodeConnection); }
private static void writeConnection(JsonSerializer serializer, Dictionary <Node, int> nodes, JsonWriter writer, SegmentNodeConnection connection, string type) { writer.WritePropertyName(type); writer.WriteStartObject(); { writer.WritePropertyName(Constants.TAG_SEGMENT_CONNECTION_NODE); writer.WriteValue(nodes[connection.Node]); writer.WritePropertyName(Constants.TAG_SEGMENT_CONNECTION_TANGENT); serializer.Serialize(writer, (Vector3D)connection.Tangent); writer.WritePropertyName(Constants.TAG_SEGMENT_CONNECTION_OFFSET); serializer.Serialize(writer, (Vector3D)connection.Offset); } writer.WriteEndObject(); }
private void notifyConnect(Node node, SegmentNodeConnection connection) { node.NotifyOfConnection(connection); connection.NotifyOfCreation(); }