/******************************************************************************* * Copyright (c) 2016 Weasis Team and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Nicolas Roduit - initial API and implementation *******************************************************************************/ package org.weasis.core.ui.model.graphic.imp.area; import java.awt.Shape; import java.awt.geom.Ellipse2D; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import org.weasis.core.api.gui.util.GeomUtil; import org.weasis.core.api.image.measure.MeasurementsAdapter; import org.weasis.core.api.image.util.MeasurableLayer; import org.weasis.core.api.image.util.Unit; import org.weasis.core.ui.Messages; import org.weasis.core.ui.model.graphic.AbstractDragGraphicArea; import org.weasis.core.ui.model.utils.bean.MeasureItem; import org.weasis.core.ui.model.utils.bean.Measurement; import org.weasis.core.ui.model.utils.exceptions.InvalidShapeException; import org.weasis.core.ui.util.MouseEventDouble; @XmlType(name = "threePointsCircle") @XmlRootElement(name = "threePointsCircle") public class ThreePointsCircleGraphic extends AbstractDragGraphicArea { private static final long serialVersionUID = -1806336437294860031L; public static final Integer POINTS_NUMBER = 3; public static final Icon ICON = new ImageIcon(ThreePointsCircleGraphic.class.getResource("/icon/22x22/draw-circle.png")); //$NON-NLS-1$ public static final Measurement AREA = new Measurement(Messages.getString("measure.area"), 1, true, true, true); //$NON-NLS-1$ public static final Measurement DIAMETER = new Measurement(Messages.getString("measure.diameter"), 2, true, true, false); //$NON-NLS-1$ public static final Measurement PERIMETER = new Measurement(Messages.getString("measure.perimeter"), 3, true, true, false); //$NON-NLS-1$ public static final Measurement CENTER_X = new Measurement(Messages.getString("measure.centerx"), 4, true, true, false); //$NON-NLS-1$ public static final Measurement CENTER_Y = new Measurement(Messages.getString("measure.centery"), 5, true, true, false); //$NON-NLS-1$ public static final Measurement RADIUS = new Measurement(Messages.getString("measure.radius"), 6, true, true, false); //$NON-NLS-1$ protected static final List<Measurement> MEASUREMENT_LIST = new ArrayList<>(); static { MEASUREMENT_LIST.add(CENTER_X); MEASUREMENT_LIST.add(CENTER_Y); MEASUREMENT_LIST.add(RADIUS); MEASUREMENT_LIST.add(DIAMETER); MEASUREMENT_LIST.add(AREA); MEASUREMENT_LIST.add(PERIMETER); } protected Point2D.Double centerPt; // Let O be the center of the three point interpolated circle protected Double radius; // circle radius public ThreePointsCircleGraphic() { super(POINTS_NUMBER); } public ThreePointsCircleGraphic(ThreePointsCircleGraphic graphic) { super(graphic); } @Override public ThreePointsCircleGraphic copy() { return new ThreePointsCircleGraphic(this); } @Override public Icon getIcon() { return ICON; } @Override public String getUIName() { return Messages.getString("measure.three_pt_angle"); //$NON-NLS-1$ } @Override protected void prepareShape() throws InvalidShapeException { if (!isShapeValid()) { throw new InvalidShapeException("This shape cannot be drawn"); //$NON-NLS-1$ } buildShape(null); } @Override public void buildShape(MouseEventDouble mouseEvent) { updateTool(); Shape newShape = null; if (Objects.nonNull(centerPt) && !Objects.equals(radius, 0d)) { newShape = new Ellipse2D.Double(centerPt.getX() - radius, centerPt.getY() - radius, 2 * radius, 2 * radius); } setShape(newShape, mouseEvent); updateLabel(mouseEvent, getDefaultView2d(mouseEvent)); } /** * Force to display handles even during resizing or moving sequences */ @Override public Boolean getResizingOrMoving() { return Boolean.FALSE; } @Override public List<MeasureItem> computeMeasurements(MeasurableLayer layer, boolean releaseEvent, Unit displayUnit) { if (layer != null && layer.hasContent() && isShapeValid()) { MeasurementsAdapter adapter = layer.getMeasurementAdapter(displayUnit); if (adapter != null) { ArrayList<MeasureItem> measVal = new ArrayList<>(); double ratio = adapter.getCalibRatio(); if (CENTER_X.getComputed()) { measVal.add( new MeasureItem(CENTER_X, adapter.getXCalibratedValue(centerPt.getX()), adapter.getUnit())); } if (CENTER_Y.getComputed()) { measVal.add( new MeasureItem(CENTER_Y, adapter.getYCalibratedValue(centerPt.getY()), adapter.getUnit())); } if (RADIUS.getComputed()) { measVal.add(new MeasureItem(RADIUS, ratio * radius, adapter.getUnit())); } if (DIAMETER.getComputed()) { measVal.add(new MeasureItem(DIAMETER, ratio * radius * 2.0, adapter.getUnit())); } if (AREA.getComputed()) { String unit = "pix".equals(adapter.getUnit()) ? adapter.getUnit() : adapter.getUnit() + "2"; //$NON-NLS-1$ //$NON-NLS-2$ measVal.add(new MeasureItem(AREA, Math.PI * radius * radius * ratio * ratio, unit)); } List<MeasureItem> stats = getImageStatistics(layer, releaseEvent); if (stats != null) { measVal.addAll(stats); } return measVal; } } return Collections.emptyList(); } @Override public List<Measurement> getMeasurementList() { return MEASUREMENT_LIST; } @Override public boolean isShapeValid() { updateTool(); return super.isShapeValid() && centerPt != null && radius < 50000; } protected void updateTool() { Point2D ptA = getHandlePoint(0); centerPt = GeomUtil.getCircleCenter(pts); radius = (centerPt != null && ptA != null) ? centerPt.distance(ptA) : 0; } }