private void updateEdges(HierarchicalGraph graph) {
    Modeler edgeInit = engine.getModelClasses()[AbstractEngine.CLASS_EDGE].getCurrentModeler();
    Modeler arrowInit = engine.getModelClasses()[AbstractEngine.CLASS_ARROW].getCurrentModeler();

    EdgeIterable edgeIterable;
    edgeIterable = graph.getEdges();

    float minWeight = Float.POSITIVE_INFINITY;
    float maxWeight = Float.NEGATIVE_INFINITY;

    TimeInterval timeInterval = DynamicUtilities.getVisibleInterval(dynamicModel);

    for (Edge edge : edgeIterable) {
      if (edge.getSource().getNodeData().getModel() == null
          || edge.getTarget().getNodeData().getModel() == null) {
        continue;
      }
      float weight = 1f;
      if (timeInterval == null) {
        weight = edge.getWeight();
      } else {
        weight = edge.getWeight(timeInterval.getLow(), timeInterval.getHigh());
      }
      minWeight = Math.min(minWeight, weight);
      maxWeight = Math.max(maxWeight, weight);
      Edge2dModel obj = (Edge2dModel) edge.getEdgeData().getModel();
      if (obj == null) {
        // Model is null, ADD
        obj = (Edge2dModel) edgeInit.initModel(edge.getEdgeData());
        engine.addObject(AbstractEngine.CLASS_EDGE, obj);
        if (!undirected && vizConfig.isShowArrows() && !edge.isSelfLoop()) {
          Arrow2dModel arrowObj = (Arrow2dModel) arrowInit.initModel(edge.getEdgeData());
          engine.addObject(AbstractEngine.CLASS_ARROW, arrowObj);
          arrowObj.setCacheMarker(cacheMarker);
          arrowObj.setWeight(weight);
          obj.setArrow(arrowObj);
        }
      } else if (!obj.isValid()) {
        engine.addObject(AbstractEngine.CLASS_EDGE, obj);
        if (!undirected && vizConfig.isShowArrows() && !edge.isSelfLoop()) {
          Arrow2dModel arrowObj = obj.getArrow();
          engine.addObject(AbstractEngine.CLASS_ARROW, arrowObj);
          arrowObj.setCacheMarker(cacheMarker);
          arrowObj.setWeight(weight);
        }
      } else {
        if (!undirected && vizConfig.isShowArrows() && !edge.isSelfLoop() && edge.isDirected()) {
          Arrow2dModel arrowObj = obj.getArrow();
          arrowObj.setCacheMarker(cacheMarker);
          arrowObj.setWeight(weight);
        }
      }
      obj.setWeight(weight);
      obj.setCacheMarker(cacheMarker);
    }

    limits.setMinWeight(minWeight);
    limits.setMaxWeight(maxWeight);
  }
 private void resetClasses() {
   for (ModelClass objClass : engine.getModelClasses()) {
     if (objClass.isEnabled()) {
       engine.resetObjectClass(objClass);
     }
   }
 }
  private void updateNodes(HierarchicalGraph graph) {
    Modeler nodeInit = engine.getModelClasses()[AbstractEngine.CLASS_NODE].getCurrentModeler();

    NodeIterable nodeIterable;
    nodeIterable = graph.getNodes();

    for (Node node : nodeIterable) {

      Model obj = node.getNodeData().getModel();
      if (obj == null) {
        // Model is null, ADD
        obj = nodeInit.initModel(node.getNodeData());
        engine.addObject(AbstractEngine.CLASS_NODE, (ModelImpl) obj);
      } else if (!obj.isValid()) {
        engine.addObject(AbstractEngine.CLASS_NODE, (ModelImpl) obj);
      }
      obj.setCacheMarker(cacheMarker);

      // Modeaction
      if (modeManager.getMode().equals(ModeManager.AVAILABLE_MODES.HIGHLIGHT)) {
        ModelImpl impl = (ModelImpl) obj;
        //                if (!node.isVisible()) {
        //                    ColorLayer.layerColor(impl, 0.8f, 0.8f, 0.8f);
        //                }
      }
    }
  }
  public void updatePotatoes(HierarchicalGraph graph) {

    ModelClass potatoClass = engine.getModelClasses()[AbstractEngine.CLASS_POTATO];
    if (potatoClass.isEnabled()) {
      Modeler potInit = engine.getModelClasses()[AbstractEngine.CLASS_POTATO].getCurrentModeler();

      List<ModelImpl> hulls = new ArrayList<ModelImpl>();
      Node[] nodes = graph.getNodes().toArray();
      for (Node n : nodes) {
        Node parent = graph.getParent(n);
        if (parent != null) {
          Group group = (Group) parent;
          Model hullModel = group.getGroupData().getHullModel();
          if (hullModel != null && hullModel.isCacheMatching(cacheMarker)) {
            ConvexHull hull = (ConvexHull) hullModel.getObj();
            hull.addNode(n);
            hull.setModel(hullModel);
          } else if (hullModel != null) {
            // Its not the first time the hull exist
            ConvexHullModel model = (ConvexHullModel) hullModel;
            model.setScale(1f);
            hullModel.setCacheMarker(cacheMarker);
            hulls.add((ModelImpl) hullModel);
          } else {
            ConvexHull ch = new ConvexHull();
            ch.setMetaNode(parent);
            ch.addNode(n);
            ModelImpl obj = potInit.initModel(ch);
            group.getGroupData().setHullModel(obj);
            obj.setCacheMarker(cacheMarker);
            hulls.add(obj);
          }
        }
      }
      for (ModelImpl im : hulls) {
        ConvexHull hull = (ConvexHull) im.getObj();
        hull.recompute();
        engine.addObject(AbstractEngine.CLASS_POTATO, im);
      }
    }
  }
  public void updateWorld() {
    // System.out.println("update world");
    cacheMarker++;

    GraphModel graphModel = controller.getModel();
    if (graphModel == null) {
      engine.worldUpdated(cacheMarker);
      return;
    }
    if (gm != null && gm != graphModel) {
      reset();
    }
    gm = graphModel;
    HierarchicalGraph graph;
    if (graphModel.isDirected()) {
      undirected = false;
      graph = graphModel.getHierarchicalDirectedGraphVisible();
    } else if (graphModel.isUndirected()) {
      undirected = true;
      graph = graphModel.getHierarchicalUndirectedGraphVisible();
    } else if (graphModel.isMixed()) {
      undirected = false;
      graph = graphModel.getHierarchicalMixedGraphVisible();
    } else {
      undirected = false;
      graph = graphModel.getHierarchicalDirectedGraphVisible();
    }

    if (dynamicModel == null) {
      DynamicController dynamicController = Lookup.getDefault().lookup(DynamicController.class);
      dynamicModel = dynamicController.getModel();
    }

    graphView = graph.getView().getViewId();

    ModelClass[] object3dClasses = engine.getModelClasses();

    graph.readLock();

    ModelClass nodeClass = object3dClasses[AbstractEngine.CLASS_NODE];
    if (nodeClass.isEnabled()
        && (graph.getNodeVersion() > nodeVersion || modeManager.requireModeChange())) {
      updateNodes(graph);
      nodeClass.setCacheMarker(cacheMarker);
    }

    ModelClass edgeClass = object3dClasses[AbstractEngine.CLASS_EDGE];
    if (edgeClass.isEnabled()
        && (graph.getEdgeVersion() > edgeVersion || modeManager.requireModeChange())) {
      updateEdges(graph);
      updateMetaEdges(graph);
      edgeClass.setCacheMarker(cacheMarker);
      if (!undirected && vizConfig.isShowArrows()) {
        object3dClasses[AbstractEngine.CLASS_ARROW].setCacheMarker(cacheMarker);
      }
    }

    ModelClass potatoClass = object3dClasses[AbstractEngine.CLASS_POTATO];
    if (potatoClass.isEnabled()
        && (graph.getNodeVersion() > nodeVersion || modeManager.requireModeChange())) {
      updatePotatoes(graph);
      potatoClass.setCacheMarker(cacheMarker);
    }

    nodeVersion = graph.getNodeVersion();
    edgeVersion = graph.getEdgeVersion();

    graph.readUnlock();

    engine.worldUpdated(cacheMarker);
  }