private static bool CanNodeBranchInDirection(ushort nodeId, Vector3 direction) { var closestSegmentId = NetNodeUtility.GetClosestSegmentId(nodeId, direction); var exitDirection = NetNodeUtility.GetSegmentExitDirection(nodeId, closestSegmentId); var exitAngle = Vector3Extensions.GetSignedAngleBetween(direction.Flatten(), exitDirection.Flatten(), Vector3.up); return(Mathf.Abs(exitAngle) >= 45f); }
public static NetTool.ControlPoint SnapDirectionOverride(NetTool.ControlPoint newPoint, NetTool.ControlPoint oldPoint, NetInfo info, out bool success, out float minDistanceSq) { if (Debug.Enabled) { DebugPrint = string.Format("oldPoint: {0}\nnewPoint:{1}", StringUtil.ToString(oldPoint), StringUtil.ToString(newPoint)); } GuideLines.Clear(); SnappedGuideLine = null; minDistanceSq = info.GetMinNodeDistance(); minDistanceSq = minDistanceSq * minDistanceSq; var controlPoint = newPoint; success = false; if (EnableSnapping) { // If dragging from a node if (oldPoint.m_node != 0 && !newPoint.m_outside) { // Node the road build operation is starting from var sourceNodeId = oldPoint.m_node; var sourceNode = NetManager.instance.m_nodes.m_buffer[sourceNodeId]; // Direction and length of the line from the node to the users control point var userLineDirection = (newPoint.m_position - sourceNode.m_position).Flatten(); var userLineLength = userLineDirection.magnitude; userLineDirection.Normalize(); var closestSegmentId = NetNodeUtility.GetClosestSegmentId(sourceNodeId, userLineDirection); if (closestSegmentId > 0) { // Snap to angle increments originating from this closest segment var closestSegmentDirection = NetNodeUtility.GetSegmentExitDirection(sourceNodeId, closestSegmentId); var currentAngle = Vector3Extensions.Angle(closestSegmentDirection, userLineDirection, Vector3.up); var snappedAngle = Mathf.Round(currentAngle / Settings.SnapAngle) * Settings.SnapAngle; var snappedDirection = Quaternion.AngleAxis(snappedAngle, Vector3.up) * closestSegmentDirection; controlPoint.m_direction = snappedDirection.normalized; controlPoint.m_position = sourceNode.m_position + userLineLength * controlPoint.m_direction; controlPoint.m_position.y = newPoint.m_position.y; minDistanceSq = (newPoint.m_position - controlPoint.m_position).sqrMagnitude; success = true; //minDistanceSq = olpo; } } else if (oldPoint.m_segment != 0 && !newPoint.m_outside) { // Else if dragging from a segment // Segment the road build operation is starting from var sourceSegmentId = oldPoint.m_segment; var sourceSegment = NetManager.instance.m_segments.m_buffer[sourceSegmentId]; Vector3 segmentDirection; Vector3 segmentPosition; // Direction and length of the line between control points var userLineDirection = (newPoint.m_position - oldPoint.m_position).Flatten(); var userLineLength = userLineDirection.magnitude; userLineDirection.Normalize(); // Get direction of the segment at the branch position sourceSegment.GetClosestPositionAndDirection(oldPoint.m_position, out segmentPosition, out segmentDirection); var currentAngle = Vector3Extensions.Angle(segmentDirection, userLineDirection, Vector3.up); segmentDirection = segmentDirection.Flatten().normalized; var snappedAngle = Mathf.Round(currentAngle / Settings.SnapAngle) * Settings.SnapAngle; var snappedDirection = Quaternion.AngleAxis(snappedAngle, Vector3.up) * segmentDirection; controlPoint.m_direction = snappedDirection.normalized; controlPoint.m_position = oldPoint.m_position + userLineLength * controlPoint.m_direction; controlPoint.m_position.y = newPoint.m_position.y; minDistanceSq = (newPoint.m_position - controlPoint.m_position).sqrMagnitude; success = true; } else if (oldPoint.m_direction.sqrMagnitude > 0.5f) { if (newPoint.m_node == 0 && !newPoint.m_outside) { // Let's do some snapping between control point directions var currentAngle = Vector3Extensions.Angle(oldPoint.m_direction, newPoint.m_direction, Vector3.up); var snappedAngle = Mathf.Round(currentAngle / Settings.SnapAngle) * Settings.SnapAngle; var snappedDirection = Quaternion.AngleAxis(snappedAngle, Vector3.up) * oldPoint.m_direction.Flatten(); controlPoint.m_direction = snappedDirection.normalized; controlPoint.m_position = oldPoint.m_position + Vector3.Distance(oldPoint.m_position.Flatten(), newPoint.m_position.Flatten()) * controlPoint.m_direction; controlPoint.m_position.y = newPoint.m_position.y; success = true; } } else if (oldPoint.m_segment == 0 && oldPoint.m_node == 0 && newPoint.m_segment == 0 && oldPoint.m_segment == 0) { // Snap to angles based from north var userLineDirection = (newPoint.m_position - oldPoint.m_position).Flatten(); var userLineLength = userLineDirection.magnitude; userLineDirection.Normalize(); var snapDirection = Vector3.forward; var currentAngle = Vector3Extensions.Angle(snapDirection, userLineDirection, Vector3.up); var snappedAngle = Mathf.Round(currentAngle / Settings.SnapAngle) * Settings.SnapAngle; var snappedDirection = Quaternion.AngleAxis(snappedAngle, Vector3.up) * snapDirection; controlPoint.m_direction = snappedDirection.normalized; controlPoint.m_position = oldPoint.m_position + userLineLength * controlPoint.m_direction; controlPoint.m_position.y = newPoint.m_position.y; minDistanceSq = (newPoint.m_position - controlPoint.m_position).sqrMagnitude; success = true; } } else { // Run the default snapping Revert(); controlPoint = NetTool.SnapDirection(newPoint, oldPoint, info, out success, out minDistanceSq); Deploy(); } if (EnableAdvancedSnapping) { if (controlPoint.m_segment == 0 && controlPoint.m_node == 0) { controlPoint = SnapDirectionGuideLines(controlPoint, oldPoint, info, ref success, ref minDistanceSq); } } return(controlPoint); }
public static void CalculateAngles(ushort nodeId, Vector3 direction, ICollection <Measurement> measurements) { direction = direction.Flatten(); var node = NetManager.instance.m_nodes.m_buffer[nodeId]; var existingSegments = NetNodeUtility.GetNodeSegmentIds(node); if (existingSegments.Count == 0) { return; } var nearestLeftAngle = 360f; ushort nearestLeftSegmentId = 0; var nearestLeftNormal = Vector3.zero; var nearestRightAngle = 360f; ushort nearestRightSegmentId = 0; var nearestRightNormal = Vector3.zero; for (var i = 0; i < existingSegments.Count; i++) { var s = NetManager.instance.m_segments.m_buffer[existingSegments[i]]; var d = s.m_startNode == nodeId ? s.m_startDirection : s.m_endDirection; d = d.Flatten(); var angle = Vector3Extensions.GetClockwiseAngleBetween(-d, direction, Vector3.up); var leftAngle = 360f - angle; var rightAngle = angle; var n = Vector3.Normalize(direction + d); if (leftAngle < nearestLeftAngle) { nearestLeftAngle = leftAngle; nearestLeftSegmentId = existingSegments[i]; nearestLeftNormal = Quaternion.AngleAxis(leftAngle * 0.5f, Vector3.up) * direction; } if (rightAngle < nearestRightAngle) { nearestRightAngle = rightAngle; nearestRightSegmentId = existingSegments[i]; nearestRightNormal = Quaternion.AngleAxis(rightAngle * -0.5f, Vector3.up) * direction; } } // When both angles are 180, only show the one on the right. if (Math.Abs(nearestLeftAngle - 180f) < 0.25f && Math.Abs(nearestRightAngle - 180f) < 0.25f) { measurements.Add(new AngleMeasurement(nearestRightAngle, node.m_position, nearestRightNormal, MeasurementFlags.Primary)); return; } var leftFlags = nearestRightSegmentId > 0 ? (nearestLeftAngle < nearestRightAngle ? MeasurementFlags.Primary : MeasurementFlags.Secondary) : MeasurementFlags.Secondary; var rightFlags = nearestLeftSegmentId > 0 ? (nearestRightAngle <= nearestLeftAngle ? MeasurementFlags.Primary : MeasurementFlags.Secondary) : MeasurementFlags.Secondary; if (nearestLeftSegmentId > 0) { measurements.Add(new AngleMeasurement(nearestLeftAngle, node.m_position, nearestLeftNormal, leftFlags)); } if (nearestRightSegmentId > 0) { measurements.Add(new AngleMeasurement(nearestRightAngle, node.m_position, nearestRightNormal, rightFlags)); } }