/**
   * Ensures that the pointList holds n points.
   *
   * @param n
   */
  private void updateOutput(int n) {

    int nOld = outputPoints.size() + 2;

    // App.error("nOld="+nOld+", n="+n);

    if (nOld == n) return;

    // update points and segments
    if (n > nOld) {
      showNewPointsLabels =
          labelPointsAndSegments
              && (A.isEuclidianVisible() && A.isLabelVisible()
                  || B.isEuclidianVisible() && B.isLabelVisible());
      outputPoints.augmentOutputSize(n - nOld, false);
      if (labelPointsAndSegments && !labelsNeedIniting) outputPoints.updateLabels();

      showNewSegmentsLabels = false;
      for (int i = 0; i < outputSegments.size(); i++)
        showNewSegmentsLabels =
            showNewSegmentsLabels || outputSegments.getElement(i).isLabelVisible();
      outputSegments.augmentOutputSize(n - nOld, false);
      if (labelPointsAndSegments && !labelsNeedIniting) outputSegments.updateLabels();
    } else {
      for (int i = n; i < nOld; i++) {
        outputPoints.getElement(i - 2).setUndefined();
        outputSegments.getElement(i).setUndefined();
      }
      // update last segment
      if (n > 2)
        ((GeoSegmentND) outputSegments.getElement(n - 1))
            .modifyInputPoints((GeoPointND) outputPoints.getElement(n - 3), A);
      else ((GeoSegmentND) outputSegments.getElement(n - 1)).modifyInputPoints(B, A);
    }
  }
  /**
   * Creates a new regular polygon algorithm
   *
   * @param c construction
   * @param labels labels[0] for polygon, then labels for segments and then for points
   * @param A1 first input point
   * @param B1 second input point
   * @param num number of vertices
   */
  public AlgoPolygonRegularND(
      Construction c,
      String[] labels,
      GeoPointND A1,
      GeoPointND B1,
      NumberValue num,
      GeoDirectionND direction) {
    super(c);

    labelsNeedIniting = true;

    this.A = A1;
    this.B = B1;
    this.num = num;
    setDirection(direction);

    // labels given by user or loaded from file
    int labelsLength = labels == null ? 0 : labels.length;

    // set labels for segments only when points have labels
    labelPointsAndSegments = A.isLabelSet() || B.isLabelSet() || labelsLength > 1;
    showNewSegmentsLabels = false;
    showNewPointsLabels = false;

    // temp center point of regular polygon
    centerPoint = (GeoPointND) newGeoPoint(c);
    rotAngle = new MyDouble(kernel);

    outputPolygon =
        new OutputHandler<GeoPolygon>(
            new elementFactory<GeoPolygon>() {
              public GeoPolygon newElement() {
                GeoPolygon p = newGeoPolygon(cons);
                p.setParentAlgorithm(AlgoPolygonRegularND.this);
                return p;
              }
            });

    outputSegments =
        new OutputHandler<GeoElement>(
            new elementFactory<GeoElement>() {
              public GeoElement newElement() {
                GeoElement segment =
                    (GeoElement) outputPolygon.getElement(0).createSegment(A, B, true);
                segment.setAuxiliaryObject(true);
                boolean segmentsVisible = false;
                int size = outputSegments.size();
                if (size > 0) { // check if at least one segment is
                  // visible
                  for (int i = 0; i < size && !segmentsVisible; i++) {
                    segmentsVisible =
                        segmentsVisible || outputSegments.getElement(i).isEuclidianVisible();
                  }
                } else { // no segment yet
                  segmentsVisible = true;
                }
                segment.setEuclidianVisible(segmentsVisible);
                segment.setLabelVisible(showNewSegmentsLabels);
                segment.setViewFlags(((GeoElement) A).getViewSet());
                segment.setVisibleInView3D((GeoElement) A);
                segment.setVisibleInViewForPlane((GeoElement) A);
                return segment;
              }
            });

    if (!labelPointsAndSegments) outputSegments.removeFromHandler(); // no segments has output

    outputPoints =
        new OutputHandler<GeoElement>(
            new elementFactory<GeoElement>() {
              public GeoElement newElement() {
                GeoElement newPoint = newGeoPoint(cons);
                newPoint.setParentAlgorithm(AlgoPolygonRegularND.this);
                newPoint.setAuxiliaryObject(true);
                ((GeoPointND) newPoint).setPointSize(A.getPointSize());
                newPoint.setEuclidianVisible(A.isEuclidianVisible() || B.isEuclidianVisible());
                newPoint.setAuxiliaryObject(true);
                newPoint.setLabelVisible(showNewPointsLabels);
                newPoint.setViewFlags(((GeoElement) A).getViewSet());
                newPoint.setVisibleInView3D((GeoElement) A);
                newPoint.setVisibleInViewForPlane((GeoElement) A);
                GeoBoolean conditionToShow = ((GeoElement) A).getShowObjectCondition();
                if (conditionToShow == null)
                  conditionToShow = ((GeoElement) B).getShowObjectCondition();
                if (conditionToShow != null) {
                  try {
                    newPoint.setShowObjectCondition(conditionToShow);
                  } catch (Exception e) {
                    // circular exception -- do nothing
                  }
                }
                return newPoint;
              }
            });

    if (!labelPointsAndSegments) outputPoints.removeFromHandler(); // no segments has output

    // create polygon
    outputPolygon.adjustOutputSize(1);

    // create 2 first segments
    outputSegments.augmentOutputSize(2, false);
    outputSegments.getElement(0).setAuxiliaryObject(false);
    ((GeoSegmentND) outputSegments.getElement(1)).modifyInputPoints(B, A);

    // for AlgoElement
    setInputOutput();

    GeoPolygon poly = getPoly();

    // set that the poly output can have different points length
    poly.setNotFixedPointsLength(true);

    // compute poly
    if (labelsLength > 1) {
      compute((labelsLength + 1) / 2); // create maybe undefined outputs
      poly.setLabel(labels[0]);
      int d = 1;
      for (int i = 0; i < outputSegments.size(); i++)
        outputSegments.getElement(i).setLabel(labels[d + i]);
      d += outputSegments.size();
      for (int i = 0; i < outputPoints.size(); i++)
        outputPoints.getElement(i).setLabel(labels[d + i]);
    } else if (labelsLength == 1) {
      poly.setLabel(labels[0]);
    } else {
      poly.setLabel(null);
    }

    labelsNeedIniting = false;

    update();

    /*
     * if (labelPointsAndSegments) { //poly.initLabels(labels); } else if
     * (labelsLength == 1) { poly.setLabel(labels[0]); } else {
     * poly.setLabel(null); }
     *
     *
     * labelsNeedIniting = false;
     */
    // make sure that we set all point and segment labels when needed
    // updateSegmentsAndPointsLabels(points.length);
  }