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;&nbsp;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;&nbsp;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 + -
显示快捷键?