Logo Search packages:      
Sourcecode: latexdraw version File versions  Download package

Figure.java

package latexDraw.figures;

import static java.lang.Math.PI;
import static java.lang.Math.atan;
import static java.lang.Math.toDegrees;

import java.awt.*;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;

import javax.swing.JLabel;

import latexDraw.figures.properties.Arrowable;
import latexDraw.figures.properties.Drawable;
import latexDraw.lang.LaTeXDrawLang;
import latexDraw.psTricks.DviPsColors;
import latexDraw.psTricks.PSTricksConstants;
import latexDraw.ui.components.Delimitor;
import latexDraw.ui.components.LaTeXDrawComboBox;
import latexDraw.ui.components.LabelListCellRenderer;
import latexDraw.ui.components.MagneticGrid;
import latexDraw.util.LaTeXDrawException;
import latexDraw.util.LaTeXDrawPoint2D;
import latexDraw.util.LaTeXDrawResources;

/**
 * This class defines what it is, in general, a figure.<br>
 * <br>
 * This file is part of LaTeXDraw<br>
 * Copyright (c) 2005-2008 Arnaud BLOUIN<br>
 * <br>
 * LaTeXDraw is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.<br>
 * <br>
 * LaTeXDraw is distributed without any warranty; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.<br>
 * <br>
 * 03/17/2007<br>
 * @author Arnaud BLOUIN<br>
 * @version 2.0.0<br>
 */
00048 public abstract class Figure implements Serializable, Cloneable, Drawable
{
      private static final long serialVersionUID = 1L;
      
      /** The number by default of pixels per cm. */
00053       public static final int PPC = 50;
      
      /** Corresponds to the thickness of the borders of the figure (in pixels). */
00056       protected float thickness;

      /** Corresponds to the selected delimiter (if there is a one selected) */
00059       protected Delimitor dSelected;

      /** Allows to know if the figure is selected */
00062       protected boolean isSelected;

      /** Allows to know if the figure can be filled by a colour */
00065       protected boolean canBeFilled;

      /** Allows to know if the figure is filled by a colour */
00068       protected boolean isFilled;

      /** Allows to know if the thickness of the figure can be changed */
00071       protected boolean isThicknessable;

      /** Allows to know if the borders of the figure are movable */
00074       protected boolean isBordersMovable;

      /** The colour of the borders */
00077       protected Color linesColor;

      /** The colour of the interior of the figure */
00080       protected Color interiorColor;

      /** The number of the figure. */
00083       protected int number;

      /** The meter of figures */
00086       private static int meter = 0;

      /** Allows to know if the figure is customisable or not */
00089       protected boolean isCustomizable;

      /** Allows to know if the bounds are double */
00092       protected boolean hasDoubleBoundary;

      /** Allows to know if the figure can have double boundary */
00095       protected boolean isDoubleBoundaryable;

      /** The colour of the double boundary */
00098       protected Color doubleColor;

      /** The position of the double boundary */
00101       protected String bordersPosition;

      /** Allows to know if the figure can be dotted or dashed */
00104       protected boolean isDashableOrDotable;

      /** The colour of the hatch */
00107       protected Color hatchingColor;

      /** The angle of the hatch (in rad). */
00110       protected double hatchingAngle;

      /** The width of the lines of the hatch (in pixels). */
00113       protected float hatchingWidth;

      /** Allows to know if the figure is resizable or not */
00116       protected boolean isResizable;

      /** The kind of hatch used by the figure */
00119       protected String hatchingStyle;

      /** True if the figure has a shadow. */
00122       protected boolean hasShadow;
      
      /** The size of the shadow (in pixels). */
00125       protected double shadowSize;
      
      /** The angle of the shadow (in rad). */
00128       protected double shadowAngle;
      
      /** The colour of the shadow. */
00131       protected Color shadowColor;
      
      /** Define if the figure can have a shadow. */
00134       protected boolean canHaveShadow;
      
      /** The angle of the gradient (in rad). */
00137       protected double gradientAngle;
      
      /** The position of the midpoint, as a fraction of the distance from
            top to bottom. Should be between 0 and 1. */
00141       protected double gradientMidPoint;
      
      /** The first colour of the gradient. */
00144       protected Color gradientStartColor;
      
      /** The second colour of the gradient. */
00147       protected Color gradientEndColor;
      
      /** The position of the midpoint, as a fraction of the distance from
      top to bottom. Should be between 0 and 1. */
00151       public static final double DEFAULT_GRADIENT_MID_POINT = 1;
      
      /** The angle of the gradient in radian. */
00154       public static final double DEFAULT_GRADIENT_ANGLE = Math.toRadians(PSTricksConstants.DEFAULT_GRADIENT_ANGLE);
      
      /** The value by default of hasShadow. */
00157       public static final boolean DEFAULT_SHADOW_HAS =  PSTricksConstants.DEFAULT_SHADOW;
      
      /** The value by default of shadowSize (in pixels). */
00160       public static final double DEFAULT_SHADOW_SIZE =  PSTricksConstants.DEFAULT_SHADOW_SIZE*PPC;
      
      /** The value by default of shadowAngle (in rad). */
00163       public static final double DEFAULT_SHADOW_ANGLE =  Math.toRadians(PSTricksConstants.DEFAULT_SHADOW_ANGLE);
      
      /** The value by default of shadowAngle. */
00166       public static final Color DEFAULT_SHADOW_COLOR =  PSTricksConstants.DEFAULT_SHADOW_COLOR;
      
      /** The position by default of the double boundary */
00169       public static final String DEFAULT_BORDERS_POSITION = PSTricksConstants.BORDERS_INSIDE;

      /** The colour of the double boundary of the figure by default */
00172       public static final Color DEFAULT_DOUBLE_COLOR = PSTricksConstants.DEFAULT_DOUBLE_COLOR;

      /** The value by default of the attribute hasDoubleBoudary */
00175       public static final boolean DEFAULT_HAS_DOUBLE_BOUNDARY = false;

      /** The angle of the lines of the hatch by default */
00178       public static final double DEFAULT_HATCH_ANGLE = 0.;
      
      /** The size of the separation between the hatching by default. */
00181       public static final double DEFAULT_HATCH_SEP = PSTricksConstants.DEFAULT_HATCH_SEP*PPC;

      /** A figure is customisable by default ? */
00184       public static final boolean DEFAULT_IS_CUSTOMISABLE = true;

      /** The borders of the figure are movable by default */
00187       public static final boolean DEFAULT_IS_BORDERS_MOVABLE = true;

      /** The colour by default of the borders of the figure */
00190       public static final Color DEFAULT_BORDERS_COL = Color.BLACK;

      /** The colour by default of the interior of the figure */
00193       public static final Color DEFAULT_INTERIOR_COL = Color.WHITE;

      /** The colour by default of the hatch of the figure */
00196       public static final Color DEFAULT_HATCH_COL = Color.BLACK;

      /** The value by default of the attribute isThicknessable */
00199       public static final boolean DEFAULT_IS_THICKNESSABLE = true;

      /** value of the thickness by default (in pixels). */
00202       public static final float DEFAULT_THICKNESS = 2; 

      /** The style of the lines of the figure */
00205       protected String lineStyle;

      /** The style of lines by default */
00208       public static final String DEFAULT_LINE_STYLE = PSTricksConstants.LINE_NONE_STYLE;

      /** If a figure is filled by default */
00211       public static final boolean DEFAULT_IS_FILLED = false;

      /** The label of the ComboBox containing all kinds of hatches */
00214       public static final String LABEL_HATCH_CHOICE = "Hatch choice"; //$NON-NLS-1$

      /** The label of the field which allows to change the width of the hatch */
00217       public static final String LABEL_HATCH_WIDTH = "Hatch width"; //$NON-NLS-1$

      /** The label of the hatch used by default */
00220       public static final String DEFAULT_HATCH_STYLE = PSTricksConstants.TOKEN_FILL_NONE;

      /** The value by default of the width of the hatch (in pixels). */
00223       public static final float DEFAULT_HATCH_WIDTH = DEFAULT_THICKNESS;

      /** The value by default of the attribute isResizable */
00226       public static final boolean DEFAULT_ISRESIZABLE = true;

      /** The value by default of the attribute isHatched */
00229       public static final boolean DEFAULT_IS_HATCHED = false;

      /** The label of double boundary choice */
00232       public static final String LABEL_BORDERS_POSITION_CHOICE = LaTeXDrawLang.getOthersString("Figure.boundPos"); //$NON-NLS-1$

      /** The centre of the rotation */
00235       protected LaTeXDrawPoint2D gravityCenter;

      /** The angle of rotation (in rad) */
00238       public double rotationAngle;

      /** Allows to know if the figure is on rotation */
00241       protected boolean isOnRotation;

      /** The size of the separation between the double line in pixels */
00244       protected double doubleSep;

      /** The value by default of the attribute doubleLine */
00247       public static final boolean DEFAULT_DOUBLELINE = false;

      /** The value by default of the attribute doubleSep (in pixels). */
00250       public static final double DEFAULT_DOUBLESEP = 6;

      /** The angle of rotation by default */
00253       public static final double DEFAULT_ROTATION_ANGLE = 0.;

      public static final float DEFAULT_BLACK_DASH_LGTH = 8;

      public static final float DEFAULT_WHITE_DASH_LGTH = 8;

      /** The separator between dots by default (in pixels). */
00260       public static final float DEFAULT_DOT_SEP = 8;

      /** The length of the black dash of a line (in pixels). */
00263       protected float blackDashLength;

      /** The length of the white dash of a line (in pixels). */
00266       protected float whiteDashLength;

      /** The separation between two dots in a dotted line (in pixels). */
00269       protected float dotSep;

      /** The borders of the figure */
00272       protected LaTeXDrawRectangle borders;

      /** The shape of the figure */
00275       protected transient Shape shape; 

      /** The size of the separation between the hatching (in pixels). */
00278       protected double hatchingSep;
      
      /** Define if the shape can have arrows. */
00281       protected boolean canHaveArrow;
      
      /** The token used for Horizontal hatch in LaTeXDraw 1.5.1.1, 1.5.1 and 1.5.<br>
       * Useful to read file ldp of these versions of LaTeXDraw.*/
00285       public static final String DECREPETED_FILL_HORIZ = "Horizontal hatch";//$NON-NLS-1$
      
      /** The token used for Vertical hatch in LaTeXDraw 1.5.1.1, 1.5.1 and 1.5.<br>
       * Useful to read file ldp of these versions of LaTeXDraw.*/
00289       public static final String DECREPETED_FILL_VERT  = "Vertical hatch";//$NON-NLS-1$
      
      /** The token used for Cross hatch in LaTeXDraw 1.5.1.1, 1.5.1 and 1.5.<br>
       * Useful to read file ldp of these versions of LaTeXDraw.*/
00293       public static final String DECREPETED_FILL_CROSS = "Cross hatch";//$NON-NLS-1$
      
      /** The token used for No hatch in LaTeXDraw 1.5.1.1, 1.5.1 and 1.5.<br>
       * Useful to read file ldp of these versions of LaTeXDraw.*/
00297       public static final String DECREPETED_FILL_NO    = "No hatch";//$NON-NLS-1$

      public static final short DELIMITOR_ORIENTATION_NONE  = -1;
      
      public static final short DELIMITOR_ORIENTATION_WEST  = 0;
      
      public static final short DELIMITOR_ORIENTATION_EAST  = 2;
      
      public static final short DELIMITOR_ORIENTATION_NORTH = 3;
      
      public static final short DELIMITOR_ORIENTATION_SOUTH = 8;
      
      public static final short DELIMITOR_ORIENTATION_NW    = 4;
      
      public static final short DELIMITOR_ORIENTATION_SW    = 5;
      
      public static final short DELIMITOR_ORIENTATION_NE    = 6;
      
      public static final short DELIMITOR_ORIENTATION_SE    = 7;
      
      public static final short DELIMITOR_ROTATION          = 9;
      
      

      /**
       * The constructor.
       * @param increaseMeter If the figure must increase the meter of figure {@literal number}.
       */
00325       protected Figure(boolean increaseMeter)
      {
            canHaveArrow = false;
            hatchingSep = DEFAULT_HATCH_SEP;
            isBordersMovable = DEFAULT_IS_BORDERS_MOVABLE;
            bordersPosition = DEFAULT_BORDERS_POSITION;
            doubleColor = DEFAULT_DOUBLE_COLOR;
            isResizable = DEFAULT_ISRESIZABLE;
            doubleSep = DEFAULT_DOUBLESEP;
            isDashableOrDotable = true;
            isDoubleBoundaryable = true;
            isCustomizable = DEFAULT_IS_CUSTOMISABLE;
            isOnRotation = false;
            isThicknessable = DEFAULT_IS_THICKNESSABLE;
            rotationAngle = DEFAULT_ROTATION_ANGLE;
            isSelected = false;
            interiorColor = DEFAULT_INTERIOR_COL;
            linesColor = DEFAULT_BORDERS_COL;
            hatchingColor = DEFAULT_BORDERS_COL;
            hatchingStyle = DEFAULT_HATCH_STYLE;
            isFilled = DEFAULT_IS_FILLED;
            canBeFilled = true;
            dSelected = null;
            number = increaseMeter ? meter++ : -1;
            blackDashLength = DEFAULT_BLACK_DASH_LGTH;
            whiteDashLength = DEFAULT_WHITE_DASH_LGTH;
            lineStyle = PSTricksConstants.LINE_NONE_STYLE;
            dotSep = DEFAULT_DOT_SEP;
            thickness = DEFAULT_THICKNESS;
            hatchingWidth = DEFAULT_HATCH_WIDTH;
            gravityCenter = new LaTeXDrawPoint2D();
            isResizable = true;
            shadowAngle = DEFAULT_SHADOW_ANGLE;
            shadowColor = DEFAULT_SHADOW_COLOR;
            shadowSize  = DEFAULT_SHADOW_SIZE;
            hasShadow   = DEFAULT_SHADOW_HAS;
            canHaveShadow = true;
            gradientAngle           = DEFAULT_GRADIENT_ANGLE;
            gradientEndColor  = PSTricksConstants.DEFAULT_GRADIENT_END_COLOR;
            gradientStartColor      = PSTricksConstants.DEFAULT_GRADIENT_START_COLOR;
            gradientMidPoint  = DEFAULT_GRADIENT_MID_POINT;
      }



      
      /**
       * Creates a figure from one another (but do not create the gravity centre, the border and the shape).
       * @param f The figure to copy.
       * @param sameNumber True is the new figure must have the same number as the other.
       * @throws IllegalArgumentException If f is null.
       */
00377       protected Figure(Figure f, boolean sameNumber)
      {
            if(f==null)
                  throw new IllegalArgumentException();
            
            canBeFilled       = f.canBeFilled;
            canHaveShadow     = f.canHaveShadow;
            isBordersMovable= f.isBordersMovable;
            isCustomizable    = f.isCustomizable;
            isDashableOrDotable = f.isDashableOrDotable;
            isDoubleBoundaryable= f.isDoubleBoundaryable;
            isFilled          = f.isFilled;
            isOnRotation      = f.isOnRotation;
            isResizable       = f.isResizable;
            isSelected        = f.isSelected;
            interiorColor     = f.interiorColor;
            isThicknessable   = f.isThicknessable;
            blackDashLength = f.blackDashLength;
            bordersPosition = f.bordersPosition;
            dotSep                  = f.dotSep;
            doubleColor       = f.doubleColor;
            doubleSep         = f.doubleSep;
            gradientAngle     = f.gradientAngle;
            gradientEndColor= f.gradientEndColor;
            gradientMidPoint= f.gradientMidPoint;
            gradientStartColor=f.gradientStartColor;
            hasDoubleBoundary=f.hasDoubleBoundary;
            hasShadow         = f.hasShadow;
            hatchingAngle     = f.hatchingAngle;
            hatchingColor     = f.hatchingColor;
            hatchingStyle     = f.hatchingStyle;
            hatchingWidth     = f.hatchingWidth;
            hatchingSep       = f.hatchingSep;
            linesColor        = f.linesColor;
            lineStyle         = f.lineStyle;
            number                  = sameNumber ? f.number : meter++;
            rotationAngle     = f.rotationAngle;
            shadowAngle       = f.shadowAngle;
            shadowColor       = f.shadowColor;
            shadowSize        = f.shadowSize;
            thickness         = f.thickness;
            whiteDashLength   = f.whiteDashLength;
      }
      
      

      /**
       * Allows to know if the new position is a valid borders position.
       * @param pos The position to check.
       * @return True is the position is valid.
       */
00428       public static boolean isValidBordersPosition(String pos)
      {
            return pos.equals(PSTricksConstants.BORDERS_INSIDE)
                        || pos.equals(PSTricksConstants.BORDERS_MIDDLE)
                        || pos.equals(PSTricksConstants.BORDERS_OUTSIDE);
      }




      /**
       * @return True if the figure is in rotation.
       */
00441       public boolean isOnRotation()
      {
            return isOnRotation;
      }




      /**
       * @return True if the figure is hatched.
       */
00452       public synchronized boolean isHatched()
      {
            return !hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_NONE) &&
                        !hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_SOLID) &&
                        !hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_GRADIENT) ;
      }




      /**
       * Allows to set if the figure must be in rotation or not.
       * @param on True : the figure must be on rotation.
       */
