regularline.java
来自「用Java开发的、实现类似Visio功能的应用程序源码」· Java 代码 · 共 1,911 行 · 第 1/4 页
JAVA
1,911 行
/**
* Create a new point node. We will firstly to find a FREE node from temp node list, false to create a new one.
* @return a new point node object.
*
*/
private JFPointNode newNode(){
return newNode(0,0,0);
}
/**
* Create a new point node. We will firstly to find a FREE node from temp node list, false to create a new one.
*
* @param pnt A JFPoint.
*
* @param nodeType A new node type.
*
* @return a new point node object.
*
*/
private JFPointNode newNode(JFPoint pnt, int nodeType){
return newNode(pnt.getX(),pnt.getY(),nodeType);
}
/**
* Create a new point node. We will firstly to find a FREE node from temp node list, false to create a new one.
*
* @param node A JFPointNode.
* @return a new point node object.
*
*/
private JFPointNode newNode(JFPointNode node){
return newNode(node.getX(),node.getY(),node.getNodeType());
}
/**
* Create a new point node. We will firstly to find a FREE node from temp node list, false to create a new one.
*
* @param x X coordiate.
*
* @param y Y coordiate.
*
* @param nodeType A new node type.
*
* @return a new point node object.
*/
private JFPointNode newNode(double x, double y, int nodeType){
JFPointNode node=null;
int size =m_tempNodeList.size();
if (size>0){
try{
node =(JFPointNode)m_tempNodeList.get(size-1);
m_tempNodeList.remove(size-1);
}catch(Exception e){
node =null;
}
}
if (node!=null){
node.setValue(x,y);
node.setNodeType(nodeType);
}else{
node =new JFPointNode(x,y,nodeType);
}
return node;
}
/**
* Minimum line segment(MIN_LINELENGTH_SEGMENT) that can be divided into four slips. It's not equal as MIN_LINELENGTH,
* that's a length that don't need to be divided, so it(MIN_LINELENGTH)) is a very small pixel numbers than MIN_LINELENGTH_SEGMENT.
*/
private static final int MIN_LINELENGTH_SEGMENT =60;
private static final int MIN_LINELENGTH_SEGMENT_HALF=30;
/**
* Add a new node to regular line. The coordinates of this node has been adjusted to according to REGULAR rules elsewhere.
* @param nodeList A node list that a new node will be added in.
* @param x; y A new node.
* @param extendLastNode True if extend the last node only, false otherwise.
*/
private void addNodeFinally(List nodeList,double x, double y,boolean extendLastNode){
JFPointNode lastNode =getLastNode(nodeList,true);
if (lastNode==null){
nodeList.add(newNode(x,y,JFPointNode.NODETYPE_END));
return;
}
if (lastNode.distance(x,y)<1)
return;
JFPointNode lastSecNode =getLastSecondNode(nodeList,true);
//a line segment will constructed by a start point, an end point, a middle point and two sub middle point
JFPointNode node;
JFPointNode startNode;
if (lastSecNode!=null && extendLastNode){
//truncate the tail of list to last second node.
truncateTail(nodeList,lastSecNode,true);
startNode =lastSecNode;
}else{
startNode =lastNode;
}
double len=startNode.distance(x,y);
if (len < MIN_LINELENGTH_SEGMENT_HALF){
//can not be divided into any slips.
//end point
node =newNode(x,y,JFPointNode.NODETYPE_END);
nodeList.add(node);
}else if (len < MIN_LINELENGTH_SEGMENT){
//can only be divided into two slips.
//mid point
node =newNode(startNode.midPoint(x,y), JFPointNode.NODETYPE_MIDDLE);
nodeList.add(node);
//end point
node =newNode(x,y,JFPointNode.NODETYPE_END);
nodeList.add(node);
}else{
//can be divided into four slips.
//mid point
node =newNode(startNode.midPoint(x,y), JFPointNode.NODETYPE_MIDDLE);
//sub middle point 1(between start node and middle node)
JFPointNode sub1 =newNode(startNode.midPoint(node), JFPointNode.NODETYPE_SUBMIDDLE);
//sub middle point 2(between middle node and end node)
JFPointNode sub2 =newNode(node.midPoint(x,y), JFPointNode.NODETYPE_SUBMIDDLE);
//end point
JFPointNode endNode =newNode(x,y,JFPointNode.NODETYPE_END);
//add for nodes into list:
nodeList.add(sub1);
nodeList.add(node);
nodeList.add(sub2);
nodeList.add(endNode);
}
}
/**
* Add a new node to regular line.
* @param node A new node.
*/
public void addNode(JFPoint pnt){
if (pnt==null)
return;
addNode(pnt.getX(),pnt.getY());
}
/**
* Add a new node to regular line.
* @param x; y A new node.
*/
public void addNode(double x, double y){
addNode(m_nodeList,x,y,true);
}
/**
* Add a new node to regular line.
* @param nodeList A node list that a new node will be added in.
* @param x; y A new node.
* @param allowExtend Allow to extend last line segment while the new point is under the Regular rules.
*/
private void addNode(List nodeList,double x, double y, boolean allowExtend){
JFPointNode node;
if (nodeList.size()==0){
//not assigned any node yet.
node =newNode(x,y, JFPointNode.NODETYPE_END);
nodeList.add(node);
}else{
JFPointNode lastNode =getLastNode(nodeList,true);
if (lastNode==null)
return;
if (lastNode.distance(x,y)<=GeomConst.MIN_LINELENGTH)
return;
double width =lastNode.distance(x,lastNode.getY());
double height =lastNode.distance(lastNode.getX(),y);
JFPointNode lastSecNode =getLastSecondNode(nodeList,true);
int lineType =getSegmentType(lastNode,lastSecNode);
if (width<=GeomConst.MIN_LINELENGTH){
//ignore width offset of new node.
switch (lineType){
case LINETYPE_NONE: //only assigned a start node now.
case LINETYPE_HORIZONTAL: //simply append a new node
addNodeFinally(nodeList,lastNode.getX(),y,false);
break;
case LINETYPE_VERTICAL:
//extend this vertical line.
addNodeFinally(nodeList,lastNode.getX(),y,true && allowExtend);
break;
}
}else if (height<=GeomConst.MIN_LINELENGTH){
//ignore height offset of new node.
switch (lineType){
case LINETYPE_NONE: //only assigned a start node now.
case LINETYPE_VERTICAL: //simply append a new node
addNodeFinally(nodeList,x,lastNode.getY(),false);
break;
case LINETYPE_HORIZONTAL:
//extend this horizontal line.
addNodeFinally(nodeList,x,lastNode.getY(),true && allowExtend);
break;
}
}else{
switch (lineType){
case LINETYPE_NONE: //only assigned a start node now.
if (width>=height)
addNodeFinally(nodeList,x,lastNode.getY(),false);
else
addNodeFinally(nodeList,lastNode.getX(),y,false);
addNodeFinally(nodeList,x,y,false);
break;
case LINETYPE_VERTICAL:
//last second node and current new node are on the same side according to last node,
//so we make an upright corner according to last node.
if ((lastSecNode.getY()>lastNode.getY() && y>lastNode.getY())||
(lastSecNode.getY()<lastNode.getY() && y<lastNode.getY())){
addNodeFinally(nodeList,x,lastNode.getY(),false);
//last second node and current new node are on the different side according to last node,
//so we extend last node firstly.
}else{
addNodeFinally(nodeList,lastNode.getX(),y,true && allowExtend);
}
addNodeFinally(nodeList,x,y,false);
break;
case LINETYPE_HORIZONTAL:
//last second node and current new node are on the same side according to last node,
//so we make an upright corner according to last node.
if ((lastSecNode.getX()>lastNode.getX() && x>lastNode.getX())||
(lastSecNode.getX()<lastNode.getX() && x<lastNode.getX())){
addNodeFinally(nodeList,lastNode.getX(),y,false);
//last second node and current new node are on the different side according to last node,
//so we extend last node firstly.
}else{
addNodeFinally(nodeList,x,lastNode.getY(),true && allowExtend);
}
addNodeFinally(nodeList,x,y,false);
break;
}
}
}
}
/**
* Store nodes into a list(start from 0 or max item in list, end at specified node).
* @param fromNodeList A nodes list to be partly stored into list.
* @param toNodeList Target node list that the nodes will be stored in.
* @param node A node indicates the position to stop saving.(but save this node also) if this node is null, save all.
* @param reverse True if start at size-1, False 0.
*/
private static void saveToList(List fromNodeList,List toNodeList,JFPointNode node, boolean reverse){
if (fromNodeList==null || fromNodeList.size()==0 ||toNodeList==null)
return;
int size = fromNodeList.size();
int start=0;
int end=0;
if (reverse){
start =size-1;
if (node!=null)
end =getNodeIndex(fromNodeList,node);
else
end =0;
if (start<end) return;
}else{
start =0;
if (node!=null)
end =getNodeIndex(fromNodeList,node);
else
end =size-1;
if (start>end) return;
}
int deleteFrom =Math.max(start,end);
int deleteTo =Math.min(start,end);
//save firstly
while (true){
try{
JFPointNode newNode=(JFPointNode)fromNodeList.get(start);
toNodeList.add(newNode);
if (node!=null && newNode.equals(node))
break;
if (reverse){
start--;
if (start<end) break;
}
else{
start++;
if (start>end) break;
}
}catch(Exception e){
break;
}
}
//remove then
for (int i=deleteFrom; i>=deleteTo; i--){
try{
fromNodeList.remove(i);
}catch(Exception e){
break;
}
}
}
/**
* A temperary point node list for storing nodes. used by moving.
*/
private List m_storeList =new ArrayList();
/**
* A variable indicates if move action started.
*/
private boolean m_moveStarted =false;
/**
* A variable indicates that the original index of node to be moved.
*/
private int m_originalIndex =0;
/**
* Replace part of a node list with a new list.
* @param srcList Source nodes list to be partly replaced.
* @param destList Destination nodes list to replace part of source list.
* @param startNode Position to start replacing.
* @param endNode Position to end replacing.
*/
private void replaceNodes(List srcList,List destList,JFPointNode startNode,JFPointNode endNode){
if (srcList==null || destList==null)
return;
int start=0;
int end=0;
if (startNode==null)
start =0;
else
start =getNodeIndex(srcList,startNode);
if (endNode==null)
end =srcList.size()-1;
else
end =getNodeIndex(srcList,endNode);
//remove nodes
for (int i=end; i>=start; i--){
try{
srcList.remove(i);
}catch(Exception e){
}
}
//insert nodes list.
if (start>srcList.size()-1){
srcList.addAll(destList);
}else{
srcList.addAll(start,destList);
}
//clear dest list nodes.
clearNodes(destList,false);
}
/*
private void printList(List l,String memo){
Iterator it =l.iterator();
int i=0;
StringBuffer buf=new StringBuffer();
buf.append(memo);
buf.append(" nodeCount:");
buf.append(l.size());
buf.append("----------\n");
while (it!=null && it.hasNext()){
JFPointNode node=(JFPointNode)it.next();
buf.append("node");
buf.append(++i);
buf.append("=");
buf.append((float)node.getX());
buf.append(",");
buf.append((float)node.getY());
buf.append(" nodeType=");
switch (node.getNodeType()){
case JFPointNode.NODETYPE_END:
buf.append("end");
break;
case JFPointNode.NODETYPE_MIDDLE:
buf.append("Middle");
break;
case JFPointNode.NODETYPE_SUBMIDDLE:
buf.append("subMiddle");
break;
}
buf.append(";\n");
}
System.out.println(buf.toString());
}
*/
/**
* Get a unpright foot that the target point according to the line from refNode1 to refNode 2
* If the upright node is refNode1, or refNode2, or is x,y itself, we'll simply return a NULL.
*/
private JFPointNode getUprightFoot(JFPointNode refNode1, JFPointNode refNode2, double x, double y){
JFPointNode ret =newNode();
ret.setNodeType(JFPointNode.NODETYPE_END);
if (refNode1==null){
return null;
}
if (refNode2==null){
double width =refNode1.distance(x,refNode1.getY());
double height =refNode1.distance(refNode1.getX(),y);
if ((float)width==0 || (float)height==0)
return null;
if (width>=height){
ret.setX(refNode1.getX());
ret.setY(y);
}else{
ret.setX(x);
ret.setY(refNode1.getY());
}
return ret;
}else{
if ((float)refNode1.getX()==(float)refNode2.getX()){
ret.setX(refNode1.getX());
ret.setY(y);
}else{
ret.setX(x);
ret.setY(refNode1.getY());
}
//here we allow a new node equal as refNode1, because of refNode1 is only a reference one, not an actual one.
if ((float)ret.distance(refNode2)==0 || (float)ret.distance(x,y)==0)
return null;
else
return ret;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?