using Microsoft.Msagl.Core.Geometry;
using Microsoft.Msagl.Core.Geometry.Curves;
namespace Microsoft.Msagl.Routing.Rectilinear.Nudging {
///
/// A place holder for an edge in a path to keep it inside of a linked list representing a path.
/// Each PathEdge belongs to only one path
///
/// PathEdge passes through the AxisEdge that it points to but may go to the different direction.
/// In the last case the PathEdge is marked as Reversed. Several PathEdges can share the same AxisEdge.
internal class PathEdge {
internal AxisEdge AxisEdge { get; set; }
internal PathEdge Next { get; set; }
internal PathEdge Prev { get; set; }
internal double Width { get; set; }
internal Path Path { get; set; }
#if TEST_MSAGL
public override string ToString() {
return Source + " " + Target;
}
#endif
internal PathEdge(AxisEdge edgeForNudging, double width) {
AxisEdge = edgeForNudging;
Width = width;
}
LongestNudgedSegment longestNudgedSegment;
///
/// It is the offset of the edge from the underlying line segment
/// [VisibilityEdge.SourcePoint, VisibilityEdge.TargetPoint] in to the direction of the VisibilityEdge.Perpendicular.
/// Offset holder is the same for the maximal parallel sequence of connected PathEdges
///
internal LongestNudgedSegment LongestNudgedSegment {
get { return longestNudgedSegment; }
set {
longestNudgedSegment = value;
if (longestNudgedSegment != null){
longestNudgedSegment.AddEdge(this);
AxisEdge.AddLongestNudgedSegment(longestNudgedSegment);
}
}
}
///
/// A fixed edge cannot be shifted from its visibility edge; offset is always 0.
/// Such an edge can be, for example, a terminal edge going to a port.
///
internal bool IsFixed { get; set; }
internal Point Source {
get { return !Reversed? AxisEdge.SourcePoint: AxisEdge.TargetPoint; }
}
internal Point Target {
get { return Reversed ? AxisEdge.SourcePoint : AxisEdge.TargetPoint; }
}
static internal bool VectorsAreParallel(Point a, Point b) {
return ApproximateComparer.Close(a.X * b.Y - a.Y * b.X, 0);
}
public static bool EdgesAreParallel(PathEdge edge, PathEdge pathEdge) {
return VectorsAreParallel(edge.AxisEdge.TargetPoint-edge.AxisEdge.SourcePoint,
pathEdge.AxisEdge.TargetPoint-pathEdge.AxisEdge.SourcePoint);
}
internal Directions Direction { get { return Reversed ? CompassVector.OppositeDir(AxisEdge.Direction) : AxisEdge.Direction;} }
///
/// if set to true then in the path the edge is reversed
///
internal bool Reversed {get; set;}
int index=-1;//not set yet
///
/// the index of the edge in the order
///
internal int Index {
get { return index; }
set { index = value; }
}
}
}