Package org.eclipse.sapphire.ui.swt.gef.figures

Source Code of org.eclipse.sapphire.ui.swt.gef.figures.FigureUtil

/******************************************************************************
* Copyright (c) 2014 Oracle
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    Ling Hao - initial implementation and ongoing maintenance
******************************************************************************/

package org.eclipse.sapphire.ui.swt.gef.figures;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.geometry.Vector;
import org.eclipse.sapphire.ui.LineStyle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Path;

/**
* @author <a href="mailto:ling.hao@oracle.com">Ling Hao</a>
*/

public class FigureUtil {

  public static PointList getAdjustedPointList(PointList points, double zoom, double lw) {
    Rectangle zoomedBounds = points.getBounds().getCopy().scale(zoom);
    double middlex = zoomedBounds.x + (zoomedBounds.width / 2);
    double middley = zoomedBounds.y + (zoomedBounds.height / 2);

    PointList ret = new PointList();
    for (int i = 0; i < points.size(); i++) {
      Point point = points.getPoint(i);
      point.scale(zoom);

      // translate all points towards the middle depending on the
      // line-width, so that the polyline remains inside the bounds
      // Note, that the delta has to be rounded up/down depending on the
      // relative location from point to middle.
      double dx;
      double dy;
      if (point.x < middlex) {
        dx = Math.ceil(((middlex - point.x) / zoomedBounds.width) * lw);
      } else {
        dx = Math.floor(((middlex - point.x) / zoomedBounds.width) * lw);
      }
      if (point.y < middley) {
        dy = Math.ceil(((middley - point.y) / zoomedBounds.height) * lw);
      } else {
        dy = Math.floor(((middley - point.y) / zoomedBounds.height) * lw);
      }

      point.translate((int) dx, (int) dy);

      ret.addPoint(point);
    }
    return ret;
  }

  public static Path getBezierPath(List<BezierPoint> origPoints, boolean isClosed) {
    Path path = new Path(null);
    // make a copy, so that we can change it
    List<BezierPoint> points = new ArrayList<BezierPoint>(origPoints.size() + 2);
    points.addAll(origPoints);

    // Draw simple lines, as bezier-curve doesn't make sense
    if (points.size() < 3 || !hasBezierDistance(origPoints)) {
      if (points.size() != 0) {
        path.moveTo(points.get(0).getX(), points.get(0).getY());
        for (int i = 1; i < points.size(); i++) {
          path.lineTo(points.get(i).getX(), points.get(i).getY());
        }
      }
    } else { // Draw bezier curve

      // Idea for the closed bezier curve:
      // The first two points are added to the end of the point-list.
      // Afterwards the bezier-curve through the points is drawn as usual,
      // except that the first line and the last line are not drawn.

      // Adjust point-list if closing is needed: add the first two points
      // again at the end
      if (isClosed) {
        if (!points.get(points.size() - 1).equals(points.get(0))) { // first
                                      // !=
                                      // last
                                      // =>
                                      // only
                                      // then
                                      // double
                                      // first
                                      // point
          points.add(points.get(0));
        }
        points.add(points.get(1));
      }

      // Initialize the points for calculation
      Point c = points.get(0).createDraw2dPoint(); // the current
                              // control-point
      Point q = points.get(1).createDraw2dPoint(); // the point following
                              // the current
      // control-point
      Point r = new Point();
      Point s = new Point();

      // If not closed, draw the first line from the first point to r,
      // otherwise move to r
      determineBezierPoints(c, q, r, s, points.get(0).getBezierDistanceAfter(), points.get(1).getBezierDistanceBefore());
      if (!isClosed) {
        path.moveTo(points.get(0).getX(), points.get(0).getY());
        path.lineTo(r.x, r.y);
      } else {
        path.moveTo(r.x, r.y);
      }

      for (int index = 2; index < points.size(); index++) {
        // Move c and q one position forward
        c.setLocation(q);
        points.get(index).copyToDraw2dPoint(q);

        // Update r and s
        determineBezierPoints(c, q, r, s, points.get(index - 1).getBezierDistanceAfter(), points.get(index)
            .getBezierDistanceBefore());

        // draw the curve
        path.quadTo(c.x, c.y, s.x, s.y);
        path.lineTo(r.x, r.y);
      }

      // If not closed, draw the final line from r to the last point,
      // otherwise do nothing
      if (!isClosed) {
        // Draw the final line from r to the last point.
        path.lineTo(points.get(points.size() - 1).getX(), points.get(points.size() - 1).getY());
      }
    }

    // The algorithm already takes care, that the line ends again at the
    // start-point.
    // But a final path.close() takes care of drawing problems.
    if (isClosed) {
      path.close();
    }

    return path;
  }

