$search
00001 package edu.tum.cs.ias.knowrob.vis.applets; 00002 00003 import java.awt.Color; 00004 import java.awt.Cursor; 00005 import java.awt.event.MouseEvent; 00006 import java.awt.event.MouseListener; 00007 import java.awt.event.MouseMotionListener; 00008 import java.awt.event.MouseWheelEvent; 00009 import java.awt.event.MouseWheelListener; 00010 import java.util.ArrayList; 00011 import java.util.HashMap; 00012 import java.util.HashSet; 00013 import java.util.Iterator; 00014 import java.util.Vector; 00015 00016 import javax.vecmath.Vector2f; 00017 00018 import edu.tum.cs.ias.knowrob.owl.OWLThing; 00019 import edu.tum.cs.ias.knowrob.prolog.PrologInterface; 00020 import edu.tum.cs.ias.knowrob.vis.actions.Action; 00021 import edu.tum.cs.ias.knowrob.vis.actions.ActionSelectHistoryInfo; 00022 00023 import processing.core.PApplet; 00024 import processing.core.PFont; 00025 00031 public class PlanVisApplet extends PApplet implements MouseListener, MouseMotionListener,MouseWheelListener { 00032 00033 private static final long serialVersionUID = 7695328948788620463L; 00034 00038 private PFont dejavuFont; 00039 00043 private Action currAction; 00044 00048 private static final Cursor normalCursor = new Cursor(Cursor.DEFAULT_CURSOR); 00049 00053 private static final Cursor handCursor = new Cursor(Cursor.HAND_CURSOR); 00054 00058 private static final Cursor moveCursor = new Cursor(Cursor.MOVE_CURSOR); 00059 00064 private long lastClickTime = 0; 00065 00071 private ArrayList<ActionSelectHistoryInfo> clickHistory = new ArrayList<ActionSelectHistoryInfo>(); 00072 00076 private Vector2f drawOffset = new Vector2f(0,0); 00080 private Vector2f draggingStart = new Vector2f(0,0); 00081 00085 public PlanVisApplet() 00086 { 00087 this.redraw(); 00088 } 00089 00090 @Override 00091 public void setup() 00092 { 00093 size(1600, 600, P2D); 00094 if (this.frame != null) 00095 { 00096 this.frame.setTitle("Action plans visualisation"); 00097 this.frame.setBackground(new Color(10, 10, 10)); 00098 } 00099 00100 addMouseMotionListener(this); 00101 addMouseListener(this); 00102 00103 dejavuFont = createFont("DejaVu Sans",13); 00104 textFont(dejavuFont); 00105 hint(ENABLE_ACCURATE_TEXTURES); 00106 ellipseMode(RADIUS); 00107 frameRate(20); 00108 } 00109 00110 @Override 00111 public void draw() { 00112 00113 background(40); 00114 00115 textFont(dejavuFont); 00116 textMode(SCREEN); 00117 00118 00119 drawCurrAction(); 00120 drawHistory(); 00121 00122 00123 } 00124 00130 private Action loadPrologPlanRecursive(String iri) 00131 { 00132 00133 //Get the action name 00134 String label = ""; 00135 try 00136 { 00137 HashMap<String, Vector<String>> qLabel = PrologInterface.executeQuery("rdf_has('"+iri+"',rdfs:label,L),util:strip_literal_type(L,Label)"); 00138 00139 label = qLabel.get("Label").get(0); 00140 if (label.startsWith("'") && label.endsWith("'")) 00141 { 00142 label = label.substring(1,label.length()-1); 00143 } 00144 } catch (Exception e) 00145 { 00146 if (iri.indexOf('#') >=0) 00147 { 00148 label = iri.substring(iri.lastIndexOf('#')+1); 00149 } else { 00150 label = iri; 00151 } 00152 } 00153 00154 Action ret = Action.getAction(iri, label); 00155 00156 //get properties 00157 try 00158 { 00159 HashMap<String, Vector<String>> qProp = PrologInterface.executeQuery("class_properties('"+iri+"', Key, V), util:strip_literal_type(V,Val)"); 00160 00161 if(qProp != null) { 00162 Vector<String> key = qProp.get("Key"); 00163 Vector<String> val = qProp.get("Val"); 00164 00165 //Make sure each property is added only once, it may be that some properties are present two or more times 00166 HashSet<String> alreadyAdded = new HashSet<String>(); 00167 if(key != null && val != null) 00168 for(int i=0;i<key.size() && i<val.size();i++) { 00169 if (alreadyAdded.contains(key.get(i)+val.get(i))) 00170 continue; 00171 alreadyAdded.add(key.get(i)+val.get(i)); 00172 String k = OWLThing.getShortNameOfIRI(key.get(i)); 00173 String v = OWLThing.getShortNameOfIRI(OWLThing.removeSingleQuotes(val.get(i))); 00174 00175 if (k.compareToIgnoreCase("subAction") != 0) 00176 ret.addHasValue(k, v); 00177 } 00178 } 00179 } catch (Exception e) 00180 { 00181 e.printStackTrace(); 00182 } 00183 00184 //get subactions 00185 try { 00186 HashMap<String, Vector<String>> qSub = PrologInterface.executeQuery("plan_subevents('"+iri+"',List)"); 00187 00188 if(qSub!=null) { 00189 00190 Vector<String> list = qSub.get("List"); 00191 00192 //Add each action only once 00193 HashSet<String> alreadyAdded = new HashSet<String>(); 00194 00195 if(list != null) { 00196 for (Iterator<String> i = list.iterator(); i.hasNext();) 00197 { 00198 String o = i.next(); //Is array of strings 00199 00200 for (String sArr[] : PrologInterface.dottedPairsToArrayList(o)) 00201 { 00202 for (String s : sArr) 00203 { 00204 if (alreadyAdded.contains(s)) 00205 continue; 00206 alreadyAdded.add(s); 00207 ret.addSubAction(loadPrologPlanRecursive(PrologInterface.removeSingleQuotes(s))); 00208 } 00209 } 00210 } 00211 } 00212 } 00213 } catch (Exception e) 00214 { 00215 e.printStackTrace(); 00216 } 00217 00218 return ret; 00219 } 00220 00225 public void loadPrologPlan(String identifier) 00226 { 00227 Action a = loadPrologPlanRecursive(identifier); 00228 if (a!= null) 00229 setMainAction(a); 00230 } 00231 00232 00238 public void setMainAction(Action action) 00239 { 00240 currAction = action; 00241 clickHistory.add(new ActionSelectHistoryInfo(currAction)); 00242 updateHistoryPosition(); 00243 this.redraw(); 00244 } 00245 00253 public static void arrowFromTo(PApplet applet, Vector2f from, Vector2f to, float lineWidth, float blockLength) 00254 { 00255 Vector2f norm = new Vector2f(to.x - from.x, to.y-from.y); 00256 float len = norm.length(); 00257 norm.normalize(); 00258 Vector2f rot90 = new Vector2f(norm.x*(float)Math.cos(Math.PI/2f)-norm.y*(float)Math.sin(Math.PI/2f),norm.x*(float)Math.sin(Math.PI/2f)+norm.y*(float)Math.cos(Math.PI/2f)); 00259 Vector2f distLeft = new Vector2f(rot90); 00260 distLeft.scale(-lineWidth); 00261 Vector2f distRight = new Vector2f(rot90); 00262 distRight.scale(lineWidth); 00263 00264 //following points are described as if the arrow is pointing from left to right horizontally 00265 00266 //upper left 00267 Vector2f p1 = new Vector2f(distLeft); 00268 p1.add(from); 00269 //bottom left 00270 Vector2f p7 = new Vector2f(distRight); 00271 p7.add(from); 00272 00273 if (blockLength < 0) 00274 { 00275 blockLength = Math.max(len*0.5f, len - 3*lineWidth); 00276 } 00277 Vector2f transl = new Vector2f(norm); 00278 transl.scale(blockLength); 00279 00280 //middle up on line 00281 Vector2f p2 = new Vector2f(distLeft); 00282 //upper tip 00283 Vector2f p3 = new Vector2f(distLeft); 00284 p3.scale(2); 00285 p2.add(transl); 00286 p2.add(from); 00287 p3.add(transl); 00288 p3.add(from); 00289 00290 //middle bottom on line 00291 Vector2f p6 = new Vector2f(distRight); 00292 //bottom tip 00293 Vector2f p5 = new Vector2f(distRight); 00294 p5.scale(2); 00295 p6.add(transl); 00296 p6.add(from); 00297 p5.add(transl); 00298 p5.add(from); 00299 00300 00301 applet.beginShape(); 00302 00303 applet.vertex(p1.x,p1.y); 00304 applet.vertex(p2.x,p2.y); 00305 applet.vertex(p3.x,p3.y); 00306 applet.vertex(to.x,to.y); //front tip 00307 applet.vertex(p5.x,p5.y); 00308 applet.vertex(p6.x,p6.y); 00309 applet.vertex(p7.x,p7.y); 00310 00311 applet.endShape(CLOSE); 00312 00313 00314 } 00315 00324 public static void arrow(PApplet applet, float x, float y, float width, float height) 00325 { 00326 applet.beginShape(); 00327 00328 float indentY = 2f/7f*height; 00329 float indentX = 4f/9f*width; 00330 00331 applet.vertex(x,y+indentY); 00332 applet.vertex(x+indentX,y+indentY); 00333 applet.vertex(x+indentX,y); 00334 applet.vertex(x+width,y+height/2f); 00335 applet.vertex(x+indentX,y+height); 00336 applet.vertex(x+indentX,y+height-indentY); 00337 applet.vertex(x,y+height-indentY); 00338 00339 applet.endShape(CLOSE); 00340 } 00341 00346 private void updateHistoryPosition() 00347 { 00348 float fullWidth = 0; 00349 for (int i= clickHistory.size()-1; i>=0; i--) 00350 { 00351 fullWidth += clickHistory.get(i).getDimension().x; 00352 } 00353 if (fullWidth+50 > this.getSize().width) 00354 { 00355 //There is not enough space for all history, so begin from right to left 00356 float prevX = this.getSize().width-50; 00357 for (int i= clickHistory.size()-1; i>=0; i--) 00358 { 00359 float newX = prevX - clickHistory.get(i).getDimension().x; 00360 prevX = newX; 00361 clickHistory.get(i).setPosition(newX, 0, i==clickHistory.size()-1); 00362 } 00363 } else { 00364 //Enough space, begin from left 00365 float currX = 0; 00366 for (int i= 0; i<clickHistory.size(); i++) 00367 { 00368 clickHistory.get(i).setPosition(currX, 0, i==clickHistory.size()-1); 00369 currX += clickHistory.get(i).getDimension().x; 00370 } 00371 } 00372 } 00373 00377 private void drawHistory() 00378 { 00379 if(clickHistory.size()>=1) { 00380 for (int i= clickHistory.size()-1; i>=0; i--) 00381 { 00382 clickHistory.get(i).Draw(this); 00383 } 00384 } 00385 } 00386 00390 private void drawCurrAction() 00391 { 00392 if (currAction == null) 00393 return; 00394 00395 currAction.getDrawInfo().drawExtendedBox(this, new Vector2f(50+drawOffset.x,80+drawOffset.y), drawOffset); 00396 } 00397 00398 @Override 00399 public void mouseMoved(MouseEvent e) { 00400 if (getHistoryHover(e.getX(), e.getY())>=0) 00401 { 00402 setCursor(handCursor); 00403 return; 00404 } 00405 00406 if (currAction ==null) 00407 { 00408 setCursor(normalCursor); 00409 return; 00410 } 00411 if (currAction.getDrawInfo().updateHover(e.getX(), e.getY())) 00412 setCursor(handCursor); 00413 else 00414 setCursor(normalCursor); 00415 } 00416 00417 @Override 00418 public void mouseDragged(MouseEvent e) { 00419 if (draggingStart != null && currAction != null) 00420 { 00421 drawOffset.x = Math.min(0, drawOffset.x+ e.getX() - draggingStart.x); 00422 drawOffset.y = Math.min(0,drawOffset.y + e.getY() - draggingStart.y); 00423 00424 float viewOffsetX = Math.min(0, this.getWidth()-(currAction.getDrawInfo().getBoundingBox().width+100)); 00425 float viewOffsetY = Math.min(0, this.getHeight()-(currAction.getDrawInfo().getBoundingBox().height+130)); 00426 00427 drawOffset.x = Math.max(viewOffsetX,drawOffset.x); 00428 drawOffset.y = Math.max(viewOffsetY,drawOffset.y); 00429 00430 draggingStart.x = e.getX(); 00431 draggingStart.y = e.getY(); 00432 } 00433 } 00434 00435 @Override 00436 public void mousePressed(MouseEvent e) { 00437 if (e.getButton() == 3) 00438 { 00439 draggingStart = new Vector2f(e.getX(),e.getY()); 00440 setCursor(moveCursor); 00441 } else { 00442 setCursor(normalCursor); 00443 } 00444 } 00445 00446 @Override 00447 public void mouseReleased(MouseEvent e) { 00448 setCursor(normalCursor); 00449 } 00450 00451 @Override 00452 public void mouseEntered(MouseEvent e) { 00453 } 00454 00455 @Override 00456 public void mouseExited(MouseEvent e) { 00457 } 00458 00459 @Override 00460 public void mouseClicked(MouseEvent e) { 00461 long diff = System.currentTimeMillis()-lastClickTime; 00462 lastClickTime = System.currentTimeMillis(); 00463 if (diff < 10) //double fired event 00464 return; 00465 if (e.getButton() == MouseEvent.BUTTON1 && currAction != null) 00466 { 00467 //Check if clicked on history element 00468 int idx = getHistoryHover(e.getX(), e.getY()); 00469 if (idx >= 0) 00470 { 00471 currAction = clickHistory.get(idx).getAction(); 00472 for (int i=clickHistory.size()-1; i>idx; i--) 00473 { 00474 clickHistory.remove(i); 00475 } 00476 updateHistoryPosition(); 00477 return; 00478 } 00479 00480 //Check if clicked on an expand button 00481 Action a = currAction.getDrawInfo().checkClickExpand(e.getX(), e.getY()); 00482 if (a!= null) 00483 { 00484 a.toggleExpand(); 00485 currAction.getDrawInfo().notifyModified(); 00486 return; 00487 } 00488 00489 //Check if clicked on an action 00490 a = currAction.getDrawInfo().checkClick(e.getX(), e.getY()); 00491 if (a!= null && a != currAction) 00492 { 00493 currAction = a; 00494 if (clickHistory.size()>1 && clickHistory.get(clickHistory.size()-2).getAction()==a) 00495 clickHistory.remove(clickHistory.size()-1); 00496 else 00497 clickHistory.add(new ActionSelectHistoryInfo(currAction)); 00498 updateHistoryPosition(); 00499 } 00500 00501 00502 } 00503 } 00504 00512 private int getHistoryHover(float x, float y) 00513 { 00514 int idx = -1; 00515 for (int i= 0; i<clickHistory.size()-1; i++) 00516 { 00517 if (idx >= 0) 00518 { 00519 clickHistory.get(i).setHover(false); 00520 } else { 00521 if (clickHistory.get(i).checkHover(x, y)) 00522 { 00523 idx = i; 00524 } 00525 } 00526 } 00527 return idx; 00528 } 00529 00536 public boolean highlightAction(Action a, boolean expand) 00537 { 00538 if (currAction == null) 00539 return false; 00540 currAction.getDrawInfo().clearHightlight(); 00541 return currAction.getDrawInfo().highlightSubsequence(a,expand); 00542 } 00543 00550 public boolean highlightAction(String identifier, boolean expand) 00551 { 00552 if (currAction == null) 00553 return false; 00554 currAction.getDrawInfo().clearHightlight(); 00555 return currAction.getDrawInfo().highlightSubsequence(identifier,expand); 00556 } 00557 00561 public void clearHighlight() 00562 { 00563 if (currAction == null) 00564 return; 00565 currAction.getDrawInfo().clearHightlight(); 00566 } 00567 00568 @Override 00569 public void mouseWheelMoved(MouseWheelEvent e) { 00570 int totalScrollAmount = 0; 00571 if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) 00572 { 00573 totalScrollAmount = e.getUnitsToScroll() * e.getScrollAmount(); 00574 } else { 00575 totalScrollAmount = e.getWheelRotation() * 30; 00576 } 00577 draggingStart.y += totalScrollAmount; 00578 } 00579 00580 }