@Override
  protected void updateOutput(int newBottomPointsLength, GeoPointND[] bottomPoints) {

    // current length of top points
    int nOld = outputPoints.size() + getShift();

    if (newBottomPointsLength > nOld) {

      int length = newBottomPointsLength - nOld;
      outputPoints.augmentOutputSize(length);
      outputPoints.setLabels(null);

      updateOutputPoints();

      // new sides of the prism
      int l = nOld + length;
      for (int i = nOld; i < l; i++) {
        polyhedron.startNewFace();
        polyhedron.addPointToCurrentFace(bottomPoints[i]);
        polyhedron.addPointToCurrentFace(bottomPoints[(i + 1) % l]);
        polyhedron.addPointToCurrentFace(getTopPoint((i + 1) % l));
        polyhedron.addPointToCurrentFace(getTopPoint(i));
        polyhedron.endCurrentFace();
        GeoPolygon3D polygon = polyhedron.createPolygon(i + 1); // i+1 due to top face
        outputPolygonsSide.addOutput(polygon, false);
        outputSegmentsSide.addOutput((GeoSegment3D) polygon.getSegments()[3], false);
        outputSegmentsTop.addOutput((GeoSegment3D) polygon.getSegments()[2], false);
      }
      outputSegmentsSide.setLabels(null);
      outputSegmentsTop.setLabels(null);

      refreshOutput();
    } else if (newBottomPointsLength < nOld) {

      for (int i = newBottomPointsLength; i < bottomPointsLength; i++) {
        outputPoints.getElement(i - getShift()).setUndefined();
      }

      updateOutputPoints();

      // update top side
      outputSegmentsTop
          .getElement(newBottomPointsLength - 1)
          .modifyInputPoints(getTopPoint(newBottomPointsLength - 1), getTopPoint());
      GeoPolygon polygon = getTopFace();
      GeoPointND[] p = new GeoPointND[newBottomPointsLength];
      p[0] = getTopPoint();
      for (int i = 0; i < newBottomPointsLength - 1; i++) p[1 + i] = getTopPoint(i + 1);
      // polygon.setPoints(p,null,false); //don't create segments
      polygon.modifyInputPoints(p);
      polygon.setSegments(outputSegmentsTop.getOutput(new GeoSegment3D[newBottomPointsLength]));
      polygon.calcArea();

      // update last side
      polygon = outputPolygonsSide.getElement(newBottomPointsLength - 1);
      p = new GeoPointND[4];
      p[0] = bottomPoints[newBottomPointsLength - 1];
      p[1] = bottomPoints[0];
      p[2] = getTopPoint();
      p[3] = getTopPoint(newBottomPointsLength - 1);
      polygon.setPoints(p, null, false); // don't create segments
      GeoSegmentND[] s = new GeoSegmentND[4];
      s[0] = getBottom().getSegments()[newBottomPointsLength];
      s[1] = outputSegmentsSide.getElement(newBottomPointsLength);
      s[2] = outputSegmentsTop.getElement(newBottomPointsLength);
      s[3] = outputSegmentsSide.getElement(newBottomPointsLength - 1);
      polygon.setSegments(s);
      polygon.calcArea();

    } else updateOutputPoints();

    if (bottomPointsLength < newBottomPointsLength) {

      // update top side
      updateTop(newBottomPointsLength);

      // update last sides
      for (int i = bottomPointsLength; i < newBottomPointsLength; i++) updateSide(i, bottomPoints);
    }

    bottomPointsLength = newBottomPointsLength;
  }
  public void createDefaultGeoElements() {
    super.createDefaultGeoElements();

    // angle
    GeoAngle3D angle = new GeoAngle3D(cons);
    angle.setVisualStyle(super.getDefaultGeo(DEFAULT_ANGLE));
    angle.setAngleStyle(GeoAngle.ANGLE_ISNOTREFLEX);
    defaultGeoElements.put(DEFAULT_ANGLE3D, angle);

    // free point
    GeoPoint3D freePoint = new GeoPoint3D(cons);
    freePoint.setPointSize(EuclidianStyleConstants.DEFAULT_POINT_SIZE);
    freePoint.setPointStyle(EuclidianStyleConstants.POINT_STYLE_DOT);
    freePoint.setLocalVariableLabel("Point3D" + strFree);
    freePoint.setObjColor(colPoint);
    // freePoint.setLabelOffset(5, -5);
    defaultGeoElements.put(DEFAULT_POINT3D_FREE, freePoint);

    // dependent point
    GeoPoint3D depPoint = new GeoPoint3D(cons);
    depPoint.setPointSize(EuclidianStyleConstants.DEFAULT_POINT_SIZE);
    depPoint.setPointStyle(EuclidianStyleConstants.POINT_STYLE_DOT);
    depPoint.setLocalVariableLabel("Point3D" + strDependent);
    depPoint.setObjColor(colDepPoint);
    // depPoint.setLabelOffset(5, -5);
    defaultGeoElements.put(DEFAULT_POINT3D_DEPENDENT, depPoint);

    // point on path
    GeoPoint3D pathPoint = new GeoPoint3D(cons);
    pathPoint.setPointSize(EuclidianStyleConstants.DEFAULT_POINT_SIZE);
    pathPoint.setPointStyle(EuclidianStyleConstants.POINT_STYLE_DOT);
    pathPoint.setLocalVariableLabel("Point3DOn");
    pathPoint.setObjColor(colPathPoint);
    // pathPoint.setLabelOffset(5, -5);
    defaultGeoElements.put(DEFAULT_POINT3D_ON_PATH, pathPoint);

    // point in region
    GeoPoint3D regionPoint = new GeoPoint3D(cons);
    regionPoint.setPointSize(EuclidianStyleConstants.DEFAULT_POINT_SIZE);
    regionPoint.setPointStyle(EuclidianStyleConstants.POINT_STYLE_DOT);
    regionPoint.setLocalVariableLabel("Point3DInRegion");
    regionPoint.setObjColor(colRegionPoint);
    // regionPoint.setLabelOffset(5, -5);
    defaultGeoElements.put(DEFAULT_POINT3D_IN_REGION, regionPoint);

    // line
    GeoLine3D line = new GeoLine3D(cons);
    // line.setLineType(EuclidianStyleConstants.LINE_TYPE_DASHED_LONG);
    line.setLocalVariableLabel("Line3D");
    defaultGeoElements.put(DEFAULT_LINE3D, line);

    // segment
    GeoSegment3D segment = new GeoSegment3D(cons);
    // segment.setLineType(EuclidianStyleConstants.LINE_TYPE_DASHED_LONG);
    segment.setLocalVariableLabel("Segment3D");
    defaultGeoElements.put(DEFAULT_SEGMENT3D, segment);

    // ray
    GeoRay3D ray = new GeoRay3D(cons);
    // ray.setLineType(EuclidianStyleConstants.LINE_TYPE_DASHED_LONG);
    ray.setLocalVariableLabel("Ray3D");
    defaultGeoElements.put(DEFAULT_RAY3D, ray);

    // line intersection
    GeoLine3D lineIntersection = new GeoLine3D(cons);
    // line.setLineType(EuclidianStyleConstants.LINE_TYPE_DASHED_LONG);
    lineIntersection.setLocalVariableLabel("Line3D" + strIntersection);
    lineIntersection.setObjColor(colIntersectionLine);
    defaultGeoElements.put(DEFAULT_LINE3D_INTERSECTION, lineIntersection);

    // segment intersection
    GeoSegment3D segmentIntersection = new GeoSegment3D(cons);
    // segment.setLineType(EuclidianStyleConstants.LINE_TYPE_DASHED_LONG);
    segmentIntersection.setLocalVariableLabel("Segment3D" + strIntersection);
    lineIntersection.setObjColor(colIntersectionLine);
    defaultGeoElements.put(DEFAULT_SEGMENT3D_INTERSECTION, segmentIntersection);

    // ray intersection
    GeoRay3D rayIntersection = new GeoRay3D(cons);
    // ray.setLineType(EuclidianStyleConstants.LINE_TYPE_DASHED_LONG);
    rayIntersection.setLocalVariableLabel("Ray3D" + strIntersection);
    lineIntersection.setObjColor(colIntersectionLine);
    defaultGeoElements.put(DEFAULT_RAY3D_INTERSECTION, rayIntersection);

    // axis
    GeoAxis3D axis = new GeoAxis3D(cons);
    // axis.setLineType(EuclidianStyleConstants.LINE_TYPE_DASHED_SHORT);
    axis.setLocalVariableLabel("Axis3D");
    defaultGeoElements.put(DEFAULT_AXIS3D, axis);

    // vector 3D
    GeoVector3D vector = new GeoVector3D(cons);
    // vector.setLineType(EuclidianStyleConstants.LINE_TYPE_DASHED_LONG);
    vector.setObjColor(colVector);
    vector.setLocalVariableLabel("Vector3D");
    defaultGeoElements.put(DEFAULT_VECTOR3D, vector);

    // conic
    GeoConic3D conic = new GeoConic3D(cons);
    conic.setLocalVariableLabel("Conic3D");
    // conic.setLineType(EuclidianStyleConstants.LINE_TYPE_DASHED_LONG);
    conic.setObjColor(colConic3D);
    defaultGeoElements.put(DEFAULT_CONIC3D, conic);

    // conic intersection
    GeoConic3D conicIntersection = new GeoConic3D(cons);
    conicIntersection.setLocalVariableLabel("Conic3D" + strIntersection);
    conicIntersection.setObjColor(colIntersectionCurve);
    defaultGeoElements.put(DEFAULT_CONIC3D_INTERSECTION, conicIntersection);

    // curve
    GeoCurveCartesian3D curve = new GeoCurveCartesian3D(cons);
    curve.setLocalVariableLabel("Curve3D");
    // curve.setLineType(EuclidianStyleConstants.LINE_TYPE_DASHED_LONG);
    curve.setObjColor(colCurveCartesian3D);
    defaultGeoElements.put(DEFAULT_CURVECARTESIAN3D, curve);

    // plane
    GeoPlane3D plane = new GeoPlane3D(cons);
    plane.setLocalVariableLabel("Plane3D");
    plane.setObjColor(colPlane3D);
    plane.setAlphaValue(DEFAULT_PLANE3D_ALPHA);
    plane.setLineThickness(DEFAULT_PLANE3D_GRID_THICKNESS);
    plane.setFading(DEFAULT_PLANE3D_FADING);
    // plane.setLineType(EuclidianStyleConstants.LINE_TYPE_DASHED_SHORT);
    defaultGeoElements.put(DEFAULT_PLANE3D, plane);

    // polygon
    GeoPolygon3D polygon = new GeoPolygon3D(cons, null, null, false);
    polygon.setLocalVariableLabel("Polygon3D");
    polygon.setObjColor(colPolygon3D);
    polygon.setAlphaValue(DEFAULT_POLYGON3D_ALPHA);
    defaultGeoElements.put(DEFAULT_POLYGON3D, polygon);

    // polyhedron
    GeoPolyhedron polyhedron = new GeoPolyhedron(cons);
    polyhedron.setLocalVariableLabel("Polyhedron");
    polyhedron.setObjColor(colPolyhedron);
    polyhedron.setAlphaValue(DEFAULT_POLYGON3D_ALPHA);
    defaultGeoElements.put(DEFAULT_POLYHEDRON, polyhedron);

    // quadric
    GeoQuadric3D quadric = new GeoQuadric3D(cons);
    quadric.setLocalVariableLabel("Quadric");
    quadric.setObjColor(colQuadric);
    quadric.setAlphaValue(DEFAULT_QUADRIC_ALPHA);
    defaultGeoElements.put(DEFAULT_QUADRIC, quadric);

    // limited quadric
    GeoQuadric3D limitedQuadric = new GeoQuadric3D(cons);
    limitedQuadric.setLocalVariableLabel("QuadricLimited");
    limitedQuadric.setObjColor(colPolyhedron);
    limitedQuadric.setAlphaValue(DEFAULT_QUADRIC_LIMITED_ALPHA);
    defaultGeoElements.put(DEFAULT_QUADRIC_LIMITED, limitedQuadric);

    // function n var
    GeoFunctionNVar function = new GeoFunctionNVar(cons);
    function.setLocalVariableLabel("function");
    function.setObjColor(colQuadric);
    function.setAlphaValue(DEFAULT_QUADRIC_ALPHA);
    defaultGeoElements.put(DEFAULT_FUNCTION_NVAR, function);

    // surface
    GeoSurfaceCartesian3D surface = new GeoSurfaceCartesian3D(cons);
    surface.setLocalVariableLabel("surface");
    surface.setObjColor(colQuadric);
    surface.setAlphaValue(DEFAULT_QUADRIC_ALPHA);
    defaultGeoElements.put(DEFAULT_SURFACECARTESIAN3D, surface);
  }