ArrowItem.cs

Go to the documentation of this file.
00001 /*
00002 NPlot - A charting library for .NET
00003 
00004 ArrowItem.cs
00005 Copyright (C) 2003
00006 Matt Howlett
00007 
00008 Redistribution and use of NPlot or parts there-of in source and
00009 binary forms, with or without modification, are permitted provided
00010 that the following conditions are met:
00011 
00012 1. Re-distributions in source form must retain at the head of each
00013    source file the above copyright notice, this list of conditions
00014    and the following disclaimer.
00015 
00016 2. Any product ("the product") that makes use NPlot or parts 
00017    there-of must either:
00018   
00019     (a) allow any user of the product to obtain a complete machine-
00020         readable copy of the corresponding source code for the 
00021         product and the version of NPlot used for a charge no more
00022         than your cost of physically performing source distribution,
00023             on a medium customarily used for software interchange, or:
00024 
00025     (b) reproduce the following text in the documentation, about 
00026         box or other materials intended to be read by human users
00027         of the product that is provided to every human user of the
00028         product: 
00029    
00030               "This product includes software developed as 
00031               part of the NPlot library project available 
00032               from: http://www.nplot.com/" 
00033 
00034         The words "This product" may optionally be replace with 
00035         the actual name of the product.
00036 
00037 ------------------------------------------------------------------------
00038 
00039 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00040 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00041 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00042 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00043 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00044 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00045 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00046 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00047 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00048 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00049 
00050 */
00051 
00052 using System;
00053 using System.Drawing;
00054 
00055 namespace NPlot
00056 {
00057 
00065         public class ArrowItem : IDrawable
00066         {
00067 
00068                 private void Init()
00069                 {
00070                         FontFamily fontFamily = new FontFamily("Arial");
00071                         font_ = new Font(fontFamily, 10, FontStyle.Regular, GraphicsUnit.Pixel);
00072                 }
00073 
00074 
00081                 public ArrowItem( PointD position )
00082                 {
00083                         to_ = position;
00084                         Init();
00085                 }
00086 
00087 
00093                 public ArrowItem( PointD position, double angle )
00094                 {
00095                         to_ = position;
00096                         angle_ = -angle;
00097                         Init();
00098                 }
00099 
00100 
00107                 public ArrowItem( PointD position, double angle, string text )
00108                 {
00109                         to_ = position;
00110                         angle_ = -angle;
00111                         text_ = text;
00112                         Init();
00113                 }
00114 
00115 
00119                 public string Text 
00120                 {
00121                         get
00122                         {
00123                                 return text_;
00124                         }
00125                         set
00126                         {
00127                                 text_ = value;
00128                         }
00129                 }
00130                 private string text_ = "";
00131 
00132 
00142                 public double Angle
00143                 {
00144                         get
00145                         {
00146                                 return -angle_;
00147                         }
00148                         set
00149                         {
00150                                 angle_ = -value;
00151                         }
00152                 }
00153                 private double angle_ = -45.0;
00154 
00155 
00159                 public float PhysicalLength
00160                 {
00161                         get
00162                         {
00163                                 return physicalLength_;
00164                         }
00165                         set
00166                         {
00167                                 physicalLength_ = value;
00168                         }
00169                 }
00170                 private float physicalLength_ = 40.0f;
00171 
00172 
00176                 public PointD To
00177                 {
00178                         get
00179                         {
00180                                 return to_;
00181                         }
00182                         set
00183                         {
00184                                 to_ = value;
00185                         }
00186                 }
00187                 private PointD to_;
00188 
00189 
00193                 public float HeadSize
00194                 {
00195                         get
00196                         {
00197                                 return headSize_;
00198                         }
00199                         set
00200                         {
00201                                 headSize_ = value;
00202                         }
00203                 }
00204                 private float headSize_ = 10.0f;
00205 
00206 
00210                 public float HeadAngle
00211                 {
00212                         get
00213                         {
00214                                 return headAngle_;
00215                         }
00216                         set
00217                         {
00218                                 headAngle_ = value;
00219                         }
00220                 }
00221                 private float headAngle_ = 40.0f;
00222 
00223 
00230                 public void Draw( System.Drawing.Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
00231                 {
00232             if (this.To.X > xAxis.Axis.WorldMax || this.To.X < xAxis.Axis.WorldMin)
00233                 return;
00234 
00235             if (this.To.Y > yAxis.Axis.WorldMax || this.To.Y < yAxis.Axis.WorldMin)
00236                 return;
00237 
00238             double angle = this.angle_;
00239 
00240                         if (this.angle_ < 0.0)
00241                         {
00242                                 int mul = -(int)(this.angle_ / 360.0) + 2;
00243                                 angle = angle_ + 360.0 * (double)mul;
00244                         }
00245 
00246                         double normAngle = (double)angle % 360.0;   // angle in range 0 -> 360.
00247 
00248                         Point toPoint = new Point( 
00249                                 (int)xAxis.WorldToPhysical( to_.X, true ).X,
00250                                 (int)yAxis.WorldToPhysical( to_.Y, true ).Y );
00251 
00252 
00253                         float xDir = (float)Math.Cos( normAngle * 2.0 * Math.PI / 360.0 );
00254                         float yDir = (float)Math.Sin( normAngle * 2.0 * Math.PI / 360.0 );
00255 
00256                         toPoint.X += (int)(xDir*headOffset_);
00257                         toPoint.Y += (int)(yDir*headOffset_);
00258 
00259                         float xOff = physicalLength_ * xDir;
00260                         float yOff = physicalLength_ * yDir;
00261 
00262                         Point fromPoint = new Point(
00263                                 (int)(toPoint.X + xOff),
00264                                 (int)(toPoint.Y + yOff) );
00265 
00266                         g.DrawLine( pen_, toPoint, fromPoint );
00267 
00268                         Point[] head = new Point[3];
00269 
00270                         head[0] = toPoint;
00271 
00272                         xOff = headSize_ * (float)Math.Cos( (normAngle-headAngle_/2.0f) * 2.0 * Math.PI / 360.0 );
00273                         yOff = headSize_ * (float)Math.Sin( (normAngle-headAngle_/2.0f) * 2.0 * Math.PI / 360.0 );
00274 
00275                         head[1] = new Point(
00276                                 (int)(toPoint.X + xOff),
00277                                 (int)(toPoint.Y + yOff) );
00278 
00279                         float xOff2 = headSize_ * (float)Math.Cos( (normAngle+headAngle_/2.0f) * 2.0 * Math.PI / 360.0 );
00280                         float yOff2 = headSize_ * (float)Math.Sin( (normAngle+headAngle_/2.0f) * 2.0 * Math.PI / 360.0 );
00281 
00282                         head[2] = new Point(
00283                                 (int)(toPoint.X + xOff2),
00284                                 (int)(toPoint.Y + yOff2) );
00285 
00286                         g.FillPolygon( arrowBrush_, head );
00287 
00288                         SizeF textSize = g.MeasureString( text_, font_ );
00289                         SizeF halfSize = new SizeF( textSize.Width / 2.0f, textSize.Height / 2.0f );
00290 
00291                         float quadrantSlideLength = halfSize.Width + halfSize.Height;
00292 
00293                         float quadrantF = (float)normAngle / 90.0f;       // integer part gives quadrant.
00294                         int quadrant = (int)quadrantF;            // quadrant in. 
00295                         float prop = quadrantF - (float)quadrant; // proportion of way through this qadrant. 
00296                         float dist = prop * quadrantSlideLength;          // distance along quarter of bounds rectangle.
00297                         
00298                         // now find the offset from the middle of the text box that the
00299                         // rear end of the arrow should end at (reverse this to get position
00300                         // of text box with respect to rear end of arrow).
00301                         //
00302                         // There is almost certainly an elgant way of doing this involving
00303                         // trig functions to get all the signs right, but I'm about ready to 
00304                         // drop off to sleep at the moment, so this blatent method will have 
00305                         // to do.
00306                         PointF offsetFromMiddle = new PointF( 0.0f, 0.0f );
00307                         switch (quadrant)
00308                         {
00309                                 case 0:
00310                                         if (dist > halfSize.Height)
00311                                         {
00312                                                 dist -= halfSize.Height;
00313                                                 offsetFromMiddle = new PointF( -halfSize.Width + dist, halfSize.Height );
00314                                         }
00315                                         else
00316                                         {
00317                                                 offsetFromMiddle = new PointF( -halfSize.Width, - dist );
00318                                         }
00319                                         break;
00320 
00321                                 case 1:
00322                                         if (dist > halfSize.Width)
00323                                         {
00324                                                 dist -= halfSize.Width;
00325                                                 offsetFromMiddle = new PointF( halfSize.Width, halfSize.Height - dist );
00326                                         }
00327                                         else
00328                                         {
00329                                                 offsetFromMiddle = new PointF( dist, halfSize.Height );
00330                                         }
00331                                         break;
00332 
00333                                 case 2:
00334                                         if (dist > halfSize.Height)
00335                                         {
00336                                                 dist -= halfSize.Height;
00337                                                 offsetFromMiddle = new PointF( halfSize.Width - dist, -halfSize.Height );
00338                                         }
00339                                         else
00340                                         {
00341                                                 offsetFromMiddle = new PointF( halfSize.Width, -dist );
00342                                         }
00343 
00344                                         break;
00345 
00346                                 case 3:
00347                                         if (dist > halfSize.Width)
00348                                         {
00349                                                 dist -= halfSize.Width;
00350                                                 offsetFromMiddle = new PointF( -halfSize.Width, -halfSize.Height + dist );
00351                                         }
00352                                         else
00353                                         {
00354                                                 offsetFromMiddle = new PointF( -dist, -halfSize.Height );
00355                                         }
00356 
00357                                         break;
00358 
00359                                 default:
00360                                         throw new NPlotException( "Programmer error." );
00361 
00362                         }
00363 
00364                         g.DrawString( 
00365                                 text_, font_, textBrush_,
00366                                 (int)(fromPoint.X - halfSize.Width - offsetFromMiddle.X),
00367                                 (int)(fromPoint.Y - halfSize.Height + offsetFromMiddle.Y) );
00368 
00369                 }
00370 
00371 
00375                 public Brush TextBrush
00376                 {
00377                         get
00378                         {
00379                                 return textBrush_;
00380                         }
00381                         set
00382                         {
00383                                 textBrush_ = value;
00384                         }
00385                 }
00386 
00387         
00391                 public Color TextColor
00392                 {
00393                         set
00394                         {
00395                                 textBrush_ = new SolidBrush( value );
00396                         }
00397                 }
00398 
00399 
00403                 public Color ArrowColor
00404                 {
00405                         get
00406                         {
00407                                 return pen_.Color;
00408                         }
00409                         set
00410                         {
00411                                 pen_.Color = value;
00412                                 arrowBrush_ = new SolidBrush( value );
00413                         }
00414                 }
00415                         
00416                 
00420                 public Font TextFont
00421                 {
00422                         get
00423                         {
00424                                 return this.font_;
00425                         }
00426                         set
00427                         {
00428                                 this.font_ = value;
00429                         }
00430                 }
00431 
00432 
00436                 public int HeadOffset
00437                 {
00438                         get
00439                         {
00440                                 return headOffset_;
00441                         }
00442                         set
00443                         {
00444                                 headOffset_ = value;
00445                         }
00446                 }
00447                 private int headOffset_ = 2;
00448 
00449 
00450                 private Brush arrowBrush_ = new SolidBrush( Color.Black );
00451                 private Brush textBrush_ = new SolidBrush( Color.Black );
00452                 private Pen pen_ = new Pen( Color.Black );
00453                 private Font font_;
00454         }
00455 }

Generated on Sat Nov 5 01:04:05 2005 for NPlot by  doxygen 1.4.5