7
\$\begingroup\$

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 Nodes 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 Segments. It's important that if I do this and I have a reference to this object in, say, a Polygon (made up of LineSegments 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 Nodes 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 Segments or SingleEndSegments which connect at it:

public class Node
{
      private vector m_point;
      private List<Segment> m_links;
}

As Intersections of Circles and Lines are key to my main geometry focus, I must derive an Intersection class from Node which also defines the two Curves which pass through it (though they would perhaps also be available through the Segments).

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 Nodes 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 Segments:

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 Segments 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 Segments.

\$\endgroup\$
  • \$\begingroup\$ Consider using auto-properties with get; private set; in the Segment 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\$ – Leonid Mar 22 '12 at 19:10
  • \$\begingroup\$ Just a question, Have you looked at WPF? Path in the WPF is not sufficient for what you need? I am just asking so we don't reinvent the wheel. \$\endgroup\$ – Arjang Mar 23 '12 at 22:47
  • \$\begingroup\$ This is a heck of a project. Take a look at the implementation of the Asymptote language / tool. sourceforge.net/scm/?type=svn&group_id=120000 \$\endgroup\$ – Leonid Mar 24 '12 at 1:00
1
\$\begingroup\$

First of all I really would like to have a good computational library in C#, will be your OS? Anyway my two cents:

  • I really appreciate the fact you are considering circular segmants to ( arcs ), if you manage to use it properly everywere ( distance/intersection, offseting ) this would be great.
  • I'm not sure I want all the object in that library deriving from shape, leave object for the algorithms, try to keep the geometrics entities as small as possible

  • The pat too, leave it as an entity apart. It will be something like a linked list ( leveraging the fact the end point of a single segment is necessarily the start of the next one ) and differentiate each segment type ( line, arc ) with a plain old enum. This probably will sound as a not good OOP, but trust me it will pay back much more.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.