/* * Apache License * Version 2.0, January 2004 * http://www.apache.org/licenses/ * * Copyright 2013 Aurelian Tutuianu * Copyright 2014 Aurelian Tutuianu * Copyright 2015 Aurelian Tutuianu * Copyright 2016 Aurelian Tutuianu * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package rapaio.graphics.plot.plotcomp; import rapaio.data.Var; import rapaio.experiment.grid.MeshGrid; import rapaio.graphics.base.Range; import rapaio.graphics.opt.GOpt; import rapaio.graphics.plot.PlotComponent; import java.awt.*; import java.awt.geom.Line2D; import java.awt.geom.Path2D; import java.awt.geom.Point2D; import java.util.LinkedList; /** * Created by <a href="mailto:padreati@yahoo.com">Aurelian Tutuianu</a> at 1/20/15. */ @Deprecated public class MeshContour extends PlotComponent { private static final long serialVersionUID = -642370269224702175L; private final MeshGrid mg; private boolean contour = false; private boolean fill = false; public MeshContour(MeshGrid mg, boolean contour, boolean fill, GOpt... opts) { this.mg = mg; this.contour = contour; this.fill = fill; this.options.apply(opts); } @Override protected Range buildRange() { return new Range( mg.x().value(0), mg.y().value(0), mg.x().value(mg.x().rowCount() - 1), mg.y().value(mg.y().rowCount() - 1) ); } @Override public void paint(Graphics2D g2d) { Composite old = g2d.getComposite(); g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, options.getAlpha())); Var x = mg.x(); Var y = mg.y(); LinkedList<Point2D.Double> lines = new LinkedList<>(); for (int i = 0; i < mg.x().rowCount() - 1; i++) { for (int j = 0; j < mg.y().rowCount() - 1; j++) { if (!parent.getRange().contains(x.value(i), y.value(j))) continue; if (!parent.getRange().contains(x.value(i + 1), y.value(j + 1))) continue; int k = mg.side(i, j); k = k * 10 + mg.side(i + 1, j); k = k * 10 + mg.side(i + 1, j + 1); k = k * 10 + mg.side(i, j + 1); switch (k) { case 0: case 2222: // no contour // no fill break; case 1111: // no contour // full fill if (fill) { Path2D.Double path = new Path2D.Double(); path.moveTo(parent.xScale(x.value(i)), parent.yScale(y.value(j))); path.lineTo(parent.xScale(x.value(i + 1)), parent.yScale(y.value(j))); path.lineTo(parent.xScale(x.value(i + 1)), parent.yScale(y.value(j + 1))); path.lineTo(parent.xScale(x.value(i)), parent.yScale(y.value(j + 1))); path.lineTo(parent.xScale(x.value(i)), parent.yScale(y.value(j))); g2d.setColor(options.getColor(0)); g2d.setStroke(new BasicStroke()); g2d.draw(path); g2d.fill(path); } break; default: // no saddle point impl for now Point.Double[] points = new Point2D.Double[12]; int[] sides = new int[12]; // first fill corners points[0] = new Point2D.Double(parent.xScale(x.value(i)), parent.yScale(y.value(j))); sides[0] = mg.side(i, j); points[3] = new Point2D.Double(parent.xScale(x.value(i + 1)), parent.yScale(y.value(j))); sides[3] = mg.side(i + 1, j); points[6] = new Point2D.Double(parent.xScale(x.value(i + 1)), parent.yScale(y.value(j + 1))); sides[6] = mg.side(i + 1, j + 1); points[9] = new Point2D.Double(parent.xScale(x.value(i)), parent.yScale(y.value(j + 1))); sides[9] = mg.side(i, j + 1); // now fill middle points // (i,j) -> (i+1,j) if (sides[0] == 0 && sides[3] >= 1) { points[1] = new Point2D.Double(parent.xScale(mg.xLow(i, j)), parent.yScale(y.value(j))); sides[1] = 1; } if (sides[0] >= 1 && sides[3] == 0) { points[2] = new Point2D.Double(parent.xScale(mg.xLow(i, j)), parent.yScale(y.value(j))); sides[2] = 1; } if (sides[0] <= 1 && sides[3] == 2) { points[2] = new Point2D.Double(parent.xScale(mg.xHigh(i, j)), parent.yScale(y.value(j))); sides[2] = 2; } if (sides[0] == 2 && sides[3] <= 1) { points[1] = new Point2D.Double(parent.xScale(mg.xHigh(i, j)), parent.yScale(y.value(j))); sides[1] = 2; } // (i+1,j) -> (i+1,j+1) if (sides[3] == 0 && sides[6] >= 1) { points[4] = new Point2D.Double(parent.xScale(x.value(i + 1)), parent.yScale(mg.yLow(i + 1, j))); sides[4] = 1; } if (sides[3] >= 1 && sides[6] == 0) { points[5] = new Point2D.Double(parent.xScale(x.value(i + 1)), parent.yScale(mg.yLow(i + 1, j))); sides[5] = 1; } if (sides[3] <= 1 && sides[6] == 2) { points[5] = new Point2D.Double(parent.xScale(x.value(i + 1)), parent.yScale(mg.yHigh(i + 1, j))); sides[5] = 2; } if (sides[3] == 2 && sides[6] <= 1) { points[4] = new Point2D.Double(parent.xScale(x.value(i + 1)), parent.yScale(mg.yHigh(i + 1, j))); sides[4] = 2; } // (i+1,j+1) -> (i,j+1) if (sides[6] == 0 && sides[9] >= 1) { points[7] = new Point2D.Double(parent.xScale(mg.xLow(i, j + 1)), parent.yScale(y.value(j + 1))); sides[7] = 1; } if (sides[6] >= 1 && sides[9] == 0) { points[8] = new Point2D.Double(parent.xScale(mg.xLow(i, j + 1)), parent.yScale(y.value(j + 1))); sides[8] = 1; } if (sides[6] <= 1 && sides[9] == 2) { points[8] = new Point2D.Double(parent.xScale(mg.xHigh(i, j + 1)), parent.yScale(y.value(j + 1))); sides[8] = 2; } if (sides[6] == 2 && sides[9] <= 1) { points[7] = new Point2D.Double(parent.xScale(mg.xHigh(i, j + 1)), parent.yScale(y.value(j + 1))); sides[7] = 2; } // (i,j+1) -> (i,j) if (sides[9] == 0 && sides[0] >= 1) { points[10] = new Point2D.Double(parent.xScale(x.value(i)), parent.yScale(mg.yLow(i, j))); sides[10] = 1; } if (sides[9] >= 1 && sides[0] == 0) { points[11] = new Point2D.Double(parent.xScale(x.value(i)), parent.yScale(mg.yLow(i, j))); sides[11] = 1; } if (sides[9] <= 1 && sides[0] == 2) { points[11] = new Point2D.Double(parent.xScale(x.value(i)), parent.yScale(mg.yHigh(i, j))); sides[11] = 2; } if (sides[9] == 2 && sides[0] <= 1) { points[10] = new Point2D.Double(parent.xScale(x.value(i)), parent.yScale(mg.yHigh(i, j))); sides[11] = 2; } if (fill) { Path2D.Double path = new Path2D.Double(); Point2D.Double start = null; for (int q = 0; q < points.length; q++) { Point2D.Double p = points[q]; if (p == null || ((q % 3 == 0) && (sides[q] == 0 || sides[q] == 2))) continue; if (start == null) { start = p; path.moveTo(p.x, p.y); } else { path.lineTo(p.x, p.y); } } if (start == null) { continue; } path.lineTo(start.x, start.y); g2d.setColor(options.getColor(0)); g2d.setStroke(new BasicStroke()); g2d.draw(path); g2d.fill(path); } if (contour) { LinkedList<Point2D.Double> list = new LinkedList<>(); LinkedList<Integer> sideList = new LinkedList<>(); for (int q = 0; q < points.length; q++) { Point2D.Double p = points[q]; if (p == null || q % 3 == 0) continue; list.add(p); sideList.add(sides[q]); } if (sideList.size() > 1 && (Math.abs(sideList.get(0) - sideList.get(1)) < 1e-20)) { Point2D.Double p = list.pollLast(); list.addFirst(p); } lines.addAll(list); } } } } while (!lines.isEmpty()) { Point2D.Double from = lines.pollLast(); Point2D.Double to = lines.pollLast(); g2d.setColor(Color.BLACK); g2d.setStroke(new BasicStroke(options.getLwd())); g2d.draw(new Line2D.Double(from, to)); } g2d.setComposite(old); } }