00466       public synchronized void setOnRotation(boolean on)
      {
            if(borders != null)
                  borders.setOnRotation(on);
            
            isOnRotation = on;
            updateStyleOfDelimitors();
      }




      /**
       * Allows to change the style of the delimiters following the actions to do (rotation, ...).
       */
00481       public void updateStyleOfDelimitors()
      {
            if(borders != null)
                  borders.updateStyleOfDelimitors();
      }




      /**
       * Allows to create a Java Swing shape from the figure.
       * @return The Java Swing shape.
       */
      public abstract Shape createShape2D();


      
      /**
       * Allows to create a java swing shape from the figure (without any rotation).
       * @return The java swing shape.
       */
      public abstract Shape createNonRotatedShape2D();



      @Override
      public Object clone() throws CloneNotSupportedException
      {
            Figure f = (Figure)super.clone();
            f.dSelected = null;
            f.isOnRotation = isOnRotation;
            f.rotationAngle = rotationAngle;
            f.isSelected = isSelected;
            f.interiorColor = interiorColor;
            f.linesColor = linesColor;
            f.isFilled = isFilled;
            f.canBeFilled = canBeFilled;
            f.number = meter++;
            f.blackDashLength = blackDashLength;
            f.whiteDashLength = whiteDashLength;
            f.lineStyle = lineStyle;
            f.dotSep = dotSep;
            f.thickness = thickness;
            f.gravityCenter = (LaTeXDrawPoint2D)gravityCenter.clone();
            
            f.doubleColor = doubleColor;
            f.doubleSep = doubleSep;
            f.hasDoubleBoundary = hasDoubleBoundary;
            f.hatchingAngle = hatchingAngle;
            f.hatchingColor = hatchingColor;
            f.hatchingStyle = hatchingStyle;
            f.hatchingWidth = hatchingWidth;
            f.isBordersMovable = isBordersMovable;
            f.isCustomizable = isCustomizable;
            f.isDashableOrDotable = isDashableOrDotable;
            f.isDoubleBoundaryable = isDoubleBoundaryable;
            f.isResizable = isResizable;
            f.isThicknessable = isThicknessable;
            f.bordersPosition = bordersPosition;
            
            f.hasShadow       = hasShadow;
            f.shadowAngle     = shadowAngle;
            f.shadowColor     = shadowColor;
            f.shadowSize      = shadowSize;
            f.canHaveShadow = canHaveShadow;
            f.gradientAngle = gradientAngle;
            f.gradientEndColor            = gradientEndColor;
            f.gradientStartColor    = gradientStartColor;
            f.gradientMidPoint            = gradientMidPoint;

            f.hatchingSep = hatchingSep;
            
            return f;
      }




      /**
       * Allows to know if the figure can be filled or not.
       * @return True if the figure can be filled.
       */
