/* Copyright (c) 2010, Chris Want Please see BSD style licence at the end of this file */ import javax.swing.*; import controlP5.*; final int MAX_VARIO_STRUCT = 3; final int MAX_ISOSURFACES = 20; class ControlModel { DataModel data; ViewModel view; ControlP5 controlP5; JFileChooser fileDialog; NumberFormat textFloat; int xylayer = 0, xzlayer = 0, yzlayer = 0; int xRes, yRes, zRes; int numSurf; float xMin, yMin, zMin; float xMax, yMax, zMax; float[] probe=null; float[] clicked=null; KrigData clickedData=null; Kriging krig = null;; //Variogram vario = null; ControlModel(PApplet p, DataModel data) { controlP5 = new ControlP5(p); controlP5.setAutoInitialization(false); this.data = data; textFloat = new DecimalFormat("0.0###"); getKrigingVars(); try { fileDialog = new JFileChooser(); } catch (Exception e) { e.printStackTrace(); } } void addViewModel(ViewModel view) { this.view = view; } void setKrigingVars() { data.krig.out.xRes = xRes; data.krig.out.yRes = yRes; data.krig.out.zRes = zRes; data.krig.out.xMin = xMin; data.krig.out.yMin = yMin; data.krig.out.zMin = zMin; data.krig.out.xMax = xMax; data.krig.out.yMax = yMax; data.krig.out.zMax = zMax; data.numSurf = numSurf; if (krig != null) { data.krig = krig.duplicate(); } if (krig.vario != null) { data.krig.vario = krig.vario.duplicate(); } if (krig.search != null) { data.krig.search = krig.search.duplicate(); } } void getKrigingVars() { xRes = data.krig.out.xRes; yRes = data.krig.out.yRes; zRes = data.krig.out.zRes; xMin = data.krig.out.xMin; yMin = data.krig.out.yMin; zMin = data.krig.out.zMin; xMax = data.krig.out.xMax; yMax = data.krig.out.yMax; zMax = data.krig.out.zMax; if (zRes == 1) { xylayer = 0; clicked = null; } numSurf = data.numSurf; if (data.krig!=null) { krig = data.krig.duplicate(); } if (data.krig.vario!=null) { krig.vario = data.krig.vario.duplicate(); } if (data.krig.search!=null) { krig.search = data.krig.search.duplicate(); } } void updateXYLayer(int value) { if (xylayer != value) { xylayer = value; view.slicePanel.sliceXY.setImage(getXYSlice()); view.slicePanel.flagRedraw(); view.slicePanel.sliceXY.flagRedraw(); view.iso3d.flagRedraw(); } } void updateXZLayer(int value) { if (xzlayer != value) { xzlayer = value; view.slicePanel.sliceXZ.setImage(getXZSlice()); view.slicePanel.flagRedraw(); view.slicePanel.sliceXZ.flagRedraw(); view.iso3d.flagRedraw(); } } void updateYZLayer(int value) { if (yzlayer != value) { yzlayer = value; view.slicePanel.sliceYZ.setImage(getYZSlice()); view.slicePanel.flagRedraw(); view.slicePanel.sliceYZ.flagRedraw(); view.iso3d.flagRedraw(); } } void updateNumIso(int value) { if (numSurf != value) { numSurf = data.numSurf = value; data.updateIsoSurfaces(); view.iso3d.flagRedraw(); view.numIsoPanel.flagRedraw(); } } PImage getXYSlice() { return data.getXYSlice(data.krig.out, xylayer); } PImage getXZSlice() { return data.getXZSlice(data.krig.out, xzlayer); } PImage getYZSlice() { return data.getYZSlice(data.krig.out, yzlayer); } /////////////// Probe /////////////////// boolean updateProbe() { if (view.slicePanel.mouseOver()) { if (updateProbeXY(view.slicePanel.sliceXY)) return true; if (updateProbeXZ(view.slicePanel.sliceXZ)) return true; if (updateProbeYZ(view.slicePanel.sliceYZ)) return true; } return false; } boolean updateProbeXY(PlacementElement slice) { return updateProbeXY(slice, data.krig.out, xylayer); } boolean updateProbeXY(PlacementElement slice, ScalarField sc, float layer) { float[] unit; probe = null; if (slice.mouseOver()) { probe = new float[3]; unit = slice.mouseNormalized(); probe[0] = sc.xMin + unit[0] * (sc.xMax - sc.xMin); probe[1] = sc.yMin + (1.0 - unit[1]) * (sc.yMax - sc.yMin); if (sc.zRes > 1) { probe[2] = sc.zMin + (sc.zMax - sc.zMin) * layer / (sc.zRes - 1); } else { probe[2] = sc.zMin; } return true; } return false; } boolean updateProbeXZ(PlacementElement slice) { return updateProbeXZ(slice, data.krig.out, xzlayer); } boolean updateProbeXZ(PlacementElement slice, ScalarField sc, float layer) { float[] unit; probe = null; if (slice == null) return false; if (slice.mouseOver()) { probe = new float[3]; unit = slice.mouseNormalized(); probe[0] = sc.xMin + unit[0] * (sc.xMax - sc.xMin); probe[1] = sc.yMin + (sc.yMax - sc.yMin) * layer / (sc.yRes - 1); probe[2] = sc.zMin + (1.0 - unit[1]) * (sc.zMax - sc.zMin); return true; } return false; } boolean updateProbeYZ(PlacementElement slice) { return updateProbeYZ(slice, data.krig.out, yzlayer); } boolean updateProbeYZ(PlacementElement slice, ScalarField sc, float layer) { float[] unit; probe = null; if (slice == null) return false; if (slice.mouseOver()) { probe = new float[3]; unit = slice.mouseNormalized(); probe[0] = sc.xMin + (sc.xMax - sc.xMin) * layer / (sc.xRes - 1); probe[1] = sc.yMin + (1.0 - unit[1]) * (sc.yMax - sc.yMin); probe[2] = sc.zMin + unit[0] * (sc.zMax - sc.zMin); return true; } return false; } boolean probeOverXY() { if ( (probe != null) && view.slicePanel.sliceXY.mouseOver() ) { return true; } return false; } boolean probeOverXZ() { if (view.slicePanel.sliceXZ == null) return false; if ( (probe != null) && view.slicePanel.sliceXZ.mouseOver() ) { return true; } return false; } boolean probeOverYZ() { if (view.slicePanel.sliceYZ == null) return false; if ( (probe != null) && view.slicePanel.sliceYZ.mouseOver() ) { return true; } return false; } int[] nearestCell(float[] point) { return data.getNearestCell(point); } boolean invalidValue(int[] cell) { return data.krig.out.isInvalid(cell[0], cell[1], cell[2]); } float estValue(int[] cell) { return data.krig.out.getData(EST, cell[0], cell[1], cell[2]); } float varValue(int[] cell) { return data.krig.out.getData(ESTVAR, cell[0], cell[1], cell[2]); } File chooseReadFile() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { e.printStackTrace(); } JFileChooser fileDialog = new JFileChooser(); int returnVal = fileDialog.showOpenDialog(null); if(returnVal == JFileChooser.APPROVE_OPTION) { return fileDialog.getSelectedFile(); } return null; } File chooseWriteFile() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); int returnVal = fileDialog.showSaveDialog(null); if(returnVal == JFileChooser.APPROVE_OPTION) { return fileDialog.getSelectedFile(); } } catch (Exception e) { e.printStackTrace(); } return null; } void calcKriging() { view.updateControllers(); setKrigingVars(); data.updateKriging(); getKrigingVars(); updateLambdas(); view.updateState(); } void controlP5Event(ControlEvent theEvent) { Variogram vario = krig.vario; Search search = krig.search; if (theEvent == null) return; if (theEvent.isController()) { if (!theEvent.controller().isVisible()) return; if (theEvent.controller().name().equals("calcKriging")) { calcKriging(); return; } if (theEvent.controller().name().equals("xMin")) { xMin = controllerToFloat(theEvent.controller(), xMin); return; } if (theEvent.controller().name().equals("yMin")) { yMin = controllerToFloat(theEvent.controller(), yMin); return; } if (theEvent.controller().name().equals("zMin")) { zMin = controllerToFloat(theEvent.controller(), zMin); return; } if (theEvent.controller().name().equals("xMax")) { xMax = controllerToFloat(theEvent.controller(), xMax); return; } if (theEvent.controller().name().equals("yMax")) { yMax = controllerToFloat(theEvent.controller(), yMax); return; } if (theEvent.controller().name().equals("zMax")) { zMax = controllerToFloat(theEvent.controller(), zMax); return; } if (theEvent.controller().name().equals("nugget")) { krig.vario.nugget = controllerToFloat(theEvent.controller(), krig.vario.nugget); return; } if (theEvent.controller().name().equals("meanSet")) { krig.setMean(controllerToFloat(theEvent.controller(), krig.getMean(krig.kd))); return; } if (theEvent.controller().name().equals("dataMean")) { krig.setMean(krig.kd.computeMean()); view.updateKrigingControls(); return; } if (krig.search instanceof EllipsoidSearch) { EllipsoidSearch es = (EllipsoidSearch) krig.search; if (theEvent.controller().name().equals("minPoints")) { es.minPoints = (int) theEvent.controller().value(); view.updateSearchControls(); return; } if (theEvent.controller().name().equals("maxPoints")) { es.maxPoints = (int) theEvent.controller().value(); view.updateSearchControls(); return; } for (int j=0; j<3; ++j) { if (theEvent.controller().name().equals("es_anis" + j)) { es.rot.anis[j] = controllerToFloat(theEvent.controller(), es.rot.anis[j]); } if (theEvent.controller().name().equals("es_angles" + j)) { es.rot.angles[j] = controllerToFloat(theEvent.controller(), es.rot.angles[j]); } } } for (int i=0; i < vario.structures.length; ++i) { VariogramStructure structure = vario.structures[i]; if (theEvent.controller().name().equals("deleteVarioStruct"+i)) { vario.deleteStructure(i); view.updateVariogramControls(); return; } for (int j=0; j<3; ++j) { if (theEvent.controller().name().equals("anis" + j + i)) { structure.rot.anis[j] = controllerToFloat(theEvent.controller(), structure.rot.anis[j]); } if (theEvent.controller().name().equals("angles" + j + i)) { structure.rot.angles[j] = controllerToFloat(theEvent.controller(), structure.rot.angles[j]); } } if (theEvent.controller().name().equals("cc" + i)) { structure.cc = controllerToFloat(theEvent.controller(), structure.cc); } } if (theEvent.controller().name().equals("addVarioStruct")) { vario.addStructure(); view.updateVariogramControls(); return; } /* if (theEvent.controller().name().equals("searchOn")) { if (((Toggle) theEvent.controller()).getState()) { if (control.krig.search == null) { control.krig.search = new RadiusNumSearch(5.0, 10); } control.krig.search.enable(); } else { if (control.krig.search == null) { control.krig.search = new RadiusNumSearch(5.0, 10); } control.krig.search.disable(); } view.updateSearchControls(); return; } if (theEvent.controller().name().equals("searchRadiusOn")) { if (((Toggle) theEvent.controller()).getState()) { ((RadiusNumSearch) control.krig.search).radiusSearch.enable(); } else { ((RadiusNumSearch) control.krig.search).radiusSearch.disable(); } view.updateSearchControls(); return; } if (theEvent.controller().name().equals("searchRadius")) { ((RadiusNumSearch) control.krig.search).radiusSearch.setRadius(theEvent.value()); } */ } else if(theEvent.isGroup()) { if (theEvent.group().isVisible() && ((int) theEvent.group().value() >= 0)) { if (theEvent.group().name().equals("tabGridVarioStat")) { view.setGridVarioStatTab((int) theEvent.group().value()); return; } for (int i=0; i < vario.structures.length; ++i) { if (theEvent.group().name().equals("varioStructType"+i)) { int code = radioToCode((RadioButton) theEvent.group()); if (code < 0) return; if (code > 4) return; if (code != vario.structures[i].getCode()) { vario.structures[i] = vario.structures[i].switchType(code); } return; } } if (theEvent.group().name().equals("krigType")) { int code = radioToCode((RadioButton) theEvent.group()); if (code < 0) return; if (code > 1) return; if (code != krig.getCode()) { krig = krig.switchType(code); view.updateKrigingControls(); } return; } if (theEvent.group().name().equals("searchType")) { if (control.krig.search != null) { int code = radioToCode((RadioButton) theEvent.group()); if (code == 0) { control.krig.search.disable(); } else { control.krig.search.enable(); } view.updateSearchControls(); } } } } } int radioToCode(RadioButton radiob) { for (int i=0; i < radiob.arrayValue().length; ++i) { if (radiob.arrayValue()[i] > 0.0) { return i; } } return -1; } /////// Load & Save ///////////// void readData(int value) { File myFile = control.chooseReadFile(); if (myFile != null) { try { krig.readData(myFile); calcKriging(); println("Read file: " + myFile); } catch (Exception e) { krig = null; e.printStackTrace(); } } } void writeData(int value) { File myFile = control.chooseWriteFile(); if (myFile != null) { try { krig.writeData(myFile); } catch (Exception e) { krig = null; e.printStackTrace(); } } } void updateLambdas() { if (clicked != null) { if ((data.krig.search != null) && data.krig.search.isEnabled()) { clickedData = data.krig.search.search(data.krig.kd, clicked[0], clicked[1], clicked[2]); } else { clickedData = data.krig.kd; } data.computeLambda(clickedData, clicked[0], clicked[1], clicked[2]); } } } void controlEvent(ControlEvent theEvent) { control.controlP5Event(theEvent); } float controllerToFloat(Controller controller, float old) { Float f; Textfield tf = (Textfield) controller; String newStr, oldStr = control.textFloat.format(old); try { f = new Float(tf.stringValue()); } catch (Exception e) { e.printStackTrace(); tf.setText(oldStr); return old; } tf = (Textfield) controller; newStr = control.textFloat.format(f.floatValue()); tf.setText(newStr); if (oldStr.equals(newStr)) return old; return f.floatValue(); } void xLayer(int value) { control.updateYZLayer(value); } void yLayer(int value) { control.updateXZLayer(value); } void zLayer(int value) { control.updateXYLayer(value); } void numIso(int value) { control.updateNumIso(value); } void xRes(int value) { control.xRes = value; } void yRes(int value) { control.yRes = value; } void zRes(int value) { control.zRes = value; } void minPoints(int value) { } void maxPoints(int value) { } void readData(int value) { noLoop(); control.readData(value); loop(); } void writeData(int value) { noLoop(); control.writeData(value); loop(); } /* Copyright (c) 2010, Chris Want, Research Support Group, AICT, University of Alberta. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Contributors: Chris Want (University of Alberta) */