Example #1
0
 GraphComponent ComposeRendering(GraphComponent component, Strand strand, double y0 = 0)
 // We render a strand as a linear sequence of spring-separated particles.
 // We initially lay things out in a linear line, either to the right (for 
 // normally oriented strands) or left (for reverse oriented strands).
     {
     if (null==component)
         component = new GraphComponent(this);
     //
     // Compose edges for domains along the strand backbone
     // 
     List<GraphVertex> strandVertices = new List<GraphVertex>();
     List<GraphEdge>   strandEdges    = new List<GraphEdge>();
     //
     double count  = strand.AllDomains().Count();
     double length = strand.AllDomains().Sum(d => this.EdgeFromDomain(component, d).PreferredLength);
     double radius = length / 2.0 / Math.PI;
     //
     radius /= 3; // hack -> otherwise the forces pulling the circle together overshoot
     //
     int i = 0;
     foreach (Domain d in strand.AllDomains())
         {
         GraphEdge edge = this.EdgeFromDomain(component, d);
         strandEdges.Add(edge);
         //
         // The first vertex in the strand needs to be explicitly positioned
         //
         double x,y;
         //
         if (strandVertices.IsEmpty())
             {
             strandVertices.Add(edge.A);
             if (strand.IsCircular)
                 x = strand.Orientation==Strand.Direction.FiveToThree ? -radius : radius;
             else
                 x = 0;
             edge.A.SetLocation(x,y0);
             }
         //
         // Position the B vertex of the edge
         //
         if (strand.IsCircular)
             {
             double theta = i / count * 2 * Math.PI;
             x = radius * Math.Cos(theta);
             y = radius * Math.Sin(theta);
             if (strand.Orientation==Strand.Direction.FiveToThree)
                 {
                 x = -x;
                 y = -y;
                 }
             }
         else
             {
             y = y0; 
             x = edge.PreferredLength;
             if (strand.Orientation == Strand.Direction.ThreeToFive)
                 x = -x;
             x += strandVertices.Last().Location.X;
             }
         //
         edge.B.SetLocation(x, y);
         strandVertices.Add(edge.B);
         //
         i++;
         }
     //
     // Make a spline for the strand as a whole
     // 
     if (strandVertices.NotEmpty())
         {
         VisualStrand vStrand = new VisualStrand(strand, component, strandEdges, strandVertices);
         this.mpStrandVisualization[strand] = vStrand;
         //
         // Place ticks at the ends of each of the interior domains in the strand
         //
         for (i = strand.IsCircular ? 0 : 1; i < strandVertices.Count-1; i++)
             {
             new VisualDomainEndTick(component, vStrand, i, Constants.DomainEndLength);
             }
         //
         // Add domain labels and nucleotides
         //
         foreach (Domain d in strand.AllDomains())
             {
             i = d.StrandIndex;
             //
             VisualStrandLabel label = new VisualStrandLabel(component, vStrand, i, i+1, d.FullDisplayName, Constants.StyleDomainLabel);
             label.LabelType = VisualStrandLabel.LABELTYPE.DOMAIN;
             vStrand.NoteDomainLabel(i, label);
             //
             if (d.Nucleotides.Length > 0 && true)
                 {
                 label = new VisualStrandLabel(component, vStrand, i, i+1, d.Nucleotides, Constants.StyleNucleotides);
                 label.LabelType = VisualStrandLabel.LABELTYPE.NUCLEOTIDE;
                 label.FontVerticallyCentered = true;
                 label.AutoReverseText = true;
                 }
             }
         }
     //
     if (strandVertices.NotEmpty())
         {
         // Help a bit with initial placement: left align if we moved leftward
         // from zero due to strand direction.
         //
         if (!strand.IsCircular && strand.Orientation == Strand.Direction.ThreeToFive)
             {
             double dx = -strandVertices.Last().Location.X;
             foreach (GraphVertex v in strandVertices)
                 {
                 v.TranslateBy(dx, 0);
                 }
             }
         }
     //
     // Put in stiffness along the strand
     //
     foreach (Domain d in strand.AllDomains())
         {
         if (d.CircularNextTo5 != null)
             {
             GraphEdge curEdge  = this.EdgeFromDomain(component, d);
             GraphEdge prevEdge = this.EdgeFromDomain(component, d.CircularNextTo5);
             //
             new StraighteningForce(component, prevEdge.A, curEdge.A, curEdge.B, Constants.StraighteningStrength);
             }
         }
     //
     return component;
     }
Example #2
0
 public static PathFigure PathFigureFromPoints(IEnumerable<Point> points, bool isClosed) // REVIEW: General utility, should be elsewhere
     {
     List<Point> pathPoints = new List<Point>(points);
     Point ptFirst = new Point();
     if (pathPoints.NotEmpty())
         {
         ptFirst = pathPoints[0];
         pathPoints.RemoveAt(0);
         }
     //
     PathFigure pathFigure = new PathFigure();
     pathFigure.StartPoint = ptFirst;
     pathFigure.IsClosed = isClosed;
     //
     if (pathPoints.NotEmpty())
         {
         PolyLineSegment polyLineSegment = new PolyLineSegment();
         polyLineSegment.Points = new PointCollection(pathPoints);
         pathFigure.Segments.Add(polyLineSegment);
         }
     //
     return pathFigure;
     }