00563       public boolean canBeFilled()
      {
            return canBeFilled;
      }




      /**
       * Allows to know if the figure can be hatched or not
       * @return True if the figure can be hatched (for most of figures, if it can be filled, it can be hatched)
       */
00575       public boolean canBeHatched()
      {
            return canBeFilled;
      }




      /**
       * Allows to get the number of the figure
       * @return The number of the figure
       */
00587       public synchronized int getNumber()
      {
            return number;
      }




      /**
       * Allows to get a point of the borders
       * @param id The position of the point (-1 : return the last point, in fact  the south-east point)
       * @return The point
       */
00600       public synchronized LaTeXDrawPoint2D getBordersPoint(int id)
      {
            if(borders == null)
                  return null;

            if(id == -1)
                  return borders.getPoint(borders.getNbPoints()-1);

            if(id<0 || id>LaTeXDrawRectangle.NB_POINTS_FRAME-1)
                  throw new IllegalArgumentException();

            return borders.getPoint(id);
      }




      /**
       * Allows to get the angle of rotation (in rad).
       * @return The angle of rotation.
       */
00621       public synchronized double getRotationAngle()
      {
            return rotationAngle;
      }




      /**
       * Allows to set the angle of rotation
       * @param theta The new angle of rotation in radian.
       */
00633       public synchronized void setRotationAngle(double theta)
      {
            if(!Double.isInfinite(theta) && !Double.isNaN(theta))
            {
                  rotationAngle = theta%(PI*2.);
                  
                  if(borders != null)
                        borders.setRotationAngle(rotationAngle);
            }
      }




      /**
       * Allows to set the variable isSelected
       * @param state The new value of isSelected
       */
00651       public synchronized void setSelected(boolean state)
      {
            if(!state)
            {
                  onRelease();
                  onDelimitorRelease();
            }
            else
            {
                  isSelected = state;
                  if(borders != null)
                        borders.setSelected(state);
            }
      }





      /**
       * Allows to set the colour of the borders of the figure
       * @param c The new colour of the borders
       */
00674       public synchronized void setLinesColor(Color c)
      {
            if(c!=null)
                  linesColor = c;
      }




      /**
       * Allows to set the colour of the interior of the figure
       * @param c The new colour of the interior
       */
00687       public synchronized void setInteriorColor(Color c)
      {
            if(c!=null)
                  interiorColor = c;
      }





      /**
       * Allows to set the style of the lines of the figure
       * @param style The new style of the lines of the figure
       * @throws IllegalArgumentException If the style is invalid.
       */
00702       public synchronized void setLineStyle(String style)
      {
            if(isValidStyle(style))
                  lineStyle = style;
            else
                  throw new IllegalArgumentException();
      }




      /**
       * Allows to change the kid of hatch of the figure.
       * @param style The new style.
       * @throws IllegalArgumentException If the style is invalid.
       */
00718       public synchronized void setHatchingStyle(String style)
      {
            if(PSTricksConstants.isValidFillStyle(style))
                  hatchingStyle = style;
            else
                  throw new IllegalArgumentException();
      }




      /**
       * Allows to set the attribute isFilled
       * @param state The new value of
       */
00733       public synchronized void setIsFilled(boolean state)
      {
            isFilled = state;
      }




      /**
       * Allows to set the colour of the hatch of the figure
       * @param color The new colour of the hatch
       */
00745       public synchronized void setHatchingColor(Color color)
      {
            if(canBeFilled() && color!=null)
                  hatchingColor = color;
      }




      /**
       * Allows to set the width of the hatch.
       * @param width The new width of the hatch.
       */
00758       public synchronized void setHatchingWidth(float width)
      {
            if(width>0 && !Double.isInfinite(width) && !Double.isNaN(width))
                  hatchingWidth = width;
      }




      /**
       * Allows to set the thickness of the figure
       * @param value The new
       */
00771       public synchronized void setThickness(float value) 
      {
            if(value<=0 || Float.isInfinite(value) || Float.isNaN(value))
                  return ;

            if(borders != null)
                  borders.setThickness(value);
            
            thickness = value;
      }




      /**
       * Defines the actions to do when the figure is dragged.
       * @param formerPt The former position of the cursor.
       * @param newPt The new position of the cursor.
       * @throws Exception
       */
      public abstract void onDragged(Point formerPt, Point newPt) throws Exception;




      /**
       * Allows to draw the figure.
       * @param g The graphic
       * @param antiAlias The antialiasing value
       * @param rendering The rendering value
       * @param alphaInter The alpha interpolation value
       * @param colorRendering The colour rendering value
       */
      public abstract void draw(Graphics2D g, Object antiAlias, Object rendering, Object alphaInter, Object colorRendering);




      /**
       * Allows to set the last point of the figure
       * @param pt The new point
       */
00813       public synchronized void setLastPoint(LaTeXDrawPoint2D pt)
      {
            setLastPoint(pt.x, pt.y);
      }




      /**
       * Allows to set the last point of the figure
       * @param x The X-coordinates of the new point
       * @param y The Y-coordinates of the new point
       */
      public abstract void setLastPoint(double x, double y);


      
      /**
       * @return The last point, null if there is no last point.
       */
      public abstract LaTeXDrawPoint2D getLastPoint();
      
      
      
      /**
       * Allows to set the first point of the figure
       * @param pt The new point
       */
00841       public synchronized void setFirstPoint(LaTeXDrawPoint2D pt)
      {
            setFirstPoint(pt.x, pt.y);
      }




      /**
       * Allows to set the first point of the figure
       * @param x The X-coordinates of the new point
       * @param y The Y-coordinates of the new point
       */
      public abstract void setFirstPoint(double x, double y);




      /**
       * Allows to gap the figure
       * @param shiftX The X-coordinates gap
       * @param shiftY The Y-coordinates gap
       */
      public abstract void shift(double shiftX, double shiftY);




      /**
       * Allows to gap the figure.
       * @param formerPt The former position of the figure.
       * @param newPt The new position of the figure.
       * @throws IllegalArgumentException If one of the point is null.
       */
00875       public void shift(LaTeXDrawPoint2D formerPt, LaTeXDrawPoint2D newPt)
      {
            if(formerPt==null || newPt==null)
                  throw new IllegalArgumentException();
            
            shift(newPt.x - formerPt.x, newPt.y - formerPt.y);
      }




      /**
       * Allows to gap the figure
       * 
       * @param formerPt The former position of the figure
       * @param newPt The new position of the figure
       */
00892       public void shift(Point formerPt, Point newPt)
      {
            shift(newPt.x - formerPt.x, newPt.y - formerPt.y);
      }




      /**
       * Allows to rescale the polygon in width
       * @param formerX The old value of the X-coordinate to change
       * @param newX The X-coordinate of the point which rescale the figure. It's
       * Useful for determinate of which side (east or west) we must enlarge thecfigure
       * @param percent The new width of the figure in percent
       * @param bound The reference for moving points (the borders of the figure
       * or, for example, the borders of the drawing containing the figure)
       */
      public abstract void rescaleX(double formerX, double newX, double percent, LaTeXDrawRectangle bound);




      /**
       * Allows to rescale the polygon in width
       * @param formerY The former value of the y
       * @param newY The Y-coordinate of the point which rescale the polygon. It's
       * Useful for determinate of which side (east or west) we must enlarge the polygon
       * @param percent The new width of the polygon in percent
       * @param bound The reference for moving points (the borders of the figure
       * or, for example, the borders of the drawing containing the figure)
       */
      public abstract void rescaleY(double formerY, double newY, double percent, LaTeXDrawRectangle bound);




      /**
       * Allows to rotate, following the angle of rotation, the given point.
       * @param p The point to rotate.
       * @return The new point rotated.
       */
00933       public LaTeXDrawPoint2D rotatePoint(LaTeXDrawPoint2D p)
      {
            return rotatePoint(p, gravityCenter, rotationAngle);
      }




      /**
       * Allows to rotate a point with the gravity centre of the figure.
       * @param p The point to rotate.
       * @param theta The angle of rotation.
       * @return The rotated point.
       */
00947       public synchronized LaTeXDrawPoint2D rotatePoint(LaTeXDrawPoint2D p, double theta)
      {
            return rotatePoint(p, getGravityCenter(), theta);
      }


      
      
      /**
       * Allows to rotate a point with as reference an other point.
       * @param p The point to rotate.
       * @param gravityC The point of reference.
       * @param theta The angle of rotation (in rad).
       * @return The rotated point.
       */
00962       public static LaTeXDrawPoint2D rotatePoint(LaTeXDrawPoint2D p, LaTeXDrawPoint2D gravityC, double theta)
      {
            LaTeXDrawPoint2D pt = new LaTeXDrawPoint2D();
            double cosTheta;
            double sinTheta;
            
            if(theta<0.)
                  theta = 2.*PI + theta;
            
            if((theta%(2.*PI))==0.)
                  return (LaTeXDrawPoint2D)p.clone();
            
            if(Math.abs(theta%(2.*PI)-PI/2.)<0.000001)
            {     
                  cosTheta = 0.;
                  sinTheta = 1.;
            }
            else
            {
                  if(Math.abs(theta%(2.*PI)-PI)<0.000001)
                  {
                        cosTheta = -1.;
                        sinTheta = 0.;
                  }
                  else
                  {
                        if(Math.abs(theta%(2.*PI)-(3.*PI/2.))<0.000001)
                        {
                              cosTheta = 0.;
                              sinTheta = -1.;
                        }
                        else
                        {
                              cosTheta = Math.cos(theta);
                              sinTheta = Math.sin(theta);
                        }
                  }
            }

            pt.x = cosTheta * (p.x - gravityC.x) - sinTheta * (p.y - gravityC.y) + gravityC.x;
            pt.y = sinTheta * (p.x - gravityC.x) + cosTheta * (p.y - gravityC.y) + gravityC.y;

            return pt;
      }
      
      


      /**
       * Allows to rotate, following the negation of angle of rotation, the given point.
       * @param p The point to rotate.
       * @return The new point rotated.
       */
