package org.geogebra.common.euclidian.plot; import org.apache.commons.math3.util.Cloner; import org.geogebra.common.awt.GPoint2D; import org.geogebra.common.euclidian.EuclidianView; import org.geogebra.common.euclidian.EuclidianViewInterfaceSlim; import org.geogebra.common.euclidian.GeneralPathClipped; import org.geogebra.common.euclidian.plot.CurvePlotter.Gap; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.kernel.MyPoint; import org.geogebra.common.kernel.SegmentType; import org.geogebra.common.kernel.Matrix.CoordSys; import org.geogebra.common.kernel.Matrix.Coords; /** * General path clipped with methods for CurvePlotter * * @author mathieu * */ public class GeneralPathClippedForCurvePlotter extends GeneralPathClipped implements PathPlotter { private boolean lineDrawn; /** * constructor * * @param view * Euclidian view */ public GeneralPathClippedForCurvePlotter(EuclidianViewInterfaceSlim view) { super(view); } @Override public void lineTo(double[] pos) { drawTo(pos, SegmentType.LINE_TO); } @Override public void moveTo(double[] pos) { drawTo(pos, SegmentType.MOVE_TO); } @Override public void drawTo(double[] pos, SegmentType segmentType) { double[] p = Cloner.clone(pos); ((EuclidianView) view).toScreenCoords(p); drawTo(p[0], p[1], segmentType); } private void drawTo(double x, double y, SegmentType lineTo) { GPoint2D point = getCurrentPoint(); // no points in path yet if (point == null) { moveTo(x, y); lineDrawn = false; return; } boolean distant = !Kernel.isEqual(x, point.getX(), view.getMinPixelDistance()) || !Kernel.isEqual(y, point.getY(), view.getMinPixelDistance()); if (lineTo == SegmentType.CONTROL || lineTo == SegmentType.CURVE_TO || lineTo == SegmentType.ARC_TO || lineTo == SegmentType.AUXILIARY) { distant = true; } // only add points that are more than MIN_PIXEL_DISTANCE // from current location boolean isLine = lineTo != SegmentType.MOVE_TO; if (!distant && isLine == lineDrawn) { return; } if (lineTo == SegmentType.CONTROL || lineTo == SegmentType.CURVE_TO) { addPoint(x, y, lineTo); lineDrawn = true; return; } if (isLine) { addPoint(x, y, lineTo); lineDrawn = true; } else { moveTo(x, y); lineDrawn = false; } } private void drawTo(double x, double y, boolean lineTo) { drawTo(x, y, lineTo ? SegmentType.LINE_TO : SegmentType.MOVE_TO); } @Override public void corner() { MyPoint fp = firstPoint(); if (fp != null) { corner(fp.x, fp.y); closePath(); } } @Override public void corner(double[] pos) { double[] p = Cloner.clone(pos); ((EuclidianView) view).toScreenCoords(p); corner(p[0], p[1]); } private void corner(double x0, double y0) { int w = view.getWidth(); int h = view.getHeight(); GPoint2D pt = getCurrentPoint(); if (pt == null) { return; } double x = pt.getX(); double y = pt.getY(); if ((x < 0 && x0 > w) || (x > w && x0 < 0)) { drawTo(x, -10, true); drawTo(x0, -10, true); return; } if ((y < 0 && y0 > h) || (y > h && y0 < 0)) { drawTo(-10, y, true); drawTo(-10, y0, true); return; } if ((x > w || x < 0) && (y0 < 0 || y0 > h)) { drawTo(x, y0, true); return; } if ((x0 > w || x0 < 0) && (y < 0 || y > h)) { drawTo(x0, y, true); return; } } @Override public void firstPoint(double pos[], Gap moveToAllowed) { double[] p = Cloner.clone(pos); ((EuclidianView) view).toScreenCoords(p); final double x0 = p[0]; final double y0 = p[1]; // FIRST POINT // c(t1) and c(t2) are defined, lets go ahead and move to our first // point (x0, y0) // note: lineTo will automatically do a moveTo if this is the first gp // point if (moveToAllowed == Gap.MOVE_TO) { drawTo(x0, y0, false); } else if (moveToAllowed == Gap.LINE_TO || moveToAllowed == Gap.CORNER) { drawTo(x0, y0, true); } else if (moveToAllowed == Gap.RESET_XMIN) { double d = getCurrentPoint().getY(); if (!Kernel.isEqual(d, y0)) { drawTo(-10, d, true); drawTo(-10, y0, true); } drawTo(x0, y0, true); } else if (moveToAllowed == Gap.RESET_XMAX) { double d = getCurrentPoint().getY(); if (!Kernel.isEqual(d, y0)) { drawTo(view.getWidth() + 10, d, true); drawTo(view.getWidth() + 10, y0, true); } drawTo(x0, y0, true); } else if (moveToAllowed == Gap.RESET_YMIN) { double d = getCurrentPoint().getX(); if (!Kernel.isEqual(d, x0)) { drawTo(d, -10, true); drawTo(x0, -10, true); } drawTo(x0, y0, true); } else if (moveToAllowed == Gap.RESET_YMAX) { double d = getCurrentPoint().getX(); if (!Kernel.isEqual(d, x0)) { drawTo(getCurrentPoint().getX(), view.getHeight() + 10, true); drawTo(x0, view.getHeight() + 10, true); } drawTo(x0, y0, true); } } @Override public double[] newDoubleArray() { return new double[2]; } @Override public boolean copyCoords(MyPoint point, double[] ret, CoordSys transformSys) { Coords coords = new Coords(point.x, point.y, point.getZ(), 1); if (transformSys != CoordSys.XOY) { transformSys.getPointFromOriginVectors(coords, tmpCoords); coords.set(tmpCoords); } Coords projection = ((EuclidianView) view).getCoordsForView(coords); ret[0] = projection.getX(); ret[1] = projection.getY(); return true; } @Override public void endPlot() { // TODO Auto-generated method stub } private Coords tmpCoords = new Coords(4); @Override public boolean supports(CoordSys transformSys) { return view.isInPlane(transformSys); } }