I'm trying to implement a custom made 2D geometry library. Originally I was looking at the problem of intersections of many circles but wanted to widen the scope of the code to deal with many future geometry based problems.
I already have a vector (2D) class defined. I wish to derive all my other geometrical entities from Shape
. These will include 0D objects, 1D objects (and 2D objects, though i think this is best achieved through a custom made IArea
interface supported by for example closed loops (1D objects) and special polygons, figures (i.e. Circle
)).
In this question I want to focus on the best way to define a 1D Path, but first my definitions for 0D objects.
Node
will be my 0D base class Segment
(Node
to Node
), SingleEndSegment
(Node
to infinity) and Curve
(no nodes) will be my 1D base classes (I have some misgivings over the best way to define these). The links between Node
s can be line vectors, circular arcs, any type of curve function really, though initially just lines and circular arcs.
One important point to note hear is that I'd like Segment
and SingleEndSegment
to be free from Internal Nodes. Meaning, if I want to add a Node
along a Segment
, I need to convert it to two Segment
s. It's important that if I do this and I have a reference to this object in, say, a Polygon
(made up of LineSegment
s derived from Segment
), then the Polygon
object takes account of this change. On the other hand, I'd like curves to contain a list of Node
s along them (i.e. a Line
has a reference list of its intersections).
Thinking about this now, I am not sure whether to derive the Segment
classes and SingleEndSegment
classes from Curve
classes (i.e. LineSegment : Line : Shape and ArcSegment : Circle : Shape
) or in my current approach from an abstract Segment
class. I can't have both without perhaps creating a Segment
interface.
I will define a Node
to contain a vector and an ordered List
of the Segment
s or SingleEndSegments
which connect at it:
public class Node
{
private vector m_point;
private List<Segment> m_links;
}
As Intersection
s of Circle
s and Line
s are key to my main geometry focus, I must derive an Intersection
class from Node
which also defines the two Curve
s which pass through it (though they would perhaps also be available through the Segment
s).
public class Intersection : Node
{
private Curve[] m_curves = new Curve[2];
//some code
}
Now onto the 1D objects (I have Start
and End
because I may consider some notion of direction at a later date):
public abstract class Segment : Shape
{
private Node m_start;
private Node m_end;
public Node Start
{
get { return m_start; }
set { m_start = value; }
}
public Node End
{
get { return m_end; }
set { m_end = value; }
}
public Segment() : base()
{
Start = null;
End = null;
}
public Segment(Node s, Node e) : base()
{
Start = s;
End = e;
}
}
An example of a derived class would be:
public class LineSegment : Segment
{
private vector m_vector;
public vector Vec
{
get { return m_vector; }
set { m_vector = value; }
}
}
Note that in my current implementation I have a vector whereas, I could have LineSegment
contain a Line
(which naturally possesses the vector of its direction).
But I'd also like to have a derived abstract class called IntersectionSegment
between two known intersection points (to be the base of IntersectionLineSegment
). I could do this as follows, but would ideally prefer to deal with the Node
s being Intersections in a better way. How can I best do that?
public abstract class IntersectionSegment : Segment
{
private Intersection m_inters_start;
public Intersection Start
{
get { return m_inters_start; }
set { m_inters_start = value; }
}
}
Not ideal.
Now the main trouble I'm having comes in defining a Path
as a collection of Segment
s:
public class Path<T> : IEnumerable<T> where T : Segment
{
private List<T> segments = new List<T>();
public List<T> Segments
{
set { segments = value;}
get { return this.segments; }
}
public T this[int pos]
{
get { return (T)segments[pos]; }
set { segments[pos] = value; }
}
public Path()
{
this.Segments = new List<T>();
}
public Path(List<T> s)
{
this.Segments = s;
}
public void AddSegment(T s) {Segments.Add(s);}
public int Count {get {return Segments.Count;}}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{ return Segments.GetEnumerator();}
IEnumerator IEnumerable.GetEnumerator()
{ return Segments.GetEnumerator(); }
}
I'm having major problems working out how to define derived types from this Path
and how to use this generic Path in an efficient way.
One key method I wish to implement is an Intersection
(method here not 0D object defined above) of say a Line
with a (closed) Path
. I'll need to check the Intersection
with all Segment
s and I'd like to under certain conditions replace a Segment
within a Path
with a LineSegment
and an altered version of the existing Segment
, maintaining the order of the Path
Segment
s.
get; private set;
in theSegment
class. I would also chain constructors like so:public Segment() : this(s: null, e: null)
. Finally, can you post at least the signature of the methods that you need to create? Not many people will read this question in its entirety. \$\endgroup\$