01015       public LaTeXDrawPoint2D rotateInvertPoint(LaTeXDrawPoint2D p)
      {
            LaTeXDrawPoint2D pt = new LaTeXDrawPoint2D();
            double angle = -rotationAngle;
            double cosTheta;
            double sinTheta;

            if(angle<0)
                  angle = 2.*PI + angle;
            
            angle = angle%(2.*PI);
            
            if(angle==0.)
                  return (LaTeXDrawPoint2D)p.clone();
            
            if(Math.abs(angle-(PI/2.))<0.000001)
            {     
                  cosTheta = 0.;
                  sinTheta = 1.;
            }
            else
            {
                  if(Math.abs(angle-PI)<0.000001)
                  {
                        cosTheta = -1.;
                        sinTheta = 0.;
                  }
                  else
                  {
                        if(Math.abs(angle-(3.*PI/2.))<0.000001)
                        {
                              cosTheta = 0.;
                              sinTheta = -1.;
                        }
                        else
                        {
                              cosTheta = Math.cos(angle);
                              sinTheta = Math.sin(angle);
                        }
                  }
            }
            
            pt.x = cosTheta * (p.x - gravityCenter.x) - sinTheta * (p.y - gravityCenter.y) + gravityCenter.x;
            pt.y = sinTheta * (p.x - gravityCenter.x) + cosTheta * (p.y - gravityCenter.y) + gravityCenter.y;

            return pt;
      }




      /**
       * Allows to rotate, following the angle of rotation, the given point.
       * @param p The point to rotate.
       * @return The new point rotated.
       */
01071       public LaTeXDrawPoint2D rotatePoint(Point p)
      {
            return rotatePoint(new LaTeXDrawPoint2D(p.x, p.y));
      }




      /**
       * Allows to rotate, following the negation of the angle of rotation, the given point.
       * @param p The point to rotate.
       * @return The new point rotated.
       */
01084       public LaTeXDrawPoint2D rotateInvertPoint(Point p)
      {
            return rotateInvertPoint(new LaTeXDrawPoint2D(p.x, p.y));
      }




      /**
       * Actions to do when the figure is released.
       */
01095       public synchronized void onDelimitorRelease()
      {
            updateStyleOfDelimitors();
            dSelected = null;
            if(borders != null)
                  borders.onDelimitorRelease();
      }




      /**
       * Fills a figure.
       * @param g The graphics.
       * @param antiAlias The antialiasing value.
       * @param rendering The rendering value.
       * @param alphaInter The alpha interpolation value.
       * @param colorRendering The colour rendering value.
       * @param s The pattern of the figure to fill.
       */
01115       protected void fillFigure(Graphics2D g, Object antiAlias, Object rendering, Object alphaInter, Object colorRendering, Shape s)
      {
            Color formerColor = g.getColor();
            GeneralPath p = new GeneralPath(s);
            p.setWindingRule(GeneralPath.WIND_NON_ZERO);
            
            try
            {
                  if(!hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_NONE))
                  {
                        if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_SOLID))
                        {
                              g.setColor(interiorColor);
                              g.fill(shape);
                              g.setColor(formerColor);
                              return;
                        }
                        
                        if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_GRADIENT))
                        {
                              LaTeXDrawPoint2D NW = getTheNWPoint();
                              LaTeXDrawPoint2D SE = getTheSEPoint();
                              LaTeXDrawPoint2D pt1 = new LaTeXDrawPoint2D((NW.x+SE.x)/2., NW.y);
                              LaTeXDrawPoint2D pt2 = new LaTeXDrawPoint2D((NW.x+SE.x)/2., SE.y);
                              double angle = gradientAngle%(2*PI);
                              double gradMidPt = gradientMidPoint;
                              if(angle<0)
                                    angle = 2*PI + angle;
                              
                              if(angle>=PI)
                              {
                                    gradMidPt = 1 - gradientMidPoint;
                                    angle = angle-PI;
                              }
                              
                              if(angle!=0)
                              {
                                    if((angle%(PI/2.))==0)
                                    {
                                          pt1 = new LaTeXDrawPoint2D(NW.x, (NW.y+SE.y)/2.);
                                          pt2 = new LaTeXDrawPoint2D(SE.x, (NW.y+SE.y)/2.);
                                          if(gradMidPt<0.5)
                                                pt1.x = pt2.x - Point2D.distance(pt2.x, pt2.y, SE.x,(NW.y+SE.y)/2.);
                                          pt2.x = (NW.x+(SE.x-NW.x)*gradMidPt);
                                    }
                                    else
                                    {
                                          LaTeXDrawPoint2D cg = getGravityCenter();
                                          Line l2, l;
                                          
                                          pt1 = Figure.rotatePoint(pt1, cg, -angle);
                                          pt2 = Figure.rotatePoint(pt2, cg, -angle);
                                          l = new Line(pt1, pt2, false);
                                          
                                          if(angle>=0 && angle<(PI/2.))
                                                 l2 = l.getPerpendicularLine(NW, false);
                                          else l2 = l.getPerpendicularLine(new LaTeXDrawPoint2D(NW.x,SE.y), false);
                                          
                                          pt1 = l.getIntersection(l2);
                                          double distance = Point2D.distance(cg.x, cg.y, pt1.x, pt1.y);
                                          l.setPointAt(pt1, 0);
                                          LaTeXDrawPoint2D[] pts = l.findPoints(pt1, 2*distance*gradMidPt);
                                          pt2 = pts[0];
                                          
                                          if(gradMidPt<0.5)
                                                pt1 = Figure.rotatePoint(pt1, gravityCenter, PI);
                                    }
                              }//if(angle!=0)
                              else 
                              {
                                    if(gradMidPt<0.5)
                                          pt1.y = pt2.y - Point2D.distance(pt2.x, pt2.y, (NW.x+SE.x)/2.,SE.y);
                                    pt2.y = (NW.y+(SE.y-NW.y)*gradMidPt);
                              }
                              
                              g.setPaint(new GradientPaint(
                                          (float)pt1.x, (float)pt1.y, gradientStartColor, 
                                          (float)pt2.x, (float)pt2.y, gradientEndColor,true));
                              g.fill(p);
                              g.setColor(formerColor);
                              return;
                        }
                        
                        Shape oldClip           = g.getClip();
                        Rectangle2D bounds  = s.getBounds2D();
                        g.setClip(s);
                        
                        if(isFilled() || hasShadow())
                        {
                              g.setColor(interiorColor);
                              g.fill(bounds);
                        }
                        
                        if(isHatched())
                        {
                              Stroke oldStroke = g.getStroke();
                              
                              if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_VLINES) || 
                                    hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_VLINES_F)) 
                                    paintHatchings2(g, hatchingAngle, bounds);
                              else 
                                    if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_HLINES) || 
                                       hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_HLINES_F)) 
                                    paintHatchings2(g, hatchingAngle>0?hatchingAngle-Math.PI/2.:hatchingAngle+Math.PI/2., bounds);
                              else 
                                    if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_CROSSHATCH) ||
                                       hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_CROSSHATCH_F)) 
                                    {
                                          paintHatchings2(g, hatchingAngle, bounds);
                                          paintHatchings2(g, hatchingAngle>0?hatchingAngle-Math.PI/2.:hatchingAngle+Math.PI/2., bounds);
                                    }
                              
                              g.setStroke(oldStroke);
                        }
                        
                        g.setClip(oldClip);
                  }
                  else
                        if(isFilled)
                        {
                              g.setColor(interiorColor);
                              g.fill(p);
                        }
            }catch(LaTeXDrawException e)
            {
                  e.printStackTrace();
            }
            g.setColor(formerColor);
      }

      
      
      /**
       * Paints the hatchings.
       * @param g The graphics to paint.
       * @param angle The angle of the hatchings (in radian).
       * @param clip The clip box.
       */