  public static boolean hasBezierDistance(List<BezierPoint> points) {
    for (BezierPoint point : points) {
      if (point.getBezierDistanceBefore() != 0 || point.getBezierDistanceAfter() != 0)
        return true;
    }
    return false;
  }
 
  private static void determineBezierPoints(Point c, Point q, Point r, Point s, int distanceAfterCurrent, int distanceBeforeNext) {
    // Determine v and m
    // Ray v = new Ray();
    int vx = q.x - c.x;
    int vy = q.y - c.y;
    Vector v = new Vector(vx, vy);
    double absV = v.getLength();
    // Ray m = new Ray();
    int mx = Math.round(c.x + ( (float) vx ) / 2);
    int my = Math.round(c.y + ( (float) vy ) / 2);

    // Determine tolerance
    // Idea:
    // The vector v is the line after the current control-point c.
    // If the sum of the bezier-distances is greater than the half
    // line-length of v,
    // then a simplified calculation for the bezier-points r and s must be
    // done.
    int tolerance = distanceAfterCurrent + distanceBeforeNext;

    // Determine the "results" r and s
    if (absV < tolerance) {
      // use the the midpoint m for r and s
      r.x = mx;
      r.y = my;
      s.x = mx;
      s.y = my;
    } else {
      double x = (absV - distanceBeforeNext) / absV;
      r.x = Math.round(c.x + (float) x * vx);
      r.y = Math.round(c.y + (float) x * vy);
      double y = distanceAfterCurrent / absV;
      s.x = Math.round(c.x + (float) y * vx);
      s.y = Math.round(c.y + (float) y * vy);
    }
  }
 
  public static int convertLineStyle(LineStyle style)
  {
    int swtStyle = SWT.LINE_SOLID;
    if (style == LineStyle.DASH)
    {
      swtStyle = SWT.LINE_DASH;
    }
    else if (style == LineStyle.DASH_DOT)
    {
      swtStyle = SWT.LINE_DASHDOT;
    }
    else if (style == LineStyle.DOT)
    {
      swtStyle = SWT.LINE_DOT;
    }
    return swtStyle;
  }
 
  public static Rectangle getAdjustedRectangle(Rectangle rectangle, double zoom, int lw) {
    if (rectangle == null) {
      return null;
    }

    Rectangle ret = new Rectangle(rectangle);

    if (zoom != 1.0) {
      ret.x = (int) (Math.floor(rectangle.x * zoom));
      ret.y = (int) (Math.floor(rectangle.y * zoom));
      ret.width = (int) (Math.floor(((rectangle.x + rectangle.width) * zoom))) - ret.x;
      ret.height = (int) (Math.floor(((rectangle.y + rectangle.height) * zoom))) - ret.y;
    }

    int adjustmentTopLeft = lw / 2;
    int adjustmentBottomRight = lw;
    ret.x += adjustmentTopLeft;
    ret.y += adjustmentTopLeft;
    ret.width -= adjustmentBottomRight;
    ret.height -= adjustmentBottomRight;

    return ret;
  }

}
TOP

Related Classes of org.eclipse.sapphire.ui.swt.gef.figures.FigureUtil

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.