Math2mat
|
00001 00018 package m2m.frontend.dynamicview.editPart; 00019 00020 import java.beans.PropertyChangeEvent; 00021 import java.util.Iterator; 00022 import java.util.LinkedList; 00023 import java.util.Vector; 00024 00025 import m2m.frontend.dynamicview.editpolicies.EditLayoutPolicy; 00026 import m2m.frontend.dynamicview.figure.SchemaFigure; 00027 import m2m.frontend.dynamicview.model.BendPoint; 00028 import m2m.frontend.dynamicview.model.Connection; 00029 import m2m.frontend.dynamicview.model.GraphicFunction; 00030 import m2m.frontend.dynamicview.model.GraphicOperation; 00031 import m2m.frontend.dynamicview.model.InternPointConnection; 00032 import m2m.frontend.dynamicview.model.Node; 00033 import m2m.frontend.dynamicview.model.Schema; 00034 00035 import org.eclipse.draw2d.IFigure; 00036 import org.eclipse.draw2d.geometry.Point; 00037 import org.eclipse.draw2d.geometry.Rectangle; 00038 import org.eclipse.gef.EditPolicy; 00039 00040 00041 public class SchemaPart extends AbstractEditPart 00042 { 00046 private static int BUSY_POINT = -1; 00050 private static int FREE_POINT = Integer.MAX_VALUE; 00054 private static int CONNECTION_POINT = Integer.MAX_VALUE-1; 00058 private static int FUNCTION_POINT = Integer.MAX_VALUE-2; 00062 private int [][] tabRouter = new int [2000] [2000]; 00066 private int [][] tabTemp; 00067 00068 00073 @Override 00074 protected IFigure createFigure() 00075 { 00076 IFigure figure = new SchemaFigure(); 00077 ((SchemaFigure) figure).addMouseMotionListener(this); 00078 ((SchemaFigure) figure).addMouseListener(this); 00079 ((Schema)getModel()).setLayout(((SchemaFigure) figure).getBounds()); 00080 return figure; 00081 } 00082 00083 00087 @Override 00088 protected void createEditPolicies() 00089 { 00090 installEditPolicy(EditPolicy.LAYOUT_ROLE, new EditLayoutPolicy()); 00091 } 00092 00093 00098 public Vector<Node> getModelChildren() 00099 { 00100 return ((Schema)getModel()).getChildrenArray(); 00101 } 00102 00103 00108 @Override 00109 public void propertyChange(PropertyChangeEvent evt) 00110 { 00111 if (evt.getPropertyName().equals(Node.LAYOUT)) 00112 refreshVisuals(); 00113 } 00114 00115 00120 private void routeConnections(Vector<Connection> conList) 00121 { 00122 initTabRouter(); 00123 00124 for(Connection con : conList) 00125 { 00126 if(!(con.getSource() instanceof GraphicOperation)) 00127 { 00128 // Get and convert the oldest parent of the connection 00129 Rectangle parentAbsoluteLayout = getAbsoluteLayout(getOldParent(con.getSource(), con.getTarget())); 00130 00131 // Initialize the size of the tabTemp 00132 tabTemp = new int [parentAbsoluteLayout.width][parentAbsoluteLayout.height]; 00133 00134 /* Duplicate the interest part of the tabRouter */ 00135 for(int i = 0; i < tabTemp.length; i++) 00136 for(int j = 0; j < tabTemp[i].length; j++) 00137 if ((i == 0 || i == tabTemp.length-1) || (j == 0 || j == tabTemp[i].length-1)) 00138 tabTemp[i][j] = -1; 00139 else 00140 tabTemp[i][j] = tabRouter[i+parentAbsoluteLayout.x][j+parentAbsoluteLayout.y]; 00141 00142 /* Get the start and end layout connection node */ 00143 Rectangle startLayout = getAbsoluteLayout(con.getSource()); 00144 Rectangle endLayout = getAbsoluteLayout(con.getTarget()); 00145 00146 /* Get the start point outside the node source anchor */ 00147 Point startAnchorPoint = getAnchorPoint(new Point(startLayout.x+startLayout.width/2, startLayout.y+startLayout.height/2)); 00148 startAnchorPoint.performTranslate(-parentAbsoluteLayout.x, -parentAbsoluteLayout.y); 00149 00150 /* Get the end point outside the node target anchor */ 00151 Point endAnchorPoint = getAnchorPoint(new Point(endLayout.x+endLayout.width/2-1, endLayout.y+endLayout.height/2)); 00152 endAnchorPoint.performTranslate(-parentAbsoluteLayout.x, -parentAbsoluteLayout.y); 00153 00154 // Initialize the start point of the tabTemp 00155 tabTemp[startAnchorPoint.x] [startAnchorPoint.y] = 1; 00156 00157 /* Use to go through points of the tabTemp */ 00158 LinkedList<Point> pointList = new LinkedList<Point>(); 00159 pointList.add(startAnchorPoint); 00160 Point point = new Point(0,0); 00161 Point tempPoint = new Point(0,0); 00162 int valeurTab; 00163 int maxDepth = ((Schema)getModel()).maxDepth; 00164 int currentDepthSource; 00165 int currentDepthTarget; 00166 int maxCurrentDepth; 00167 00168 Iterator<Point> iterPoint = pointList.iterator(); 00169 while (iterPoint.hasNext()) 00170 { 00171 point.setLocation(iterPoint.next()); 00172 00173 /* Go through the four neighbors of the current point */ 00174 for(int i = 0; i < 4; i++) 00175 { 00176 switch(i) 00177 { 00178 case 0: tempPoint.setLocation(point.x-1, point.y); break; 00179 case 1: tempPoint.setLocation(point.x, point.y-1); break; 00180 case 2: tempPoint.setLocation(point.x+1, point.y); break; 00181 case 3: tempPoint.setLocation(point.x, point.y+1); break; 00182 } 00183 00184 valeurTab = tabTemp[tempPoint.x][tempPoint.y]; 00185 00186 currentDepthSource = con.getSource().getDepthLevel(); 00187 currentDepthTarget = con.getTarget().getDepthLevel(); 00188 maxCurrentDepth = currentDepthSource > currentDepthTarget ? currentDepthSource : currentDepthTarget; 00189 00190 if(!(valeurTab >= FUNCTION_POINT-maxDepth && valeurTab <= FUNCTION_POINT-maxCurrentDepth) && valeurTab != BUSY_POINT && valeurTab > tabTemp[point.x][point.y]+1) 00191 { 00192 if(tabRouter[tempPoint.x+parentAbsoluteLayout.x][tempPoint.y+parentAbsoluteLayout.y] == CONNECTION_POINT) 00193 { 00194 if(valeurTab > tabTemp[point.x][point.y]+10) 00195 { 00196 tabTemp[tempPoint.x][tempPoint.y] = tabTemp[point.x][point.y]+10; 00197 pointList.add(new Point(tempPoint.x, tempPoint.y)); 00198 } 00199 } 00200 else 00201 { 00202 tabTemp[tempPoint.x][tempPoint.y] = tabTemp[point.x][point.y]+1; 00203 pointList.add(new Point(tempPoint.x, tempPoint.y)); 00204 } 00205 } 00206 } 00207 00208 /* Update the list of points ans its iterator */ 00209 pointList.remove(pointList.indexOf(point)); 00210 iterPoint = pointList.iterator(); 00211 } 00212 00213 // Find the best way of the connection 00214 findBestWay(endAnchorPoint, startAnchorPoint, 00215 new Point(endLayout.x +endLayout.width/2-1, endLayout.y + endLayout.height/2), 00216 new Point(startLayout.x+startLayout.width/2, startLayout.y + startLayout.height/2), 00217 con); 00218 } 00219 } 00220 } 00221 00222 00226 private void initTabRouter() 00227 { 00228 Schema schema = (Schema)getModel(); 00229 Node node; 00230 Rectangle rectTemp = new Rectangle(0,0,0,0); 00231 00232 /* Initialize all the cell of tabRouter with Integer.MAX_VALUE and border with -1 */ 00233 for(int i = 0; i < tabRouter.length; i++) 00234 for(int j = 0; j < tabRouter[i].length; j++) 00235 if ((i == 0 || i == tabRouter.length-1) || (j == 0 || j == tabRouter[i].length-1)) 00236 tabRouter[i][j] = BUSY_POINT; 00237 else 00238 tabRouter[i][j] = FREE_POINT; 00239 00240 LinkedList<Node> nodeList = new LinkedList<Node>(); 00241 nodeList.addAll(schema.getChildrenArray()); 00242 Iterator<Node> iterNode = nodeList.iterator(); 00243 00244 /* Initialize the tabRouter with actually node positions */ 00245 while (iterNode.hasNext()) 00246 { 00247 node = iterNode.next(); 00248 00249 if(node.getVisible()) 00250 { 00251 /* Check if the node has children */ 00252 if(node.getChildrenArray().size() != 0) 00253 nodeList.addAll(node.getChildrenArray()); 00254 00255 /* Get the absolute layout of the node */ 00256 rectTemp = getAbsoluteLayout(node); 00257 00258 if (!(node instanceof GraphicFunction)) 00259 { 00260 /* Initialize the tabRouter with the node position */ 00261 for(int i = rectTemp.x-5; i < rectTemp.x+rectTemp.width+5; i++) 00262 for(int j = rectTemp.y-5; j < rectTemp.y+rectTemp.height+5; j++) 00263 tabRouter[i][j] = BUSY_POINT; 00264 } 00265 else 00266 { 00267 int depthLevel = node.getDepthLevel(); 00268 00269 /* Initialize the tabRouter with verctical borders of function position */ 00270 for(int i = rectTemp.x-5; i <= rectTemp.x+rectTemp.width+5; i++) 00271 { 00272 tabRouter[i][rectTemp.y-5] = FUNCTION_POINT-depthLevel; 00273 tabRouter[i][rectTemp.y+rectTemp.height+5] = FUNCTION_POINT-depthLevel; 00274 } 00275 00276 /* Initialize the tabRouter with horizontal borders of function position */ 00277 for(int j = rectTemp.y-5; j <= rectTemp.y+rectTemp.height+5; j++) 00278 { 00279 tabRouter[rectTemp.x-5][j] = FUNCTION_POINT-depthLevel; 00280 tabRouter[rectTemp.x+rectTemp.width+5][j] = FUNCTION_POINT-depthLevel; 00281 } 00282 } 00283 } 00284 00285 nodeList.remove(nodeList.indexOf(node)); 00286 iterNode = nodeList.iterator(); 00287 } 00288 } 00289 00290 00296 private Rectangle getAbsoluteLayout(Node node) 00297 { 00298 Rectangle layout = new Rectangle (0, 0, node.getLayout().width, node.getLayout().height); 00299 Node nodeTemp = node; 00300 00301 /* Go through all parents of the node */ 00302 while(!(nodeTemp instanceof Schema)) 00303 { 00304 layout.x += nodeTemp.getLayout().x; 00305 layout.y += nodeTemp.getLayout().y; 00306 nodeTemp = nodeTemp.getParent(); 00307 } 00308 00309 return layout; 00310 } 00311 00312 00318 private Point getAnchorPoint(Point point) 00319 { 00320 /* Create and initialize an array containing the four neighbors of the start point */ 00321 Point[] tabPoint = new Point[4]; 00322 tabPoint[0] = new Point(point.x-1, point.y); 00323 tabPoint[1] = new Point(point.x, point.y-1); 00324 tabPoint[2] = new Point(point.x+1, point.y); 00325 tabPoint[3] = new Point(point.x, point.y+1); 00326 00327 while(true) 00328 { 00329 /* Go through the four neighbors */ 00330 for(int i = 0; i < tabPoint.length; i++) 00331 { 00332 /* Check if the anchor point is found */ 00333 if(tabRouter[tabPoint[i].x] [tabPoint[i].y] != -1) 00334 return tabPoint[i]; 00335 00336 else 00337 /* Get the four next neighbors of the start point */ 00338 switch(i) 00339 { 00340 case 0: tabPoint[i].x--; break; 00341 case 1: tabPoint[i].y--; break; 00342 case 2: tabPoint[i].x++; break; 00343 case 3: tabPoint[i].y++; break; 00344 } 00345 } 00346 } 00347 } 00348 00349 00358 private void findBestWay(Point endAnchorPoint, Point startAnchorPoint, Point endPoint, Point startPoint, Connection con) 00359 { 00360 Rectangle parentAbsoluteLayout = getAbsoluteLayout(getOldParent(con.getSource(), con.getTarget())); 00361 00362 /* Use to go through all points */ 00363 Point currentPoint = new Point(endAnchorPoint); 00364 Point nextPoint = new Point(0,0); 00365 Point tempPoint = new Point(0,0); 00366 00367 /* Convert start and end anchor point with the absolute parent layout */ 00368 startAnchorPoint.performTranslate(parentAbsoluteLayout.x, parentAbsoluteLayout.y); 00369 endAnchorPoint.performTranslate(parentAbsoluteLayout.x, parentAbsoluteLayout.y); 00370 00371 int minValue = tabTemp[currentPoint.x][currentPoint.y]; 00372 int temSens = 0; 00373 int sens = 0; 00374 00375 // Get the sens of the end point 00376 sens = getSens(endPoint, endAnchorPoint); 00377 00378 // Remove alle bend points of the connection 00379 con.getBendPoints().removeAll(con.getBendPoints()); 00380 00381 while(minValue != 1) 00382 { 00383 /* Get the neighbor who represent the least value */ 00384 for(int i = 0; i < 4; i++) 00385 { 00386 switch(i) 00387 { 00388 case 0: tempPoint.setLocation(currentPoint.x-1, currentPoint.y); break; 00389 case 1: tempPoint.setLocation(currentPoint.x, currentPoint.y-1); break; 00390 case 2: tempPoint.setLocation(currentPoint.x+1, currentPoint.y); break; 00391 case 3: tempPoint.setLocation(currentPoint.x, currentPoint.y+1); break; 00392 } 00393 00394 if(tabTemp[tempPoint.x][tempPoint.y] < minValue && tabTemp[tempPoint.x][tempPoint.y] != -1) 00395 { 00396 minValue = tabTemp[tempPoint.x][tempPoint.y]; 00397 nextPoint.setLocation(tempPoint); 00398 temSens = i; 00399 } 00400 } 00401 00402 /* Set all busy the point of the connection */ 00403 tabRouter[nextPoint.x+parentAbsoluteLayout.x][nextPoint.y+parentAbsoluteLayout.y] = CONNECTION_POINT; 00404 for(int i = 1; i < 6; i++) 00405 for(int j = 0; j < 7; j++) 00406 { 00407 switch(j) 00408 { 00409 case 0: tempPoint.setLocation(nextPoint.x-i, nextPoint.y); break; 00410 case 1: tempPoint.setLocation(nextPoint.x, nextPoint.y-i); break; 00411 case 2: tempPoint.setLocation(nextPoint.x+i, nextPoint.y); break; 00412 case 3: tempPoint.setLocation(nextPoint.x, nextPoint.y+i); break; 00413 case 4: tempPoint.setLocation(nextPoint.x-i, nextPoint.y+i); break; 00414 case 5: tempPoint.setLocation(nextPoint.x-i, nextPoint.y-i); break; 00415 case 6: tempPoint.setLocation(nextPoint.x+i, nextPoint.y-i); break; 00416 case 7: tempPoint.setLocation(nextPoint.x+i, nextPoint.y+i); break; 00417 } 00418 tempPoint.performTranslate(parentAbsoluteLayout.x, parentAbsoluteLayout.y); 00419 if(tempPoint.x < tabRouter.length && tempPoint.y < tabRouter[0].length && tabRouter[tempPoint.x][tempPoint.y] != -1 && tabRouter[tempPoint.x][tempPoint.y] != FUNCTION_POINT) 00420 tabRouter[tempPoint.x][tempPoint.y] = CONNECTION_POINT; 00421 } 00422 00423 00424 /* Add a bendPoint if the sens is different */ 00425 if(sens != temSens) 00426 { 00427 BendPoint bp = new BendPoint(); 00428 currentPoint.performTranslate(parentAbsoluteLayout.x, parentAbsoluteLayout.y); 00429 bp.setHeight(currentPoint.getDifference(startPoint).height, currentPoint.getDifference(endPoint).height); 00430 bp.setWidth(currentPoint.getDifference(startPoint).width, currentPoint.getDifference(endPoint).width); 00431 00432 bp.setConnection(con); 00433 bp.setIndex(0); 00434 con.addBendPoint(bp); 00435 00436 sens = temSens; 00437 } 00438 currentPoint.setLocation(nextPoint); 00439 } 00440 00441 // Get the sens of the start point 00442 sens = getSens(startPoint, startAnchorPoint); 00443 00444 /* Add the last bendPoint if the sens is different */ 00445 if(sens != temSens) 00446 { 00447 BendPoint bp = new BendPoint(); 00448 currentPoint.performTranslate(parentAbsoluteLayout.x, parentAbsoluteLayout.y); 00449 bp.setHeight(currentPoint.getDifference(startPoint).height, currentPoint.getDifference(endPoint).height); 00450 bp.setWidth(currentPoint.getDifference(startPoint).width, currentPoint.getDifference(endPoint).width); 00451 00452 bp.setConnection(con); 00453 bp.setIndex(0); 00454 con.addBendPoint(bp); 00455 00456 sens = temSens; 00457 } 00458 } 00459 00460 00464 public void Intersections() 00465 { 00466 // Vector of connections who must be route 00467 Vector<Connection> routeConList = new Vector<Connection>(); 00468 00469 /* Use to go through all connections and nodes */ 00470 Vector<Connection> conList = new Vector<Connection>(); 00471 Vector<Node> nodeList = new Vector<Node>(); 00472 00473 /* Use to get all nodes and connections */ 00474 Node tempNode; 00475 LinkedList<Node> tempNodeList = new LinkedList<Node>(); 00476 Iterator<Node> iterNode; 00477 00478 /* Initialize node lists and the node iterator */ 00479 nodeList.addAll(((Schema)getModel()).getChildrenArray()); 00480 tempNodeList.addAll(((Schema)getModel()).getChildrenArray()); 00481 iterNode = tempNodeList.iterator(); 00482 00483 /* Get all nodes and connections inside the schema */ 00484 while (iterNode.hasNext()) 00485 { 00486 tempNode = iterNode.next(); 00487 00488 /* Check if the node has children */ 00489 if(tempNode.getChildrenArray().size() != 0) 00490 { 00491 nodeList.addAll(tempNode.getChildrenArray()); 00492 tempNodeList.addAll(tempNode.getChildrenArray()); 00493 } 00494 00495 conList.addAll(tempNode.getSourceConnections()); 00496 tempNodeList.remove(tempNodeList.indexOf(tempNode)); 00497 iterNode = tempNodeList.iterator(); 00498 } 00499 00500 00501 /* Go through all nodes and connections */ 00502 for(Connection con : conList) 00503 { 00504 if(con.getMustBeRoute()) 00505 { 00506 for(Node node : nodeList) 00507 { 00508 /* Check if there are intersections between some nodes and connections */ 00509 if(node != con.getSource() && node != con.getTarget() && node.getVisible() && con.getTarget().getVisible() && con.getSource().getVisible() && con.getVisible()) 00510 { 00511 if(node instanceof GraphicFunction) 00512 { 00513 if(node.getDepthLevel() >= con.getSource().getDepthLevel() && node.getDepthLevel() >= con.getTarget().getDepthLevel()) 00514 if(connectionNodeIntersection(con, getAbsoluteLayout(node)) && !routeConList.contains(con)) 00515 routeConList.add(con); 00516 } 00517 else if(connectionNodeIntersection(con, getAbsoluteLayout(node)) && !routeConList.contains(con)) 00518 routeConList.add(con); 00519 } 00520 } 00521 00522 if(!routeConList.contains(con)) 00523 con.removeAllBendPoint(); 00524 } 00525 } 00526 00527 routeConnections(routeConList); 00528 } 00529 00530 00537 private boolean connectionNodeIntersection(Connection con, Rectangle layout) 00538 { 00539 /* Get the start and the end absolute layout of the connection */ 00540 Rectangle startNodeLayout = getAbsoluteLayout(con.getSource()); 00541 Rectangle endNodeLayout = getAbsoluteLayout(con.getTarget()); 00542 00543 /* Get the start and the end anchor point of the connection */ 00544 Point A = new Point(startNodeLayout.x+startNodeLayout.width/2, startNodeLayout.y+startNodeLayout.height/2); 00545 Point B = new Point(endNodeLayout.x+endNodeLayout.width/2, endNodeLayout.y+endNodeLayout.height/2); 00546 00547 /* Check each segment of the node layout */ 00548 if(segmentIntersection(A, B, new Point(layout.x, layout.y), new Point(layout.x, layout.y+layout.height))) 00549 if(!(con.getTarget() instanceof InternPointConnection)) 00550 return true; 00551 if(segmentIntersection(A, B, new Point(layout.x, layout.y), new Point(layout.x+layout.width, layout.y))) 00552 return true; 00553 if(segmentIntersection(A, B, new Point(layout.x, layout.y+layout.height), new Point(layout.x+layout.width, layout.y+layout.height))) 00554 return true; 00555 if(segmentIntersection(A, B, new Point(layout.x+layout.width, layout.y), new Point(layout.x+layout.width, layout.y+layout.height))) 00556 if(!(con.getSource() instanceof InternPointConnection)) 00557 return true; 00558 00559 return false; 00560 } 00561 00562 00571 private boolean segmentIntersection(Point a1, Point a2, Point b1, Point b2) 00572 { 00573 int d = (a1.x-a2.x)*(b1.y-b2.y) - (a1.y-a2.y)*(b1.x-b2.x); 00574 if (d == 0) 00575 return false; 00576 00577 /* Calculate the intersection point */ 00578 int xi = ((b1.x-b2.x)*(a1.x*a2.y-a1.y*a2.x)-(a1.x-a2.x)*(b1.x*b2.y-b1.y*b2.x))/d; 00579 int yi = ((b1.y-b2.y)*(a1.x*a2.y-a1.y*a2.x)-(a1.y-a2.y)*(b1.x*b2.y-b1.y*b2.x))/d; 00580 00581 /* Check if the intersection point is on segments */ 00582 if (xi < Math.min(a1.x,a2.x) || xi > Math.max(a1.x,a2.x)) 00583 return false; 00584 if (xi < Math.min(b1.x,b2.x) || xi > Math.max(b1.x,b2.x)) 00585 return false; 00586 if (yi < Math.min(a1.y,a2.y) || yi > Math.max(a1.y,a2.y)) 00587 return false; 00588 if (yi < Math.min(b1.y,b2.y) || yi > Math.max(b1.y,b2.y)) 00589 return false; 00590 00591 return true; 00592 } 00593 00594 00600 private int getSens(Point point, Point anchorPoint) 00601 { 00602 if(Math.abs(point.x-anchorPoint.x) > 4) 00603 if(point.x > anchorPoint.x) 00604 return 0; 00605 else 00606 return 2; 00607 else if(Math.abs(point.y-anchorPoint.y) > 4) 00608 if(point.y > anchorPoint.y) 00609 return 1; 00610 else 00611 return 3; 00612 00613 return -1; 00614 } 00615 00616 00623 private Node getOldParent(Node nodeSource, Node nodeTarget) 00624 { 00625 Rectangle parentSourceLayout = getAbsoluteLayout(nodeSource.getParent()); 00626 Rectangle parentTargetLayout = getAbsoluteLayout(nodeTarget.getParent()); 00627 00628 return parentSourceLayout.contains(parentTargetLayout) ? nodeSource.getParent() : nodeTarget.getParent(); 00629 } 00630 00631 00636 public int [][] getTabRouter() 00637 { 00638 return tabRouter; 00639 } 00640 }