01253       private void paintHatchings2(Graphics2D g, double angle, Rectangle2D clip)
      {
            if(g==null || clip==null)
                  return ;
      
            double angle2 = angle%(Math.PI*2.);
            float halphPI = (float)(Math.PI/2.);
            
            if(angle2>0)
            {
                  if((float)angle2>3f*halphPI)
                        angle2 = angle2-Math.PI*2.;
                  else
                        if((float)angle2>halphPI)
                              angle2 = angle2-Math.PI;
            }
            else
                  if((float)angle2<-3f*halphPI)
                        angle2 = angle2+Math.PI*2.;
                  else
                        if((float)angle2<-halphPI)
                              angle2 = angle2+Math.PI;
            
            Line2D.Double line  = new Line2D.Double();
            double val              = hatchingWidth+hatchingSep;
            float fAngle            = (float)angle2;
            
            g.setStroke(new BasicStroke(hatchingWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
            g.setPaint(getHatchingColor());
            
            if(fAngle==0f)
            {
                  line.y1     = clip.getMinY();
                  line.y2     = clip.getMaxY();
                  double maxX = clip.getMaxX();
                  
                  for(double x = clip.getMinX(); x<maxX; x+=val)
                  {
                        line.x1 = line.x2 = x;
                        g.draw(line);
                  }
            }
            else 
                  if(fAngle==halphPI || fAngle==-halphPI)
                  {
                        line.x1     = clip.getMinX();
                        line.x2     = clip.getMaxX();
                        double maxY = clip.getMaxY();
                        
                        for(double y = clip.getMinY(); y<maxY; y+=val)
                        {
                              line.y1 = line.y2 = y;
                              g.draw(line);
                        }
                  }
                  else 
                  {
                        double incX = val/Math.cos(angle2);
                        double incY = val/Math.sin(angle2);
                        double maxX;
                        
                        if(fAngle>0f) 
                        {
                              line.y1 = clip.getMinY();
                              maxX  = clip.getMaxX() + (clip.getMaxY()-(clip.getMinY()<0?clip.getMinY():0)) * Math.tan(angle2);
                        }
                        else 
                        {
                              line.y1 = clip.getMaxY();
                              maxX  = clip.getMaxX() - clip.getMaxY() * Math.tan(angle2);
                        }
                        
                        line.x1 = clip.getMinX();
                        line.x2 = line.x1;
                        line.y2 = line.y1;
                        
                        if(((float)incX)<=0f)
                              return ;
                        
                        while(line.x2 < maxX)
                        {
                              line.x2 += incX;
                              line.y1 += incY;
                              g.draw(line);
                        }
                  }
      }
      


      /**
       * Allows to know if the point pt is in (or on) the figure.
       * @param pt The point
       * @return true: if the point is in or on the figure.
       */
01348       public boolean isIn(Point pt)
      {
            return isIn(new LaTeXDrawPoint2D(pt.x, pt.y));
      }




      /**
       * Allows to know if the point pt is in(or on) the figure.
       * @param pt The point
       * @return true : if the point is in or on the figure.
       */
      public abstract boolean isIn(LaTeXDrawPoint2D pt);




      /**
       * @return True if the figure is filled by a colour.
       */
01369       public synchronized boolean isFilled()
      {
            return isFilled;
      }




      /**
       * @return True if a delimiter is selected.
       */
01380       public synchronized boolean isADelimitorSelected()
      {
            return dSelected != null;
      }




      /**
       * Allows to know if the figure intersects the given shape.
       * @param r The shape.
       * @return True if the figure intersects the shape.
       */
01393       public boolean intersected(Rectangle2D.Double r)
      {
            if(r==null)
                  return false;
            
            Shape s = createShape2D();
                  
            Shape sTooSmall = getTooSmallShape(s);
            
            if(sTooSmall!=null)
                  s = sTooSmall;
            
            BasicStroke wideline = new BasicStroke(thickness);
        Shape outline = wideline.createStrokedShape(s);
            
            return outline.intersects(r) && !outline.contains(r);
      }




      /**
       * Allows to check if the style is possible.
       * @param style The style to check.
       * @return True if the style is valid.
       */
01419       public static boolean isValidStyle(String style)
      {
            if(style.equals(PSTricksConstants.LINE_NONE_STYLE)|| 
                  style.equals(PSTricksConstants.LINE_DASHED_STYLE) || 
                  style.equals(PSTricksConstants.LINE_DOTTED_STYLE))
                  return true;

            return false;
      }




      /**
       * Allows to create a list of the different position of the borders.
       * @return The list.
       */
01436       public static LaTeXDrawComboBox createBordersPositionChoice()
      {
            LaTeXDrawComboBox dbPositionChoice = new LaTeXDrawComboBox();
            dbPositionChoice.setRenderer(new LabelListCellRenderer());

            JLabel label = new JLabel(PSTricksConstants.BORDERS_OUTSIDE);
            label.setName(PSTricksConstants.BORDERS_OUTSIDE);
            label.setIcon(LaTeXDrawResources.innerIcon);
            dbPositionChoice.addItem(label);

            label = new JLabel(PSTricksConstants.BORDERS_INSIDE);
            label.setName(PSTricksConstants.BORDERS_INSIDE);
            label.setIcon(LaTeXDrawResources.outerIcon);
            dbPositionChoice.addItem(label);

            label = new JLabel(PSTricksConstants.BORDERS_MIDDLE);
            label.setName(PSTricksConstants.BORDERS_MIDDLE);
            label.setIcon(LaTeXDrawResources.middleIcon);
            dbPositionChoice.addItem(label);

            dbPositionChoice.setName(Figure.LABEL_BORDERS_POSITION_CHOICE);
            dbPositionChoice.setActionCommand(Figure.LABEL_BORDERS_POSITION_CHOICE);
            dbPositionChoice.setSelectedItem(Figure.DEFAULT_BORDERS_POSITION);

            return dbPositionChoice;
      }


      
      
      /**
       * Allows to create a list of the different style of line.
       * @return The list.
       */
01470       public static LaTeXDrawComboBox createStyleLineChoice()
      {
            LaTeXDrawComboBox lineChoice  = new LaTeXDrawComboBox();
            lineChoice.setRenderer(new LabelListCellRenderer());
            JLabel label = new JLabel(PSTricksConstants.LINE_NONE_STYLE);
            label.setName(PSTricksConstants.LINE_NONE_STYLE);
            label.setIcon(LaTeXDrawResources.lineStyleNoneIcon);
      lineChoice.addItem(label);
            label = new JLabel(PSTricksConstants.LINE_DASHED_STYLE);
            label.setName(PSTricksConstants.LINE_DASHED_STYLE);
            label.setIcon(LaTeXDrawResources.lineStyleDashedIcon);
      lineChoice.addItem(label);
      label = new JLabel(PSTricksConstants.LINE_DOTTED_STYLE);
      label.setName(PSTricksConstants.LINE_DOTTED_STYLE);
            label.setIcon(LaTeXDrawResources.lineStyleDottedIcon);
      lineChoice.addItem(label);          
      
      lineChoice.setSelectedItem(PSTricksConstants.LINE_NONE_STYLE);
      
      return lineChoice;
      }
      
      


      /**
       * Allows to create a list containing all kinds of hatch.
       * @return A JComboBox.
       */
01499       public static LaTeXDrawComboBox createFillChoice()
      {
            LaTeXDrawComboBox list = new LaTeXDrawComboBox();
            list.setRenderer(new LabelListCellRenderer());
            list.setName(LABEL_HATCH_CHOICE);
            list.setActionCommand(LABEL_HATCH_CHOICE);

            JLabel l = new JLabel(PSTricksConstants.TOKEN_FILL_NONE);
            l.setName(PSTricksConstants.TOKEN_FILL_NONE);
            l.setIcon(LaTeXDrawResources.hatchNoneIcon);
            list.addItem(l);
            l = new JLabel(PSTricksConstants.TOKEN_FILL_CROSSHATCH);
            l.setName(PSTricksConstants.TOKEN_FILL_CROSSHATCH);
            l.setIcon(LaTeXDrawResources.hatchCrossIcon);
            list.addItem(l);
            l = new JLabel(PSTricksConstants.TOKEN_FILL_HLINES);
            l.setName(PSTricksConstants.TOKEN_FILL_HLINES);
            l.setIcon(LaTeXDrawResources.hatchHorizIcon);
            list.addItem(l);
            l = new JLabel(PSTricksConstants.TOKEN_FILL_VLINES);
            l.setName(PSTricksConstants.TOKEN_FILL_VLINES);
            l.setIcon(LaTeXDrawResources.hatchVertIcon);
            list.addItem(l);
            l = new JLabel(PSTricksConstants.TOKEN_FILL_GRADIENT);
            l.setName(PSTricksConstants.TOKEN_FILL_GRADIENT);
            l.setIcon(LaTeXDrawResources.gradientIcon);
            list.addItem(l);

            return list;
      }




      /**
       * Allows to obtain the point most to the North and on the West of the figure.
       * @return the point most to the North and on the West of the figure.
       */
01537       public LaTeXDrawPoint2D getTheNWPoint()
      {
            if(borders != null)
                  return borders.getTheNWPoint();
            return null;
      }




      /**
       * Allows to get the south-east point by taking into account the angle of rotation.
       * @return The south-east point of the rotated rectangle.
       */
01551       public synchronized LaTeXDrawPoint2D getTheSERotatedPoint()
      {
            if(borders != null)
                  return borders.getTheSERotatedPoint();
            return null;
      }




      /**
       * Allows to get the north-west point by taking into account the angle of rotation.
       * @return The north-west point of the rotated rectangle.
       */
01565       public LaTeXDrawPoint2D getTheNWRotatedPoint()
      {
            if(borders != null)
                  return borders.getTheNWRotatedPoint();
            return null;
      }




      /**
       * Allows to get a clone of the centre of gravity of the figure.
       * @return The centre of gravity of the figure.
       */
01579       public synchronized LaTeXDrawPoint2D getGravityCenter()
      {
            updateGravityCenter();
            return (LaTeXDrawPoint2D)gravityCenter.clone();
      }




      /**
       * Allows to get the LaTeX code of the figure.
       * @return the LaTeX code of the figure.
       */
      public abstract String getCodePSTricks(DrawBorders drawBorders, float ppc);




      /**
       * Allows to get the colour of the borders of the figure.
       * @return The colour of the borders of the figure.
       */
01601       public synchronized Color getLinesColor()
      {
            return linesColor;
      }




      /**
       * @return The borders of the figure.
       */
01612       public synchronized LaTeXDrawRectangle getBorders()
      {
            return borders;
      }



      /**
       * @return The colour of the interior of the figure.
       */
01622       public synchronized Color getInteriorColor()
      {
            return interiorColor;
      }



      /**
       * @return The style of the lines of the figure.
       */
01632       public synchronized String getLineStyle()
      {
            return lineStyle;
      }



      /**
       * @return The kind of hatch.
       */
01642       public synchronized String getHatchingStyle()
      {
            return hatchingStyle;
      }



      /**
       * @return The colour of the hatch.
       */
01652       public synchronized Color getHatchingColor()
      {
            return hatchingColor;
      }



      /**
       * @return The width of the lines of the hatch.
       */
01662       public synchronized float getHatchingWidth()
      {
            return hatchingWidth;
      }



      /**
       * @return The thickness of the figure.
       */
01672       public synchronized float getThickness()
      {
            return thickness;
      }



      /**
       * Corresponds to what to do when the user click on the figure.
       * @param pt The clicked point.
       */
01683       public synchronized void onClick(Point pt)
      {
            isSelected = true;

            if (borders != null)
                  borders.onClick(pt);
      }




      /**
       * Corresponds to what to do when the user release the mouse.
       */
01697       public synchronized void onRelease()
      {
            setOnRotation(false);
            isSelected = false;
            dSelected = null;
            if(borders != null)
                  borders.onRelease();
      }




      /**
       * Allows to obtain the point most to the South and on the East of the figure.
       * @return the point most to the South and on the East of the figure.
       */
01713       public synchronized LaTeXDrawPoint2D getTheSEPoint()
      {
            if(borders != null)
                  return borders.getTheSEPoint();
            return null;
      }




      /**
       * @return True if the figure is selected.
       */
01726       public synchronized boolean isSelected()
      {
            return isSelected;
      }




      /**
       * Allows to update the centre of gravity of the figure (Useful for rotation).
       */
01737       public synchronized void updateGravityCenter()
      {
            if(borders==null)
                  return ;
            
            borders.updateGravityCenter();
            
            LaTeXDrawPoint2D gc = borders.getGravityCenter();
            
            if(gravityCenter!=null)
            {
                  if(gc!=null)
                        gravityCenter.setLocation(gc);
            }
            else gravityCenter = gc;
      }



      /**
       * @return Returns the isCustomizable.
       */
01759       public synchronized boolean isCustomizable()
      {
            return isCustomizable;
      }



      /**
       * @return Returns the isThicknessable.
       */
01769       public synchronized boolean isThicknessable()
      {
            return isThicknessable;
      }



      /**
       * @return Returns the doubleSep.
       */
01779       public synchronized double getDoubleSep()
      {
            return doubleSep;
      }



      /**
       * @param doubleSep The doubleSep to set.
       */
01789       public synchronized void setDoubleSep(double doubleSep)
      {
            if(!Double.isInfinite(doubleSep) && !Double.isNaN(doubleSep))
                  this.doubleSep = doubleSep;
      }



      /**
       * @return Returns the hasDoubleBoundary.
       */
01800       public synchronized boolean hasDoubleBoundary()
      {
            return hasDoubleBoundary;
      }



      /**
       * @param hasDoubleBoundary The hasDoubleBoundary to set.
       */
01810       public synchronized void setHasDoubleBoundary(boolean hasDoubleBoundary)
      {
            this.hasDoubleBoundary = hasDoubleBoundary;
            updateShape();
      }



      /**
       * @return Returns the isDashableOrDotable.
       */
01821       public synchronized boolean isDashableOrDotable()
      {
            return isDashableOrDotable;
      }



      /**
       * @return Returns the isDoubleBoundaryable.
       */
01831       public synchronized boolean isDoubleBoundaryable()
      {
            return isDoubleBoundaryable;
      }



      /**
       * @param isCustomizable The isCustomizable to set.
       */
01841       public synchronized void setCustomizable(boolean isCustomizable)
      {
            this.isCustomizable = isCustomizable;
      }



      /**
       * @return Returns the isResizable.
       */
01851       public synchronized boolean isResizable()
      {
            return isResizable;
      }



      /**
       * @param isResizable The isResizable to set.
       */
01861       public synchronized void setResizable(boolean isResizable)
      {
            this.isResizable = isResizable;
      }



      /**
       * @return Returns the doubleColor.
       */
01871       public synchronized Color getDoubleColor()
      {
            return doubleColor;
      }



      /**
       * @param doublecolor The doubleColor to set.
       */
01881       public synchronized void setDoubleColor(Color doublecolor)
      {
            if(doublecolor!=null)
                  this.doubleColor = doublecolor;
      }



      /**
       * @return Returns the doubleLinePosition.
       */
01892       public synchronized String getBordersPosition()
      {
            return bordersPosition;
      }



      /**
       * @param doubleLinePosition The doubleLinePosition to set.
       */
01902       public synchronized void setBordersPosition(String doubleLinePosition)
      {
            if(isValidBordersPosition(doubleLinePosition) && isBordersMovable)
            {
                  this.bordersPosition = doubleLinePosition;
                  updateShape();
            }
      }



      /**
       * Allows to get the north-westiest point of the bounds of the figure (the
       * bounds consider the thickness of the figure and the position of the  borders).
       * @return The north-westiest point of the bounds of the figure
       */
01918       public LaTeXDrawPoint2D getTheNWBoundPoint()
      {
            Rectangle2D bounds = createShape2D().getBounds2D();

            if(bounds == null)
                  return null;

            if(hasShadow)
            {
                  double dx=0, dy=0;
                  LaTeXDrawPoint2D cg = getGravityCenter();
                  LaTeXDrawPoint2D shadowCg = (LaTeXDrawPoint2D)cg.clone();
                  shadowCg.setLocation(cg.x+shadowSize, cg.y);
                  shadowCg = Figure.rotatePoint(shadowCg, cg, shadowAngle);
                  dx = shadowCg.x-cg.x;
                  dy = cg.y-shadowCg.y;
                  Rectangle2D.Double bounds2 = new Rectangle2D.Double(bounds.getX()+dx,bounds.getY()+dy,
                                                                  bounds.getWidth(), bounds.getHeight());
                  bounds2.add(bounds);
                  bounds = bounds2;
            }
            
            return new LaTeXDrawPoint2D(bounds.getX()-thickness/2., bounds.getY()-thickness/2.);
      }


      
      
      /**
       * Allows to get the north-westiest point of the bounds of the figure (the
       * bounds consider the thickness of the figure and the position of the
       * borders), without any rotation of the figure. It doesn't take account  of the shadow.
       */
01951       public LaTeXDrawPoint2D getTheNWNonRotatedBoundPoint()
      {
            Rectangle2D bounds = createNonRotatedShape2D().getBounds2D();

            if(bounds == null)
                  return null;

            return new LaTeXDrawPoint2D(bounds.getMinX() - thickness / 2., 
                                                      bounds.getMinY() - thickness / 2.);
      }

      
      
      

      /**
       * Allows to get the south-eastiest point of the bounds of the figure (the
       * bounds consider the thickness of the figure and the position of the
       * borders), without any rotation of the figure. It doesn't take account of the shadow.
       * @return The south-eastiest point of the bounds of the figure.
       */
01972       public LaTeXDrawPoint2D getTheSENonRotatedBoundPoint()
      {
            Rectangle2D bounds = createNonRotatedShape2D().getBounds2D();

            if (bounds == null)
                  return null;

            return new LaTeXDrawPoint2D(bounds.getMaxX() + thickness / 2., bounds.getMaxY() + thickness / 2.);
      }
      
      
      

      /**
       * Allows to get the south-eastiest point of the bounds of the figure (the
       * bounds consider the thickness of the figure and the position of the borders).
       * @return The south-eastiest point of the bounds of the figure.
       */
01990       public LaTeXDrawPoint2D getTheSEBoundPoint()
      {
            Rectangle2D bounds = createShape2D().getBounds2D();

            if(bounds == null)
                  return null;
            
            if(hasShadow)
            {
                  double dx=0, dy=0;
                  LaTeXDrawPoint2D cg = getGravityCenter();
                  LaTeXDrawPoint2D shadowCg = (LaTeXDrawPoint2D)cg.clone();
                  shadowCg.setLocation(cg.x+shadowSize, cg.y);
                  shadowCg = Figure.rotatePoint(shadowCg, cg, shadowAngle);
                  dx = shadowCg.x-cg.x;
                  dy = cg.y-shadowCg.y;
                  Rectangle2D.Double bounds2 = new Rectangle2D.Double(bounds.getX()+dx,bounds.getY()+dy,
                                                                  bounds.getWidth(), bounds.getHeight());
                  bounds2.add(bounds);
                  bounds = bounds2;
            }

            return new LaTeXDrawPoint2D(bounds.getX() + thickness / 2.
                        + bounds.getWidth(), bounds.getY() + thickness / 2. + bounds.getHeight());
      }



      /**
       * @return True if the borders of the figure can move.
       */
02021       public synchronized boolean isBordersMovable()
      {
            return isBordersMovable;
      }
      
      
      
      /**
       * Allows to change the number of the figure.
       */
02031       public synchronized void changeMeter()
      {
            number = meter++;
      }
      

      
      /**
       * Allows to compute the angle of the point pt.
       * @param pt The point of reference.
       * @param gravityC The centre of gravity of the trigonometric circle.
       * @return The angle.
       */
02044       public static double computeAngle(Point pt, LaTeXDrawPoint2D gravityC)
      {
            double c = gravityC.y-pt.y;
            double b = gravityC.x-pt.x;
            
            return atan(c/b);
      }
      
      
      
      
      /**
       * Allows to compute the angle of rotation between two points.
       * using the gravity centre of the figure.
       * @param formerPt The first point.
       * @param newPt The second point.
       * @return The rotation point.
       * @throws IllegalArgumentException If formerPt or newPt are null.
       */
02063       public double computeRotationAngle(Point formerPt, Point newPt) throws IllegalArgumentException
      {
            double thetaOld = Figure.computeAngle(formerPt, gravityCenter);
            double thetaNew = Figure.computeAngle(newPt, gravityCenter);

            if((thetaNew-thetaOld)>(PI/2.) || (thetaNew-thetaOld)<-(PI/2.))
                  return thetaNew+thetaOld;

            return thetaNew-thetaOld;
      }
      
      
      
      
      /**
       * Allows to rotate the figure around its gravity centre.
       * @param formerPt The former point.
       * @param newPt The new point.
       * @throws IllegalArgumentException If formerPt or newPt is null.
       */
02083       public void rotate(Point formerPt, Point newPt) throws IllegalArgumentException
      {
            setRotationAngle(rotationAngle+computeRotationAngle(formerPt, newPt));
      }
      
      
      
      
      /**
       * Allows rotate the figure around the point gravityC.
       * @param gravityC The point of reference of the rotation.
       * @param angle The angle of the rotation.
       */
02096       public void rotate(LaTeXDrawPoint2D gravityC, double angle)
      {
            if(!gravityC.equals(gravityCenter))
            {// We must rotate the position of the figure
                  LaTeXDrawPoint2D rotGC = rotatePoint(gravityCenter, gravityC, angle);
                  shift(gravityCenter, rotGC);
                  updateGravityCenter();
            }
            
            setRotationAngle(rotationAngle+angle);
      }



      /**
       * @return the blackDashLength.
       */
02113       public synchronized float getBlackDashLength()
      {
            return blackDashLength;
      }



      /**
       * @param blackDashLength the blackDashLength to set.
       */
02123       public synchronized void setBlackDashLength(float blackDashLength)
      {
            if(blackDashLength>0 && !Float.isInfinite(blackDashLength) && !Float.isNaN(blackDashLength))
                  this.blackDashLength = blackDashLength;
      }



      /**
       * @return the hatchingAngle.
       */
02134       public synchronized double getHatchingAngle()
      {
            return hatchingAngle;
      }



      /**
       * @param hatchingAngle the hatchingAngle to set.
       */
02144       public synchronized void setHatchingAngle(double hatchingAngle)
      {
            if(!Double.isInfinite(hatchingAngle) && !Double.isNaN(hatchingAngle))
                  this.hatchingAngle = hatchingAngle%(Math.PI*2.);
      }



      /**
       * @return the whiteDashLength.
       */
02155       public synchronized float getWhiteDashLength()
      {
            return whiteDashLength;
      }



      /**
       * @param whiteDashLength the whiteDashLength to set.
       */
02165       public synchronized void setWhiteDashLength(float whiteDashLength)
      {
            if(whiteDashLength>0 && !Float.isInfinite(whiteDashLength) && !Float.isNaN(whiteDashLength))
                  this.whiteDashLength = whiteDashLength;
      }



      /**
       * @return the dotSep.
       */
02176       public synchronized float getDotSep()
      {
            return dotSep;
      }



      /**
       * @param dotSep the dotSep to set.
       */
02186       public synchronized void setDotSep(float dotSep)
      {
            if(dotSep>0 && !Float.isInfinite(dotSep) && !Float.isNaN(dotSep))
                  this.dotSep = dotSep;
      }
      
      
      
      /**
       * Allows to update the shape of the figure.
       */
      public abstract void updateShape();
      
      
      /**
       * Allows to know if the figure is too small to be rescaled.
       * @return True if the figure is too small to be rescaled.
       */
      public abstract boolean isTooSmallToBeRescaled();



      /**
       * @return the hasShadow.
       * @since 1.7
       */
02212       public synchronized boolean hasShadow()
      {
            return hasShadow;
      }



      /**
       * @param hasShadow the hasShadow to set.
       * @since 1.7
       */
02223       public synchronized void setHasShadow(boolean hasShadow)
      {
            this.hasShadow = hasShadow;
      }



      /**
       * @return The shadowAngle (in rad).
       * @since 1.7
       */
02234       public synchronized double getShadowAngle()
      {
            return shadowAngle;
      }



      /**
       * @param shadowAngle the shadowAngle to set in radian.
       * @since 1.7
       */
02245       public synchronized void setShadowAngle(double shadowAngle)
      {
            if(!Double.isInfinite(shadowAngle) && !Double.isNaN(shadowAngle))
                  this.shadowAngle = shadowAngle%(2*Math.PI);
      }



      /**
       * @return the shadowColor.
       * @since 1.7
       */
02257       public synchronized Color getShadowColor()
      {
            return shadowColor;
      }



      /**
       * @param shadowColor the shadowColor to set.
       * @since 1.7
       */
02268       public synchronized void setShadowColor(Color shadowColor)
      {
            if(shadowColor!=null)
                  this.shadowColor = shadowColor;
      }



      /**
       * @return the shadowSize.
       * @since 1.7
       */
02280       public synchronized double getShadowSize()
      {
            return shadowSize;
      }



      /**
       * @param shadowSize the shadowSize to set.
       * @since 1.7
       */
02291       public synchronized void setShadowSize(double shadowSize)
      {
            if(!Double.isInfinite(shadowSize) && !Double.isNaN(shadowSize))
                  this.shadowSize = shadowSize;
      }



      /**
       * @return the canHaveShadow.
       * @since 1.7
       */
02303       public boolean canHaveShadow()
      {
            return canHaveShadow;
      }
      
      
      
      /**
       * Allows to create a shape corresponding to the shadow of the figure.
       * @return The shadow.
       * @since 1.7
       */
02315       public Shape createShadowShape()
      {
            if(!canHaveShadow || !hasShadow) return shape;
            
            Rectangle2D shadowS = createShape2D().getBounds2D();
            double dx=0, dy=0;
            LaTeXDrawPoint2D cg = getGravityCenter();
            LaTeXDrawPoint2D shadowCg = (LaTeXDrawPoint2D)cg.clone();
            shadowCg.setLocation(cg.x+shadowSize, cg.y);
            shadowCg = Figure.rotatePoint(shadowCg, cg, shadowAngle);
            dx = shadowCg.x-cg.x;
            dy = cg.y-shadowCg.y;
            Rectangle2D.Double bounds2 = new Rectangle2D.Double(shadowS.getX()+dx-thickness/2.,
                                                            shadowS.getY()+dy-thickness/2.,
                                                            shadowS.getWidth()+thickness, shadowS.getHeight()+thickness);
            return bounds2;
      }



      /**
       * @return the gradientAngle.
       * @since 1.7
       */
02339       public synchronized double getGradientAngle()
      {
            return gradientAngle;
      }



      /**
       * @param gradientAngle the gradientAngle to set (in radian).
       * @since 1.7
       */
02350       public synchronized void setGradientAngle(double gradientAngle)
      {
            if(!Double.isInfinite(gradientAngle) && !Double.isNaN(gradientAngle))
                  this.gradientAngle = gradientAngle;
      }



      /**
       * @return the gradientEndColor.
       * @since 1.7
       */
02362       public synchronized Color getGradientEndColor()
      {
            return gradientEndColor;
      }



      /**
       * @param gradientEndColor the gradientEndColor to set.
       * @since 1.7
       */
02373       public synchronized void setGradientEndColor(Color gradientEndColor)
      {
            if(gradientEndColor!=null)
                  this.gradientEndColor = gradientEndColor;
      }



      /**
       * @return the gradientMidPoint.
       * @since 1.7
       */
02385       public synchronized double getGradientMidPoint()
      {
            return gradientMidPoint;
      }



      /**
       * @param gradientMidPoint the gradientMidPoint to set.
       * @since 1.7
       */
02396       public synchronized void setGradientMidPoint(double gradientMidPoint)
      {
            if(gradientMidPoint>=0 && gradientMidPoint<=1)
                  this.gradientMidPoint = gradientMidPoint;
      }



      /**
       * @return the gradientStartColor.
       * @since 1.7
       */
02408       public synchronized Color getGradientStartColor()
      {
            return gradientStartColor;
      }



      /**
       * @param gradientStartColor the gradientStartColor to set.
       * @since 1.7
       */
02419       public synchronized void setGradientStartColor(Color gradientStartColor)
      {
            if(gradientStartColor!=null)
                  this.gradientStartColor = gradientStartColor;
      }
      
      
      
      /**
       * @return The PSTricks code for the filling of the figure.
       * @since 1.7
       */
02431       public String getPSTricksCodeFilling(float ppc)
      {
            String str="fillstyle=";//$NON-NLS-1$

            if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_NONE))
            {
                  if(isFilled)
                        str += "solid"; //$NON-NLS-1$
                  else str = "";//$NON-NLS-1$
            }
            else
                  if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_GRADIENT))
                  {
                        str+= "gradient,gradlines=2000";//$NON-NLS-1$
                        
                        if(!gradientStartColor.equals(PSTricksConstants.DEFAULT_GRADIENT_START_COLOR))
                        {
                              String name = DviPsColors.getColourName(gradientStartColor);
                              if(name==null)
                              {
                                    name = "color"+number+'g';//$NON-NLS-1$
                                    DviPsColors.addUserColour(gradientStartColor, name); 
                              }
                              str += ",gradbegin=" + name; //$NON-NLS-1$
                        }
                        
                        if(!gradientEndColor.equals(PSTricksConstants.DEFAULT_GRADIENT_END_COLOR))
                        {
                              String name = DviPsColors.getColourName(gradientEndColor);
                              if(name==null)
                              {
                                    name = "color"+number+'f';//$NON-NLS-1$
                                    DviPsColors.addUserColour(gradientEndColor, name); 
                              }
                              str += ",gradend=" + name; //$NON-NLS-1$
                        }
                        
                        if(gradientMidPoint!=PSTricksConstants.DEFAULT_GRADIENT_MID_POINT)
                              str+=",gradmidpoint="+(float)gradientMidPoint;//$NON-NLS-1$
                        
                        if(gradientAngle!=PSTricksConstants.DEFAULT_GRADIENT_ANGLE)
                              str+=",gradangle="+(float)toDegrees(gradientAngle);//$NON-NLS-1$
                  }
                  else
                  {
                        if(hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_CROSSHATCH))
                              str += "crosshatch"; //$NON-NLS-1$
                        else
                              if (hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_HLINES))
                                    str += "hlines"; //$NON-NLS-1$
                              else
                                    str += "vlines"; //$NON-NLS-1$
      
                        if(isFilled)
                              str += "*"; //$NON-NLS-1$
      
                        str += ",hatchwidth=" + (getHatchingWidth()/ppc) + ",hatchangle=" + //$NON-NLS-1$ //$NON-NLS-2$
                                    (float)Math.toDegrees(hatchingAngle);
                        
                        if(((float)hatchingSep)!=((float)DEFAULT_HATCH_SEP))
                              str+=",hatchsep="+(float)(hatchingSep/PPC); //$NON-NLS-1$
                        
                        if(!hatchingColor.equals(PSTricksConstants.DEFAULT_HATCHING_COLOR))
                        {
                              String name = DviPsColors.getColourName(hatchingColor);
                              if(name==null)
                              {
                                    name = "color"+number+'c';//$NON-NLS-1$
                                    DviPsColors.addUserColour(hatchingColor, name); 
                              }
                              str += ",hatchcolor=" + name; //$NON-NLS-1$
                        }
                  }
            
            if(isFilled)
            {
                  if(!interiorColor.equals(PSTricksConstants.DEFAULT_INTERIOR_COLOR))
                  {
                        String name = DviPsColors.getColourName(interiorColor);
                        if(name==null)
                        {
                              name = "color"+number+'b';//$NON-NLS-1$
                              DviPsColors.addUserColour(interiorColor, name); 
                        }
                        str += ",fillcolor=" + name; //$NON-NLS-1$
                  }
            }
            
            return str;
      }
      
      
      
      
      /**
       * @return The PSTricks code for the shape of the lines of the figure.
       * @since 1.7
       */
