Live Geometry Documentation
- Contributing - contributing to the project, working with source control
- CodingGuidelines - the project's coding guidelines
The project is built using Visual Studio 2008 with Silverlight Tools installed (currently Silverlight 3.0). The language is C# 3.0, and the projects exist that target both WPF (.NET Framework 3.5) and Silverlight 3.0. Same source code files are used for WPF and Silverlight versions.
Source code overview
The source code (Main
) consists of several projects:
The dynamic geometry library (framework) that provides types and services to model geometric figures and drawings.
DynamicGeometry.csproj is the WPF (desktop) project, and SilverlightDynamicGeometry.csproj is the Silverlight project. They both reference the same set of .cs files.
Silverlight client application (front-end) for the Dynamic Geometry library.
WPF (desktop) version. It is currently less maintained and I concentrate more efforts on the Silverlight version. It doesn't expose all the feature that are available in the DynamicGeometryLibrary yet. I will come back to WPF at a later point and update it to surface more features and to reach parity with Silverlight client.
Samples folder currently contains one sample application that is built on top of the dynamic geometry library. It is called PolylineRouting and it is a simple app that connects two dots with the shortest path around a polygon. Read more here: http://blogs.msdn.com/kirillosenkov/archive/2009/06/07/algorithms-in-c-shortest-path-around-a-polygon-polyline-routing.aspx
The central class of the DynamicGeometry library is a Drawing. A Drawing represents a set of figures as a logical entity. It's not a WPF/Silverlight control, so you can't directly place a Drawing on a Canvas. Instead, you can associate a Drawing with any existing Canvas control. A Drawing HAS a Canvas, not Drawing IS Canvas.
A Drawing references several other parts, such as a RootFigureList, an ActionManager, a Behavior, a CoordinateSystem, a CoordinateGrid (CartesianGrid) etc.
To experiment with hosting a Drawing on your own Canvas, you can view the PolylineRouting sample: Main\Samples\PolylineRouting\Page.xaml.cs
A FigureList is a list of figures in a Drawing. Actually, Drawing references a derived class called RootFigureList.
Dynamic geometry stores an algorithm of a construction, and figure coordinates are recalculated every time a drawing is changed. All the figures are classified into three groups: independent, semi-dependent and dependent.
- Figures can be independent of other figures, for instance a point can exist all by itself and its coordinates are determined by the user who drags the point around.
- Other figures can be partially dependent on other figures (for example, a point on a line can be both dragged by the user or moved with the line as the line moves around).
- Finally, a figure can be fully dependent on other figures. For example, a segment is fully defined by two points, so the user has no way of influencing the segment other than moving its endpoints. A caveat here is that if you drag a dependent figure, the dynamic geometry engine computes the least set of independent figures that fully defines the one the user is dragging, and drags this set, so the user has the impression of dragging the figure itself.
- Independent figures are: Point, Label, Hyperlink, FunctionGraph.
- Semi-dependent figure is: PointOnFigure.
- All other figures are dependent (e.g. Segment, Line, Circle, IntersectionOfCircleAndLine, Polygon, CoordinatesMeasurement, etc.)
A figure can have dependencies (figures it depends on) and dependents (figures that are depending on it). This relationship can be modeled using "in" and "out" edges of a dependency graph. The dependency graph doesn't have cycles, so it's really a DAG
Since all the figures form a DAG with respect to the dependency relationship, we sort the figures using topological sorting
. Here's an example of the DAG for a circle circumscribed around a triangle (dependencies are in parentheses):
4. Segment (1, 2)
5. Segment (2, 3)
6. Segment (1, 3)
7. Midpoint (1, 2)
8. Midpoint (1, 3)
9. Perpendicular (7, 4)
10. Perpendicular (8, 6)
11. Intersection (9, 10)
12. Circle (11, 1)
This is sufficient description to fully define the drawing given the coordinates of the first three points as input. The coordinates of all figures are recalculated every time an independent or semi-dependent figure has been moved by user. Figures are recalculated in topological order (top-to-bottom in our example). Topological order means that all dependencies of each figure come before it (and all dependents come after it). A drawing is usually fully defined by several independent figures (points).
Each figure (IFigure) has a property called Dependencies, which is a list of figures that the current figure depends on. Also each figure has a property called Dependents which stores all figures that directly depend on this one. When a new figure is created, a RegisterWithDependencies() method is called, that fills the new figure's Dependencies list and then goes through all the figures in it and adds the new figure to their Dependents list. So the relationship is bi-directional.
The TopologicalSort method is used to sort all figures topologically with regards to the dependency relationship. You can read more at : http://blogs.msdn.com/kirillosenkov/archive/2008/08/10/representing-dependencies-in-code.aspx
The Silverlight client exposes a feature that allows the user to plot function graphs given a string such as "sin(x)" or "x*2 + 3". To evaluate arithmetical expression, we host the DLR and piggyback on its ability to compile a string to an executable delegate. Read more at: http://blogs.msdn.com/kirillosenkov/archive/2009/03/26/dlr-hosting-in-silverlight.aspx