/* * This file is part of LaTeXDraw. * Copyright (c) 2005-2017 Arnaud BLOUIN * 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. * 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. */ package net.sf.latexdraw.view; import java.util.ArrayList; import java.util.List; import net.sf.latexdraw.models.ShapeFactory; import net.sf.latexdraw.models.interfaces.shape.IBezierCurve; import net.sf.latexdraw.models.interfaces.shape.IDot; import net.sf.latexdraw.models.interfaces.shape.IModifiablePointsShape; import net.sf.latexdraw.models.interfaces.shape.IPlot; import net.sf.latexdraw.models.interfaces.shape.IPoint; import net.sf.latexdraw.models.interfaces.shape.IPolygon; import net.sf.latexdraw.models.interfaces.shape.IPolyline; import net.sf.latexdraw.models.interfaces.shape.IShape; import net.sf.latexdraw.models.interfaces.shape.PlotStyle; /** * @author Arnaud Blouin */ public final class PlotViewHelper { public static final PlotViewHelper INSTANCE = new PlotViewHelper(); private PlotViewHelper() { super(); } private IPoint getPolarPoint(final IPlot shape, final double x, final double xs, final double ys, final double posX, final double posY) { final double radius = shape.getY(x); final double angle = Math.toRadians(x); final double x1 = radius * Math.cos(angle); final double y1 = -radius * Math.sin(angle); return ShapeFactory.INST.createPoint(x1 * IShape.PPC * xs + posX, y1 * IShape.PPC * ys + posY); } public void fillPoints(final IPlot shape, final IModifiablePointsShape sh, final double posX, final double posY, final double minX, final double maxX, final double step) { final double xs = shape.getXScale(); final double ys = shape.getYScale(); double x = minX; if(shape.isPolar()) { for(int i = 0; i < shape.getNbPlottedPoints(); i++, x += step) { sh.addPoint(getPolarPoint(shape, x, xs, ys, posX, posY)); } sh.addPoint(getPolarPoint(shape, maxX, xs, ys, posX, posY)); }else { for(int i = 0; i < shape.getNbPlottedPoints(); i++, x += step) { sh.addPoint(ShapeFactory.INST.createPoint(x * IShape.PPC * xs + posX, -shape.getY(x) * IShape.PPC * ys + posY)); } sh.addPoint(ShapeFactory.INST.createPoint(maxX * IShape.PPC * xs + posX, -shape.getY(maxX) * IShape.PPC * ys + posY)); } } public List<IDot> updatePoints(final IPlot shape, final double posX, final double posY, final double minX, final double maxX, final double step) { final IPolyline pl = ShapeFactory.INST.createPolyline(); final List<IDot> dots = new ArrayList<>(); fillPoints(shape, pl, posX, posY, minX, maxX, step); for(IPoint pt : pl.getPoints()) { final IDot dot = ShapeFactory.INST.createDot(pt); dot.copy(shape); dot.setRotationAngle(0.0); dots.add(dot); } return dots; } public IPolygon updatePolygon(final IPlot shape, final double posX, final double posY, final double minX, final double maxX, final double step) { final IPolygon pg = ShapeFactory.INST.createPolygon(); fillPoints(shape, pg, posX, posY, minX, maxX, step); pg.copy(shape); return pg; } public IPolyline updateLine(final IPlot shape, final double posX, final double posY, final double minX, final double maxX, final double step) { final IPolyline pl = ShapeFactory.INST.createPolyline(); fillPoints(shape, pl, posX, posY, minX, maxX, step); pl.copy(shape); return pl; } public IBezierCurve updateCurve(final IPlot shape, final double posX, final double posY, final double minX, final double maxX, final double step) { // The algorithm follows this definition: // https://stackoverflow.com/questions/15864441/how-to-make-a-line-curve-through-points final double scale = 0.33; final IBezierCurve bc = ShapeFactory.INST.createBezierCurve(); fillPoints(shape, bc, posX, posY, minX, maxX, step); bc.setIsClosed(shape.getPlotStyle() == PlotStyle.CCURVE); bc.copy(shape); int i = 0; final int last = bc.getPoints().size() - 1; for(IPoint pt : bc.getPoints()) { if(i == 0) { final IPoint p2 = bc.getPtAt(i + 1); final IPoint tangent = p2.substract(pt); final IPoint q1 = pt.add(tangent.zoom(scale)); bc.setXFirstCtrlPt(q1.getX(), i); bc.setYFirstCtrlPt(q1.getY(), i); }else if(i == last) { final IPoint p0 = bc.getPtAt(i - 1); final IPoint tangent = pt.substract(p0); final IPoint q0 = pt.substract(tangent.zoom(scale)); bc.setXFirstCtrlPt(q0.getX(), i); bc.setYFirstCtrlPt(q0.getY(), i); }else { final IPoint p0 = bc.getPtAt(i - 1); final IPoint p2 = bc.getPtAt(i + 1); final IPoint tangent = p2.substract(p0).normalise(); final IPoint q0 = pt.substract(tangent.zoom(scale * pt.substract(p0).magnitude())); bc.setXFirstCtrlPt(q0.getX(), i); bc.setYFirstCtrlPt(q0.getY(), i); } i++; } bc.updateSecondControlPoints(); return bc; } }