02529       public String getPSTricksCodeLine(float ppc)
      {
            String str = "";//$NON-NLS-1$
            boolean coma = false;
            
            if(!linesColor.equals(PSTricksConstants.DEFAULT_LINE_COLOR))
            {
                  String name = DviPsColors.getColourName(linesColor);
                  if(name==null)
                  {
                        name = "color"+number;//$NON-NLS-1$
                        DviPsColors.addUserColour(linesColor, name); 
                  }
                  str += "linecolor=" + name; //$NON-NLS-1$
                  coma = true;
            }
            
            if(lineStyle.equals(PSTricksConstants.LINE_DOTTED_STYLE))
                  str += (coma ? "," : "")+ "linestyle=" + lineStyle + ",dotsep=" + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
                              (getDotSep() / ppc) + "cm"; //$NON-NLS-1$
            else
                  if (lineStyle.equals(PSTricksConstants.LINE_DASHED_STYLE))
                        str += (coma ? "," : "") +"linestyle=" + lineStyle + ",dash=" + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
                                    (getBlackDashLength() / ppc) + "cm " + //$NON-NLS-1$
                                    (getWhiteDashLength() / ppc) + "cm"; //$NON-NLS-1$

            return str;
      }
      
      
      
      
      /**
       * @return True if the current style of the interior of the figure is a gradient.
       * @since 1.7
       */
