/* * * October 17, 1996, by John R. Smith Copyright 1997 by John R. Smith and Columbia University, all rights reserved. This code is provided as-is and may be used freely by universities for research and system prototyping purposes. This code may not be incorporated into any commercial system without permission from the author. This code is being provided as part of the IEEE MMSP97 CDROM contribution related to the author's manuscript entitled: SaFe: A General Framework for Integrated Spatial and Feature Image Search, by John R. Smith and Shih-Fu Chang Please address any questions or comments to jrsmith@ctr.columbia.edu. * */ /* NOT A LOT OF COMMENTS, SORRY */ /* Spatial is a Java program for spatial querying */ import java.io.*; import java.awt.*; import sun.awt.image.URLImageSource; import java.applet.Applet; import java.lang.Math;import java.net.URL; import java.net.MalformedURLException; public class Spatial extends Applet { int numcolors; int numsymbols = 28; Symbol symbol[]; QueryCanvas querycanvas; SymbolTable symboltable; PositionArea positionarea; ScrollArea scrollarea; GridBagLayout gridbag; GridBagConstraints gbc; Button querybutton, clearbutton, resetbutton, helpbutton; Button gridbutton, setbutton, paintbutton; ColorPanel colorpanel; Choice dbchoice; String ColorFileIn; Color C[]; String DB[], DBNAME[]; int seldb; String clearURL, queryURL, helpURL, peer; public void init() { resize(175, 600); numcolors = getIntParameter("numcolors"); if (numcolors==-1) numcolors = 166; ColorFileIn = getParameter("colorfilein"); if (ColorFileIn==null) ColorFileIn = "rgb.lut"; clearURL = getParameter("clearurl"); if (clearURL==null) clearURL = "right.html"; helpURL = getParameter("helpurl"); if (helpURL==null) helpURL = "help.html"; queryURL = getParameter("queryurl"); if (queryURL==null) queryURL = "http://disney.ctr.columbia.edu/safe-bin"; peer = getParameter("peer"); if (peer==null) peer = "right"; Color foreground = getColorParameter("foreground"); if (foreground==null) this.setForeground(Color.black); Color background = getColorParameter("background"); if (background==null) this.setBackground(Color.white); setFont(new Font("Helvetica", Font.PLAIN, 10)); C = new Color[numcolors+1]; getColors(ColorFileIn); gridbag = new GridBagLayout(); gbc = new GridBagConstraints(); gbc.weightx = 1.0; gbc.weighty = 1.0; setLayout(gridbag); symbol = new Symbol[numsymbols]; for (int i = 0; i < numsymbols; i++) symbol[i] = new Symbol(); gbc.gridwidth = 1; querybutton = new Button("Query"); gridbag.setConstraints(querybutton, gbc); add(querybutton); clearbutton = new Button("Clear"); gridbag.setConstraints(clearbutton, gbc); add(clearbutton); gbc.gridwidth = GridBagConstraints.REMAINDER; resetbutton = new Button("Reset"); gridbag.setConstraints(resetbutton, gbc); add(resetbutton); gbc.gridwidth = GridBagConstraints.REMAINDER; querycanvas = new QueryCanvas(this, symbol); gridbag.setConstraints(querycanvas, gbc); add(querycanvas); setLayout(gridbag); gbc.gridwidth = 1; gridbutton = new Button("Grid"); gridbag.setConstraints(gridbutton, gbc); add(gridbutton); paintbutton = new Button("Paint"); gridbag.setConstraints(paintbutton, gbc); add(paintbutton); gbc.gridwidth = GridBagConstraints.REMAINDER; helpbutton = new Button("Help"); gridbag.setConstraints(helpbutton, gbc); add(helpbutton); symboltable = new SymbolTable(this); gridbag.setConstraints(symboltable, gbc); add(symboltable); positionarea = new PositionArea(this); gridbag.setConstraints(positionarea, gbc); add(positionarea); scrollarea = new ScrollArea(this); gridbag.setConstraints(scrollarea, gbc); add(scrollarea); colorpanel = new ColorPanel(this); gridbag.setConstraints(colorpanel, gbc); add(colorpanel); dbchoice = new Choice(); seldb = getIntParameter("seldb"); if (seldb==-1) seldb = 0; DB = new String[10]; DBNAME = new String[10]; for (int i = 0; i < 10; i++) { DB[i] = getParameter("db" + i); DBNAME[i] = getParameter("dbname" + i); if (DB[i]!=null && DBNAME[i]!=null) dbchoice.addItem(DBNAME[i]); if (i==seldb) dbchoice.select(DBNAME[i]); } gridbag.setConstraints(dbchoice, gbc); add(dbchoice); show(); } Color convertColor(int H, int S, int V) { return Color.getHSBColor((float)((float)H/18.0), (float)((float)S/3.0), (float)((float)V/3.0)); } public void reset() { querycanvas.reset(); update(); } public void update() { positionarea.update(); scrollarea.update(); querycanvas.update(); colorpanel.update(); } protected Color getColorParameter(String name) { String value = this.getParameter(name); int val = 0; try { val = Integer.parseInt(value, 16); } catch (NumberFormatException e) { return null; } return new Color(val); } public void retrieveURL(String arg, String target) { URL u; try { u = new URL(getDocumentBase(), arg); } catch (MalformedURLException e) { u = null; showStatus("Error " + e); } if (u != null) { System.out.println(u); getAppletContext().showDocument(u, target); } } public boolean action(Event evt, Object arg) { if (evt.target==clearbutton) { querycanvas.clear(); } else if (evt.target==querybutton) { //querycanvas.select=-1; //reset(); retrieveURL(queryURL + "/" + dbchoice.getSelectedIndex() + "/safe?" + querycanvas.query(), peer); } else if (evt.target==helpbutton) { retrieveURL(helpURL, peer); } else if (evt.target==resetbutton) { querycanvas.select=-1; reset(); retrieveURL(clearURL, peer); } else if (evt.target==gridbutton) { querycanvas.setGrid(15); update(); } else if (evt.target==setbutton) { querycanvas.select=-1; update(); } else if (evt.target==paintbutton) { querycanvas.setPainting(); update(); } return true; } public int getColors(String filename) { InputStream is = null; int n = 0; try { is = new URL(getDocumentBase(), filename).openStream(); StreamTokenizer st = new StreamTokenizer(is); int c, r, g, b; while (st.nextToken()!=StreamTokenizer.TT_EOF) { c = (int) st.nval; st.nextToken(); r = (int) st.nval; st.nextToken(); g = (int) st.nval; st.nextToken(); b = (int) st.nval; //System.out.println(c + " = " + r + " + " + g + " + " + b); c--; if (c>=0 && c=0) { featlabel.setText(String.valueOf(applet.querycanvas.S[applet.querycanvas.select].featwt)); spatlabel.setText(String.valueOf(applet.querycanvas.S[applet.querycanvas.select].spatwt)); sizelabel.setText(String.valueOf(applet.querycanvas.S[applet.querycanvas.select].sizewt)); reglabel.setText(String.valueOf(applet.querycanvas.S[applet.querycanvas.select].regwt)); featscroll.setValue(applet.querycanvas.S[applet.querycanvas.select].featwt); spatscroll.setValue(applet.querycanvas.S[applet.querycanvas.select].spatwt); sizescroll.setValue(applet.querycanvas.S[applet.querycanvas.select].sizewt); regscroll.setValue(applet.querycanvas.S[applet.querycanvas.select].regwt); return true; } return false; } public boolean handleEvent(Event evt) { if (evt.target == featscroll || evt.target == spatscroll || evt.target == sizescroll || evt.target == regscroll) { featlabel.setText(String.valueOf(featscroll.getValue())); spatlabel.setText(String.valueOf(spatscroll.getValue())); sizelabel.setText(String.valueOf(sizescroll.getValue())); reglabel.setText(String.valueOf(regscroll.getValue())); if (applet.querycanvas.select>=0) { applet.querycanvas.S[applet.querycanvas.select].featwt = featscroll.getValue(); applet.querycanvas.S[applet.querycanvas.select].spatwt = spatscroll.getValue(); applet.querycanvas.S[applet.querycanvas.select].sizewt = sizescroll.getValue(); applet.querycanvas.S[applet.querycanvas.select].regwt = regscroll.getValue(); } } else return super.handleEvent(evt); applet.update(); return true; } } class ColorControl extends Canvas { Spatial applet; Scrollbar colorscroll; int start; int index; ColorControl(Spatial app) { applet = app; resize(110, 40); start=140; index=5; } public void paint(Graphics g) { Rectangle r = bounds(); for (int i = 0; i < 11; i++) { g.setColor(applet.C[i+start]); g.fillRect(i*10, 0, 10, r.height-1); } g.setColor(Color.darkGray); g.drawRect(0, 0, r.width-1, r.height-1); g.drawRect(index*10, 0, 12, r.height-1); g.setColor(Color.white); g.drawRect(index*10+1, 1, 10, r.height-3); g.drawRect(index*10, 0, 10, r.height-1); g.setColor(Color.darkGray); g.drawRect(index*10+2, 2, 8, r.height-5); } /*public boolean mouseDown(Event evt, int x, int y) { if (x>=0 && x<=110) { index=(int)((float)x/10); repaint(); } return true; } public boolean mouseUp(Event evt, int x, int y) { if (x>=0 && x<=110) { index=(int)((float)x/10); repaint(); if (applet.querycanvas.select>=0) applet.querycanvas.S[applet.querycanvas.select].color=start+index; applet.update(); } return true; }*/ public void update() { repaint(); } } class ColorPanel extends Panel { GridBagLayout gridbag; GridBagConstraints gbc; ColorControl colorcontrol; Scrollbar colorscroll; Spatial applet; ColorPanel(Spatial app) { applet = app; resize(150, 75); colorcontrol = new ColorControl(app); gridbag = new GridBagLayout(); gbc = new GridBagConstraints(); setLayout(gridbag); gbc.gridwidth = GridBagConstraints.REMAINDER; gridbag.setConstraints(colorcontrol, gbc); add(colorcontrol); colorscroll = new Scrollbar(Scrollbar.HORIZONTAL); colorscroll.setValues(140, 1, 0, 165); colorscroll.setPageIncrement(1); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.ipady = -4; gbc.ipadx = 60; gridbag.setConstraints(colorscroll, gbc); add(colorscroll); } public boolean update() { colorcontrol.update(); return true; } public boolean mouseDown(Event evt, int x, int y) { if (evt.target == colorcontrol){ if (x>=0 && x<=110) { colorcontrol.index=(int)((float)x/10); colorscroll.setValue(colorcontrol.index+colorcontrol.start); repaint(); return true; } } return false; } public boolean mouseUp(Event evt, int x, int y) { if (evt.target == colorcontrol){ if (x>=0 && x<=110) { colorcontrol.index=(int)((float)x/10); repaint(); if (applet.querycanvas.select>=0) applet.querycanvas.S[applet.querycanvas.select].color =colorcontrol.start+colorcontrol.index; applet.update(); return true; } } return false; } public boolean handleEvent(Event evt) { if (evt.target == colorscroll) { if (applet.querycanvas.select>=0) { applet.querycanvas.S[applet.querycanvas.select].color = colorscroll.getValue(); } int val=colorscroll.getValue()-colorcontrol.index; if (val<0) { colorcontrol.index=colorscroll.getValue(); colorcontrol.start=0; } else if (val>155) { colorcontrol.index=colorscroll.getValue()-155; colorcontrol.start=155; } else { colorcontrol.start=val; } } else return super.handleEvent(evt); applet.update(); return true; } } class SymbolTable extends Panel { GridBagLayout gridbag; GridBagConstraints gbc; Button[][] buttonarray; Spatial applet; String symbols[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "1", "2", "3"}; SymbolTable(Spatial app) { applet = app; buttonarray = new Button[4][7]; resize(120, 150); gridbag = new GridBagLayout(); gbc = new GridBagConstraints(); setLayout(gridbag); gbc.gridwidth = 1; for (int i = 0; i < 4; i++) { gbc.gridwidth = 1; for (int j = 0; j < 7; j++) { if (j == 6) gbc.gridwidth = GridBagConstraints.REMAINDER; buttonarray[i][j] = addButton(symbols[i*7+j], gbc); } } } public boolean action(Event evt, Object arg) { String s = new String("A"); String t = s.valueOf(arg); int i = 0; while (i < applet.numsymbols && !symbols[i].equals(t)) i++; if (i < applet.numsymbols) { if (applet.querycanvas.S[i].on==0) { applet.querycanvas.select = i; applet.querycanvas.S[i].S = t; applet.querycanvas.S[i].on = 1; applet.update(); } else { if (applet.querycanvas.select == i) { applet.querycanvas.S[i].on = 0; applet.querycanvas.select = -1; applet.update(); } else { applet.querycanvas.select = i; applet.querycanvas.S[i].on = 1; applet.update(); } applet.querycanvas.reset(); } } applet.querycanvas.reset(); return true; } protected Button addButton(String name, GridBagConstraints c) { Button button = new Button(name); gridbag.setConstraints(button, c); add(button); return button; } } class QueryCanvas extends Canvas { boolean absolute, relative; Symbol S[]; Spatial applet; int select; int grid; boolean resizing, setting, dragging; int painting; int canwidth, canheight; /* QueryCanvas class constrcutor function */ public QueryCanvas(Spatial app, Symbol[] symbol) { canwidth = 150; canheight = 150; resize(canwidth, canheight); absolute = true; relative = false; resizing = false; dragging = false; painting = 1; setting = false; select = -1; grid = 50; applet = app; S = symbol; setFont(new Font("Helvetica", Font.PLAIN, 14)); setBackground(Color.white); S[0].on=1; S[0].X=30; S[0].Y=40; S[0].W=50; S[0].H=35; S[0].color=158; S[0].S = "A"; S[1].on=1; S[1].X=75; S[1].Y=95; S[1].W=45; S[1].H=40; S[1].color=164; S[1].S = "B"; select=1; } /* paint the motion in the display area */ public String query() { String query = new String(""); int n = 0, numon = 0; for (int i = 0; i < applet.numsymbols; i++) if (S[i].on==1) numon++; query+=new String("NUM" + "=" + numon + "&"); //query+=new String("DB" + "=" + applet.dbchoice.getSelectedIndex() + "&"); query+=new String("DB" + "=" + applet.DB[applet.dbchoice.getSelectedIndex()] + "&"); for (int i = 0; i < applet.numsymbols; i++) if (S[i].on==1) { int x, y, w, h; x = (int)((float)S[i].X/1.5); y = (int)((float)S[i].Y/1.5); w = (int)((float)S[i].W/1.5); h = (int)((float)S[i].H/1.5); int fwt, swt, zwt, rwt; float norm = (float)(1.0/(float)(S[i].featwt+S[i].spatwt+S[i].sizewt)); fwt = (int)(30*(float)S[i].featwt*norm); swt = (int)(30*(float)S[i].spatwt*norm); zwt = (int)(30*(float)S[i].sizewt*norm); if (n>0) query+=new String("&"); query+=new String("S" + n + "=" + S[i].S + "&"); query+=new String("X" + n + "=" + x + "&"); query+=new String("Y" + n + "=" + y + "&"); query+=new String("W" + n + "=" + w + "&"); query+=new String("H" + n + "=" + h + "&"); query+=new String("COL" + n + "=" + (S[i].color+1) + "&"); query+=new String("FWT" + n + "=" + fwt + "&"); query+=new String("SWT" + n + "=" + swt + "&"); query+=new String("ZWT" + n + "=" + zwt + "&"); query+=new String("RWT" + n + "=" + S[i].regwt + "&"); n++; } if (absolute) query+=new String("ABS=1&"); else query+=new String("ABS=0&"); if (relative) query+=new String("REL=1&"); else query+=new String("REL=0&"); int G; if (grid!=0) G=(int)(150.0/(float)grid); else G=10; query+=new String("GRID=" + G); return query; } public void paint(Graphics g) { Rectangle r = bounds(); g.setColor(Color.darkGray); g.drawRect(0, 0, canheight-1, canheight-1); if (grid>0) { g.setColor(Color.gray); for (int i = 0; i < canwidth; i+=grid) g.drawLine(i, 0, i, canheight-1); for (int i = 0; i < canheight; i+=grid) g.drawLine(0, i, canwidth-1, i); g.drawLine(canwidth-1, 0, canwidth-1, canheight-1); g.drawLine(0, canheight-1, canwidth-1, canheight-1); } g.setColor(Color.darkGray); for (int i = 0; i < applet.numsymbols; i++) if (S[i].on==1) { if (painting==0) g.drawString(S[i].S, S[i].X, S[i].Y); else if (painting==1) { int sx = S[i].X-4, sy = S[i].Y-14; if (sx>0 && sy>0) { g.setColor(applet.C[S[i].color]); g.fillRect(sx, sy, S[i].W, S[i].H); g.clearRect(sx+S[i].W-5, sy+S[i].H-5, 4, 4); g.setColor(Color.darkGray); g.drawString(S[i].S, S[i].X, S[i].Y); } } else if (painting==2) { int sx = S[i].X-4, sy = S[i].Y-14; if (sx>0 && sy>0) { g.setColor(applet.C[S[i].color]); g.drawRect(sx, sy, S[i].W, S[i].H); g.fillRect(sx+S[i].W-4, sy+S[i].H-4, 4, 4); g.drawString(S[i].S, S[i].X, S[i].Y); } } } if (select>=0 && S[select].on==1) { int sx = S[select].X-4, sy = S[select].Y-14; if (sx>0 && sy>0) { g.setColor(Color.darkGray); g.drawRect(sx-2, sy-2, S[select].W+4, S[select].H+4); g.drawRect(sx-1, sy-1, S[select].W+2, S[select].H+2); if (painting==1) { g.setColor(applet.C[S[select].color]); g.drawRect(sx, sy, S[select].W, S[select].H); g.fillRect(sx, sy, S[select].W, S[select].H); g.clearRect(sx+S[select].W-5, sy+S[select].H-5, 4, 4); g.setColor(Color.darkGray); g.drawString(S[select].S, S[select].X, S[select].Y); } else if (painting==0 || painting==2) { if (resizing) g.setColor(Color.blue); else g.setColor(applet.C[S[select].color]); g.drawRect(sx, sy, S[select].W, S[select].H); g.fillRect(sx+S[select].W-4, sy+S[select].H-4, 4, 4); g.drawString(S[select].S, S[select].X, S[select].Y); } } } } public int ABS(int val) { if (val>0) return val; else return -1 * val; } public boolean mouseDown(Event evt, int x, int y) { int newselect = -1; int m = 0, minm = 10000, minind = -1; for (int i = 0; i < applet.numsymbols; i++) { m = ABS(x - S[i].X) + ABS(y - S[i].Y); if (m=0) || (newselect == select && select>=0)) { int sx = S[select].X-4, sy = S[select].Y-14; if (x>=sx+S[select].W-4 && y>=S[select].H-4+sy && x<=sx+S[select].W && y<=sy+S[select].H) { resizing = true; } else if (select>=0) { if (S[select].X==0 && S[select].Y==0) { if (x>0 && x8 && y=0) { select = newselect; /* if (x>0 && x8 && y=0) { if (resizing) { int sx = S[select].X-4, sy = S[select].Y-14; if (x>0 && xsx+20) S[select].W = x - sx; if (y>8 && ysy+20) S[select].H = y - sy; repaint(); } else if (dragging) { if (x>0 && x8 && y2) painting = 0; repaint(); } public void reset() { repaint(); } public void clear() { for (int i = 0; i < applet.numsymbols; i++) S[i].on = 0; select = -1; repaint(); } public boolean update() { repaint(); return true; } }