import java.util.Scanner;
public class Main
{
private static final char FULL = '#';
private static final char EMPTY = ' ';
private static final int preferredHeight = 14;
private static final int preferredWidth = 12;
public static void main(String args[])
{
System.out.print("Height? ");
int height = new Scanner(System.in).nextInt();
float scaleY = (float)height / preferredHeight;
float scaleX = scaleY;
Renderer renderer = new Renderer();
renderer.Add(new Triangle(new Point(0, 4), new Point(12, 4), new Point(6, 14)).Scale(scaleX, scaleY));
renderer.Add(new Triangle(new Point(0, 10), new Point(12, 10), new Point(6, 0)).Scale(scaleX, scaleY));
renderer.Render(new Point(0, 0), new Point(preferredWidth, preferredHeight).Scale(scaleX, scaleY), FULL, EMPTY);
}
}
import java.util.ArrayList;
public class Renderer
{
/*
Coordinate System:
==================
(0,0)
+-------------+
| |
| |
| |
+-------------+
(X,Y)
*/
private final ArrayList<IPlotable> _plotables = new ArrayList<IPlotable>();
public void Add(IPlotable plotable)
{
_plotables.add(plotable);
}
public void Render(Point topLeft, Point bottomRight, char fill, char empty)
{
for (int row = topLeft.y; row <= bottomRight.y; row++)
{
for (int column = topLeft.x; column <= bottomRight.x; column++)
System.out.print(PlotAny(new Point(column, row)) ? fill : empty);
System.out.println();
}
}
private boolean PlotAny(Point point)
{
for (IPlotable plotable : _plotables)
if (plotable.Plot(point))
return true;
return false;
}
}
public class Triangle implements IPlotable
{
// The line segments (sides) of the triangle
private LineSegment[] _lineSegments;
// The verticies of the triangle. Stored for scaling purposes only.
private Point _v1;
private Point _v2;
private Point _v3;
public Triangle(Point v1, Point v2, Point v3)
{
_v1 = v1;
_v2 = v2;
_v3 = v3;
_lineSegments = new LineSegment[3];
_lineSegments[0] = new LineSegment(v1, v2);
_lineSegments[1] = new LineSegment(v2, v3);
_lineSegments[2] = new LineSegment(v3, v1);
}
public boolean Plot(Point vertex)
{
for (int i = 0; i < 3; i++)
if (_lineSegments[i].Plot(vertex))
return true;
return false;
}
public Triangle Scale(float scaleX, float scaleY)
{
_v1.Scale(scaleX, scaleY);
_v2.Scale(scaleX, scaleY);
_v3.Scale(scaleX, scaleY);
for (int i = 0; i < 3; i++)
_lineSegments[i].CalculateParameters();
return this;
}
}
public class Point
{
public int x;
public int y;
public Point(int x_, int y_)
{
x = x_;
y = y_;
}
public Point Scale(float scaleX, float scaleY)
{
x = java.lang.Math.round(x * scaleX);
y = java.lang.Math.round(y * scaleY);
return this;
}
}
public class LineSegment implements IPlotable
{
// The vertices of the line segment
public final Point v1;
public final Point v2;
private float _m; // The slope of the line
private float _b; // The point where the line would cross the Y axis
private boolean _leftToRight; // The vertical direction
private boolean _topToBottom; // The horizontal direction
public LineSegment(Point v1_, Point v2_)
{
v1 = v1_;
v2 = v2_;
CalculateParameters();
}
public void CalculateParameters()
{
float xOffset = v2.x - v1.x;
float yOffset = v2.y - v1.y;
if (xOffset == 0.0)
{
_m = Float.NaN;
_b = Float.NaN;
}
else
{
_m = yOffset / xOffset;
_b = v1.y - _m * v1.x;
}
_leftToRight = xOffset >= 0.0;
_topToBottom = yOffset >= 0.0;
}
private boolean IsContainedX(int x)
{
return _leftToRight && v1.x <= x && x <= v2.x ||
!_leftToRight && v2.x <= x && x <= v1.x;
}
private boolean IsContainedY(int y)
{
return _topToBottom && v1.y <= y && y <= v2.y ||
!_topToBottom && v2.y <= y && y <= v1.y;
}
public boolean Plot(Point vertex)
{
//y = mx + b
//x = (y - b) / m;
if (Float.isNaN(_m))
return vertex.x == v1.x && IsContainedY(vertex.y);
/*
System.out.println("x: " + vertex.x + "\ty: " + vertex.y);
System.out.println("IsContainedX(vertex.x): " + IsContainedX(vertex.x));
System.out.println("IsContainedY(vertex.y): " + IsContainedY(vertex.y));
System.out.println("(vertex.x * _m + _b): " + (vertex.x * _m + _b));
*/
return IsContainedX(vertex.x) && IsContainedY(vertex.y) &&
(-0.5 <= _m && _m <= 0.5 && java.lang.Math.round(vertex.x * _m + _b) == vertex.y ||
(_m < -0.5 || 0.5 < _m) && java.lang.Math.round((vertex.y - _b) / _m) == vertex.x);
}
public LineSegment Scale(float scaleX, float scaleY)
{
v1.Scale(scaleX, scaleY);
v2.Scale(scaleX, scaleY);
CalculateParameters();
return this;
}
}
interface IPlotable
{
public boolean Plot(Point vertex);
}