//This file is part of SECONDO. //Copyright (C) 2004, University in Hagen, Department of Computer Science, //Database Systems for New Applications. //SECONDO 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. //SECONDO 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 SECONDO; if not, write to the Free Software //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA package viewer; import com.sun.j3d.utils.image.TextureLoader; import com.sun.j3d.utils.picking.behaviors.*; import com.sun.j3d.utils.picking.PickCanvas; import com.sun.j3d.utils.picking.PickResult; import com.sun.j3d.utils.universe.SimpleUniverse; import gui.*; import gui.idmanager.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.awt.image.BufferedImage; import java.sql.Timestamp; import java.util.*; import javax.media.j3d.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.Vector3d; import project.OSMMercator; import sj.lang.ListExpr; import viewer.spacetimecube.*; /** * Class representing the Secondo SpaceTimeCube viewer. * It enables to view the data object moving point * in a 3-dimensional way. * @author Franz Fahrmeier * */ public class SpaceTimeCubeViewer extends SecondoViewer implements ActionListener, ChangeListener, MouseListener, ItemListener, ComponentListener { private MenuVector MenuExtension; private JMenuItem miShowSettings; private JMenu STCMenu; private Vector objectList; // stores all queried SecondoObjects private SpaceTimeCube STC; private Canvas3D canvas; private PickCanvas pickCanvas; private SimpleUniverse universe; private Transform3D transform, transformMap; private TransformGroup tg, tgMap; // tgMap only includes the map and is a part of tg private Vector mPoints; // stores all currently maintained moving points as java3d Shape3D objects private BranchGroup lastBg; private BufferedImage map; private Shape3D mapShape, topShape; // topShape is the top shape of the cube private Shape3D lineXaxis, lineYaxis, lineZaxis, lineBottomBack, lineBottomRight, lineLeftBack, lineRightFront, lineRightBack; // lines to construct the cube private Point3d bottomFrontLeft, bottomFrontRight, bottomBackLeft, bottomBackRight, topFrontLeft, topFrontRight, topBackLeft, topBackRight; // points helping to construct the cube private JSlider zMinSlide, zMaxSlide, mapSlide; // sliders for timeframe filter and map movement private JSpinner rotXspinner, rotZspinner; // spinners for rotation about X and Z axis private JLabel zMinLabel, zMaxLabel; private JLabel labelDateMap, labelTimeMap; // labels for timestamp connected to map slider private JButton butSubmit, butRetry, butReset, butBack, butMapTimeStart, butMapTimeEnd; private JFrame frameLoad, frameMPoint; // frameLoad = dialog when loading of the map takes time // frameMPoint = frame showing additional information when right-clicking a mpoint private View2DSTC panelMapOverview; // panel on the top right showing the 2D map private OSMMercator osmm; private int rotXlastVal, rotZlastVal; // last rotation value needs to be stored so that only deltas can be rotated private double minXlimitLast, maxXlimitLast, minYlimitLast, maxYlimitLast; // last filter values private long minZlimitLast, maxZlimitLast; private SettingsDialog frameSettings; // settings dialog to be opened from Secondo menu private Vector lastLimits; // stores all filter values to make "back"-button work multiple times private JComboBox cbView; private Vector views; // stores rotation values private double[] referenceView = {0, 0, 0}; private double factorCanvas = 1; // ratio between canvas width and height //< Settings (from settings dialog) private Hashtable colorSO; // color information for each SecondoObject in the STC private boolean drawVertLines = false; // switch for drawing vertical lines private Color3f colorCanvas = new Color3f(0,0,0); // background color private float lineWidth = 1.0f; // weight of MPoint lines private float transpMPoints = 0.0f; // transparency value of the MPoints // > /** * Constructor doing several attribute initializations * for common attributes and setting initial layout. */ public SpaceTimeCubeViewer(){ this.addComponentListener(this); MenuExtension = new MenuVector(); STCMenu = new JMenu("STC-Viewer"); MenuExtension.addMenu(STCMenu); miShowSettings = STCMenu.add("Settings"); miShowSettings.addActionListener(this); objectList = new Vector(); mPoints = new Vector(); STC = new SpaceTimeCube(this); osmm = new OSMMercator(); lastLimits = new Vector(); colorSO = new Hashtable(); // combobox holding all view possibilities cbView = new JComboBox(); cbView.addItemListener(this); cbView.addItem("---------"); cbView.addItem("Overview"); cbView.addItem("Front"); cbView.addItem("Top"); // buttons in this viewer butSubmit = new JButton("OK"); butBack = new JButton("Back"); butReset = new JButton("Reset"); butRetry = new JButton("Retry"); butMapTimeStart = new JButton("set map time"); butMapTimeEnd = new JButton("set map time"); butMapTimeStart.setFont(new Font("Arial", Font.BOLD, 10)); butMapTimeEnd.setFont(new Font("Arial", Font.BOLD, 10)); butMapTimeStart.setMargin(new Insets(1,2,1,2)); butMapTimeEnd.setMargin(new Insets(1,2,1,2)); // spinners in this viewer rotXspinner = new JSpinner(); rotXspinner.setPreferredSize(new Dimension(45, rotXspinner.getPreferredSize().height)); rotZspinner = new JSpinner(); rotZspinner.setPreferredSize(new Dimension(45, rotZspinner.getPreferredSize().height)); // sliders in this viewer zMinSlide = new JSlider(); zMaxSlide = new JSlider(); mapSlide = new JSlider(); mapSlide.setOrientation(SwingConstants.VERTICAL); setLayout(new BorderLayout()); //< Definition of settings panel on the right of the viewer JPanel panelSettings = new JPanel(); GridBagLayout gblSettings = new GridBagLayout(); GridBagConstraints gbcSettings = new GridBagConstraints(); gbcSettings.fill=GridBagConstraints.HORIZONTAL; gbcSettings.insets = new Insets(2,2,2,2); panelSettings.setLayout(gblSettings); JSeparator sepHori1 = new JSeparator(); JSeparator sepHori2 = new JSeparator(); JSeparator sepVert = new JSeparator(SwingConstants.VERTICAL); zMinLabel = new JLabel("Timestamp"); zMinLabel.setFont(new Font("Arial", Font.BOLD, 10)); zMaxLabel = new JLabel("Timestamp"); zMaxLabel.setFont(new Font("Arial", Font.BOLD, 10)); JLabel labelAreaSelection = new JLabel("Area selection:"); labelAreaSelection.setFont(new Font("Arial", Font.BOLD, 12)); JLabel labelTimeframe = new JLabel("Timeframe:"); labelTimeframe.setFont(new Font("Arial", Font.BOLD, 12)); JLabel labelMap = new JLabel("Map:"); labelMap.setFont(new Font("Arial", Font.BOLD, 12)); JLabel labelVon = new JLabel("From:"); labelVon.setFont(new Font("Arial", Font.BOLD, 10)); JLabel labelBis = new JLabel("Till:"); labelBis.setFont(new Font("Arial", Font.BOLD, 10)); JLabel labelViewOp = new JLabel("View operations:"); labelViewOp.setFont(new Font("Arial", Font.BOLD, 12)); JLabel labelView = new JLabel("View:"); labelView.setFont(new Font("Arial", Font.BOLD, 10)); JLabel labelRotX = new JLabel("Rot. X:"); labelRotX.setFont(new Font("Arial", Font.BOLD, 10)); JLabel labelRotZ = new JLabel("Rot. Z:"); labelRotZ.setFont(new Font("Arial", Font.BOLD, 10)); labelDateMap = new JLabel("Date"); labelDateMap.setFont(new Font("Arial", Font.BOLD, 10)); labelTimeMap = new JLabel("Time"); labelTimeMap.setFont(new Font("Arial", Font.BOLD, 10)); JLabel placeholder1 = new JLabel(""); JLabel placeholder2 = new JLabel(""); JLabel placeholder3 = new JLabel(""); JPanel panelBut = new JPanel(new FlowLayout()); panelBut.add(butSubmit); panelBut.add(butBack); panelBut.add(butReset); JPanel panelStartTime = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0)); JPanel panelEndTime = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0)); panelStartTime.add(zMinLabel); panelStartTime.add(butMapTimeStart); panelEndTime.add(zMaxLabel); panelEndTime.add(butMapTimeEnd); panelMapOverview = new View2DSTC(); // this is the 2D map on the top right panelMapOverview.setPreferredSize(new Dimension(250,250)); // size of the 2D map ! panelMapOverview.setBorder(new LineBorder(Color.BLUE, 1)); JPanel panelRotation = new JPanel(new FlowLayout(FlowLayout.LEFT)); // panel for rotation operations panelRotation.add(labelRotX); panelRotation.add(rotXspinner); panelRotation.add(labelRotZ); panelRotation.add(rotZspinner); gbcSettings.gridx=2; gbcSettings.gridy=0; gbcSettings.gridheight=1; gbcSettings.gridwidth=2; gblSettings.setConstraints(labelAreaSelection, gbcSettings); panelSettings.add(labelAreaSelection); gbcSettings.gridx+=0; gbcSettings.gridy+=1; gbcSettings.gridheight=1; gbcSettings.gridwidth=2; gblSettings.setConstraints(panelMapOverview, gbcSettings); panelSettings.add(panelMapOverview); gbcSettings.gridx+=0; gbcSettings.gridy+=1; gbcSettings.gridheight=1; gbcSettings.gridwidth=2; gblSettings.setConstraints(sepHori1, gbcSettings); panelSettings.add(sepHori1); gbcSettings.gridx+=0; gbcSettings.gridy+=1; gbcSettings.gridheight=1; gbcSettings.gridwidth=2; gblSettings.setConstraints(labelTimeframe, gbcSettings); panelSettings.add(labelTimeframe); gbcSettings.gridx+=0; gbcSettings.gridy+=1; gbcSettings.gridheight=1; gbcSettings.gridwidth=1; gblSettings.setConstraints(labelVon, gbcSettings); panelSettings.add(labelVon); gbcSettings.gridx+=1; gbcSettings.gridy+=0; gbcSettings.gridheight=1; gbcSettings.gridwidth=1; gbcSettings.weightx=1; gblSettings.setConstraints(zMinSlide, gbcSettings); panelSettings.add(zMinSlide); gbcSettings.weightx=0; gbcSettings.gridx=2; gbcSettings.gridy+=1; gbcSettings.gridheight=1; gbcSettings.gridwidth=1; gblSettings.setConstraints(placeholder1, gbcSettings); panelSettings.add(placeholder1); gbcSettings.gridx+=1; gbcSettings.gridy+=0; gbcSettings.gridheight=1; gbcSettings.gridwidth=1; gbcSettings.weightx=1; gblSettings.setConstraints(panelStartTime, gbcSettings); panelSettings.add(panelStartTime); gbcSettings.weightx=0; gbcSettings.gridx=2; gbcSettings.gridy+=1; gbcSettings.gridheight=1; gbcSettings.gridwidth=1; gblSettings.setConstraints(labelBis, gbcSettings); panelSettings.add(labelBis); gbcSettings.gridx+=1; gbcSettings.gridy+=0; gbcSettings.gridheight=1; gbcSettings.gridwidth=1; gbcSettings.weightx=1; gblSettings.setConstraints(zMaxSlide, gbcSettings); panelSettings.add(zMaxSlide); gbcSettings.weightx=0; gbcSettings.gridx=2; gbcSettings.gridy+=1; gbcSettings.gridheight=1; gbcSettings.gridwidth=1; gblSettings.setConstraints(placeholder2, gbcSettings); panelSettings.add(placeholder2); gbcSettings.gridx+=1; gbcSettings.gridy+=0; gbcSettings.gridheight=1; gbcSettings.gridwidth=1; gbcSettings.weightx=1; gblSettings.setConstraints(panelEndTime, gbcSettings); panelSettings.add(panelEndTime); gbcSettings.weightx=0; gbcSettings.gridx=2; gbcSettings.gridy+=1; gbcSettings.gridheight=1; gbcSettings.gridwidth=2; gblSettings.setConstraints(panelBut, gbcSettings); panelSettings.add(panelBut); gbcSettings.gridx=2; gbcSettings.gridy+=1; gbcSettings.gridheight=1; gbcSettings.gridwidth=2; gblSettings.setConstraints(sepHori2, gbcSettings); panelSettings.add(sepHori2); gbcSettings.gridx=2; gbcSettings.gridy+=1; gbcSettings.gridheight=1; gbcSettings.gridwidth=2; gblSettings.setConstraints(labelViewOp, gbcSettings); panelSettings.add(labelViewOp); gbcSettings.gridx=2; gbcSettings.gridy+=1; gbcSettings.gridheight=1; gbcSettings.gridwidth=1; gblSettings.setConstraints(labelView, gbcSettings); panelSettings.add(labelView); gbcSettings.gridx+=1; gbcSettings.gridy+=0; gbcSettings.gridheight=1; gbcSettings.gridwidth=1; gblSettings.setConstraints(cbView, gbcSettings); panelSettings.add(cbView); gbcSettings.gridx=2; gbcSettings.gridy+=1; gbcSettings.gridheight=1; gbcSettings.gridwidth=2; gblSettings.setConstraints(panelRotation, gbcSettings); panelSettings.add(panelRotation); gbcSettings.gridx=0; gbcSettings.gridy+=1; gbcSettings.gridheight=1; gbcSettings.gridwidth=4; gbcSettings.weighty=1; gblSettings.setConstraints(placeholder3, gbcSettings); panelSettings.add(placeholder3); gbcSettings.weighty=0; Dimension d = sepVert.getPreferredSize(); d.height = panelSettings.getPreferredSize().height; sepVert.setPreferredSize(d); gbcSettings.gridx=0; gbcSettings.gridy=0; gbcSettings.gridheight=1; gbcSettings.gridwidth=1; gblSettings.setConstraints(labelMap, gbcSettings); panelSettings.add(labelMap); Dimension d2 = mapSlide.getPreferredSize(); d2.height = 410; mapSlide.setPreferredSize(d2); gbcSettings.gridx+=0; gbcSettings.gridy+=1; gbcSettings.gridheight=10; gbcSettings.gridwidth=1; gblSettings.setConstraints(mapSlide, gbcSettings); panelSettings.add(mapSlide); gbcSettings.gridx+=0; gbcSettings.gridy=11; gbcSettings.gridheight=1; gbcSettings.gridwidth=1; gblSettings.setConstraints(labelDateMap, gbcSettings); panelSettings.add(labelDateMap); gbcSettings.gridx+=0; gbcSettings.gridy+=1; gbcSettings.gridheight=1; gbcSettings.gridwidth=1; gblSettings.setConstraints(labelTimeMap, gbcSettings); panelSettings.add(labelTimeMap); gbcSettings.gridx+=1; gbcSettings.gridy=0; gbcSettings.gridheight=13; gbcSettings.gridwidth=1; gblSettings.setConstraints(sepVert, gbcSettings); panelSettings.add(sepVert); //> add(panelSettings, BorderLayout.EAST); transform = new Transform3D(); // base transform for the whole cube transformMap = new Transform3D(); canvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration()); add(canvas,BorderLayout.CENTER); universe = new SimpleUniverse(canvas); universe.getViewingPlatform().setNominalViewingTransform(); // points helping to construct the cube bottomFrontLeft = new Point3d(-0.5+0,-0.5+0,-0.5+0); bottomFrontRight = new Point3d(-0.5+1,-0.5+0,-0.5+0); bottomBackLeft = new Point3d(-0.5+0,-0.5+1,-0.5+0); bottomBackRight = new Point3d(-0.5+1,-0.5+1,-0.5+0); topFrontLeft = new Point3d(-0.5+0,-0.5+0,-0.5+1); topFrontRight = new Point3d(-0.5+1,-0.5+0,-0.5+1); topBackLeft = new Point3d(-0.5+0,-0.5+1,-0.5+1); topBackRight = new Point3d(-0.5+1,-0.5+1,-0.5+1); rotXspinner.addChangeListener(this); rotZspinner.addChangeListener(this); butSubmit.addActionListener(this); butReset.addActionListener(this); butBack.addActionListener(this); butBack.setEnabled(false); butRetry.addActionListener(this); butMapTimeStart.addActionListener(this); butMapTimeEnd.addActionListener(this); // definition of dialog when loading of the map takes time (frameLoad) GridBagConstraints gbcLoad = new GridBagConstraints(); GridBagLayout gblLoad = new GridBagLayout(); gbcLoad.fill=GridBagConstraints.HORIZONTAL; gbcLoad.insets = new Insets(2,2,2,2); frameLoad = new JFrame(); frameLoad.setLayout(gblLoad); frameLoad.setTitle("loading..."); JLabel labelLoadingMap = new JLabel("Loading map..."); JLabel labelInternetRequired = new JLabel("(Internet connection required)"); gbcLoad.gridx = 0; gbcLoad.gridy = 0; gbcLoad.gridwidth = 2; gblLoad.setConstraints(labelLoadingMap, gbcLoad); frameLoad.add(labelLoadingMap); gbcLoad.gridx = 0; gbcLoad.gridy += 1; gbcLoad.gridwidth = 2; gblLoad.setConstraints(labelInternetRequired, gbcLoad); frameLoad.add(labelInternetRequired); gbcLoad.gridx = 0; gbcLoad.gridy += 1; gbcLoad.gridwidth = 1; gbcLoad.insets = new Insets(6,2,2,2); gblLoad.setConstraints(butRetry, gbcLoad); frameLoad.add(butRetry); gbcLoad.gridx += 1; gbcLoad.gridy += 0; gbcLoad.gridwidth = 1; gbcLoad.weightx = 1; gbcLoad.insets = new Insets(2,2,2,2); gblLoad.setConstraints(new JLabel(), gbcLoad); frameLoad.setSize(230,130); // all defined views are added to the views vector views = new Vector(); double[] viewOverview = {25,0,-25}; // {rotationX, rotationY, rotationZ} double[] viewFront = {0,0,0}; // similar to reference view !!! double[] viewTop = {90,0,0}; views.add(viewOverview); views.add(viewFront); views.add(viewTop); } /** * Checks if a recently queried SecondoObject is already displayed. * @return * true if SecondoObject is already displayed in viewer. */ public boolean isDisplayed(SecondoObject o){ for (int i=0;i=6) { if (s.substring(s.length()-6, s.length()).equals("mpoint")) { return true; } } tempLE = tempLE.rest(); } return false; } // if a single MPoint was queried else if (typeName.equals("mpoint")) { return true; } else { return false; } } } /** * Removes a given SecondoObject from the viewer. */ public void removeObject(SecondoObject o){ if(isDisplayed(o)) { objectList.remove(o); STC.removeMPoints(o.getID()); recompute(); } } /** * Not relevant for this viewer. */ public boolean selectObject(SecondoObject o){ return true; } /** * Gives the name of the viewer. */ public String getName(){ return "SpaceTimeCube-Viewer"; } /** * @return * List of all SecondoObjects that are currently maintained in this viewer. */ public Vector getSecondoObjectList() { return objectList; } /** * Adds a given SecondoObject to the viewer. * @return * true if adding the object was successful. */ public boolean addObject(SecondoObject o){ if(isDisplayed(o)) { return true; } try { MPointQuery mpQuery = new MPointQuery(); if (mpQuery.readFromSecondoObject(o)) { STC.addMPointsVector(mpQuery.getMPointsVector()); } float[] tmpCol = {1, 0, 0}; colorSO.put(o.getID(), tmpCol); objectList.add(o); recompute(); } catch (Exception e) { e.printStackTrace(); } return true; } /** * Called when AWT action performed. */ public void actionPerformed(ActionEvent e) { // submit button clicked if (e.getSource() == butSubmit) { if (STC.getLimitSet()) { minXlimitLast = STC.getMinXlimit(); maxXlimitLast = STC.getMaxXlimit(); minYlimitLast = STC.getMinYlimit(); maxYlimitLast = STC.getMaxYlimit(); minZlimitLast = STC.getMinZlimit(); maxZlimitLast = STC.getMaxZlimit(); } else { minXlimitLast = STC.getMinXnoLimit(); maxXlimitLast = STC.getMaxXnoLimit(); minYlimitLast = STC.getMinYnoLimit(); maxYlimitLast = STC.getMaxYnoLimit(); minZlimitLast = STC.getMinZnoLimit(); maxZlimitLast = STC.getMaxZnoLimit(); } LastLimits tmpLL = new LastLimits(minXlimitLast, maxXlimitLast, minYlimitLast, maxYlimitLast, minZlimitLast, maxZlimitLast); lastLimits.add(tmpLL); // store actual filter/limit so that multiple back actions will work STC.setMinZlimit((long)zMinSlide.getValue()*1000); STC.setMaxZlimit((long)zMaxSlide.getValue()*1000); // *1000 to get milliseconds setAreaFilter(); STC.setLimitSet(true); // tell the STC that a limit is set now STC.recompute(); recompute(); } // back button clicked else if (e.getSource() == butBack) { if (STC.getLimitSet()) { STC.setMinXlimit(lastLimits.get(lastLimits.size()-1).getMinXlimit()); STC.setMaxXlimit(lastLimits.get(lastLimits.size()-1).getMaxXlimit()); STC.setMinYlimit(lastLimits.get(lastLimits.size()-1).getMinYlimit()); STC.setMaxYlimit(lastLimits.get(lastLimits.size()-1).getMaxYlimit()); STC.setMinZlimit(lastLimits.get(lastLimits.size()-1).getMinZlimit()); STC.setMaxZlimit(lastLimits.get(lastLimits.size()-1).getMaxZlimit()); } STC.setLimitSet(true); STC.recompute(); lastLimits.remove(lastLimits.size()-1); // last filter/limit needs to be removed from lastLimits vector recompute(); } // reset button clicked else if (e.getSource() == butReset) { STC.setLimitSet(false); // like that a recalculation will be done without any filter STC.recompute(); lastLimits.clear(); recompute(); } // retry button (in loading dialog) clicked else if (e.getSource() == butRetry) { recompute(); } // menu item for showing settings clicked else if (e.getSource() == miShowSettings) { frameSettings = new SettingsDialog(this); /* always new object necessary because the frame depends on the actual viewer state */ // locate the frame in the middle of the viewer frameSettings.setLocation(getLocationOnScreen().x+(getWidth()/2)-frameSettings.getWidth()/2, getLocationOnScreen().y+(getHeight()/2)-frameSettings.getHeight()/2); frameSettings.setVisible(true); } // "set map time" button regarding start time clicked else if (e.getSource() == butMapTimeStart) { zMinSlide.setValue(mapSlide.getValue()); } // "set map time" button regarding end time clicked else if (e.getSource() == butMapTimeEnd) { zMaxSlide.setValue(mapSlide.getValue()); } } /** * Called when AWT state changed. */ public void stateChanged(ChangeEvent e) { // slider min. Z value changed if (e.getSource() == zMinSlide) { zMinLabel.setText(getTimestampForMilliseconds((long)zMinSlide.getValue()*1000)); } // slider max. Z value changed else if (e.getSource() == zMaxSlide) { zMaxLabel.setText(getTimestampForMilliseconds((long)zMaxSlide.getValue()*1000)); } // slider for map movement changed else if (e.getSource() == mapSlide) { if (tgMap != null) { int range = mapSlide.getMaximum() - mapSlide.getMinimum(); int realVal = mapSlide.getValue() - mapSlide.getMinimum(); double value = -0.5 + ((double)realVal/(double)range); // milliseconds need to be translated to a value between 0 and 1 transformMap.setTranslation(new Vector3d(-0.5+0,-0.5+0,value)); tgMap.setTransform(transformMap); String tmp[] = getTimestampForMilliseconds((long)mapSlide.getValue()*1000).split(" "); labelDateMap.setText(tmp[0]); labelTimeMap.setText(tmp[1]); } } // spinner rot. X changed else if (e.getSource() == rotXspinner) { // the actual value is always compared to the last value so that a delta rotation is possible double tmpAngle = ((Integer)rotXspinner.getValue()-rotXlastVal)*(-1); // *(-1) to change directions of the arrows rotXlastVal = (Integer)rotXspinner.getValue(); Transform3D tfRot = new Transform3D(); tfRot.rotX(tmpAngle/57.295); // convert from radian to degree Transform3D tfActual = new Transform3D(); tg.getTransform(tfActual); tfActual.mul(tfRot); // multiply the actual transform with the rotated one tg.setTransform(tfActual); cbView.setSelectedIndex(0); } // spinner rot. Z changed else if (e.getSource() == rotZspinner) { // the actual value is always compared to the last value so that a delta rotation is possible double tmpAngle = (Integer)rotZspinner.getValue()-rotZlastVal; rotZlastVal = (Integer)rotZspinner.getValue(); Transform3D tfRot = new Transform3D(); tfRot.rotZ(tmpAngle/57.295); // convert from radian to degree Transform3D tfActual = new Transform3D(); tg.getTransform(tfActual); tfActual.mul(tfRot); // multiply the actual transform with the rotated one tg.setTransform(tfActual); cbView.setSelectedIndex(0); } } /** * Called when AWT itemstate changed. */ public void itemStateChanged(ItemEvent e) { // itemstate in view combobox changed if (e.getSource() == cbView) { int ind = cbView.getSelectedIndex(); if (ind > 0) { ind-=1; Point3d eye = new Point3d(referenceView[0],referenceView[1],referenceView[2]); Vector3d up = new Vector3d(0,0,1); Point3d center = new Point3d(0.0,0.0,0.0); // (0,0,0) is the center of the cube Transform3D tfRot = new Transform3D(); Transform3D transform = new Transform3D(); transform.lookAt(eye, center, up); tfRot.rotX(views.get(ind)[0]/57.295); // convert from radian to degree transform.mul(tfRot); // multiply the actual transform with the rotated one tfRot.rotY(views.get(ind)[1]/57.295); transform.mul(tfRot); tfRot.rotZ(views.get(ind)[2]/57.295); transform.mul(tfRot); tg.setTransform(transform); rotXspinner.setValue(new Integer(0)); rotZspinner.setValue(new Integer(0)); } } } /** * Called when mouse was clicked. */ public void mouseClicked(MouseEvent e) { // click was done on canvas if (e.getSource() == canvas) { // set all dialogs invisible when clicking on the canvas if (frameMPoint != null && frameMPoint.isVisible()) frameMPoint.setVisible(false); if (frameSettings != null && frameSettings.isVisible()) frameSettings.setVisible(false); rotXlastVal = 0; rotZlastVal = 0; rotXspinner.setValue(new Integer(0)); rotZspinner.setValue(new Integer(0)); cbView.setSelectedIndex(0); } /* Right mouse button clicked. * If the cursor was located on top of a MPoint, * it's additional attributes will be shown in a frame. */ if (e.getButton() == e.BUTTON3) { pickCanvas.setShapeLocation(e); PickResult[] result = pickCanvas.pickAllSorted(); // stores potentially picked objects with right mouse button int[] indexesAfterFilter = STC.getIndexesAfterFilter(); // if a filter is applied the order of the indexes may be different. if (result != null) { for (int i=0;i tmpHt = tmpMPoint.getAdditionalAttributes(); // a frame/dialog for showing the additional attributes to an MPoint is created int rows = tmpHt.size(); frameMPoint = new JFrame(); frameMPoint.setUndecorated(true); GridBagLayout gbLayout = new GridBagLayout(); GridBagConstraints gbc = new GridBagConstraints(); gbc.fill=GridBagConstraints.HORIZONTAL; gbc.insets = new Insets(2,2,2,2); gbc.gridx=0; gbc.gridy=0; gbc.gridheight=1; gbc.gridwidth=1; frameMPoint.setLayout(gbLayout); // looping through the Hashtable that stores the addtional attributes to a MPoint JLabel labelKey=null, labelVal=null; for (Enumeration b = tmpHt.keys(); b.hasMoreElements();) { String key = b.nextElement(); labelKey = new JLabel(key+": "); labelVal = new JLabel(tmpHt.get(key)); gbLayout.setConstraints(labelKey, gbc); frameMPoint.add(labelKey); gbc.gridx++; gbLayout.setConstraints(labelVal, gbc); frameMPoint.add(labelVal); gbc.gridy++; gbc.gridx=0; } // the dialog's height is calculated based on rows, fontsize and insets int height = (rows*(labelKey.getFont().getSize()+((gbc.insets.top+2)*2))); frameMPoint.setSize(frameMPoint.getPreferredSize().width, height); // the dialog/frame will be shown in the center of the canvas Point canvasLoc = canvas.getLocationOnScreen(); frameMPoint.setLocation(canvasLoc.x+e.getPoint().x-10, canvasLoc.y+e.getPoint().y-10); frameMPoint.setVisible(true); return; } } } } } } public void mouseReleased(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mousePressed(MouseEvent e) { // mouse was pressed on viewing area/canvas if (e.getSource() == canvas) { // set all dialogs invisible when clicking on the canvas if (frameMPoint != null && frameMPoint.isVisible()) frameMPoint.setVisible(false); if (frameSettings != null && frameSettings.isVisible()) frameSettings.setVisible(false); // rotation calculation attributes are reset rotXlastVal = 0; rotZlastVal = 0; rotXspinner.setValue(new Integer(0)); rotZspinner.setValue(new Integer(0)); /* * Pressing the mouse indicates that the view was changed by dragging. * That means the user is no longer working with a pre-defined view. * => view combobox is reset. */ cbView.setSelectedIndex(0); } } public void mouseExited(MouseEvent e) { } /* * Views need to be recalculated because canvas width-height-ratio might have changed. */ public void componentResized(ComponentEvent e) { if (e.getSource() == this) { computeReferenceView(); } } public void componentHidden(ComponentEvent e) { } public void componentMoved(ComponentEvent e) { } public void componentShown(ComponentEvent e) { } public MenuVector getMenuVector(){ return MenuExtension; } // Settings section ///////////////////// /** * @return * mpoint/trajectory color for each queried SecondoObject, defined by SecondoIDs. */ public Hashtable getColorSO() { return colorSO; } /** * @param colSO * Hashtable which connects multiple SecondoIDs to colors as float[] values. */ public void setColorSO(Hashtable colSO) { colorSO = colSO; } /** * @return * true if currently vertical lines are drawn. */ public boolean isDrawVertLines() { return drawVertLines; } /** * @param b * indicates if vertical lines are currently drawn. */ public void setDrawVertLines(boolean b) { drawVertLines = b; } /** * @return * the actual background/canvas color */ public Color3f getColorCanvas() { return colorCanvas; } /** * @param col * actual background/canvas color that will be set */ public void setColorCanvas(Color3f col) { colorCanvas = col; } /** * @return * the actual mpoint/trajectory line width/weight. */ public float getLineWidth() { return lineWidth; } /** * @param weight * mpoint/trajectory line width/weight that will be set. */ public void setLineWidth(float weight) { lineWidth = weight; } /** * @return * the actual mpoint/trajectory transparency value. */ public float getTranspMPoints() { return transpMPoints; } /** * @param transp * mpoint/trajectory transparency value that will be set. */ public void setTranspMPoints(float transp) { transpMPoints = transp; } ///////////////////////////////////////// /** * Following computations are done: * 1. Map is drawn. * 2. Extraction of points out of all MPoints. * 3. Creation of linestriparrays based on "1.". * 4. Creation of the 'outside' of the cube including axis, labels, etc.. * 5. Lines and map are added to the basic TransformGroup and the TG is added to a BranchGroup. * 6. Set views depending on canvas width. * 7. Behaviors are added to the BranchGroup. */ public void recompute() { if (STC.downloadMap()) { drawMap(); if (lastLimits.size()>0) butBack.setEnabled(true); // if there is sth. to go back to else butBack.setEnabled(false); Vector STCpointArrays = STC.getPointArrays(); // corresponds to all MPoints maintained in the STC Vector mPointShapes = new Vector(); // stores all MPoints as Shape3Ds Vector vertShapes = new Vector(); // stores all vertical lines as Shape3Ds Vector p2dArrays = new Vector(); /* stores the 2D point coordinates * of the mpoints/trajectories that will have to be displayed in the 2D filter view. */ /* * For each MPoint the single points are extraced and stored to a linestriparray. * The vertical lines are also stored into a linestriparray. */ for (int i=0;i pointArray = STCpointArrays.get(i); // corresponds to a MPoint Vector p2ds = new Vector(); // stores 2D point coordinates of the mpoint p2dArrays.add(p2ds); int pointArraySize = pointArray.size(); int vertexCount = pointArraySize; boolean uneven = false; /* if it is an uneven amount of points an additional point will be added at the end * that has the same coordinates as the actual last one. */ if ((vertexCount%2)!=0) { vertexCount++; uneven = true; } int[] stripVertexCounts = new int[1]; stripVertexCounts[0] = vertexCount; LineStripArray la = new LineStripArray(vertexCount,LineStripArray.COORDINATES | LineStripArray.COLOR_3 ,stripVertexCounts); la.setCapability(LineStripArray.ALLOW_COLOR_WRITE); Point3d p3d[] = new Point3d[vertexCount]; // stores all 3D points of this mpoint double x=0,y=0,z=0; // definition for the vertical lines int[] stripVertexCountsVert = new int[1]; stripVertexCountsVert[0] = 2; int vertexCountVert = 2; int count=0; int vertLineAmount = 50; int divider; /* * Usually 50 vertical lines per mpoint are drawn. * If the area is filtered a mpoint may contain less than * 50 single points. Then 50 vertical lines can't be drawn. */ if (pointArraySize > (vertLineAmount*vertLineAmount)) divider = vertLineAmount; else divider = pointArraySize/vertLineAmount; if (divider==0) divider = 1; float[] colVert = {0.5f, 0.5f, 0.5f}; // color of vertical lines Vector linesVert = new Vector(); Appearance apVert = new Appearance(); // set 50% transparency for vertical lines TransparencyAttributes taVert = new TransparencyAttributes(TransparencyAttributes.FASTEST, 0.5f); apVert.setTransparencyAttributes(taVert); float[] colSO = {0,0,0}; // default color of all SecondoObjects/MPoints for (int a=0;a0) { map = STC.generateMap(); if (map != null) { Texture txt = new TextureLoader(map).getTexture(); Appearance ap = new Appearance(); ap.setTexture(txt); float[] tcoords = { 0, 0, 1, 0, 1, 1, 0, 1 }; QuadArray plane = new QuadArray(4, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_2); plane.setCoordinate(0, new Point3d(0,0,0)); plane.setCoordinate(1, new Point3d(1,0,0)); plane.setCoordinate(2, new Point3d(1,1,0)); plane.setCoordinate(3, new Point3d(0,1,0)); plane.setTextureCoordinates(0, 0, tcoords); mapShape = new Shape3D(plane, ap); } } } /* * Creates the 'outside' of the cube as lines, quads and texts/labels. */ private void createCube(TransformGroup tg) { Appearance ap = new Appearance(); // setting 50% transparency for the lines TransparencyAttributes ta = new TransparencyAttributes(TransparencyAttributes.FASTEST, 0.5f); PolygonAttributes pa = new PolygonAttributes(PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_NONE, 0.0f); // POLYGON_LINE is necessary so that the polygons are not filled ap.setTransparencyAttributes(ta); ap.setPolygonAttributes(pa); int[] stripVertexCounts = new int[1]; stripVertexCounts[0] = 2; int vertexCount = 2; float[] colAxis = {1,0.4f,0}; // axis color float[] colCube = {0.5f,0.5f,0.5f}; // usual line color of the cube LineStripArray laXaxis = new LineStripArray(vertexCount, LineStripArray.COORDINATES | LineStripArray.COLOR_3, stripVertexCounts); laXaxis.setCapability(LineStripArray.ALLOW_COLOR_WRITE); Point3d p3dXaxis[] = new Point3d[vertexCount]; p3dXaxis[0] = bottomFrontLeft; p3dXaxis[1] = bottomFrontRight; laXaxis.setCoordinates(0, p3dXaxis); laXaxis.setColor(0, colAxis); laXaxis.setColor(1, colAxis); lineXaxis = new Shape3D(laXaxis, ap); LineStripArray laYaxis = new LineStripArray(vertexCount, LineStripArray.COORDINATES | LineStripArray.COLOR_3, stripVertexCounts); laYaxis.setCapability(LineStripArray.ALLOW_COLOR_WRITE); Point3d p3dYaxis[] = new Point3d[vertexCount]; p3dYaxis[0] = bottomFrontLeft; p3dYaxis[1] = bottomBackLeft; laYaxis.setCoordinates(0, p3dYaxis); laYaxis.setColor(0, colAxis); laYaxis.setColor(1, colAxis); lineYaxis = new Shape3D(laYaxis, ap); LineStripArray laZaxis = new LineStripArray(vertexCount, LineStripArray.COORDINATES | LineStripArray.COLOR_3, stripVertexCounts); laZaxis.setCapability(LineStripArray.ALLOW_COLOR_WRITE); Point3d p3dZaxis[] = new Point3d[vertexCount]; p3dZaxis[0] = bottomFrontLeft; p3dZaxis[1] = topFrontLeft; laZaxis.setCoordinates(0, p3dZaxis); laZaxis.setColor(0, colAxis); laZaxis.setColor(1, colAxis); lineZaxis = new Shape3D(laZaxis, ap); LineStripArray laBottomBack = new LineStripArray(vertexCount, LineStripArray.COORDINATES | LineStripArray.COLOR_3, stripVertexCounts); laBottomBack.setCapability(LineStripArray.ALLOW_COLOR_WRITE); Point3d p3dBottomBack[] = new Point3d[vertexCount]; p3dBottomBack[0] = bottomBackLeft; p3dBottomBack[1] = bottomBackRight; laBottomBack.setCoordinates(0, p3dBottomBack); laBottomBack.setColor(0, colCube); laBottomBack.setColor(1, colCube); lineBottomBack = new Shape3D(laBottomBack, ap); LineStripArray laBottomRight = new LineStripArray(vertexCount, LineStripArray.COORDINATES | LineStripArray.COLOR_3, stripVertexCounts); laBottomRight.setCapability(LineStripArray.ALLOW_COLOR_WRITE); Point3d p3dBottomRight[] = new Point3d[vertexCount]; p3dBottomRight[0] = bottomFrontRight; p3dBottomRight[1] = bottomBackRight; laBottomRight.setCoordinates(0, p3dBottomRight); laBottomRight.setColor(0, colCube); laBottomRight.setColor(1, colCube); lineBottomRight = new Shape3D(laBottomRight, ap); LineStripArray laLeftBack = new LineStripArray(vertexCount, LineStripArray.COORDINATES | LineStripArray.COLOR_3, stripVertexCounts); laLeftBack.setCapability(LineStripArray.ALLOW_COLOR_WRITE); Point3d p3dLeftBack[] = new Point3d[vertexCount]; p3dLeftBack[0] = bottomBackLeft; p3dLeftBack[1] = topBackLeft; laLeftBack.setCoordinates(0, p3dLeftBack); laLeftBack.setColor(0, colCube); laLeftBack.setColor(1, colCube); lineLeftBack = new Shape3D(laLeftBack, ap); LineStripArray laRightFront = new LineStripArray(vertexCount, LineStripArray.COORDINATES | LineStripArray.COLOR_3, stripVertexCounts); laRightFront.setCapability(LineStripArray.ALLOW_COLOR_WRITE); Point3d p3dRightFront[] = new Point3d[vertexCount]; p3dRightFront[0] = bottomFrontRight; p3dRightFront[1] = topFrontRight; laRightFront.setCoordinates(0, p3dRightFront); laRightFront.setColor(0, colCube); laRightFront.setColor(1, colCube); lineRightFront = new Shape3D(laRightFront, ap); LineStripArray laRightBack = new LineStripArray(vertexCount, LineStripArray.COORDINATES | LineStripArray.COLOR_3, stripVertexCounts); laRightBack.setCapability(LineStripArray.ALLOW_COLOR_WRITE); Point3d p3dRightBack[] = new Point3d[vertexCount]; p3dRightBack[0] = bottomBackRight; p3dRightBack[1] = topBackRight; laRightBack.setCoordinates(0, p3dRightBack); laRightBack.setColor(0, colCube); laRightBack.setColor(1, colCube); lineRightBack = new Shape3D(laRightBack, ap); // the top of the cube can be created as whole because all lines of the quad look same QuadArray top = new QuadArray(4, QuadArray.COORDINATES | QuadArray.COLOR_3); top.setCapability(QuadArray.ALLOW_COLOR_WRITE); top.setColor(0,colCube); top.setColor(1,colCube); top.setColor(2,colCube); top.setColor(3,colCube); top.setCoordinate(0, topFrontLeft); top.setCoordinate(1, topFrontRight); top.setCoordinate(2, topBackRight); top.setCoordinate(3, topBackLeft); topShape = new Shape3D(top, ap); // all axis, lines and quads are added to the basic TransformGroup tg.addChild(new Shape3D(lineXaxis.getGeometry(),lineXaxis.getAppearance())); tg.addChild(new Shape3D(lineYaxis.getGeometry(),lineYaxis.getAppearance())); tg.addChild(new Shape3D(lineZaxis.getGeometry(),lineZaxis.getAppearance())); tg.addChild(new Shape3D(lineBottomBack.getGeometry(),lineBottomBack.getAppearance())); tg.addChild(new Shape3D(lineBottomRight.getGeometry(),lineBottomRight.getAppearance())); tg.addChild(new Shape3D(lineLeftBack.getGeometry(),lineLeftBack.getAppearance())); tg.addChild(new Shape3D(lineRightFront.getGeometry(),lineRightFront.getAppearance())); tg.addChild(new Shape3D(lineRightBack.getGeometry(),lineRightBack.getAppearance())); tg.addChild(new Shape3D(topShape.getGeometry(),topShape.getAppearance())); Color3f colTextCoords = new Color3f(0.3f,0.3f,1); // color of the coordinate labels Color3f colTextAxis = new Color3f(1,0.4f,0); // color of the axis' labels Appearance apTextCoords = new Appearance(); apTextCoords.setColoringAttributes(new ColoringAttributes(colTextCoords, ColoringAttributes.SHADE_FLAT)); Appearance apTextAxis = new Appearance(); apTextAxis.setColoringAttributes(new ColoringAttributes(colTextAxis, ColoringAttributes.SHADE_FLAT)); Font3D font = new Font3D(new Font("Arial", Font.ROMAN_BASELINE, 1), new FontExtrusion()); double scaleTextCoords = 0.25/factorCanvas; // size of coordinate labels double scaleTextAxis = 0.35/factorCanvas; // size of axis' labels String temp; Text3D textMinX = new Text3D(font); if (String.valueOf(STC.getMinXtext()).length() >= 7) temp = String.valueOf(STC.getMinXtext()).substring(0, 7); else temp = String.valueOf(STC.getMinXtext()); textMinX.setString(temp); OrientedShape3D osTextMinX = new OrientedShape3D(textMinX, apTextCoords, OrientedShape3D.ROTATE_ABOUT_POINT, new Point3f(0,0,0)); osTextMinX.setConstantScaleEnable(true); osTextMinX.setScale(scaleTextCoords); Point3d p3dTextMinX = new Point3d(-0.5+0.1,-0.5+0,-0.5+0.01); Transform3D transTextMinX = new Transform3D(); transTextMinX.setTranslation(new Vector3d(p3dTextMinX)); TransformGroup tgTextMinX = new TransformGroup(); tgTextMinX.setTransform(transTextMinX); tgTextMinX.addChild(osTextMinX); Text3D textMinY = new Text3D(font); if (String.valueOf(STC.getMinYtext()).length() >= 7) temp = String.valueOf(STC.getMinYtext()).substring(0, 7); else temp = String.valueOf(STC.getMinYtext()); textMinY.setString(temp); OrientedShape3D osTextMinY = new OrientedShape3D(textMinY, apTextCoords, OrientedShape3D.ROTATE_ABOUT_POINT, new Point3f(0,0,0)); osTextMinY.setConstantScaleEnable(true); osTextMinY.setScale(scaleTextCoords); Point3d p3dTextMinY = new Point3d(-0.5+0,-0.5+0.1,-0.5+0.01); Transform3D transTextMinY = new Transform3D(); transTextMinY.setTranslation(new Vector3d(p3dTextMinY)); TransformGroup tgTextMinY = new TransformGroup(); tgTextMinY.setTransform(transTextMinY); tgTextMinY.addChild(osTextMinY); Text3D textMinZ = new Text3D(font); if (String.valueOf(STC.getMinZtext()).length() >= 7) temp = String.valueOf(STC.getMinZtext()); else temp = String.valueOf(STC.getMinZtext()); textMinZ.setString(temp); OrientedShape3D osTextMinZ = new OrientedShape3D(textMinZ, apTextCoords, OrientedShape3D.ROTATE_ABOUT_POINT, new Point3f(0,0,0)); osTextMinZ.setConstantScaleEnable(true); osTextMinZ.setScale(scaleTextCoords); Point3d p3dTextMinZ = new Point3d(-0.5+0,-0.5+0,-0.5+0.1); Transform3D transTextMinZ = new Transform3D(); transTextMinZ.setTranslation(new Vector3d(p3dTextMinZ)); TransformGroup tgTextMinZ = new TransformGroup(); tgTextMinZ.setTransform(transTextMinZ); tgTextMinZ.addChild(osTextMinZ); Text3D textMaxX = new Text3D(font); if (String.valueOf(STC.getMaxXtext()).length() >= 7) temp = String.valueOf(STC.getMaxXtext()).substring(0, 7); else temp = String.valueOf(STC.getMaxXtext()); textMaxX.setString(temp); OrientedShape3D osTextMaxX = new OrientedShape3D(textMaxX, apTextCoords, OrientedShape3D.ROTATE_ABOUT_POINT, new Point3f(0,0,0)); osTextMaxX.setConstantScaleEnable(true); osTextMaxX.setScale(scaleTextCoords); Point3d p3dTextMaxX = new Point3d(-0.5+1-0.1,-0.5+0,-0.5+0.01); Transform3D transTextMaxX = new Transform3D(); transTextMaxX.setTranslation(new Vector3d(p3dTextMaxX)); TransformGroup tgTextMaxX = new TransformGroup(); tgTextMaxX.setTransform(transTextMaxX); tgTextMaxX.addChild(osTextMaxX); Text3D textMaxY = new Text3D(font); if (String.valueOf(STC.getMaxYtext()).length() >= 7) temp = String.valueOf(STC.getMaxYtext()).substring(0, 7); else temp = String.valueOf(STC.getMaxYtext()); textMaxY.setString(temp); OrientedShape3D osTextMaxY = new OrientedShape3D(textMaxY, apTextCoords, OrientedShape3D.ROTATE_ABOUT_POINT, new Point3f(0,0,0)); osTextMaxY.setConstantScaleEnable(true); osTextMaxY.setScale(scaleTextCoords); Point3d p3dTextMaxY = new Point3d(-0.5+0,-0.5+1-0.1,-0.5+0.01); Transform3D transTextMaxY = new Transform3D(); transTextMaxY.setTranslation(new Vector3d(p3dTextMaxY)); TransformGroup tgTextMaxY = new TransformGroup(); tgTextMaxY.setTransform(transTextMaxY); tgTextMaxY.addChild(osTextMaxY); Text3D textMaxZ = new Text3D(font); if (String.valueOf(STC.getMaxZtext()).length() >= 7) temp = String.valueOf(STC.getMaxZtext()); else temp = String.valueOf(STC.getMaxZtext()); textMaxZ.setString(temp); OrientedShape3D osTextMaxZ = new OrientedShape3D(textMaxZ, apTextCoords, OrientedShape3D.ROTATE_ABOUT_POINT, new Point3f(0,0,0)); osTextMaxZ.setConstantScaleEnable(true); osTextMaxZ.setScale(scaleTextCoords); Point3d p3dTextMaxZ = new Point3d(-0.5+0,-0.5+0,-0.5+1-0.1); Transform3D transTextMaxZ = new Transform3D(); transTextMaxZ.setTranslation(new Vector3d(p3dTextMaxZ)); TransformGroup tgTextMaxZ = new TransformGroup(); tgTextMaxZ.setTransform(transTextMaxZ); tgTextMaxZ.addChild(osTextMaxZ); Text3D textXaxis = new Text3D(font); textXaxis.setString("X"); OrientedShape3D osTextXaxis = new OrientedShape3D(textXaxis, apTextAxis, OrientedShape3D.ROTATE_ABOUT_POINT, new Point3f(0,0,0)); osTextXaxis.setConstantScaleEnable(true); osTextXaxis.setScale(scaleTextAxis); Point3d p3dTextXaxis = new Point3d(-0.5+0.5,-0.5+0,-0.5+0.01); Transform3D transTextXaxis = new Transform3D(); transTextXaxis.setTranslation(new Vector3d(p3dTextXaxis)); TransformGroup tgTextXaxis = new TransformGroup(); tgTextXaxis.setTransform(transTextXaxis); tgTextXaxis.addChild(osTextXaxis); Text3D textYaxis = new Text3D(font); textYaxis.setString("Y"); OrientedShape3D osTextYaxis = new OrientedShape3D(textYaxis, apTextAxis, OrientedShape3D.ROTATE_ABOUT_POINT, new Point3f(0,0,0)); osTextYaxis.setConstantScaleEnable(true); osTextYaxis.setScale(scaleTextAxis); Point3d p3dTextYaxis = new Point3d(-0.5+0,-0.5+0.5,-0.5+0.01); Transform3D transTextYaxis = new Transform3D(); transTextYaxis.setTranslation(new Vector3d(p3dTextYaxis)); TransformGroup tgTextYaxis = new TransformGroup(); tgTextYaxis.setTransform(transTextYaxis); tgTextYaxis.addChild(osTextYaxis); Text3D textZaxis = new Text3D(font); textZaxis.setString("Z"); OrientedShape3D osTextZaxis = new OrientedShape3D(textZaxis, apTextAxis, OrientedShape3D.ROTATE_ABOUT_POINT, new Point3f(0,0,0)); osTextZaxis.setConstantScaleEnable(true); osTextZaxis.setScale(scaleTextAxis); Point3d p3dTextZaxis = new Point3d(-0.5+0,-0.5+0,-0.5+0.5); Transform3D transTextZaxis = new Transform3D(); transTextZaxis.setTranslation(new Vector3d(p3dTextZaxis)); TransformGroup tgTextZaxis = new TransformGroup(); tgTextZaxis.setTransform(transTextZaxis); tgTextZaxis.addChild(osTextZaxis); // all texts are added to the basic TransformGroup tg.addChild(tgTextMinX); tg.addChild(tgTextMinY); tg.addChild(tgTextMinZ); tg.addChild(tgTextMaxX); tg.addChild(tgTextMaxY); tg.addChild(tgTextMaxZ); tg.addChild(tgTextXaxis); tg.addChild(tgTextYaxis); tg.addChild(tgTextZaxis); } /* * Get timestamp as String for milliseconds since 1970. */ private String getTimestampForMilliseconds(long millisec) { Timestamp ts = new Timestamp(millisec); return ts.toString(); } /* * Limits/filters the current SecondoObjects according to the selection in the 2D-view. * That means X,Y min and max limit values will be reset. */ private void setAreaFilter() { // get the selected area as pixel value // rectangle from bottom left to top right Rectangle2D.Double area2DView = panelMapOverview.getFilterArea(); // pixel values need to be translated to STC values double selectedAreaWidth = STC.getXYlength()/panelMapOverview.getWidth()*area2DView.getWidth(); double selectedAreaHeight = STC.getXYlength()/panelMapOverview.getHeight()*area2DView.getHeight(); double changeFactor = 0.05; // puffer that is added to the selection double widthChange, heightChange; // puffer values as STC values widthChange = selectedAreaWidth * changeFactor; heightChange = selectedAreaHeight * changeFactor; // X,Y values are converted to values between 0 and 1 double xMin = STC.getMinX()+(STC.getXYlength()/panelMapOverview.getWidth()*area2DView.getX())-widthChange; double yMin = STC.getMinY()+(STC.getXYlength()/panelMapOverview.getHeight()* (panelMapOverview.getHeight()-area2DView.getY()-area2DView.getHeight()))-heightChange; double xMax = xMin+selectedAreaWidth+(2*widthChange); double yMax = yMin+selectedAreaHeight+(2*heightChange); Point2D.Double p1 = new Point2D.Double(); if (STC.isWorldcoord()) osmm.getOrig(xMin,yMin,p1); else p1.setLocation(xMin, yMin); Point2D.Double p2 = new Point2D.Double(); if (STC.isWorldcoord()) osmm.getOrig(xMax,yMax,p2); else p2.setLocation(xMax, yMax); // set the new X,Y limit/filter according to the selection in the 2D-view STC.setMinXlimit(p1.getX()); STC.setMinYlimit(p1.getY()); STC.setMaxXlimit(p2.getX()); STC.setMaxYlimit(p2.getY()); } /* * Java3D's basis for dimensioning/positioning/etc. of objects is the canvas width. * That's why the eye's position needs to be related to the canvas width. */ private void computeReferenceView() { double cHeight = canvas.getHeight(); double cWidth = canvas.getWidth(); if (cHeight > cWidth) factorCanvas = cHeight/cWidth; else factorCanvas = cWidth/cHeight; double distance = 0; // following computation is based on test/trial data if (factorCanvas > 1.32) { double inc = (factorCanvas-1.32)/0.06; distance = 0.1*inc; } else distance = 0.01; referenceView[1] = -distance; } /* * Class holding all filter values to make "back"-button work multiple times. */ private class LastLimits { private double minXlimit, maxXlimit, minYlimit, maxYlimit; private long minZlimit, maxZlimit; public LastLimits(double minX ,double maxX, double minY, double maxY, long minZ, long maxZ) { minXlimit = minX; maxXlimit = maxX; minYlimit = minY; maxYlimit = maxY; minZlimit = minZ; maxZlimit = maxZ; } public double getMinXlimit() { return minXlimit; } public double getMaxXlimit() { return maxXlimit; } public double getMinYlimit() { return minYlimit; } public double getMaxYlimit() { return maxYlimit; } public long getMinZlimit() { return minZlimit; } public long getMaxZlimit() { return maxZlimit; } } }