Customizing the UI to allow editing of a polygon area measurement after it's created

Q:

After a user creates a polygon area measurement annotation they may want to adjust the area it’s covering. Is it possible to adjust an already existing annotation?

A:

Yes you could customize the UI to allow the user to select different segments and split the segments so that they can move them and cover additional area. This code is just a starting point if you would like to make more detailed customizations:

const { documentViewer, annotationManager, Annotations } = instance.Core;

// keep track of the currently selected segments for polygon annotations
const polygonSelectedSegments = {};
const getSelectedSegment = polygon => {
  return polygonSelectedSegments[polygon.Id] || 0;
};
const updateSelectedSegment = polygon => {
  // subtract 1 because the path length is the number of points, not segments
  const pathLength = polygon.getPath().length - 1;
  // update the selected segment, wrap back to zero
  polygonSelectedSegments[polygon.Id] = (getSelectedSegment(polygon) + 1) % pathLength;
};

// this button "selects" the next segment of the polygon
instance.UI.annotationPopup.add({
  type: 'actionButton',
  label: 'Next',
  dataElement: 'polygonNextButton',
  onClick: () => {
    const annot = annotationManager.getSelectedAnnotations()[0];
    updateSelectedSegment(annot);
    annotationManager.redrawAnnotation(annot);
  }
});

// this button splits the currently selected segment of the polygon
instance.UI.annotationPopup.add({
  type: 'actionButton',
  label: 'Split',
  dataElement: 'polygonSplitButton',
  onClick: () => {
    const annot = annotationManager.getSelectedAnnotations()[0];
    const selectedSegment = getSelectedSegment(annot);
    const path = annot.getPath();
    const firstPoint = path[selectedSegment];
    const secondPoint = path[selectedSegment + 1];
    const newPoint = {
      x: (firstPoint.x + secondPoint.x) / 2,
      y: (firstPoint.y + secondPoint.y) / 2
    };

    path.splice(selectedSegment + 1, 0, newPoint);
    annotationManager.redrawAnnotation(annot);
  }
});

// only show the buttons when polygons are selected
annotationManager.addEventListener('annotationSelected', (annotations, action) => {
  const isSelectingPolygon = action === 'selected' && annotations.length > 0 && annotations[0] instanceof Annotations.PolygonAnnotation;

  if (isSelectingPolygon) {
    instance.UI.enableElements(['polygonNextButton', 'polygonSplitButton']);
  } else {
    instance.UI.disableElements(['polygonNextButton', 'polygonSplitButton']);
  }
});

Annotations.setCustomDrawHandler(Annotations.PolygonAnnotation, (ctx, pageMatrix, rotation, options) => {
  options.originalDraw(ctx, pageMatrix, rotation, documentViewer.getZoomLevel());
  const { annotation } = options;

  // draw a red line over top of the selected segment if this
  // polygon is selected
  if (annotationManager.isAnnotationSelected(annotation)) {
    const selectedSegment = getSelectedSegment(annotation);
    const path = annotation.getPath();
    if (path.length > selectedSegment + 1) {
      ctx.save();
      ctx.beginPath();
      ctx.moveTo(path[selectedSegment].x, path[selectedSegment].y);
      ctx.lineTo(path[selectedSegment + 1].x, path[selectedSegment + 1].y);
      // use a larger minimum selection size for small stroke thicknesses
      ctx.lineWidth = Math.max(ctx.lineWidth, 4);
      ctx.strokeStyle = 'red';
      ctx.stroke();
      ctx.restore();
    }
  }
});