protected void Stop() { if ( !capture ) { // we're not captured so ignore captureSpiro=null; return; } if ( current < 0 ) // nothing selected so ignore return; // make sure old and new get invalidated Invalidate(CurrentSpiro); Invalidate(captureSpiro); // replace current with the modified copy spiros[current]=captureSpiro; captureSpiro.Selected=true; // re-enable the animation animateTimer.Enabled=true; // tidy up capture=false; captureSpiro=null; // ensure bounds are updated and re-locate button // (spiro may have changed size) RecalcBounds(); UpdateFloatingButton(); }
/// Helper to invalidate a given spiro region private void Invalidate(SpiroInstance si) { Rectangle rc=CanvasToClient(si.BoundingRect); Invalidate(rc); }
/// Add a new spiro provided public void AddSpiro(SpiroInstance si) { spiros.Add(si); si.CycleComplete+=new EventHandler(SpiroCycleComplete); RecalcBounds(); Invalidate(); }
protected void Start(Point pt) { // hide the button spiroMenuButton.Enabled=false; spiroMenuButton.Visible=false; if ( spiroUnderCursor < 0 && current >= 0 ) { // deselect all spiros // (click in region outside any spiro) CurrentSpiro.Selected=false; SetCurrentSpiro(-1); Invalidate(); return; } pt=ClientToCanvas(pt); if ( spiroUnderCursor != current ) { // click on a new (different) spiro if ( current >= 0 ) // deactivate current CurrentSpiro.Selected=false; // activate this one SetCurrentSpiro(spiroUnderCursor); CurrentSpiro.Selected=true; // record the drag offset dragOffset=pt; dragOffset.Offset(-CurrentSpiro.Location.X, -CurrentSpiro.Location.Y); // not too sure why we do this if ( captureHitInfo == HitInfo.Curve ) captureHitInfo=HitInfo.Bounds; // create a clone to use to draw the highlight when dragging captureSpiro=CurrentSpiro.Clone(); Invalidate(); // all done return; } if ( current < 0 ) // nothing selected so nothing to do - think this could be moved elsewhere return; // default case - click on current spiro // disable the animation // animateTimer.Enabled=false; // record the drag offset dragOffset=pt; dragOffset.Offset(-CurrentSpiro.Location.X, -CurrentSpiro.Location.Y); // record the hit info for the point clicked captureHitInfo=CurrentSpiro.HitTest(pt, HitTestMode.Selected); // create a clone for highlighting captureSpiro=CurrentSpiro.Clone(); capture=true; }
private void DrawHighlight(SpiroInstance si, Graphics g, HitInfo hi, bool showInfo) { // simple helper si.DrawHighlight(g, hi); if ( showInfo ) { Point pt=si.FocusRect.Location; pt.Offset(2,2); si.DrawInfo(g, pt, Color.Gray); } }
public bool IntersectsAny(SpiroInstance test) { foreach ( SpiroInstance si in spiros ) { if ( si.Equals(test) ) continue; if ( si.BoundingRect.IntersectsWith(test.BoundingRect) ) { return true; } } return false; }
private void AutoRandom(SpiroInstance si) { while ( true ) { si.ResetRandom(); si.Colour=RandomColour(); si.Location=RandomLocation(); si.Speed=RandomSpeed(); si.PenWidth=RandomLineThickness(); if ( !spiroCanvas1.IntersectsAny(si) ) break; } }
public void Clone(SpiroInstance from) { // copy all properties from the other spiro this.location=from.location; this.R=from.R; this.r=from.r; this.f=from.f; this.counter=from.counter; // we can copy the points since they are essentially immutable // (if this spiro is changed in any way a new array is created) this.points=from.points; this.penWidth=from.penWidth; this.revolutions=from.revolutions; this.resolution=from.resolution; this.selected=from.selected; this.complete=from.complete; this.animate=from.animate; this.repeat=from.repeat; this.randomise=from.randomise; this.showInfo=from.showInfo; this.showTrace=from.ShowTrace; this.colour=from.colour; this.baseAngle=from.baseAngle; this.baseMovingAngle=from.baseMovingAngle; this.speed=from.speed; this.MaxRandomDiameter=from.MaxRandomDiameter; // only need to reset if we're a different type (ie. different points) if ( this.GetType() != from.GetType() ) Reset(); // ensure the circle sizes are valid if ( R < MinFixedRadius ) { R=MinFixedRadius; Reset(); } // it's not actually necessary to do this if ( r > MaxMovingRadius ) { r=MaxMovingRadius; Reset(); } }
public void Resize(SpiroInstance current, int delta) { // this is a bit tricky - we need to resize both circles but give the same // (integer) ratio between them // in order to do this, each circle must increase/decrease by a multiple // of GCD(r,R)/size, ie. GCD(r,R)/R or GCD(r,R)/r // so we use the fixed circle as a base if ( delta == 0 ) return; int d=current.R + delta; int multiple_R=R/GCD(r,R); int multiple_r=r/GCD(r,R); int new_R=(int) Math.Round((double) d/multiple_R)*multiple_R; int new_r=new_R * multiple_r / multiple_R; int new_f=(int) Math.Round(1.0 * f * (float) new_R / R); if ( new_R < 5 || new_r < 5 ) // too small return; if ( new_R == R && new_r == r ) return; SaveMovingAngle(); R=new_R; r=new_r; f=new_f; Reset(); }