02565       public synchronized boolean hasGradient()
      {
            return hatchingStyle.equals(PSTricksConstants.TOKEN_FILL_GRADIENT);
      }
      
      

      
      /**
       * @return The borders of the figure (taking account of the thickness, the double borders, ...).
       * @since 1.7
       */
02577       public LaTeXDrawRectangle getBoundBorders()
      {
            LaTeXDrawPoint2D NW = getTheNWBoundPoint(), SE = getTheSEBoundPoint();
            return new LaTeXDrawRectangle(NW, SE, false);
      }





      /**
       * @return the hatchingSep.
       * @since 1.8
       */
02591       public synchronized double getHatchingSep()
      {
            return hatchingSep;
      }



      /**
       * @param hatchSep the hatchingSep to set.
       * @since 1.8
       */
02602       public synchronized void setHatchingSep(double hatchSep)
      {
            if(hatchSep>0 && !Double.isInfinite(hatchSep) && !Double.isNaN(hatchSep))
                  this.hatchingSep = hatchSep;
      }



      /**
       * @return the canHaveArrow.
       */
02613       public synchronized boolean canHaveArrow()
      {
            return canHaveArrow;
      }



      /**
       * Returns horizontally the figure.
       * @since 1.8
       * @param origin The location of the horizontal axe.
       */
      public abstract void mirrorHorizontal(LaTeXDrawPoint2D origin);


      
      /**
       * Returns vertically the figure.
       * @since 1.8
       * @param origin The location of the vertical axe.
       */
      public abstract void mirrorVertical(LaTeXDrawPoint2D origin);



      /**
       * Updates the coordinates of the figure to the grid given in parameter.<br>
       * Nothing will be done if the magnetic grid is not activated.
       * @since 1.9
       * @param grid The magnetic grid.
       */
      public abstract void updateToGrid(MagneticGrid grid);

      
      
      
      /**
       * Checks if the parameters of the figures are equals.
       * @param f The figure to compare.
       * @param considerShadow True if the parameters of the shadows must be considered.
       * @param considerArrow True if the parameters of the arrows must be considered.
       * @return True if the parameters are equals.
       * @since 1.9
       */
