工具包详细解析
( 一) 绘图处理工具类
Vector2f类
Vector2f类是一个表示二维向量的类,可以表示平面中的一个点或者一个向量。包含3个字段,x,y,w,w表示这个实例是一个点还是一个向量。对于点来说w=1,表示平移有效,可以用来变换矩阵;对于向量来说w=0,表示平移无效,不可以用来变换矩阵。
Vector2f类还包含一个静态字段EPSILON,表示可以区分Vector2f的最小值。因为浮点数的存储是不连续的,所以当两个Vector2f的距离小于EPSILON时就可以判断两个Vector2f是相等的。
- Vector2f类方法一览表
修饰符 | 返回值 | 函数名 | 参数 | 说明 |
---|---|---|---|---|
public | Vector2f | () | 默认构造函数,默认值为(0.0f, 0.0f, 1.0f) | |
public | Vector2f | (Vector2f v) | 构造函数 | |
public | Vector2f | (float x, float y) | 构造函数,默认w=1 | |
public | Vector2f | (float x, float y, float w) | 构造函数 | |
public | void | translate | (float tx, float ty) | 平移 |
public | void | scale | (float s) | x,y同比例缩放 |
public | void | scale | (float sx, float sy) | x,y不同比例缩放 |
public | void | rotate | (float rad) | 旋转 |
public | void | shear | (float s) | x,y同比例切变 |
public | void | shear | (float sx, float sy) | x,y不同比例切变 |
public | Vector2f | inv | () | 返回相反的向量(-x,-y) |
public | Vector2f | add | (Vector2f v) | 返回两个向量相加 |
public | Vector2f | sub | (Vector2f v) | 返回两个向量相减 |
public | Vector2f | mul | (float scalar) | 返回向量和实数相乘 |
public | Vector2f | div | (float scalar) | 返回向量和实数相除 |
public | float | len | () | 返回向量的长度 |
public | float | lenSqr | () | 返回向量长度的平方 |
public | Vector2f | norm | () | 返回向量的标准化向量 |
public | Vector2f | perp | () | 返回向量的垂直向量(-y,x) |
public | float | dot | (Vector2f v) | 返回两个向量点乘 |
public | float | angle | () | 返回向量与x轴正半轴的夹角,Pi~-Pi |
public static | Vector2f | polar | (float angle, float radius) | 由向量的角度和长度构造向量 |
public | String | toString | () | 打印向量 |
public | boolean | equals | (Object obj) | 比较两个向量是否相等 |
public final | boolean | similar | (Vector2f v, float EPSILON) | 判断两个向量是否在EPSILON程度上相似,即两向量之间的距离小于EPSILON |
- Vector2f类源代码
package Rendering.utils;
/**
* This class is similar to Two-dimensional vector and
* has some operating functions.
*/
public class Vector2f {
public static final float EPSILON = 0.00001f;
public final boolean similar(Vector2f v, float EPSILON) {
return this.sub(v).len() < EPSILON;
}
/**
* The first dimension of the vector.
*/
public float x;
/**
* The second dimension of the vector.
*/
public float y;
/**
* The flag of the vector.
* As for a point, the w should be 1;
* But as a vector, the w should be 0;
* Only when the w is 1 that the vector can translate a Matrix.
*/
public float w;
/**
* Constructs a zero vector.
*/
public Vector2f() {
this.x = 0.0f;
this.y = 0.0f;
this.w = 1.0f;
}
/**
* Constructs a vector copying from another vector.
* @param v The vector to copy.
*/
public Vector2f(Vector2f v) {
this.x = v.x;
this.y = v.y;
this.w = v.w;
}
/**
* Constructs a vector from two dimension.
* @param x The first dimension of the vector.
* @param y The second dimension of the vector.
*/
public Vector2f(float x, float y) {
this.x = x;
this.y = y;
this.w = 1.0f;
}
/**
* Constructs a vector from two dimension
* @param x The first dimension of the vector.
* @param y The second dimension of the vector.
* @param w The flag of the vector.
*/
public Vector2f(float x, float y, float w) {
this.x = x;
this.y = y;
this.w = w;
}
/**
* Translate the vector.
* @param tx The first dimension need to translate.
* @param ty The second dimension need to translate.
*/
public void translate(float tx, float ty) {
x += tx;
y += ty;
}
/**
* Scale the vector.
* @param s The multiple that need to scale.
*/
public void scale(float s) {
x *= s;
y *= s;
}
/**
* Scale the vector.
* @param sx The multiple that need to scale in the first dimension.
* @param sy The multiple that need to scale in the second dimension.
*/
public void scale(float sx, float sy) {
x *= sx;
y *= sy;
}
/**
* Rotate the vector.
* @param rad The radian that need to rotate.
* And an angle should call the function Math.toRadians()
* to become a radian.
*/
public void rotate(float rad) {
float tmp = (float) (x * Math.cos(rad) - y * Math.sin(rad));
y = (float) (x * Math.sin(rad) + y * Math.cos(rad));
x=tmp;
}
/**
* Shear the vector.
* @param s The parameter the need to shear.
*/
public void shear(float s) {
float tmp = x + s * y;
y = y + s * x;
x = tmp;
}
/**
* Shear the vector.
* @param sx The parameter the need to shear in the first dimension.
* @param sy The parameter the need to shear in the second dimension.
*/
public void shear(float sx, float sy) {
float tmp = x + sx * y;
y = y + sy * x;
x=tmp;
}
/**
* Change the vector to the opposite one.
* @return The opposite vector.
*/
public Vector2f inv() {
return new Vector2f(-x, -y);
}
/**
* Add two vectors together.
* @param v The add vector.
* @return The result vector after adding the two vectors together.
*/
public Vector2f add(Vector2f v) {
return new Vector2f(x + v.x, y + v.y);
}
/**
* Subtract two vectors.
* @param v The subtract vector.
* @return The result vector after subtracting the two vectors.
*/
public Vector2f sub(Vector2f v) {
return new Vector2f(x - v.x, y - v.y);
}
/**
* Multiply the vector with a float number.
* @param scalar The multiply float number.
* @return The result vector after multiplying the vector
* with a float number.
*/
public Vector2f mul(float scalar) {
return new Vector2f(scalar * x, scalar * y);
}
/**
* Divide the vector with a float number.
* @param scalar The divide float number.
* @return The result vector after dividing the vector
* with a float number.
*/
public Vector2f div(float scalar) {
return new Vector2f(x / scalar, y / scalar);
}
/**
* Calculate the square of length of the vector.
* @return The square of length of the vector.
*/
public float len() {
return (float) Math.sqrt(x * x + y * y);
}
/**
* Calculate the length of the vector.
* @return The length of the vector.
*/
public float lenSqr() {
return x * x + y * y;
}
/**
* Normalizing the vector.
* @return The normalization of the vector.
*/
public Vector2f norm() {
return div(len());
}
/**
* Calculate the vertical vector of the vector.
* @return A vertical vector of the vector.
*/
public Vector2f perp() {
return new Vector2f(-y, x);
}
/**
* Dot multiply two vectors.
* @param v The multiply vector.
* @return The result vector after dot multiplying the two vectors.
*/
public float dot(Vector2f v) {
return x * v.x + y * v.y;
}
/**
* Calculate the radian of the vector with the axis.
* @return The radian of the vector with the axis.
* Ranging from Pi to -Pi.
*/
public float angle() {
return (float) Math.atan2(y, x);
}
/**
* Create a vector with the radian and the length in
* the Polar coordinate system.
* @param angle The radian of the vector.
* @param radius The length of the vector.
* @return The vector that has this radian and length.
*/
public static Vector2f polar(float angle, float radius) {
return new Vector2f(
radius * (float) (Math.cos(angle)),
radius * (float) (Math.sin(angle))
);
}
@Override
public String toString() {
return String.format("(%s,%s)", x, y);
}
@Override
public boolean equals(Object obj) {
return this.similar((Vector2f) obj, EPSILON);
}
}
Matrix3x3f类
Matrix3x3f类是一个表示三维矩阵的类,包含矩阵之间的基本运算以及矩阵与向量的运算。包含一个存储矩阵的3×3数组字段和一个表示维度的静态字段。
在平面的图形绘制过程中,Vector2f类可以表示平面中的一个点,利用Matrix3x3f类可以对Vector2f类执行变换操作,例如,平移,缩放,旋转,切变。可以由一个向量构造一个可以执行变换操作的变换矩阵,乘以需要执行变换操作的点即得到变换之后的点。若需要连续变换多次,可以先将变换矩阵相乘,再乘以需要执行变换操作的点,但是要注意矩阵相乘的顺序决定着变换的顺序。这两个类是平面图形绘制中非常重要的两个类。
-
Matrix3x3f类方法一览表
|修饰符|返回值|函数名|参数|说明|
|—|---|—|---|—|
|public||Matrix3x3f|()|空构造函数|
|public||Matrix3x3f|(float[][] m)|构造函数|
|public|Matrix3x3f|add|(Matrix3x3f m1)|返回两个矩阵相加|
|public|Matrix3x3f|sub|(Matrix3x3f m1)|返回两个矩阵相减|
|public|Matrix3x3f|mul|(Matrix3x3f m1)|返回两个矩阵相乘|
|public|void|setMatrix|(float[][] m)|设置矩阵的值|
|public static|Matrix3x3f|zero|()|返回一个全零矩阵|
|public static|Matrix3x3f|identity|()|返回一个单位矩阵|
|public static|Matrix3x3f|translate|(Vector2f v)|返回一个执行平移操作的矩阵|
|public static|Matrix3x3f|translate|(float x,float y)|返回一个执行平移操作的矩阵|
|public static|Matrix3x3f|scale|(Vector2f v)|返回一个执行缩放操作的矩阵|
|public static|Matrix3x3f|scale|(float x,float y)|返回一个执行缩放操作的矩阵|
|public static|Matrix3x3f|shear|(Vector2f v)|返回一个执行切变操作的矩阵|
|public static|Matrix3x3f|shear|(float x,float y)|返回一个执行切变操作的矩阵|
|public static|Matrix3x3f|rotate|(float rad)|返回一个执行旋转操作的矩阵|
|public|Vector2f|mul|(Vector2f vec)|对需要执行变换的点执行变换操作|
|public|String|toString|()|打印矩阵| -
Matrix3x3f类源代码
package Rendering.utils;
/**
* This class is similar to Tri-dimensional matrix and
* has some operating functions.
*/
public class Matrix3x3f {
public static final int DIMENSION = 3;
private float[][] m = new float[DIMENSION][DIMENSION];
public Matrix3x3f() {}
public Matrix3x3f(float[][] m) {
setMatrix(m);
}
public Matrix3x3f add(Matrix3x3f m1) {
float[][] tmp = new float[DIMENSION][DIMENSION];
for (int i = 0; i < DIMENSION; i++) {
for (int j = 0; j < DIMENSION; j++) {
tmp[i][j] = m[i][j] + m1.m[i][j];
}
}
return new Matrix3x3f(tmp);
}
public Matrix3x3f sub(Matrix3x3f m1) {
float[][] tmp = new float[DIMENSION][DIMENSION];
for (int i = 0; i < DIMENSION; i++) {
for (int j = 0; j < DIMENSION; j++) {
tmp[i][j] = m[i][j] - m1.m[i][j];
}
}
return new Matrix3x3f(tmp);
}
public Matrix3x3f mul(Matrix3x3f m1) {
float[][] tmp = new float[DIMENSION][DIMENSION];
for (int i = 0; i < DIMENSION; i++) {
for (int k = 0; k < DIMENSION; k++) {
for(int j=0;j<DIMENSION;j++) {
tmp[i][j] += m[i][k] * m1.m[k][j];
}
}
}
return new Matrix3x3f(tmp);
}
public void setMatrix(float[][] m) {
if (m.length == DIMENSION && m[0].length == DIMENSION) {
this.m = m;
}
}
public static Matrix3x3f zero() {
return new Matrix3x3f(new float[DIMENSION][DIMENSION]);
}
public static Matrix3x3f identity() {
float[][] tmp = new float[DIMENSION][DIMENSION];
for (int i = 0; i < DIMENSION; i++) {
tmp[i][i] = 1.0f;
}
return new Matrix3x3f(tmp);
}
public static Matrix3x3f translate(Vector2f v) {
return translate(v.x, v.y);
}
public static Matrix3x3f translate(float x, float y) {
return new Matrix3x3f(new float[][]{
{1.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{x, y, 1.0f}
});
}
public static Matrix3x3f scale(Vector2f v) {
return scale(v.x, v.y);
}
public static Matrix3x3f scale(float x, float y) {
return new Matrix3x3f(new float[][]{
{x, 0.0f, 0.0f},
{0.0f, y, 0.0f},
{0.0f, 0.0f, 1.0f}
});
}
public static Matrix3x3f shear(Vector2f v) {
return shear(v.x, v.y);
}
public static Matrix3x3f shear(float x, float y) {
return new Matrix3x3f(new float[][]{
{1.0f, y, 0.0f},
{x, 1.0f, 0.0f},
{0.0f, 0.0f, 1.0f}
});
}
public static Matrix3x3f rotate(float rad) {
return new Matrix3x3f(new float[][]{
{(float) Math.cos(rad), (float) Math.sin(rad), 0.0f},
{(float) -Math.sin(rad), (float) Math.cos(rad), 0.0f},
{0.0f, 0.0f, 1.0f}
});
}
public Vector2f mul(Vector2f vec) {
return new Vector2f(
vec.x * this.m[0][0]
+ vec.y * this.m[1][0]
+ vec.w * this.m[2][0],
vec.x * this.m[0][1]
+ vec.y * this.m[1][1]
+ vec.w * this.m[2][1],
vec.x * this.m[0][2]
+ vec.y * this.m[1][2]
+ vec.w * this.m[2][2]
);
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
for(int i=0;i<DIMENSION;i++) {
buf.append("[");
buf.append(m[i][0]);
buf.append(",\t");
buf.append(m[i][1]);
buf.append(",\t");
buf.append(m[i][2]);
buf.append("]\n");
}
return buf.toString();
}
}
Utility类
Utility类是所有的工具函数的集合类,其中包括坐标转换工具,图形绘制工具,文字绘制工具。Utility类可以引用到任何使用Graphics进行图形绘制的程序中,其中的点,坐标变换分别用Vector2f和Matrix3x3f来表示。
- Utility类方法一览表
修饰符 | 返回值 | 函数名 | 参数 | 说明 |
---|---|---|---|---|
public static | Matrix3x3f | createViewport | (float worldWidth,float worldHeight,float screenWidth,float screenHeight) | 返回由世界坐标转换到屏幕坐标的转换矩阵 |
public static | Matrix3x3f | createReverseViewport | (float worldWidth,float worldHeight,float screenWidth,float screenHeight) | 返回由屏幕坐标转换到世界坐标的转换矩阵 |
public static | Vector2f[] | transform | (Vector2f[] poly,Matrix3x3f mat) | 对一系列的点进行指定的转换 |
public static | void | drawPolygon | (Graphics2D g2d,Vector2f[] polygon,Matrix3x3f view,Color color) | 根据点的个数绘制多边形,点,或直线 |
public static | void | drawPolygon | (Graphics2D g2d,List< Vector2f> polygon,Matrix3x3f view,Color color) | 根据点的个数绘制多边形,点,或直线 |
public static | void | fillPolygon | (Graphics2D g2d,Vector2f[] polygon,Matrix3x3f view,Color color) | 根据点的个数绘制填充多边形,点,或直线 |
public static | void | fillPolygon | (Graphics2D g2d,List< Vector2f> polygon,Matrix3x3f view,Color color) | 根据点的个数填充绘制多边形,点,或直线 |
public static | void | drawRect | (Graphics2D g2d,Vector2f topLeft,Vector2f bottomRight,Matrix3x3f view,Color color) | 由矩形的两个角的位置绘制矩形 |
public static | void | fillRect | (Graphics2D g2d,Vector2f topLeft,Vector2f bottomRight,Matrix3x3f view,Color color) | 由矩形的两个角的位置绘制填充矩形 |
public static | void | drawCircle | (Graphics2D g2d,Vector2f center,float radius,Matrix3x3f view,Color color) | 由圆心的位置和半径绘制圆 |
public static | void | fillCircle | (Graphics2D g2d,Vector2f center,float radius,Matrix3x3f view,Color color) | 由圆心的位置和半径绘制填充圆 |
public static | void | drawCircle | (Graphics2D g2d,Vector2f begin,Vector2f end,Matrix3x3f view,Color color) | 由圆心和圆上一点的位置绘制圆 |
public static | void | fillCircle | (Graphics2D g2d,Vector2f begin,Vector2f end,Matrix3x3f view,Color color) | 由圆心和圆上一点的位置绘制填充圆 |
public static | void | drawOval | (Graphics2D g2d,Vector2f topLeft,Vector2f bottomRight,Matrix3x3f view,Color color) | 由椭圆的外切矩形的两个角的位置绘制椭圆 |
public static | void | fillOval | (Graphics2D g2d,Vector2f topLeft,Vector2f bottomRight,Matrix3x3f view,Color color) | 由椭圆的外切矩形的两个角的位置绘制填充椭圆 |
public static | void | drawTriangle | (Graphics2D g2d,Vector2f begin,Vector2f center,Matrix3x3f view,Color color) | 由三角形的一个角和中心的位置绘制等边三角形 |
public static | void | fillTriangle | (Graphics2D g2d,Vector2f begin,Vector2f center,Matrix3x3f view,Color color) | 由三角形的一个角和中心的位置绘制填充等边三角形 |
public static | void | fillSimilarCircle | (Graphics2D g2d,Vector2f position,Matrix3x3f view) | 由圆心的位置绘制指定的快捷选择操作圆(快捷选择操作中用到) |
public static | void | drawString | (Graphics2D g2d,Vector2f position,Matrix3x3f view,Color color,String… str) | 在指定位置绘制字符串 |
public static | void | drawString | (Graphics2D g2d,Vector2f position,Matrix3x3f view,Color color,List< String> str) | 在指定位置绘制字符串 |
public static | void | drawString | (Graphics2D g2d,Vector2f position,Matrix3x3f view,Color color,String str) | 在指定位置绘制字符串 |
- Utility类源代码
package Rendering.utils;
import Rendering.element.BeginEndImageElement;
import java.awt.*;
import java.util.List;
public class Utility {
/****************************************************************************/
/*********************Coordinate transformation tool*************************/
/****************************************************************************/
public static Matrix3x3f createViewport(
float worldWidth, float worldHeight,
float screenWidth, float screenHeight) {
float sx = (screenWidth - 1) / worldWidth;
float sy = (screenHeight - 1) / worldHeight;
float tx = (screenWidth - 1) / 2.0f;
float ty = (screenHeight - 1) / 2.0f;
Matrix3x3f viewport = Matrix3x3f.scale(sx, -sy);
viewport = viewport.mul(Matrix3x3f.translate(tx, ty));
return viewport;
}
public static Matrix3x3f createReverseViewport(
float worldWidth, float worldHeight,
float screenWidth, float screenHeight) {
float sx = worldWidth / (screenWidth - 1);
float sy = worldHeight / (screenHeight - 1);
float tx = (screenWidth - 1) / 2.0f;
float ty = (screenHeight - 1) / 2.0f;
Matrix3x3f viewport = Matrix3x3f.translate(-tx, -ty);
viewport = viewport.mul(Matrix3x3f.scale(sx, -sy));
return viewport;
}
public static Vector2f[] transform(Vector2f[] poly, Matrix3x3f mat) {
Vector2f[] copy = new Vector2f[poly.length];
for (int i = 0; i < poly.length; i++) {
copy[i] = mat.mul(poly[i]);
}
return copy;
}
/****************************************************************************/
/*********************Graphic drawing tool***********************************/
/****************************************************************************/
public static void drawPolygon(
Graphics2D g2d, Vector2f[] polygon,
Matrix3x3f view, Color color) {
g2d.setColor(color);
Vector2f[] tmp = transform(polygon, view);
if (tmp.length == 1) {
g2d.drawRect((int) tmp[0].x, (int) tmp[0].y, 1, 1);
}
Vector2f P;
Vector2f S = tmp[tmp.length - 1];
for (int i = 0; i < tmp.length; i++) {
P = tmp[i];
g2d.drawLine((int) S.x, (int) S.y, (int) P.x, (int) P.y);
S = P;
}
}
public static void drawPolygon(
Graphics2D g2d, List<Vector2f> polygon,
Matrix3x3f view, Color color) {
drawPolygon(g2d, polygon.toArray(new Vector2f[0]), view, color);
}
public static void fillPolygon(
Graphics2D g2d, Vector2f[] polygon,
Matrix3x3f view, Color color) {
g2d.setColor(color);
Vector2f[] tmp = transform(polygon, view);
Polygon p = new Polygon();
for (Vector2f v : tmp) {
p.addPoint((int) v.x, (int) v.y);
}
g2d.fillPolygon(p);
}
public static void fillPolygon(
Graphics2D g2d, List<Vector2f> polygon,
Matrix3x3f view, Color color) {
fillPolygon(g2d, polygon.toArray(new Vector2f[0]), view, color);
}
public static void drawRect(
Graphics2D g2d, Vector2f topLeft, Vector2f bottomRight,
Matrix3x3f view, Color color) {
g2d.setColor(color);
Vector2f topLeftTmp = view.mul(topLeft);
Vector2f bottomRightTmp = view.mul(bottomRight);
if (bottomRight.y > topLeft.y) {
float tmp = topLeftTmp.y;
topLeftTmp.y = bottomRightTmp.y;
bottomRightTmp.y = tmp;
}
if (bottomRight.x < topLeft.x) {
float tmp = topLeftTmp.x;
topLeftTmp.x = bottomRightTmp.x;
bottomRightTmp.x = tmp;
}
int rectX = (int) topLeftTmp.x;
int rectY = (int) topLeftTmp.y;
int rectWidth = (int) (bottomRightTmp.x - topLeftTmp.x);
int rectHeight = (int) (bottomRightTmp.y - topLeftTmp.y);
g2d.drawRect(rectX, rectY, rectWidth, rectHeight);
}
public static void fillRect(
Graphics2D g2d, Vector2f topLeft, Vector2f bottomRight,
Matrix3x3f view, Color color) {
g2d.setColor(color);
Vector2f topLeftTmp = view.mul(topLeft);
Vector2f bottomRightTmp = view.mul(bottomRight);
if (bottomRight.y > topLeft.y) {
float tmp = topLeftTmp.y;
topLeftTmp.y = bottomRightTmp.y;
bottomRightTmp.y = tmp;
}
if (bottomRight.x < topLeft.x) {
float tmp = topLeftTmp.x;
topLeftTmp.x = bottomRightTmp.x;
bottomRightTmp.x = tmp;
}
int rectX = (int) topLeftTmp.x;
int rectY = (int) topLeftTmp.y;
int rectWidth = (int) (bottomRightTmp.x - topLeftTmp.x);
int rectHeight = (int) (bottomRightTmp.y - topLeftTmp.y);
g2d.fillRect(rectX, rectY, rectWidth, rectHeight);
}
public static void drawCircle(
Graphics2D g2d, Vector2f center, float radius,
Matrix3x3f view, Color color) {
g2d.setColor(color);
Vector2f topLeft =
new Vector2f(center.x - radius, center.y + radius);
topLeft = view.mul(topLeft);
Vector2f bottomRight =
new Vector2f(center.x + radius, center.y - radius);
bottomRight = view.mul(bottomRight);
Vector2f centerTmp = view.mul(center);
int circleX = (int) topLeft.x;
int circleY = (int) topLeft.y;
int circleWidth = (int) (bottomRight.x - topLeft.x);
int circleHeight = (int) (bottomRight.y - topLeft.y);
g2d.drawRect((int) centerTmp.x, (int) centerTmp.y, 1, 1);
g2d.drawOval(circleX, circleY, circleWidth, circleHeight);
}
public static void fillCircle(
Graphics2D g2d, Vector2f center, float radius,
Matrix3x3f view, Color color) {
g2d.setColor(color);
Vector2f topLeft =
new Vector2f(center.x - radius, center.y + radius);
topLeft = view.mul(topLeft);
Vector2f bottomRight =
new Vector2f(center.x + radius, center.y - radius);
bottomRight = view.mul(bottomRight);
int circleX = (int) topLeft.x;
int circleY = (int) topLeft.y;
int circleWidth = (int) (bottomRight.x - topLeft.x);
int circleHeight = (int) (bottomRight.y - topLeft.y);
g2d.fillOval(circleX, circleY, circleWidth, circleHeight);
}
public static void drawCircle(
Graphics2D g2d, Vector2f begin, Vector2f end,
Matrix3x3f view, Color color) {
drawCircle(g2d, begin, begin.sub(end).len(), view, color);
}
public static void fillCircle(
Graphics2D g2d, Vector2f begin, Vector2f end,
Matrix3x3f view, Color color) {
fillCircle(g2d, begin, begin.sub(end).len(), view, color);
}
public static void drawOval(
Graphics2D g2d, Vector2f topLeft, Vector2f bottomRight,
Matrix3x3f view, Color color) {
g2d.setColor(color);
Vector2f topLeftTmp = view.mul(topLeft);
Vector2f bottomRightTmp = view.mul(bottomRight);
if (bottomRight.y > topLeft.y) {
float tmp = topLeftTmp.y;
topLeftTmp.y = bottomRightTmp.y;
bottomRightTmp.y = tmp;
}
if (bottomRight.x < topLeft.x) {
float tmp = topLeftTmp.x;
topLeftTmp.x = bottomRightTmp.x;
bottomRightTmp.x = tmp;
}
int ovalX = (int) topLeftTmp.x;
int ovalY = (int) topLeftTmp.y;
int ovalWidth = (int) (bottomRightTmp.x - topLeftTmp.x);
int ovalHeight = (int) (bottomRightTmp.y - topLeftTmp.y);
g2d.drawOval(ovalX, ovalY, ovalWidth, ovalHeight);
}
public static void fillOval(
Graphics2D g2d, Vector2f topLeft, Vector2f bottomRight,
Matrix3x3f view, Color color) {
g2d.setColor(color);
Vector2f topLeftTmp = view.mul(topLeft);
Vector2f bottomRightTmp = view.mul(bottomRight);
if (bottomRight.y > topLeft.y) {
float tmp = topLeftTmp.y;
topLeftTmp.y = bottomRightTmp.y;
bottomRightTmp.y = tmp;
}
if (bottomRight.x < topLeft.x) {
float tmp = topLeftTmp.x;
topLeftTmp.x = bottomRightTmp.x;
bottomRightTmp.x = tmp;
}
int ovalX = (int) topLeftTmp.x;
int ovalY = (int) topLeftTmp.y;
int ovalWidth = (int) (bottomRightTmp.x - topLeftTmp.x);
int ovalHeight = (int) (bottomRightTmp.y - topLeftTmp.y);
g2d.fillOval(ovalX, ovalY, ovalWidth, ovalHeight);
}
public static void drawTriangle(
Graphics2D g2d, Vector2f begin, Vector2f center,
Matrix3x3f view, Color color) {
g2d.setColor(color);
Vector2f tmp = center.sub(begin);
Vector2f topTmp = begin.add(
Vector2f.polar(
new Double(tmp.angle() + Math.PI / 6.0).floatValue(),
new Double(tmp.len() * Math.sqrt(3.0)).floatValue()));
Vector2f bottomTmp = begin.add(
Vector2f.polar(
new Double(tmp.angle() - Math.PI / 6.0).floatValue(),
new Double(tmp.len() * Math.sqrt(3.0)).floatValue()));
drawPolygon(g2d, new Vector2f[]{begin, topTmp, bottomTmp}, view, color);
}
public static void fillTriangle(
Graphics2D g2d, Vector2f begin, Vector2f center,
Matrix3x3f view, Color color) {
g2d.setColor(color);
Vector2f tmp = center.sub(begin);
Vector2f topTmp = begin.add(
Vector2f.polar(
new Double(tmp.angle() + Math.PI / 6.0).floatValue(),
new Double(tmp.len() * Math.sqrt(3.0)).floatValue()));
Vector2f bottomTmp = begin.add(
Vector2f.polar(
new Double(tmp.angle() - Math.PI / 6.0).floatValue(),
new Double(tmp.len() * Math.sqrt(3.0)).floatValue()));
fillPolygon(g2d, new Vector2f[]{begin, topTmp, bottomTmp}, view, color);
}
public static void fillSimilarCircle(
Graphics2D g2d, Vector2f position, Matrix3x3f view) {
fillCircle(g2d, position, BeginEndImageElement.EPSILON, view, Color.YELLOW);
Vector2f r = Vector2f.polar((float) (Math.PI / 4), BeginEndImageElement.EPSILON);
Vector2f rightTop = position.add(r);
Vector2f leftBottom = position.sub(r);
Vector2f rightBottom = position.add(r.perp());
Vector2f leftTop = position.sub(r.perp());
drawPolygon(g2d, new Vector2f[]{rightTop, leftBottom}, view, Color.BLACK);
drawPolygon(g2d, new Vector2f[]{leftTop, rightBottom}, view, Color.BLACK);
}
/****************************************************************************/
/************************String drawing tool*********************************/
/****************************************************************************/
public static void drawString(
Graphics2D g2d, Vector2f position,
Matrix3x3f view, Color color,
String... str) {
g2d.setColor(color);
Vector2f positionTmp = view.mul(position);
float x = positionTmp.x;
float y = positionTmp.y;
FontMetrics fm = g2d.getFontMetrics();
int height = fm.getAscent() + fm.getDescent() + fm.getLeading();
g2d.setFont(new Font("Courier New", Font.PLAIN, 20));
g2d.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
for (String s : str) {
g2d.drawString(s, x, y + fm.getAscent());
y += height;
}
}
public static void drawString(
Graphics2D g2d, Vector2f position,
Matrix3x3f view, Color color,
List<String> str) {
drawString(g2d, position, view, color, str.toArray(new String[0]));
}
public static void drawString(
Graphics2D g2d, Vector2f position,
Matrix3x3f view, Color color,
String str) {
drawString(g2d, position, view, color, new String[]{str});
}
}
更多: