/*
* 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.graphics.Plotter;
import rapaio.graphics.base.Range;
import rapaio.graphics.opt.GOpt;
import rapaio.graphics.plot.PlotComponent;
import java.awt.*;
import java.awt.geom.Line2D;
/**
* Plot component which draws a line of the form y = f(x) = a*x + b
* There is a generic form of the line by calling {@link #ABLine(double, double, GOpt...)}.
* <p>
* Also there is a simpler form for drawing horizontal or vertical lines.
* The simpler form is called by using {@link #ABLine(boolean, double, GOpt...)},
* with the boolean parameter specifying if the line is horizontal or vertical.
* <p>
* Also there are two dedicated shortcuts in plotter {@link Plotter#hLine(double, GOpt...)}
* and {@link Plotter#vLine(double, GOpt...)} which can be used to have the shortest code.
* <p>
* The default color is {@link Color#LIGHT_GRAY}, making this useful for drawing guides.
*
* @author <a href="mailto:padreati@yahoo.com">Aurelian Tutuianu</a>
*/
public class ABLine extends PlotComponent {
private static final long serialVersionUID = 8980967297314815554L;
private final double a;
private final double b;
private final boolean h;
private final boolean v;
public ABLine(boolean horiz, double a, GOpt... opts) {
this.a = a;
this.b = a;
this.h = horiz;
this.v = !horiz;
this.options.setColorDefault(gOpts -> new Color[]{Color.LIGHT_GRAY});
this.options.apply(opts);
}
public ABLine(double a, double b, GOpt... opts) {
this.a = a;
this.b = b;
this.h = false;
this.v = false;
this.options.apply(opts);
this.options.setColorDefault(gOpts -> new Color[]{Color.LIGHT_GRAY});
}
@Override
public Range buildRange() {
if (h) {
return new Range(Double.NaN, a, Double.NaN, a);
}
if (v) {
return new Range(a, Double.NaN, a, Double.NaN);
}
return null;
}
@Override
public void paint(Graphics2D g2d) {
Range range = parent.getRange();
g2d.setColor(options.getColor(0));
double x1, x2, y1, y2;
if (!h && !v) {
double xx = range.x1();
double yy = a * xx + b;
if (range.contains(xx, yy)) {
x1 = (int) parent.xScale(xx);
y1 = (int) parent.yScale(yy);
} else {
y1 = (int) parent.yScale(range.y1());
x1 = (int) parent.xScale((range.y1() - b) / a);
}
xx = range.x2();
yy = a * xx + b;
if (range.contains(xx, yy)) {
x2 = (int) parent.xScale(xx);
y2 = (int) parent.yScale(yy);
} else {
y2 = (int) parent.yScale(range.y2());
x2 = (int) parent.xScale((range.y2() - b) / a);
}
} else {
if (h) {
x1 = (int) parent.xScale(range.x1());
y1 = (int) parent.yScale(a);
x2 = (int) parent.xScale(range.x2());
y2 = (int) parent.yScale(a);
} else {
x1 = (int) parent.xScale(a);
y1 = (int) parent.yScale(range.y1());
x2 = (int) parent.xScale(a);
y2 = (int) parent.yScale(range.y2());
}
}
Stroke oldStroke = g2d.getStroke();
g2d.setStroke(new BasicStroke(options.getLwd()));
g2d.draw(new Line2D.Double(x1, y1, x2, y2));
g2d.setStroke(oldStroke);
}
}