📄 silhouette.pde
字号:
/**
* Silhouette class
* Manages silhouette data, draws it and tests collisions
*
*
* Jorge Cardoso http://jorgecardoso.eu
* January 2008
*/
public class Silhouette {
// The vectorized and normalized ([0,1]) silhouette. [n][0] - x coord, [n][1] - y coord
float silhouette[][];
// computed on testing for 'insideness'. represent the index of closest point to the
// one last tested tested. See inside(x, y);
private float closestX, closestY;
// the normal of the closest segment to the last tested point
private float normalX, normalY;
// the default dimension of the silhouette
// this is just used to scale when drawing
private int width = 0, height = 0;
// the bounding box of the silhouette in the image.
private float bbx, bby, bbwidth, bbheight;
// the area of the silhouette
private float area;
// the center of mass of the silhouette
private float centerOfMassX, centerOfMassY;
public Silhouette(float [][] s) {
silhouette = s;
if (s == null) {
println("Null silhouette polygons");
return;
}
// calculate the bounding box
calculateBB();
}
public void setSize(int width, int height) {
this.width = width;
this.height = height;
// reculculate the area, center of mass and normals
area = (float)calculateArea(this.silhouette)*this.width*this.height;
Point2D.Double com = calculateCenterOfMass(this.silhouette);
centerOfMassX = (float)com.getX();
centerOfMassY = (float)com.getY();
}
// draw the silhouette with a texture image in a particular coord and scaled according to the passed
// width and height
public void draw(PImage text, int x, int y, int width, int height) {
float[][] s = silhouette;
// strokeWeight(3);
fill(255);
beginShape(POLYGON);
texture(text);
for (int i = 0; i < s.length; i++) {
vertex(s[i][0]*width+x, s[i][1]*height+y, s[i][0]*text.width, s[i][1]*text.height);
}
vertex(s[0][0]*width+x, s[0][1]*height+y, s[0][0]*text.width, s[0][1]*text.height);
endShape();
}
// draw the silhouette with a texture image
// in the default coords (0, 0) and with the default dimension
public void draw(PImage text) {
draw(text, 0, 0, this.width, this.height);
}
// draw the silhouette with a texture image
// in a particular coord and with the default dimension
public void draw(PImage text, int x, int y) {
draw(text, x, y, this.width, this.height);
}
// draws the silhoutte in a particular coord and scaled according to the passed width and height
public void draw(int x, int y, int width, int height) {
if (width == 0 || height == 0) {
println("Width or height equal to zero!!");
println("Call setSize()");
}
float[][] s = silhouette;
//strokeWeight(3);
for (int i = 0; i < s.length; i++) {
if (i > 0 ) {
line((int)(s[i-1][0]*width)+x, (int)(s[i-1][1]*height)+y, (int)(s[i][0]*width)+x, (int)(s[i][1]*height)+y);
}
}
line((int)(s[s.length-1][0]*width)+x, (int)(s[s.length-1][1]*height)+y, (int)(s[0][0]*width)+x, (int)(s[0][1]*height)+y);
}
// draws the silhoutte in a particular coord, using the default size
public void draw(int x, int y) {
draw(x, y, this.width, this.height);
}
// draws the silhoutte in the default coord, using the default size
public void draw() {
draw(0, 0, this.width, this.height);
}
// returns true if the specified point is inside this silhouette's bounding box
public boolean insideBoundingBox(float x, float y) {
if (x < bbx*this.width || x > (bbx+bbwidth)*this.width || y < bby*this.height || y > (bby+bbheight)*this.height) {
return false;
}
return true;
}
// checks if a point is inside the silhouette polygon
public boolean inside(float x, float y) {
return insidePolygon(x, y, silhouette, this.width, this.height);
}
// Code is borrowed from this http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Programs;action=display;num=118917882
// thread. Thanks to <a href="http://www.robotacid.com/">st33d</a> for the code.
// this also calculates the closest point on the silhouette to the one being tested
public boolean insidePolygon(float x,float y, float p[][], int width, int height) {
int i, j, c = 0;
x = x/width;
y = y/height;
float min = 1000000;
int minIndex = 0;
float d;
float inter[] = new float[2]; // intersection
float minInter[] = new float[2]; //
for (i = 0, j = p.length-1; i < p.length; j = i++) {
if ((((p[i][1] <= y) && (y < p[j][1])) ||
((p[j][1] <= y) && (y < p[i][1]))) &&
(x < (p[j][0] - p[i][0]) * (y - p[i][1]) / (p[j][1] - p[i][1]) + p[i][0])) {
c = (c+1)%2;
}
// calculate the intersection with the segment
inter = intersection(x, y, p[i][0], p[i][1], p[(i+1)%p.length][0], p[(i+1)%p.length][1]);
if ( inter != null && (d = dist(inter[0], inter[1], x, y)) < min ) {
min = d;
minIndex = i;
minInter[0]=inter[0];
minInter[1] = inter[1];
}
}
closestX = minInter[0]*this.width;
closestY = minInter[1]*this.height;
Point2D.Double n = normal((int)(p[minIndex][0]*this.width), (int)(p[minIndex][1]*this.height),
(int)(p[(minIndex+1)%p.length][0]*this.width), (int)(p[(minIndex+1)%p.length][1]*this.height));
normalX =(float) (n.getX());
normalY =(float) (n.getY());
//closest = minIndex;
return c==1;
}
public float distanceToSilhouette(float x, float y) {
float p[][] = silhouette;
float min = 1000000;
int minIndex = 0;
float d;
float inter[] = new float[2]; // intersection
float minInter[] = new float[2]; //
for (int i = 0; i < p.length; i++) {
// calculate the intersection with the segment
inter = intersection(x, y, p[i][0]*width, p[i][1]*height, p[(i+1)%p.length][0]*width, p[(i+1)%p.length][1]*height);
if ( inter != null && (d = dist(inter[0], inter[1], x, y)) < min ) {
min = d;
minIndex = i;
minInter[0]=inter[0];
minInter[1] = inter[1];
}
}
closestX = minInter[0];
closestY = minInter[1];
Point2D.Double n = normal((int)(p[minIndex][0]*this.width), (int)(p[minIndex][1]*this.height),
(int)(p[(minIndex+1)%p.length][0]*this.width), (int)(p[(minIndex+1)%p.length][1]*this.height));
normalX =(float) (n.getX());
normalY =(float) (n.getY());
//closest = minIndex;
return min;
}
public int bbX() {
return (int)(bbx*this.width);
}
public int bbY() {
return (int)(bby*this.height);
}
public int bbWidth() {
return (int)(bbwidth*this.width);
}
public int bbHeight() {
return (int)(bbheight*this.height);
}
public float area() {
return area;
}
public float getCenterOfMassX() {
return centerOfMassX*this.width;
}
public float getCenterOfMassY() {
return centerOfMassY*this.height;
}
public float getNormalX() {
return normalX;
}
public float getNormalY() {
return normalY;
}
public float getClosestX() {
return closestX;
}
public float getClosestY() {
return closestY;
}
//
private void calculateBB() {
float minx = 1000000, miny = 100000, maxx = -1000000, maxy = -100000;
float s[][] = silhouette;
for (int i = 0; i < s.length; i++) {
if (s[i][0] < minx) {
minx = s[i][0];
}
if (s[i][0] > maxx) {
maxx = s[i][0];
}
if (s[i][1] < miny) {
miny = s[i][1];
}
if (s[i][1] > maxy) {
maxy = s[i][1];
}
}
bbx = minx;
bby = miny;
bbwidth = (maxx-minx);
bbheight = (maxy-miny);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -