/* Turns segments into beziers. */ private List <Bezier2> makeBeziers(List <ushort> netSegmentsIds) { List <Bezier2> beziers = new List <Bezier2>(); for (int i = 0; i < netSegmentsIds.Count; i++) { NetSegment netSegment = NetUtil.Segment(netSegmentsIds[i]); bool smoothStart = (NetUtil.Node(netSegment.m_startNode).m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; bool smoothEnd = (NetUtil.Node(netSegment.m_endNode).m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; Bezier3 bezier = new Bezier3(); bezier.a = NetUtil.Node(netSegment.m_startNode).m_position; bezier.d = NetUtil.Node(netSegment.m_endNode).m_position; NetSegment.CalculateMiddlePoints(bezier.a, netSegment.m_startDirection, bezier.d, netSegment.m_endDirection, smoothStart, smoothEnd, out bezier.b, out bezier.c); beziers.Add(Bezier2.XZ(bezier)); } return(beziers); }
/* Sometimes it happens that we split the road too close to another segment. If that occur, the roads do glitch. In that case * we remove one more segment up the road. This method is still glitchy, would need improvement. */ /* intersection - node outside the ellipse */ private bool nextSegmentInfo(WrappedSegment closeSegmentW, ref WrappedNode outerNodeW, ref Vector3 endDirection) { NetSegment closeSegment = closeSegmentW.Get; //outerNodeId = 0; //directions = new Vector3(0,0,0); NetNode node = outerNodeW.Get; int segmentcount = node.CountSegments(); /* If there is an intersection right behind the ellipse, we can't go on as we can merge only segments which are in fact * only one road without an intersection. */ if (segmentcount != 2) { //Debug.Log("Ambiguous node."); return(false); } /*string debugString = "Close segment id: " + closeSegmentId + "; "; * for(int i = 0; i < 8; i++) * { * debugString += node.GetSegment(i) + ", "; * } * Debug.Log(debugString);*/ ushort nextSegmentId = NetUtil.GetNonzeroSegment(node, 0); /* We need the segment that goes away from the ellipse, not the one we already have. */ if (closeSegmentW.Id == nextSegmentId) { //Debug.Log("Taking the other of the two segments. " + node.GetSegment(1)); nextSegmentId = NetUtil.GetNonzeroSegment(node, 1); if (nextSegmentId == 0) { return(false); } } NetSegment nextSegment = NetUtil.Segment(nextSegmentId); ushort outerNodeId = nextSegment.m_startNode; Vector3 directions = nextSegment.m_startDirection; /* We need the node further away */ if (outerNodeId == outerNodeW.Id) { //Debug.Log("Taking the other of the nodes."); outerNodeId = nextSegment.m_endNode; directions = nextSegment.m_endDirection; if (outerNodeId == 0) { return(false); } } WrappedSegment nextSegmentW = networkDictionary.RegisterSegment(nextSegmentId); // Release old ToBeReleasedNodes.Add(outerNodeW); ToBeReleasedSegments.Add(nextSegmentW); // Return values outerNodeW = networkDictionary.RegisterNode(outerNodeId); endDirection = directions; /* After merging the roads, we release the segment and intersection inbetween. When I was debugging this method, I tried to release them after * everything is done. It might not be necessary.*/ return(true); }
/* Old algorithm. Originally intended only for circles. From older documentation: */ /* "For now, the intersection isn't created at the exact point where the segment crosses the circle, but rather on the intersection of * the circle and straight line, which goes from origin and ends at outer node of that segment. That could be unfortunately very * inaccurate, as the first note outside the circle could be quite far away". */ private void SnappingAlgorithmOld() { float centerX = CenterNode.m_position.x; float centerY = CenterNode.m_position.y; float centerZ = CenterNode.m_position.z; for (int i = 0; i < traveller.OuterNodes.Count; i++) { NetNode curNode = NetUtil.Node(traveller.OuterNodes[i]); Vector3 circleIntersection = new Vector3(); float directionX = (curNode.m_position.x - centerX) / VectorDistance(CenterNode.m_position, curNode.m_position); float directionZ = (curNode.m_position.z - centerZ) / VectorDistance(CenterNode.m_position, curNode.m_position); float radius = (float)ellipse.RadiusAtAbsoluteAngle(Math.Abs(Ellipse.VectorsAngle(curNode.m_position - ellipse.Center))); if (radius > 10000) { throw new Exception("Algortithm error"); } circleIntersection.x = (directionX * radius + centerX); circleIntersection.y = centerY; circleIntersection.z = (directionZ * radius + centerZ); WrappedNode newNode; WrappedSegment newSegment; newNode = new WrappedNode(); newNode.NetInfo = CenterNode.Info; newNode.Position = circleIntersection; RoundaboutNode raNode = new RoundaboutNode(newNode); raNode.Create(ActionGroupRoads); Intersections.Add(raNode); //EllipseTool.Instance.debugDrawPositions.Add(Intersections.Last().vector); NetSegment curSegment = NetUtil.Segment(traveller.OuterSegments[i]); /* For now ignoring anything regarding Y coordinate */ //float directionY2 = (GetNode(newNodeId).m_position.y - curNode.m_position.z) / NodeDistance(GetNode(newNodeId), curNode); float directionY2 = 0f; Vector3 startDirection = new Vector3(); startDirection.x = (directionX /** NodeDistance( GetNode( newNodeId ), curNode ) / 2*/); startDirection.y = directionY2; startDirection.z = (directionZ /** NodeDistance(GetNode(newNodeId), curNode) / 2*/); Vector3 endDirection = new Vector3(); endDirection.x = -startDirection.x; endDirection.y = -startDirection.y; endDirection.z = -startDirection.z; bool invert; //Debug.Log(string.Format("same node: {0}, invert: {1}", curSegment.m_startNode == traveller.OuterNodes[i], curSegment.m_flags.IsFlagSet(NetSegment.Flags.Invert))); if (curSegment.m_startNode == traveller.OuterNodes[i] ^ curSegment.m_flags.IsFlagSet(NetSegment.Flags.Invert)) { invert = true; } else { invert = false; } newSegment = new WrappedSegment(); newSegment.StartNode = newNode; newSegment.EndNode = networkDictionary.RegisterNode(traveller.OuterNodes[i]); newSegment.StartDirection = startDirection; newSegment.EndDirection = endDirection; newSegment.NetInfo = curSegment.Info; newSegment.Invert = invert; ActionGroupRoads.Actions.Add(newSegment); ActionGroupTMPE.Actions.Add(new EnteringBlockedJunctionAllowedAction(newSegment, true, true)); ActionGroupTMPE.Actions.Add(new YieldSignAction(newSegment, true)); //Debug.Log(string.Format("Segment and node created... ")); } }