public void setFieldLineManager(FieldLineManager mgr) {
   if (mgr != null) {
     manager = mgr;
     flSlider.addRoute(manager, "symmetryCount");
     manager.setSymmetryCount(((Integer) flSlider.getValue()).intValue());
     manager.setColorMode(perVertexColor ? FieldLine.COLOR_VERTEX : FieldLine.COLOR_VERTEX_FLAT);
     setFLControlsVisible(true);
     mElements.add(manager);
     if ((fWork != null) && (fWork instanceof TFramework)) {
       ((TFramework) fWork).addTElement(manager, false);
     }
   } else {
     setFLControlsVisible(false);
   }
 }
 public void propertyChange(PropertyChangeEvent pce) {
   if (pce.getSource() == colorModeCB) {
     String pn = pce.getPropertyName();
     if (pn.compareTo("value") == 0) {
       boolean state = ((Boolean) pce.getNewValue()).booleanValue();
       manager.setColorMode(state);
     }
   }
 }
  public GaussLawMagDipoleDisk() {
    super();

    // INITIALIZATION OF OBJECTS AND PARAMETERS //

    title = "Gauss's Law For A Magnetic Dipole and a Disk";
    setID(title);

    // change some features of the lighting, background color, etc., from the default values, if
    // desired
    setBackgroundColor(new Color(180, 180, 180));

    ///// Set properties on the SimEngine /////
    // Bounding area represents the characteristic size (physical extent) of the simulation space.
    theEngine.setBoundingArea(new BoundingSphere(new Point3d(), 6));
    // setDeltaTime() sets the time step of the simulation.
    theEngine.setDeltaTime(deltaTime);
    // setDamping() sets the generalized, velocity-based damping on the system.
    theEngine.setDamping(0.);
    //    theEngine.setGravity(new Vector3d(0.,0.,0.));

    // create the Disk using teal.render.geometry and add to the scene
    posDisk = new Vector3d(0., 0., 0);
    ShapeNodeDisk.setGeometry(Cylinder.makeGeometry(32, radiusDisk, heightDisk));
    ShapeNodeDisk.setTransparency(0.5f);
    Disk.setNode3D(ShapeNodeDisk);
    Disk.setColor(new Color(170, 170, 0));
    Disk.setPosition(posDisk);
    Disk.setDirection(new Vector3d(0., 1., 0.));
    Disk.setDrawn(true);
    addElement(Disk);

    ///// Initialization of the MagneticDipole /////
    // MagneticDipole constructor.
    mag = new MagneticDipole();
    // setMu() sets the strength of the MagneticDipole.
    mag.setMu(1.0);
    // setPosition() sets the position of the MagneticDipole.
    mag.setPosition(new Vector3d(0., 0., 0.));
    // setDirection() sets the direction (orientation) of the MagneticDipole.
    mag.setDirection(new Vector3d(0, -1., 0));
    // setPickable() determines whether or not this object will be pickable in the Viewer with the
    // mouse.
    // Setting an object's pickable property to TRUE is a prerequisite for being able to interact
    // with it
    // using the mouse.
    mag.setPickable(false);
    // setRotable() determines whether or not this object is free to rotate.  In this case, we want
    // the MagneticDipole
    // to be aligned with the y-axis.
    mag.setRotable(false);
    // setMoveable() determines whether or not this object is free to move (translate).  In this
    // case, we want
    // the MagneticDipole fixed at the origin.
    mag.setMoveable(false);
    // setLength() sets the length of the MagneticDipole.  For a MagneticDipole, length has no
    // physical
    // significance, and is merely a property of it's rendered model (for an LineMagneticDipole, on
    // the
    // other hand, setLength() does have physical significance).
    mag.setLength(0.75);
    // The following two properties are associated with computations required to calculate the
    // induced current
    // in a RingOfCurrent from this MagneticDipole.
    //	mag.setAvoidSingularity(true);
    //	mag.setAvoidSingularityScale(1.);
    mag.setIntegrating(false);

    //  create the magnetic field and normal vectors on the top of the disk
    theFieldDiskTop = new FieldVector[numAziTopDisk][numRadDisk];
    theNormalDiskTop = new GeneralVector[numAziTopDisk][numRadDisk];

    for (int j = 0; j < numRadDisk; j++) {
      for (int i = 0; i < numAziTopDisk; i++) {
        theFieldDiskTop[i][j] = new FieldVector();
        theFieldDiskTop[i][j].setFieldType(1);
        theFieldDiskTop[i][j].setPosition(new Vector3d(0, 0, 0));
        theFieldDiskTop[i][j].setColor(Teal.DefaultBFieldColor);
        theFieldDiskTop[i][j].setArrowScale(arrowScale);
        theFieldDiskTop[i][j].setDrawn(true);
        addElement(theFieldDiskTop[i][j]);

        theNormalDiskTop[i][j] = new GeneralVector();
        theNormalDiskTop[i][j].setPosition(new Vector3d(0, 0, 0));
        theNormalDiskTop[i][j].setColor(Color.gray);
        theNormalDiskTop[i][j].setArrowScale(arrowScale);
        theNormalDiskTop[i][j].setDrawn(true);
        addElement(theNormalDiskTop[i][j]);
      }
    }

    ///// Initializing Imported Models /////
    // The following block loads external models built in 3ds max and/or extra geometry not
    // associated with any
    // simulation objects.
    /////
    if (useModels) {

      // Generate a Rendered object to hold the first model, load the model, and transform it
      // appropriately.
      // This will be the wooden base holding the magnet.
      modelBase = new Rendered();
      TNode3D node =
          new Loader3DS().getTNode3D(URLGenerator.getResource("models/Main_Base_at_Zero.3DS"));
      node.setScale(metricScale);
      modelBase.setNode3D(node);
      modelBase.setPosition(new Vector3d(0., -2.45, 0.));
      addElement(modelBase);

      // Here we load an external model and set it to be the model used by the RingOfCurrent.
      // This is a model of a coil of wire that replaces the generic "torus" that is used as the
      // model by default.

      // Here we create a Rendered object to hold a disk that we generate internally.
      // This will be the wooden disk that the magnet rests on.
      modelMagBase = new Rendered();
      TShapeNode cylN = (TShapeNode) new ShapeNode();
      cylN.setGeometry(Cylinder.makeGeometry(16, 0.3, 2.0));
      modelMagBase.setNode3D(cylN);
      modelMagBase.setColor(new Color(160, 140, 110));
      modelMagBase.setPosition(new Vector3d(0, -1.30, 0));
      addElement(modelMagBase);

      // Here we load an external model and set it to be the model used by the MagneticDipole.
      // This is a model of a magnet (a silver chamfered disk) that replaces the generic disk used
      // by default.
      TNode3D node3 =
          new Loader3DS().getTNode3D(URLGenerator.getResource("models/Magnet_At_Zero.3DS"));
      node3.setScale(metricScale);
      mag.setNode3D(node3);
      mag.setModelOffsetPosition(new Vector3d(0., -0.5, 0.));
    }

    addElement(mag);

    ///// END INITIALIZATION OF SIMULATION OBJECTS AND PARAMETERS /////

    // INITIALIZATION OF FIELD VISUALIZATION ELEMENTS //

    // In this section we create and initialize field visualization elements such as fieldlines,
    // vector field grids, and DLIC
    // generators.  These elements will be added to the simulation by way of the GUI, which also
    // creates controls for
    // interacting with them.

    // Here we create a FieldDirectionGrid, which is a vector field grid represented in the Viewer
    // as a grid of arrows
    // that point in the direction of their local field.
    // FieldDirectionGrid constructor.
    fv = new FieldDirectionGrid();
    // setType() sets the type of field (electric, magnetic, etc.) that this vector field grid
    // should measure.
    fv.setType(Field.B_FIELD);

    // Here we add fieldlines to the simulation, which are often associated with specific simulation
    // objects.
    // First, we create a FieldLineManager, which manages groups of FieldLines.
    // FieldLineManager constructor.
    fmanager = new FieldLineManager();
    // setSymmetryCount() determines the symmetry of the fieldlines.  If the field in question is
    // symmetric about a
    // given axis, we can save an enormous amount of calculation time by calculating ONE FieldLine,
    // and then transforming
    // it several times around the axis of symmetry for a three dimensional representation.  In this
    // case, we set the
    // default symmetry count to 40.  This means that each FieldLine will be transformed and rotated
    // 40 times around
    // the axis of symmetry (the default axis of symmetry is the y-axis).
    fmanager.setSymmetryCount(40);
    fmanager.setID("fieldLineManager test name");
    // setElementManager() this associates the FieldLineManager with this simulation.  This is
    // necessary for the
    // FieldLineManager to be able to add it it's FieldLines to the simulation.
    fmanager.setElementManager(this);
    // Here we create two FluxFieldLines and add them to the manager.  See FluxFieldLine/FieldLine
    // documentation for
    // details on how FluxFieldLines work.

    // Here we create several more FluxFieldLines and add them to the manager.  The first one below
    // represents a
    // FieldLine with a very small arclength, so we need to make some slight adjustments to it's
    // default parameters.
    // FluxFieldLine constructor
    FluxFieldLine fl = new FluxFieldLine(15.0, mag, true, false);
    // setSArc() sets the individual step size of the FieldLine.  In this case, since we know the
    // arclength will be small,
    // we want a smaller than usual step size.
    fl.setSArc(0.1);
    // setKMax() sets the maximum number of steps taken along the FieldLine.  Since we have used a
    // step size that is
    // roughly one half the default, we increase the number of steps slightly to compensate, and to
    // make sure the line
    // is long enough at all times during the simulation.
    fl.setKMax(400);
    // setMinDistance() see FieldLine for details.  This sets the minimum distance from it's
    // starting point that the
    // FieldLine will terminate.  This is primarily used to terminate FieldLines "closed" FieldLines
    // that loop back
    // around on to themselves.
    fl.setMinDistance(maxDist);
    fmanager.addFieldLine(fl);
    fmanager.addFieldLine(new FluxFieldLine(25.0, mag, true, false));
    fmanager.addFieldLine(new FluxFieldLine(100.0, mag, true, false));

    // Here we set a few more properties of the FieldLines by way of the FieldLineManager.
    // setIntegrationMode() sets the integration mode used to calculate the FieldLines.  Options are
    // currently EULER or
    // RUNGE_KUTTA.
    fmanager.setIntegrationMode(FieldLine.RUNGE_KUTTA);
    // setColorMode() sets method by which the FieldLines are colored.  Currently there are
    // effectively two modes, one
    // which colors the FieldLine by vertex, and one that gives them a flat color at all points.
    // COLOR_VERTEX is the
    // by-vertex method, where the color at each vertex is determined by the magnitude of the field
    // at that point.
    fmanager.setColorMode(FieldLine.COLOR_VERTEX);
    // setColorScale() determines the rate of interpolation of colors in the COLOR_VERTEX coloring
    // mode.
    fmanager.setColorScale(0.01);

    // GUI SETUP & INITIALIZATION //

    // At this point we should add the GUI elements necessary to control our simulation.  These can
    // be buttons,
    // sliders, checkboxes, etc..  Such GUI elements are first created and initialized, and then
    // added to Groups
    // that function as "sub-windows" on the GUI panel.

    // Here we create a ControlGroup that will contain the sliders we created to control specific
    // parameters of the
    // simulation.
    // ControlGroup constructor.
    ControlGroup controls = new ControlGroup();
    // setText() sets the text label of this Group.
    controls.setText("Parameters");
    // add() adds a created GUI element (slider, etc.) to this Group.

    // addElement() adds the Group to the application.
    addElement(controls);

    // Here we create a VisualizationControl Group.  This Group automatically creates controls for
    // manipulating the
    // visualization elements we created above.
    // VisualizationControl constructor.
    visControl = new VisualizationControl();
    // setFieldLineManager() sets the FieldLineManager associated with this Group.  This is the
    // manger we created above.
    visControl.setFieldLineManager(fmanager);
    // setFieldVisGrid sets the FieldDirectionGrid associated with this Group.  This is the grid we
    // created above.
    //	visControl.setFieldVisGrid(fv);
    // setFieldConvolution() sets the FieldConvolution associated with this Group.  This is the
    // convolution we created above.
    //	visControl.setFieldConvolution(mDLIC);
    // setConvolutionModes() sets the types of convolutions we want to access from this generator.
    // In this case we
    // want to be able to generate magnetic field images (DLIC_FLAG_B) and magnetic potential images
    // (DLIC_FLAG_BP).
    //		visControl.setConvolutionModes(DLIC.DLIC_FLAG_B | DLIC.DLIC_FLAG_BP);
    // addElement() adds the VisualizationControl Group to the application.
    addElement(visControl);

    // Here we create a graph based on simulation data, and add it to the GUI.  This involves
    // creating a graph,
    // adding a "plot" to it (which defines the quantities being plotted), and adding it to the GUI
    // in it's own
    // Group.
    // Graph constructor.
    flux_graph = new Graph();
    // setSize() sets the size of the graph, in pixels.
    flux_graph.setSize(150, 250);
    // setXRange() sets the x-axis range of the graph.
    flux_graph.setXRange(0., 2.);
    // setYRange() sets the y-axis range of the graph.
    flux_graph.setYRange(-3., 3.);
    // setWrap() determines whether the graph should wrap around to the left side once the plot
    // exceeds the width of
    // the graph.
    flux_graph.setWrap(true);
    // setClearOnWrap() determines whether the graph should clear itself before wrapping.  If this
    // is set to false,
    // new data will be plotted on top of old data.
    flux_graph.setClearOnWrap(true);
    // setXLabel() sets the text label of the x-axis.
    flux_graph.setXLabel("Time");
    // setYLabel() sets the text label of the y-axis.
    flux_graph.setYLabel("Flux");
    // Here we create the PlotItem being drawn by this graph.  This defines the properties being
    // plotted. In this case
    // we want to plot flux through disk versus time, so we use a FluxThroughDiskDueToDipolePlot
    // written for this purpose.
    // FluxThroughDiskDueToDipolePlot constructor.
    flux_plot = new FluxThroughDiskDueToDipolePlot();
    // setRing() --The FluxThroughDiskDueToDipolePlot assumes the flux being plotted is due to the
    // dipole.  This sets the
    // dipole from which to retrieve flux data.
    flux_plot.setMagneticDipole(mag);
    flux_plot.setShapeNode(ShapeNodeDisk);
    // setTimeAutoscale() determines whether the graph should dynamically rescale the independent
    // axis (time) to fit
    // more data.  This is the alternative to enabling "wrapping".
    flux_plot.setRadiusDisk(radiusDisk);
    flux_plot.setTimeAutoscale(false);
    // setCurrentAutoscale() determines whether the graph should dynamically rescale the dependent
    // axis (current) to
    // fit more data.
    flux_plot.setFluxAutoscale(false);
    // addPlotItem() adds the supplied PlotItem to the graph.
    flux_graph.addPlotItem(flux_plot);

    // Here we create a new Group for the graph, and add the graph to that Group.
    ControlGroup graphPanel = new ControlGroup();
    graphPanel.setText("Graphs");
    graphPanel.addElement(flux_graph);
    addElement(graphPanel);

    // Here we set some parameters on the Viewer.
    // setFogEnabled() determines whether fog should be enabled in the Viewer.  Setting this here,
    // on the Viewer,
    // overrides any settings on the specific objects above.
    theScene.setFogEnabled(true);
    // setFogTransformFrontScale() sets distance in FRONT of the camera target at which to start fog
    // interpolation.
    theScene.setFogTransformFrontScale(0.0);
    // setFogTransformBackScale() sets the distance BEHIND the camera target at which to end fog
    // interpolation.
    // Positions beyond this point are "fully fogged".
    theScene.setFogTransformBackScale(0.35);
    // addActions() adds some GUI elements as described in the addActions() method below.
    addActions();
    // mSEC.init() initializes the Simulation Model Controls.  These are the controls for the
    // simulation itself
    // (ie. play, pause, stop, rewind, etc.)
    mSEC.init();
    // resetCamera() resets the transform of the camera to the transfrom described by the
    // resetCamera() method below.
    resetCamera();
    // reset() resets simulation parameters to the values described in the reset() method below.
    reset();

    // initFogTransform() must be called after setting the fog parameters, if they are different
    // than the the defaults.
    // mViewer.initFogTransform();

    // create the two sliders for the disk position
    posSlider_x.setText("X Position");
    posSlider_x.setMinimum(-5.);
    posSlider_x.setMaximum(5.0);
    posSlider_x.setPaintTicks(true);
    posSlider_x.addPropertyChangeListener("value", this);
    posSlider_x.setValue(0.);
    posSlider_x.setVisible(true);

    posSlider_y.setText("Y Position ");
    posSlider_y.setMinimum(-5.);
    posSlider_y.setMaximum(5.0);
    posSlider_y.setPaintTicks(true);
    posSlider_y.addPropertyChangeListener("value", this);
    posSlider_y.setValue(3.);
    posSlider_y.setVisible(true);

    // create the angle orientation slider for the disk, where angle is the angle from the x axis
    angDisk.setText("Rotation Angle");
    angDisk.setMinimum(-180.);
    angDisk.setMaximum(180.0);
    angDisk.setPaintTicks(true);
    angDisk.addPropertyChangeListener("value", this);
    angDisk.setValue(90.);
    angDisk.setVisible(true);

    // create the radius slider for the disk
    radDisk.setText("Radius of Disk");
    radDisk.setMinimum(1.);
    radDisk.setMaximum(6.);
    radDisk.setPaintTicks(true);
    radDisk.addPropertyChangeListener("value", this);
    radDisk.setValue(1.);
    radDisk.setVisible(true);

    // add the sliders to the control group and add the control group to the scene
    ControlGroup controls1 = new ControlGroup();
    controls1.setText("Disk Position Radius & Orientation");
    controls1.add(posSlider_y);
    controls1.add(posSlider_x);
    controls1.add(angDisk);
    controls1.add(radDisk);
    addElement(controls1);

    PlaceBNVectors();

    // set initial state

    theEngine.requestRefresh();
    mSEC.setVisible(true);
    reset();
    resetCamera();
  } // end of GaussLawMagDipoleDisk
  public void actionPerformed(ActionEvent evt) {
    if (evt.getSource() == showLinesCB) {
      setLinesEnabled(showLinesCB.isSelected());

    } else if (evt.getSource() == showFVisCB) {
      setFVEnabled(showFVisCB.isSelected());

    } else if (evt.getSource() == colorModeCB) {
      perVertexColor = colorModeCB.isSelected();
      manager.setColorMode(
          colorModeCB.isSelected() ? FieldLine.COLOR_VERTEX : FieldLine.COLOR_VERTEX_FLAT);

    } else {
      int cmd = Integer.parseInt(evt.getActionCommand());
      if (fconvolution != null) {
        Cursor cr = null;
        if (fWork instanceof TFramework) {
          cr = ((TFramework) fWork).getAppCursor();
          ((TFramework) fWork).setAppCursor(new Cursor(Cursor.WAIT_CURSOR));
        }
        Thread.yield();
        TSimEngine model = fconvolution.getSimEngine();
        if (model != null) {
          TEngineControl smc = model.getEngineControl();
          if (smc.getSimState() == TEngineControl.RUNNING) {
            smc.stop();
            model.refresh();
            Thread.yield();
          }

          switch (cmd) {
            case DLIC.DLIC_FLAG_E:
              //                            fconvolution.setField(((EMEngine)model).getEField());
              fconvolution.setField(model.getElementByType(EField.class));
              fconvolution.generateFieldImage();
              break;
            case DLIC.DLIC_FLAG_B:
              //                            fconvolution.setField(((EMEngine)model).getBField());
              fconvolution.setField(model.getElementByType(BField.class));
              fconvolution.generateFieldImage();
              break;
            case DLIC.DLIC_FLAG_G:
              //                            fconvolution.setField(((EMEngine)model).getGField());
              fconvolution.setField(model.getElementByType(GField.class));
              fconvolution.generateFieldImage();
              break;
            case DLIC.DLIC_FLAG_P:
              //                            fconvolution.setField(((EMEngine)model).getPField());
              fconvolution.setField(model.getElementByType(PField.class));
              fconvolution.generateFieldImage();
              break;
            case DLIC.DLIC_FLAG_EP:
              //                            fconvolution.setField(new
              // Potential(((EMEngine)model).getEField()));
              fconvolution.setField(new Potential(model.getElementByType(EField.class)));
              fconvolution.generateFieldImage();
              break;
            case DLIC.DLIC_FLAG_BP:
              //                            fconvolution.setField(new
              // Potential(((EMEngine)model).getBField()));
              fconvolution.setField(new Potential(model.getElementByType(BField.class)));
              fconvolution.generateFieldImage();
              break;
            case DLIC.DLIC_FLAG_EF:
              //                            fconvolution.setField(((EMEngine)model).getEField());
              fconvolution.setField(model.getElementByType(EField.class));
              fconvolution.generateColorMappedFluxImage();
              break;
            case DLIC.DLIC_FLAG_BF:
              //                            fconvolution.setField(((EMEngine)model).getBField());
              fconvolution.setField(model.getElementByType(BField.class));
              fconvolution.generateColorMappedFluxImage();
              break;
            default:
              break;
          }
          fconvolution.getImage();
        } else {
          TDebug.println(0, "DLIC model is null");
        }
        if (fWork instanceof TFramework) {
          ((TFramework) fWork).setAppCursor(cr);
        }
      }
    }
  }
 protected void setLinesEnabled(boolean state) {
   flSlider.setEnabled(state);
   colorModeCB.setEnabled(state);
   manager.setDrawn(state);
 }
 public void setColorPerVertex(boolean state) {
   colorModeCB.setSelected(state);
   if (manager != null) {
     manager.setColorMode(state);
   }
 }