📄 bpndraw.java
字号:
//////////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 1996 L. Patocchi & W.Gander//// This program is free software; you can redistribute it and/or modify it// under the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 of the License, or (at your option)// any later version.//// This program is distributed in the hope that it will be useful, but WITHOUT// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for// more details.//// You should have received a copy of the GNU General Public License along with// this program; if not, write to the Free Software Foundation, Inc., 675 Mass// Ave, Cambridge, MA 02139, USA.//// Contacts:// // Project Supervisor// W.Hett hew@info.isbiel.ch// // Authors// W.Gander gandw@info.isbiel.ch// L.Patocchi patol@info.isbiel.ch//// Documentation can be found at://// http://www.isbiel.ch/Projects/janet/index.html////////////////////////////////////////////////////////////////////////////////////////// File : BPNdraw.java//package jaNet.backprop.gui;import java.awt.*;import jaNet.backprop.*;public class BPNdraw extends Canvas{ private BPN currentBPN; private BPNdescriptor currentBPND; private int saturation = 90; // % private int maxInterU = 50; // pixels private int maxLinks = 20; // pixels private BPNgui dearParent; private static int oldLayer = -1; private static int oldUnit = -1; private layerMenu popMenu; private layerMenuItem menuItems[] = new layerMenuItem[5]; private int selectedLayer = -1; private int selectedUnit = -1; private String layerName = " "; private String usage = " "; private boolean haveFocus = false; private Scale scale; private static final String keyHelp = "Shortcuts: [RETURN] = Edit; [UP] = Add before; [DOWN] = Add after; [DEL] = Delete"; public BPNdraw(Frame parent){ super(); dearParent = (BPNgui) parent; } public void setBPN(BPN bpn){ currentBPN = bpn; currentBPND = bpn.getBPNdescriptor(); } public void setScale(Scale s){ scale = s; } public void updateDraw(){ updateDraw(this.getGraphics(),currentBPN); } public void updateDraw(BPN bpn){ currentBPN = bpn; currentBPND = bpn.getBPNdescriptor(); updateDraw(this.getGraphics(), currentBPN); } public void updateDraw(Graphics g, BPN bpn){ Dimension d = this.size(); int w = d.width; int h = d.height; BPNdescriptor bpnD = bpn.getBPNdescriptor(); int nLayers = bpnD.layerDef.length; Rectangle r0 = null; Rectangle r1 = null; Rectangle r2 = null; Color cH = Color.white; Color cD = Color.gray; Color cB = Color.lightGray; for(int l=0; l<nLayers; l++){ r0 = getRectangleOfLayer(bpnD,l); g.setColor(cH); g.fillRoundRect(r0.x -1, r0.y -1, r0.width,r0.height ,2,2); g.setColor(cD); g.fillRoundRect(r0.x +1, r0.y +1, r0.width,r0.height ,2,2); g.setColor(new Color(123,161,203)); g.fillRoundRect(r0.x , r0.y , r0.width,r0.height ,2,2); } for(int l=0; l<nLayers-1; l++){ // select only some neurons to perform links to reduce refreshing time // I liked so much this method that i looked it for 30 minutes !!! (LorenZ:) int ustep = 1; int lstep = 1; while(bpnD.layerDef[l]/ustep > maxLinks || ((bpnD.layerDef[l]-1)%ustep)!=0)ustep++; while(bpnD.layerDef[l+1]/lstep > maxLinks || ((bpnD.layerDef[l+1]-1)%lstep)!=0)lstep++; for(int lu=0; lu<bpnD.layerDef[l]; lu++){ r1 = getRectangleByBPNDef(bpnD,l,lu); if(lu%ustep == 0){ g.setColor(Color.black); for(int ll=0; ll<bpnD.layerDef[l+1]; ll++) if(ll%lstep == 0){ r2 = getRectangleByBPNDef(bpnD,l+1,ll); g.drawLine(r1.x,r1.y, r2.x,r2.y); } } g.setColor(cH); g.fillOval(r1.x-r1.width -1, r1.y-r1.height -1, r1.width*2,r1.height*2); g.setColor(cD); g.fillOval(r1.x-r1.width +1, r1.y-r1.height +1, r1.width*2,r1.height*2); } } // draw last layer for(int ll=0; ll<bpnD.layerDef[nLayers-1]; ll++){ r1 = getRectangleByBPNDef(bpnD,nLayers-1,ll); g.setColor(cH); g.fillOval(r1.x-r1.width -1, r1.y-r1.height -1, r1.width*2,r1.height*2); g.setColor(cD); g.fillOval(r1.x-r1.width +1, r1.y-r1.height +1, r1.width*2,r1.height*2); } updateValues(g, bpnD); } public void updateValues(BPNdescriptor bpnD){ updateValues(this.getGraphics(), bpnD); } public void updateValues(Graphics g, BPNdescriptor bpnD){ currentBPND = bpnD; for(int i=0; i<bpnD.layerDef.length; i++){ for(int j=0; j<bpnD.layerDef[i]; j++){ Rectangle r1 = getRectangleByBPNDef(bpnD,i,j); g.setColor(scale.getColor(bpnD.layerVectors[i][j])); g.fillOval(r1.x-r1.width , r1.y-r1.height , r1.width*2,r1.height*2); } } // update value also un scale field if(selectedLayer != -1 && selectedUnit != -1){ try{ scale.showValue(bpnD.layerVectors[selectedLayer][selectedUnit]); }catch(ArrayIndexOutOfBoundsException ex){ System.err.println(ex+" "+selectedLayer+"(max is "+bpnD.layerVectors.length+") "+selectedUnit+" (max is "+bpnD.layerVectors[selectedLayer].length+")"); } } } public void paint(Graphics g){ if(currentBPN != null){ updateDraw(g, currentBPN); } if(selectedLayer != -1) selectLayer(g,selectedLayer); } public Rectangle getRectangleByBPNDef(BPNdescriptor bpnD, int layer, int unit){ Dimension d = this.size(); int w = d.width; int h = d.height; int nLayers = bpnD.layerDef.length; int interL = h / (nLayers+1); int unitD = 15; int interU; int myH = interL *(layer+1); int nUnits = bpnD.layerDef[layer]; int myW; if(nUnits > 1){ //calculate unit size while(unitD>1 && unitD*nUnits > w*saturation/100) unitD --; // compute optimum interU interU = (w*saturation/100 - unitD*nUnits)/(nUnits - 1); // truncate to high distances if(interU > maxInterU) interU = maxInterU; // compute layer X origin int myX = (w-(nUnits*unitD + interU*(nUnits-1)))/2; // myW = myX+unit*(unitD+interU) + unitD/2; }else{ // very simple myW = w/2-1; } return new Rectangle(myW, myH, unitD/2, unitD/2); } public Rectangle getRectangleOfLayer(BPNdescriptor bpnD, int l){ Rectangle r1 = getRectangleByBPNDef(bpnD,l,0); Rectangle r2 = getRectangleByBPNDef(bpnD,l,bpnD.layerDef[l]-1); int len = (r2.x-r2.width+2)-(r1.x-r1.width-2)+r1.width*4; return new Rectangle(r1.x-r1.width-2 -r1.width, r1.y-r1.height-2, len,r1.width*2+4); } public int getLayerByXY(int x,int y){ Dimension d = this.size(); int h = d.height; int w = d.width; int nLayers = currentBPND.layerDef.length; int interL = h / (nLayers+1); int layerDomain = (y + interL/2) /interL -1; if(layerDomain < 0) layerDomain = 0; if(layerDomain >= nLayers)layerDomain = nLayers - 1; int unitD = 15; int interU; int myH = interL *(layerDomain+1); int nUnits = currentBPND.layerDef[layerDomain]; int layerLen; int layer = -1, unit = -1; int myX; if(nUnits > 1){ //calculate unit size while(unitD>1 && unitD*nUnits > w*saturation/100) unitD --; // compute optimum interU interU = (w*saturation/100 - unitD*nUnits)/(nUnits - 1); // truncate to high distances if(interU > maxInterU) interU = maxInterU; // compute layer X origin layerLen = (nUnits*unitD + interU*(nUnits-1)); myX = (w-layerLen)/2; unit = (x-myX)/ (unitD+interU); if(unit<0)unit=0; if(unit>=nUnits)unit = nUnits-1; }else{ // very simple layerLen = unitD; unit = 0; } if(x>(w-layerLen)/2-4 && x<(w+layerLen)/2+4 && y<myH+unitD/2+4 && y>myH-unitD/2-4) layer = layerDomain; //dearParent.putOnFooter("x="+x+" y="+y+" unit="+unit+" layer="+layer); return layer; } public int getUnitByXY(int x,int y){ Dimension d = this.size(); int h = d.height; int w = d.width; int nLayers = currentBPND.layerDef.length; int interL = h / (nLayers+1); int layerDomain = (y + interL/2) /interL -1; if(layerDomain < 0) layerDomain = 0; if(layerDomain >= nLayers)layerDomain = nLayers - 1; int unitD = 15; int interU; int myH = interL *(layerDomain+1); int myW; int nUnits = currentBPND.layerDef[layerDomain]; int layerLen; int layer = -1, unit = -1; int unitDomain; if(nUnits > 1){ //calculate unit size while(unitD>1 && unitD*nUnits > w*saturation/100) unitD --; // compute optimum interU interU = (w*saturation/100 - unitD*nUnits)/(nUnits - 1); // truncate to high distances if(interU > maxInterU) interU = maxInterU; // compute layer X origin layerLen = (nUnits*unitD + interU*(nUnits-1)); int myX = (w-layerLen)/2; unitDomain = (x-myX+(unitD+interU)/2)/ (unitD+interU); if(unitDomain<0)unitDomain=0; if(unitDomain>=nUnits)unitDomain = nUnits-1; myW = myX+unitDomain*(unitD+interU) + unitD/2; }else{ // very simple layerLen = unitD; unitDomain = 0; myW = w/2; } if(x>myW-unitD/2-1 && x<myW+unitD+1 && y>myH-unitD/2-1 && y<myH+unitD/2+1) unit = unitDomain; return unit; } public void selectLayer(int l){ selectLayer(this.getGraphics(), l); } public void selectLayer(Graphics g,int l){ g.setColor(Color.black); g.setXORMode(Color.white); Rectangle r = getRectangleOfLayer(currentBPND, l); //g.drawRect(r.x-1,r.y-1,r.width+2,r.height+2); g.drawRect(r.x-3,r.y-3,r.width+5,r.height+5); g.setPaintMode(); } public boolean handleEvent(Event event) { if (event.id == Event.MOUSE_MOVE) { int layer = getLayerByXY(event.x, event.y); int unit = getUnitByXY(event.x, event.y); if(layer!=-1 && (unit!=-1 && oldUnit==-1 || unit!=oldUnit&&unit!=-1&&oldUnit!=-1 )){ selectedUnit = unit; scale.showValue(currentBPND.layerVectors[layer][unit]); } if(unit == -1 && oldUnit != -1){ selectedUnit = -1; scale.hideValue(); } // jump from a layer to another if(layer != -1 && oldLayer != -1 && layer != oldLayer){ selectLayer(layer); selectLayer(oldLayer); selectedLayer = layer; } // enter in a layer if(layer != -1 && oldLayer == -1){ selectLayer(layer); selectedLayer = layer; } // exit from a layer if(layer == -1 && oldLayer != -1){ selectLayer(oldLayer); selectedLayer = -1; } // put some info on footer if(layer != -1){ if(layer==0){ layerName = "Input Layer"; dearParent.putOnFooter(layerName+" has "+currentBPND.layerDef[layer]+" units. "+usage); }else if(layer == currentBPND.layerDef.length-1){ layerName = "Output Layer"; dearParent.putOnFooter(layerName+" has "+currentBPND.layerDef[layer]+" units. "+usage); }else{ layerName = "Hidden Layer "+(layer-1); dearParent.putOnFooter(layerName+" has "+currentBPND.layerDef[layer]+" units. "+usage); } }else{ dearParent.putOnFooter(""); layerName = " "; } oldLayer = layer; oldUnit = unit; }else if (event.id == Event.MOUSE_DOWN){ requestFocus(); if(selectedLayer != -1){ if(popMenu == null){ // create popMenu popMenu = new layerMenu(dearParent, (Component)this, layerName); popMenu.add(menuItems[3] = new layerMenuItem("Edit")); popMenu.addSeparator(); popMenu.add(menuItems[0] = new layerMenuItem("Add before")); popMenu.add(menuItems[1] = new layerMenuItem("Add after")); popMenu.add(menuItems[2] = new layerMenuItem("Delete")); popMenu.addSeparator(); //popMenu.add(menuItems[4] = new layerMenuItem("Undo")); } popMenu.show(event.x, event.y, layerName); } }else if (event.id == Event.MOUSE_UP){ if(popMenu != null){ int sel = popMenu.getSelection(); if( sel != -1){ if(popMenu.getItem(sel) == menuItems[0]){ //dearParent.putOnMonitor("Add before\n"); dearParent.addLayerBefore(selectedLayer); }else if(popMenu.getItem(sel) == menuItems[1]){ //dearParent.putOnMonitor("Add after\n"); dearParent.addLayerAfter(selectedLayer); }else if(popMenu.getItem(sel) == menuItems[2]){ //dearParent.putOnMonitor("Delete\n"); dearParent.deleteLayer(selectedLayer); }else if(popMenu.getItem(sel) == menuItems[3]){ //dearParent.putOnMonitor("Edit\n"); dearParent.editLayer(selectedLayer); }else if(popMenu.getItem(sel) == menuItems[4]){ //dearParent.putOnMonitor("Edit\n"); dearParent.undoAction(selectedLayer); }//else dearParent.putOnMonitor("No objects for "+sel+" or "+popMenu.getItem(sel)+"\n"); } popMenu.hide(); popMenu.dispose(); popMenu = null; } }else if(event.id == Event.KEY_ACTION_RELEASE || event.id == Event.KEY_RELEASE){ if(selectedLayer != -1){ if(event.key == 127){ // DEL dearParent.deleteLayer(selectedLayer); }else if(event.key == Event.UP){ dearParent.addLayerBefore(selectedLayer); }else if(event.key == Event.DOWN){ dearParent.addLayerAfter(selectedLayer); }else if(event.key == 10){ // Return dearParent.editLayer(selectedLayer); } } }else if(event.id == Event.MOUSE_DRAG){ if(popMenu != null) return popMenu.handlePrivateEvent(event); }else{ dearParent.putOnFooter(usage); } return super.handleEvent(event); } public boolean gotFocus(Event event, Object obj){ haveFocus = true; usage = keyHelp; return true; } public boolean lostFocus(Event event, Object obj){ haveFocus = false; usage = ""; return true; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -