@Override
  public void redraw() {
    setupCSS(svgp);
    final StyleLibrary style = context.getStyleResult().getStyleLibrary();
    double dotsize = style.getLineWidth(StyleLibrary.PLOT);

    for (DBIDIter id = sample.getSample().iter(); id.valid(); id.advance()) {
      double[] v = proj.fastProjectDataToRenderSpace(rel.get(id));
      if (v[0] != v[0] || v[1] != v[1]) {
        continue; // NaN!
      }
      Element tooltip = makeTooltip(id, v[0], v[1], dotsize);
      SVGUtil.addCSSClass(tooltip, TOOLTIP_HIDDEN);

      // sensitive area.
      Element area = svgp.svgRect(v[0] - dotsize, v[1] - dotsize, 2 * dotsize, 2 * dotsize);
      SVGUtil.addCSSClass(area, TOOLTIP_AREA);

      EventTarget targ = (EventTarget) area;
      targ.addEventListener(SVGConstants.SVG_MOUSEOVER_EVENT_TYPE, hoverer, false);
      targ.addEventListener(SVGConstants.SVG_MOUSEOUT_EVENT_TYPE, hoverer, false);
      targ.addEventListener(SVGConstants.SVG_CLICK_EVENT_TYPE, hoverer, false);

      // NOTE: do not change the sequence in which these are inserted!
      layer.appendChild(area);
      layer.appendChild(tooltip);
    }
  }
    @Override
    public void fullRedraw() {
      setupCanvas();
      final StyleLibrary style = context.getStyleLibrary();
      CSSClass css = new CSSClass(svgp, POLYS);
      // TODO: separate fill and line colors?
      css.setStatement(
          SVGConstants.CSS_STROKE_WIDTH_PROPERTY, style.getLineWidth(StyleLibrary.POLYGONS));
      css.setStatement(SVGConstants.CSS_STROKE_PROPERTY, style.getColor(StyleLibrary.POLYGONS));
      css.setStatement(SVGConstants.CSS_FILL_PROPERTY, SVGConstants.CSS_NONE_VALUE);
      svgp.addCSSClassOrLogError(css);
      svgp.updateStyleElement();

      // draw data
      for (DBIDIter iditer = rep.iterDBIDs(); iditer.valid(); iditer.advance()) {
        try {
          PolygonsObject poly = rep.get(iditer);
          if (poly == null) {
            continue;
          }
          SVGPath path = new SVGPath();
          for (Polygon ppoly : poly.getPolygons()) {
            Vector first = ppoly.get(0);
            double[] f = proj.fastProjectDataToRenderSpace(first.getArrayRef());
            path.moveTo(f[0], f[1]);
            for (ArrayListIter<Vector> it = ppoly.iter(); it.valid(); it.advance()) {
              if (it.getOffset() == 0) {
                continue;
              }
              double[] p = proj.fastProjectDataToRenderSpace(it.get().getArrayRef());
              path.drawTo(p[0], p[1]);
            }
            // close path.
            path.drawTo(f[0], f[1]);
          }
          Element e = path.makeElement(svgp);
          SVGUtil.addCSSClass(e, POLYS);
          layer.appendChild(e);
        } catch (ObjectNotFoundException e) {
          // ignore.
        }
      }
    }
 /** Adds the required CSS-Classes */
 private void addCSSClasses() {
   // Class for the epsilon-value
   final StyleLibrary style = context.getStyleLibrary();
   if (!svgp.getCSSClassManager().contains(CSS_EPSILON)) {
     final CSSClass label = new CSSClass(svgp, CSS_EPSILON);
     label.setStatement(
         SVGConstants.CSS_FILL_PROPERTY, style.getTextColor(StyleLibrary.AXIS_LABEL));
     label.setStatement(
         SVGConstants.CSS_FONT_FAMILY_PROPERTY, style.getFontFamily(StyleLibrary.AXIS_LABEL));
     label.setStatement(
         SVGConstants.CSS_FONT_SIZE_PROPERTY, style.getTextSize(StyleLibrary.AXIS_LABEL));
     svgp.addCSSClassOrLogError(label);
   }
   // Class for the epsilon cut line
   if (!svgp.getCSSClassManager().contains(CSS_LINE)) {
     final CSSClass lcls = new CSSClass(svgp, CSS_LINE);
     lcls.setStatement(SVGConstants.CSS_STROKE_PROPERTY, style.getColor(StyleLibrary.PLOT));
     lcls.setStatement(
         SVGConstants.CSS_STROKE_WIDTH_PROPERTY, 0.5 * style.getLineWidth(StyleLibrary.PLOT));
     svgp.addCSSClassOrLogError(lcls);
   }
 }