rect.java
来自「用Java开发的、实现类似Visio功能的应用程序源码」· Java 代码 · 共 1,488 行 · 第 1/4 页
JAVA
1,488 行
neighborVertex2 =m_leftBottom;
peerVertex =m_leftTop;
break;
default:
return;
}
switch(moveType){
case VERTEXMOVETYPE_SCALE:
moveRectangle(currVertex,neighborVertex1,neighborVertex2,peerVertex,x,y,true);
break;
case VERTEXMOVETYPE_RECTANGLE:
moveRectangle(currVertex,neighborVertex1,neighborVertex2,peerVertex,x,y,false);
break;
case VERTEXMOVETYPE_PARALLEL:
moveParallel(vertexType,x,y,moveType,this);
break;
case VERTEXMOVETYPE_TRAPEZOID:
case VERTEXMOVETYPE_ISOSCELESTRAPEZOID:
moveParallel(vertexType,x,y,moveType,this);
break;
}
}
/**
* Move a vertex of a rectangle, but force it as a rectangle.
*
* @param currVertex A vertex currently moved.
*
* @param neighborVertex1, neighborVertex2 Neibor vertexes nearby current vertex.
*
* @param peerVertex A peer vertex of current vertex, this vertex will always be a fixed one.
*
* @param x, y Coordinates of a new vertex point.
* @param isScale True if forcing a same scale on width and height, false otherwise.
*
*/
private static void moveRectangle(JFPoint currVertex,JFPoint neighborVertex1, JFPoint neighborVertex2, JFPoint peerVertex,double x, double y,boolean isScale){
/** In scaling a rectangle, we will always get a rectangle by making two uprightFeet
* that from currently moving vertex to peer two sides of the rectangle.
*/
int vertexChanged =0;
LineSeg line1, line2;
JFPoint uprightFoot1,uprightFoot2;
//one peer side and its upright foot.
line1=new LineSeg(peerVertex,neighborVertex1);
uprightFoot1 = line1.uprightFoot(x,y);
//other peer side and its upright foot.
line2=new LineSeg(peerVertex,neighborVertex2);
uprightFoot2 = line2.uprightFoot(x,y);
//if is under scale situation, we need to force a same width-height scale.
if (isScale){
double oldLen1 =peerVertex.distance(neighborVertex1);
double oldLen2 =peerVertex.distance(neighborVertex2);
double newLen1 =peerVertex.distance(uprightFoot1);
double newLen2 =peerVertex.distance(uprightFoot2);
if (oldLen1<1) oldLen1=1;
if (oldLen2<1) oldLen2=1;
double scale1 =newLen1/oldLen1;
double scale2 =newLen2/oldLen2;
//get a maximum scale from scale1 and scale2
double scale =Math.max(scale1,scale2);
//re-calculate upright feet by one scale.
newLen1 =oldLen1 * scale;
newLen2 =oldLen2 * scale;
uprightFoot1 =peerVertex.nearPoint(neighborVertex1,newLen1,true);
uprightFoot2 =peerVertex.nearPoint(neighborVertex2,newLen2,true);
}
//check the uprightfoot and restrict a minmum side length of rectangle.
if (line2.distance(uprightFoot1)>GeomConst.MIN_LINELENGTH){
//move this neibor vertex to a new position
neighborVertex1.setValue(uprightFoot1);
vertexChanged++;
}
//check the uprightfoot and restrict a minmum side length of rectangle.
if (line1.distance(uprightFoot2)>GeomConst.MIN_LINELENGTH){
//move this neibor vertex to a new position
neighborVertex2.setValue(uprightFoot2);
vertexChanged++;
}
//if two relational vertex of current vertex has been changed,
//we will consider that current vertex has successfully changed
// to new x,y position, otherwise we need to calculate the
// actual position of current vertex.
if (vertexChanged==2 && !isScale){
currVertex.setValue(x,y);
}else{
double slope1 =line1.getSlope();
double slope2 =line2.getSlope();
if (slope1==GeomConst.LARGE_VALUE || slope2==0){
//vertical line
currVertex.setValue(neighborVertex2.getX(),neighborVertex1.getY());
}else if (slope1==0 || slope2==GeomConst.LARGE_VALUE){
currVertex.setValue(neighborVertex1.getX(),neighborVertex2.getY());
}else{
//two line here:
//y=slope1 * (x-neighbor2.x) + neighbor2.y
//y=slope2 * (x-neighbor1.x) + neighbor1.y
//so:
//x=(neighbor1.y-neighbor2.y -slope2 * neighbor1.x + slope1 * neighbor2.x)/(slope1-slope2)
double newx = (neighborVertex1.getY()-neighborVertex2.getY() -slope2 * neighborVertex1.getX() + slope1 * neighborVertex2.getX())/(slope1-slope2);
double newy = slope1 * (newx-neighborVertex2.getX()) + neighborVertex2.getY();
currVertex.setValue(newx,newy);
}
}
}
/**
* Move a vertex of a parallel rectangle, e.g. parallelogram,trapezoid, isosceles trapezoid.
*
* @param vertexType An vertex type of a rectangle.
*
* @param x, y Coordinates of a new vertex point.
*
* @param moveType Arbitrary trapezoid, or isosceles trapezoid
*
* @param rect Currently changed trapezoid.
*
*/
private static void moveParallel(int vertexType,double x, double y,int moveType,Rect rect){
/**
* We will aways consider that the line left-top to right-top and
* line left-bottom to right-bottom are parallel lines.
*
* When one vertex of trapezoid is moved, the two vertex on the other parallel line
* will not move, and the other vertex on the same parallel line will move considering
* rules below.
*
* If moveType is arbitrary trapezoid, the other vertex on the same parallel line
* will maintain it's relationship(angle, slope) with the other parallel line;
* If moveType is isosceles trapezoid, the other vertex on the same parallel line
* will be forced into an isosceles trapezoid vertex.
*/
//currently moving vertex.
JFPoint currentVertex=null;
//friend vertex that on the same parallel line
JFPoint friendVertex=null;
//neibor vertex of current vertex, but on the other parallel line
JFPoint peerVertex=null;
//peer vertex of current vertex, on the other parallel line.
JFPoint peerFriendVertex=null;
switch(vertexType){
case VERTEXTYPE_LEFTTOP:
currentVertex =rect.getVertex(VERTEXTYPE_LEFTTOP);
friendVertex =rect.getVertex(VERTEXTYPE_RIGHTTOP);
peerVertex =rect.getVertex(VERTEXTYPE_LEFTBOTTOM);
peerFriendVertex =rect.getVertex(VERTEXTYPE_RIGHTBOTTOM);
break;
case VERTEXTYPE_RIGHTTOP:
currentVertex =rect.getVertex(VERTEXTYPE_RIGHTTOP);
friendVertex =rect.getVertex(VERTEXTYPE_LEFTTOP);
peerVertex =rect.getVertex(VERTEXTYPE_RIGHTBOTTOM);
peerFriendVertex =rect.getVertex(VERTEXTYPE_LEFTBOTTOM);
break;
case VERTEXTYPE_LEFTBOTTOM:
currentVertex =rect.getVertex(VERTEXTYPE_LEFTBOTTOM);
friendVertex =rect.getVertex(VERTEXTYPE_RIGHTBOTTOM);
peerVertex =rect.getVertex(VERTEXTYPE_LEFTTOP);
peerFriendVertex =rect.getVertex(VERTEXTYPE_RIGHTTOP);
break;
case VERTEXTYPE_RIGHTBOTTOM:
currentVertex =rect.getVertex(VERTEXTYPE_RIGHTBOTTOM);
friendVertex =rect.getVertex(VERTEXTYPE_LEFTBOTTOM);
peerVertex =rect.getVertex(VERTEXTYPE_RIGHTTOP);
peerFriendVertex =rect.getVertex(VERTEXTYPE_LEFTTOP);
break;
default:
return;
}
//we want to get a new friend vertex here.
double slope1=0;
double slope2=0;
double newx=0; //for new friend vertex
double newy=0; //for new friend vertex
double newx1=0; //for new peer vertex
double newy1=0; //for new peer vertex
boolean requireChangePeerVertex =false;
switch(moveType){
case VERTEXMOVETYPE_PARALLEL: //parallelogram
if (x==peerVertex.getX()){
newx =peerFriendVertex.getX();
newy =peerFriendVertex.getY() - peerVertex.getY() + y;
}else if (y==peerVertex.getY()){
newy =peerFriendVertex.getY();
newx =peerFriendVertex.getX() - peerVertex.getX() + x;
}else{
switch(vertexType){
case VERTEXTYPE_LEFTTOP:
case VERTEXTYPE_RIGHTTOP:
//only friend vertex changed here.
//slope of the line that current vertex(current mouse position instead) to peer vertex
//this slope will be changed while moving current vertex.
slope1 =(peerVertex.getY()-y)/(peerVertex.getX()-x);
//slope of the line that current vertex(current mouse position instead) to friend vertex
slope2 =(peerFriendVertex.getY()-peerVertex.getY())/(peerFriendVertex.getX()-peerVertex.getX());
//two lines below:
//peer friend vertex to friend vertex, y=k1 * (x-peerFriend.x) +peerFriend.y
//current vertex to friend vertex, y=k2 * (x-current.x) +current.y
//so x=(current.y - peerFriend.y + k1 * peerFriend.x - k2 * current.x) /(k1-k2)
newx = (y-peerFriendVertex.getY()+ slope1 * peerFriendVertex.getX() - slope2 * x)/(slope1-slope2);
newy = slope1 * (newx - peerFriendVertex.getX()) + peerFriendVertex.getY();
break;
case VERTEXTYPE_LEFTBOTTOM:
case VERTEXTYPE_RIGHTBOTTOM:
//both friend vertex and peer vertex will change here.
//slope of the line that current vertex to peer vertex
//this slope will NOT be changed while moving current vertex.
slope1 =(peerVertex.getY()-currentVertex.getY())/(peerVertex.getX()-currentVertex.getX());
//slope of the line that current vertex to friend vertex
slope2 =(peerFriendVertex.getY()-peerVertex.getY())/(peerFriendVertex.getX()-peerVertex.getX());
//calculate new friend vertex.
//two lines below:
//peer friend vertex to friend vertex, y=k1 * (x-peerFriend.x) +peerFriend.y
//current vertex to friend vertex, y=k2 * (x-current.x) +current.y
//so x=(current.y - peerFriend.y + k1 * peerFriend.x - k2 * current.x) /(k1-k2)
newx = (y-peerFriendVertex.getY() + slope1 * peerFriendVertex.getX() - slope2 * x)/(slope1-slope2);
newy = slope1 * (newx-peerFriendVertex.getX()) + peerFriendVertex.getY();
//calculate new peer vertex.
//two lines below:
//peer vertex to current vertex, y=k1 * (x-current.x) + current.y
//peer friend vertex to peer vertex, y=k2 * (x-peerFriend.x) +peerFriend.y
//so x=(peerFriend.y-current.y +k1 * current.x -k2 * peerFriend.x) /(k1-k2)
newx1 = (peerFriendVertex.getY()-y + slope1 * x - slope2 * peerFriendVertex.getX())/(slope1-slope2);
newy1 = slope1 * (newx1-x) + y;
requireChangePeerVertex =true;
break;
}
}
break;
case VERTEXMOVETYPE_TRAPEZOID: //arbitrary trapezoid
//slope of the line from peer vertex to peer friend vertex.
if ((float)peerFriendVertex.getX()==(float)peerVertex.getX())
slope1 = GeomConst.LARGE_VALUE; //this value will never be used below.
else
slope1 = (peerFriendVertex.getY()-peerVertex.getY())/(peerFriendVertex.getX()-peerVertex.getX());
//slope of the line from friend vertex to peer friend vertex.
if ((float)peerFriendVertex.getX()==(float)friendVertex.getX())
slope2 = GeomConst.LARGE_VALUE; //this value will never be used below.
else
slope2 = (peerFriendVertex.getY()-friendVertex.getY())/(peerFriendVertex.getX()-friendVertex.getX());
//friend vertex and peer friend vertex are in same x coordinates.
//so we keep the x coordinate of friend vertex here.
if ((float)friendVertex.getX()==(float)peerFriendVertex.getX()){
newx =friendVertex.getX(); //save friend vertex's x coordinate
if ((float)peerFriendVertex.getY()==(float)peerVertex.getY()){
newy =y;
//peer friend vertex and peer vertex will never under same x coordinates here.
}else{
//equation of line from current vertex to friend vertex.
//y=k *(x-currentVertex.x) + currentVertex.y;
newy = slope1 * (newx - x) + y;
}
//friend vertex and peer friend vertex are in same y coordinates,
//so we keep the y coordinate of friend vertex here.
}else if ((float)friendVertex.getY()==(float)peerFriendVertex.getY()){
newy = friendVertex.getY();
if ((float)peerFriendVertex.getX()==(float)peerVertex.getX())
newx =x;
//peer friend vertex and peer vertex will never under same y coordinates here.
else{
//equation of line from current vertex to friend vertex.
//y=k *(x-currentVertex.x) + currentVertex.y;
newx = (newy-y)/slope1 + x;
}
}else{
if ((float)peerFriendVertex.getX()==(float)peerVertex.getX()){
//equation of line from peer friend vertex to friend vertex.
//y=k *(x-peerFriend.x) + peerFriend.y;
newx = x;
newy = slope2 * (x - peerFriendVertex.getX()) + peerFriendVertex.getY();
}else{
/**
* equation of line from current vertex to friend vertex.
* y=k1 *(x-currentVertex.x) + currentVertex.y;
*
* equation of line from current vertex to peer vertex.
* y=k2 *(x-peerFriend.x) + peerFriend.y;
*
* so we get:
* x=(k1 * currentVertex.x - currentVertex.y - k2 * peerFriend.x + peerFriend.y) / (k1-k2)
*
*/
newx = (slope1 * x - y - slope2 * peerFriendVertex.getX()+peerFriendVertex.getY()) / (slope1 - slope2);
newy = slope1 * (newx - x) + y;
}
}
break;
case VERTEXMOVETYPE_ISOSCELESTRAPEZOID: //isosceles trapezoid
if ((int)peerFriendVertex.getX()==(int)peerVertex.getX()){
newx = x;
newy = peerFriendVertex.getY() - (y - peerVertex.getY());
}else if ((int)peerFriendVertex.getY()==(int)peerVertex.getY()){
newx = peerFriendVertex.getX() - (x - peerVertex.getX());
newy = y;
}else{
/**
* equation of line from current vertex to friend vertex.
* y=k1 *(x-currentVertex.x) + currentVertex.y;
*
* equation of the upright line of line from current vertex to friend vertex.
* y=k2 *(x-friendMiddle.x) + friendMiddle.y;
*
* so we get:
* x=(k1 * currentVertex.x - currentVertex.y - k2 * friendMiddle.x + friendMiddle.y) / (k1-k2)
*
*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?