Package net.sf.latexdraw.glib.models.impl

Source Code of net.sf.latexdraw.glib.models.impl.LAbstractCtrlPointShape

package net.sf.latexdraw.glib.models.impl;

import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;

import net.sf.latexdraw.glib.models.GLibUtilities;
import net.sf.latexdraw.glib.models.ShapeFactory;
import net.sf.latexdraw.glib.models.interfaces.shape.IControlPointShape;
import net.sf.latexdraw.glib.models.interfaces.shape.ILine;
import net.sf.latexdraw.glib.models.interfaces.shape.IPoint;
import net.sf.latexdraw.glib.models.interfaces.shape.IShape;

/**
* Defines a model of a abstract shape that contains control points.<br>
* <br>
* This file is part of LaTeXDraw.<br>
* Copyright (c) 2005-2014 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>
* 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>
* 07/05/2009<br>
* @author Arnaud BLOUIN
* @version 3.0
* @since 3.0
*/
abstract class LAbstractCtrlPointShape extends LModifiablePointsShape implements IControlPointShape {
  /** The default balance gap used to balance all the points of the bézier curve. */
  int DEFAULT_BALANCE_GAP = 50;

  /** This vector contains the points which allows to change the angles of the curves */
  protected final List<IPoint> firstCtrlPts;

  /** Contains the second control points of each points; useful for closed curve. */
  protected final List<IPoint> secondCtrlPts;


  /**
   * Creates the shape.
   */
    protected LAbstractCtrlPointShape() {
    super();
    firstCtrlPts  = new ArrayList<>();
    secondCtrlPts = new ArrayList<>();
  }


  @Override
  public void scale(final double x, final double y, final Position pos, final Rectangle2D bound) {
    super.scale(x, y, pos, bound);
    scaleSetPoints(firstCtrlPts, x, y, pos, bound);
    scaleSetPoints(secondCtrlPts, x, y, pos, bound);
  }

  /**
   * Method used by the balance method. Just returns the balanced control points of the given points.
   */
  private IPoint[] getBalancedPoints(final IPoint pt, final IPoint prevPt, final IPoint nextPt) {
    final ILine line = ShapeFactory.createLine(prevPt, nextPt);

    if(line.isHorizontalLine())
      line.setLine(pt.getX(), pt.getY(), pt.getX()+10, pt.getY());
    else {
      final double b = pt.getY() - line.getA()*pt.getX();
      line.setLine(pt.getX(), pt.getY(), pt.getX()+10, line.getA()*(pt.getX()+10) + b);
    }

    return line.findPoints(pt, DEFAULT_BALANCE_GAP);
  }


  /**
   * Method used by the balance method. Just sets the given control points at the given position.
   */
  private void setControlPoints(final int position, final IPoint[] ctrlPts) {
    if(ctrlPts==null || ctrlPts.length!=2) return ;

    // If there exists an intersection point between the two lines created using control points and points,
    // where is a loop that must be removed by inverting the control points.
    // For the first point, the lines are created differently.
    final int posPrev = position==0 ? 1 : position - 1;
    final int posNext = position==0 ? points.size()-1 : position==points.size()-1 ? 0 : position + 1;
    final ILine line1 = ShapeFactory.createLine(getPtAt(posPrev), ctrlPts[0]);
    final ILine line2 = ShapeFactory.createLine(getPtAt(posNext), ctrlPts[1]);

    if(line1.getIntersectionSegment(line2)==null) {
      firstCtrlPts.get(position).setPoint(ctrlPts[0]);
      secondCtrlPts.get(position).setPoint(ctrlPts[1]);
    }else {
      firstCtrlPts.get(position).setPoint(ctrlPts[1]);
      secondCtrlPts.get(position).setPoint(ctrlPts[0]);
    }
  }


  @Override
  public void balance() {
    final int size = getNbPoints();

    if(size<3) return ;//Works only with more than 2 points.

    IPoint ptPrev;
    IPoint ptNext;

    // Balancing all the points except the first and the last one.
    for(int i=1; i<size-1; i++) {
      ptPrev = points.get(i-1);
      ptNext = points.get(i+1);
      setControlPoints(i, getBalancedPoints(points.get(i), ptPrev, ptNext));
    }

    // Balancing the first and the last points.
    ptPrev = points.get(size-1);
    ptNext = points.get(1);
    setControlPoints(0, getBalancedPoints(points.get(0), ptPrev, ptNext));
    ptPrev = points.get(size-2);
    ptNext = points.get(0);
    setControlPoints(size-1, getBalancedPoints(points.get(size-1), ptPrev, ptNext));
  }


  @Override
  public IPoint getFirstCtrlPtAt(final int position) {
    final IPoint point;

    if(firstCtrlPts.isEmpty() || position<-1 || position>=firstCtrlPts.size())
      point = null;
    else
      point = position==-1 ? firstCtrlPts.get(firstCtrlPts.size()-1) : firstCtrlPts.get(position);

    return point;
  }


  @Override
  public List<IPoint> getFirstCtrlPts() {
    return firstCtrlPts;
  }


  @Override
  public IPoint getSecondCtrlPtAt(final int position) {
    final IPoint point;

    if(secondCtrlPts.isEmpty() || position<-1 || position>=secondCtrlPts.size())
      point = null;
    else
      point = position==-1 ? secondCtrlPts.get(secondCtrlPts.size()-1) : secondCtrlPts.get(position);

    return point;
  }


  @Override
  public List<IPoint> getSecondCtrlPts() {
    return secondCtrlPts;
  }


  @Override
  public void setXFirstCtrlPt(final double x, final int id) {
    if(GLibUtilities.isValidCoordinate(x) && id>=0 && id<firstCtrlPts.size())
      firstCtrlPts.get(id).setX(x);
  }


  @Override
  public void setXSecondCtrlPt(final double x, final int id) {
    if(GLibUtilities.isValidCoordinate(x) && id>=0 && id<secondCtrlPts.size())
      secondCtrlPts.get(id).setX(x);
  }


  @Override
  public void setYFirstCtrlPt(final double y, final int id) {
    if(GLibUtilities.isValidCoordinate(y) && id>=0 && id<firstCtrlPts.size())
      firstCtrlPts.get(id).setY(y);
  }


  @Override
  public void setYSecondCtrlPt(final double y, final int id) {
    if(GLibUtilities.isValidCoordinate(y) && id>=0 && id<secondCtrlPts.size())
      secondCtrlPts.get(id).setY(y);
  }


  @Override
  public void updateSecondControlPoints() {
    for(int i=0, size = points.size(); i<size; i++)
      secondCtrlPts.get(i).setPoint(firstCtrlPts.get(i).centralSymmetry(points.get(i)));
  }


  @Override
  public boolean setPoint(final double x, final double y, final int position) {
    final IPoint pt = getPtAt(position);

    if(pt==null || !GLibUtilities.isValidPoint(x, y))
      return false;

    final double tx = x - pt.getX();
    final double ty = y - pt.getY();
    super.setPoint(x, y, position);
    getFirstCtrlPtAt(position).translate(tx, ty);
    getSecondCtrlPtAt(position).translate(tx, ty);

    return true;
  }


  @Override
  public void setRotationAngle(final double rotationAngle) {
    if(GLibUtilities.isValidCoordinate(rotationAngle)) {
      final double diff = rotationAngle-this.rotationAngle;
      final IPoint gc = getGravityCentre();

      super.setRotationAngle(rotationAngle);

      for(final IPoint pt : firstCtrlPts)
        pt.setPoint(pt.rotatePoint(gc, diff));
      updateSecondControlPoints();
    }
  }


  @Override
  public boolean removePoint(final IPoint pt) {
    return removePoint(points.indexOf(pt))!=null;
  }


  @Override
  public IPoint removePoint(final int position) {
    final IPoint deleted = super.removePoint(position);

    if(deleted!=null) {
      firstCtrlPts.remove(position==-1 ? firstCtrlPts.size()-1 : position);
      secondCtrlPts.remove(position==-1 ? secondCtrlPts.size()-1 : position);
    }

    return deleted;
  }


  @Override
  public void addPoint(final IPoint pt, final int position) {
    super.addPoint(pt, position);

    // Adding the control points.
    if(GLibUtilities.isValidPoint(pt) && position>=-1 && position<points.size()) {
      final IPoint ctrlPt = ShapeFactory.createPoint(pt.getX(), pt.getY()+DEFAULT_POSITION_CTRL);
      if(position==-1) {
        firstCtrlPts.add(ctrlPt);
        secondCtrlPts.add(ctrlPt.centralSymmetry(pt));
      } else {
        firstCtrlPts.add(position, ctrlPt);
        secondCtrlPts.add(position, ctrlPt.centralSymmetry(pt));
      }
    }
  }


  @Override
  protected void copyPoints(final IShape sh) {
    super.copyPoints(sh);

    if(sh instanceof IControlPointShape) {
      final IControlPointShape cpSh = (IControlPointShape)sh;
      List<IPoint> pts      = cpSh.getFirstCtrlPts();

      firstCtrlPts.clear();
      for(final IPoint pt : pts)
        firstCtrlPts.add(ShapeFactory.createPoint(pt));

      pts = cpSh.getSecondCtrlPts();
      secondCtrlPts.clear();
      for(final IPoint pt : pts)
        secondCtrlPts.add(ShapeFactory.createPoint(pt));
    }
  }


  @Override
  public void translate(final double tx, final double ty) {
    super.translate(tx, ty);

    // Translating control points.
    if(GLibUtilities.isValidPoint(tx, ty)) {
      for(final IPoint pt : firstCtrlPts)
        pt.translate(tx, ty);
      for(final IPoint pt : secondCtrlPts)
        pt.translate(tx, ty);
    }
  }
}
TOP

Related Classes of net.sf.latexdraw.glib.models.impl.LAbstractCtrlPointShape

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.