02657       public boolean isParametersEquals(Figure f, boolean considerShadow, boolean considerArrow)
      {
            boolean lineOk = !f.isDashableOrDotable || !isDashableOrDotable || 
                                    (lineStyle.equals(f.lineStyle) && thickness==f.thickness && 
                                    (lineStyle.equals(PSTricksConstants.LINE_NONE_STYLE) ||
                                    (lineStyle.equals(PSTricksConstants.LINE_DOTTED_STYLE) && dotSep==f.dotSep) ||
                                    (lineStyle.equals(PSTricksConstants.LINE_DASHED_STYLE) && 
                                    blackDashLength==f.blackDashLength && whiteDashLength==f.whiteDashLength)));
            
            boolean filledOk = !f.canBeFilled || !canBeFilled || 
                                          (isFilled==f.isFilled && interiorColor.equals(f.interiorColor));
                                          
            boolean dblbndOk = !f.isDoubleBoundaryable || f.isDoubleBoundaryable || 
                                          (f.hasDoubleBoundary==hasDoubleBoundary &&
                                          doubleColor.equals(f.doubleColor) && doubleSep==f.doubleSep);
            
            boolean arrowOk = !considerArrow || !f.canHaveArrow || !canHaveArrow || 
                                      (((Arrowable)f).getArrowHead1().equals(((Arrowable)this).getArrowHead1()) &&
                                      ((Arrowable)f).getArrowHead2().equals(((Arrowable)this).getArrowHead2()));
            
            boolean hatchOk = (!f.canBeFilled || !canBeFilled || 
                                          ((f.hatchingStyle.equals(hatchingStyle) && (!isHatched() ||
                                          (f.hatchingAngle==hatchingAngle && f.hatchingColor.equals(hatchingColor) &&
                                          ((float)f.hatchingSep)==((float)hatchingSep) && f.hatchingWidth==hatchingWidth))) && 
                                      (hasGradient()==f.hasGradient() &&(!hasGradient() ||
                                      (gradientAngle==f.gradientAngle && gradientEndColor.equals(f.gradientEndColor) &&
                                      gradientMidPoint==f.gradientMidPoint && gradientStartColor.equals(f.gradientStartColor))))));
            
            boolean shadowOk = !considerShadow || !f.canHaveShadow || !canHaveArrow || 
                                          (hasShadow==f.hasShadow && shadowAngle==f.shadowAngle &&
                                          shadowColor.equals(f.shadowColor) && ((float)shadowSize)==((float)f.shadowSize));
            
            return linesColor.equals(f.linesColor) && lineOk && filledOk && dblbndOk && shadowOk &&
                        hatchOk && arrowOk ;
      }
      
      
      
      /**
       * @return True is a delimiter is selected.
       * @since 1.9
       */
02699       public boolean isDelimitorSelected()
      {
            return dSelected!=null || (borders==null ? false : borders.isDelimitorSelected());
      }


      
      /**
       * @return The position of the selected delimiter.
       * @since 1.9
       */
02710       public int getSelectedDelimitorOrientation()
      {
            if(isOnRotation())
                  return DELIMITOR_ROTATION;
            
            return DELIMITOR_ORIENTATION_NONE;
      }
      
      
      
      /**
       * Sometimes a rectangle is too small to be drawn; this method check if the given shape is too small
       * and if it is the case, it return a visible shape based on the given shape.
       * @param s The shape to check.
       * @return A visible check if the given shape is too small or null if it is not the case.
       * @since 1.9
       */
02727       protected Shape getTooSmallShape(Shape s)
      {
            Rectangle2D bds = s.getBounds2D();
            
            if(bds.getHeight()<=0)
            {
                  if(bds.getWidth()<=0)
                        return new Line2D.Double(bds.getMinX(), bds.getMinY(), bds.getMinX()+1, bds.getMinY()+1);
                  return new Line2D.Double(bds.getMinX(), bds.getMaxY(), bds.getMaxX(), bds.getMaxY());
            }
            
            if(bds.getWidth()<=0)
                  return new Line2D.Double(bds.getMaxX(), bds.getMinY(), bds.getMaxX(), bds.getMaxY());
            return null;
      }
      
      
      
      
      /**
       * Gives a gradient to the shape.
       * @since 1.9
       */
02750       protected void setHasGradient()
      {
            hatchingStyle = PSTricksConstants.TOKEN_FILL_GRADIENT;
      }
      
      
      
      @Override
      public int hashCode()
      {
            return (int)thickness+(int)doubleSep+(linesColor.hashCode()^interiorColor.hashCode()^
                        hatchingStyle.hashCode()^lineStyle.hashCode());
      }
      
      
      
      
      /**
       * Given a right-rectangle ABC right in A, it computes the gap created by the corner of the triangle in B
       * based on an initial gap.
       * @param a The point A.
       * @param b The point B.
       * @param c The point C.
       * @param gap The initial gap (for example, the thickness, the double border gap,...).
       * @return The gap created by the corner of the point B.
       * @since 2.0.0
       */
02777       public static double getCornerGap(Point2D a, Point2D b, Point2D c, double gap)
      {
            if(a==null || b==null || c==null)
                  return 0.;
            
            return gap / Triangle.getAltitude(a, b, c) * a.distance(b);
      }
      
      
      
      
      /**
       * @return True if when the shape has a shadow, then it is filled.
       * @since 2.0.0
       */
02792       public boolean shadowFillsShape()
      {
            return true;
      }


      /**
       * @return the shape.
       * @since 2.0.0
       */
02802       public synchronized Shape getShape()
      {
            return shape;
      }


      /**
       * @param number the number to set.
       * @since 2.0.0
       */
02812       public synchronized void setNumber(int number)
      {
            this.number = number;
      }


      public void setNewNumber()
      {
            setNumber(meter++);
      }
      
      
      
      @Override
      public String toString() 
      {
            return getClass().getName() + "#" + getNumber() + "[thick=" + getThickness() + ", bordCol=" + getLinesColor() +  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                        ", intCol=" + getInteriorColor() + ", dbleCol=" + getDoubleColor() + ", shadCol=" + getShadowColor() + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                        ", isFilled=" + isFilled() + ", hasShad=" + hasShadow() + ", hasDble=" + hasDoubleBoundary() + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                        ", shadSize=" + getShadowSize() + ", shadAngle=" + getShadowAngle() + ", gradAngle=" + getGradientAngle() + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                        ", gradMP=" + getGradientMidPoint() + ", gradCol1=" + getGradientStartColor() + ", gradCol2=" + getGradientEndColor() + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                        ", bordPos=" + getBordersPosition() + ", blackDash=" + getBlackDashLength() + ", dotSep=" + getDotSep() +  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                        ", dbleSep=" + getDoubleSep() + ", hatchAngle=" + getHatchingAngle() + ", hatchSep=" + getHatchingSep() +  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                        ", hatchStyle=" + getHatchingStyle() + ", hatchWidth=" + getHatchingWidth() + ", lineStyle=" + getLineStyle() + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                        ", rotAngle=" + getRotationAngle() + ", whiteDash=" + getWhiteDashLength() + ", gc=" + getGravityCenter() +  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                        ", isHatched=" + isHatched() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
      }
}

Generated by  Doxygen 1.6.0   Back to index