Skip to content

Commit 9d71b64

Browse files
committed
Simplify freehand-shape view.
1 parent 454d58a commit 9d71b64

File tree

5 files changed

+16
-170
lines changed

5 files changed

+16
-170
lines changed

src/main/java/com/github/mfl28/boundingboxeditor/controller/Controller.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,9 @@ public void onRegisterImageViewMouseReleasedEvent(MouseEvent event) {
586586
if(imagePane.isImageFullyLoaded() && event.getButton().equals(MouseButton.PRIMARY)) {
587587
if(event.isControlDown()) {
588588
view.getEditorImageView().setCursor(Cursor.OPEN_HAND);
589-
} else if(view.getObjectCategoryTable().isCategorySelected()) {
589+
}
590+
591+
if(view.getObjectCategoryTable().isCategorySelected()) {
590592
if(imagePane.getDrawingMode() == EditorImagePaneView.DrawingMode.BOX
591593
&& imagePane.isBoundingBoxDrawingInProgress()) {
592594
imagePane.finalizeBoundingBox();

src/main/java/com/github/mfl28/boundingboxeditor/ui/BoundingFreehandShapeView.java

Lines changed: 8 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,10 @@
2525
import javafx.geometry.Rectangle2D;
2626
import javafx.scene.control.Toggle;
2727
import javafx.scene.control.ToggleGroup;
28-
import javafx.scene.input.MouseEvent;
2928
import javafx.scene.paint.Color;
3029
import javafx.scene.shape.*;
3130

3231
import java.util.ArrayList;
33-
import java.util.Collections;
3432
import java.util.List;
3533
import java.util.Objects;
3634

@@ -41,12 +39,6 @@ public class BoundingFreehandShapeView extends Path implements View, Toggle,
4139
private static final double SELECTED_FILL_OPACITY = 0.5;
4240
private final BoundingShapeViewData boundingShapeViewData;
4341

44-
private final DoubleProperty xMin = new SimpleDoubleProperty(Double.MAX_VALUE);
45-
private final DoubleProperty yMin = new SimpleDoubleProperty(Double.MAX_VALUE);
46-
private final DoubleProperty xMax = new SimpleDoubleProperty(0);
47-
private final DoubleProperty yMax = new SimpleDoubleProperty(0);
48-
private final List<Double> pointsInImage = Collections.emptyList();
49-
5042
public BoundingFreehandShapeView(ObjectCategory category) {
5143
this.boundingShapeViewData = new BoundingShapeViewData(this, category);
5244

@@ -55,6 +47,7 @@ public BoundingFreehandShapeView(ObjectCategory category) {
5547
setId(BOUNDING_FREEHAND_SHAPE_ID);
5648

5749
boundingShapeViewData.getNodeGroup().setManaged(false);
50+
boundingShapeViewData.getNodeGroup().setViewOrder(0);
5851

5952
setUpInternalListeners();
6053
}
@@ -83,26 +76,12 @@ public BoundingShapeViewData getViewData() {
8376
@Override
8477
public void autoScaleWithBoundsAndInitialize(ReadOnlyObjectProperty<Bounds> autoScaleBounds, double imageWidth,
8578
double imageHeight) {
86-
boundingShapeViewData.autoScaleBounds().bind(autoScaleBounds);
87-
initializeFromBoundsInImage(imageWidth, imageHeight);
88-
addAutoScaleListener();
79+
autoScaleWithBounds(autoScaleBounds);
8980
}
9081

9182
@Override
9283
public Rectangle2D getRelativeOutlineRectangle() {
93-
final Bounds imageViewBounds = boundingShapeViewData.autoScaleBounds().getValue();
94-
95-
double relativeXMin = (xMin.get() - imageViewBounds.getMinX()) / imageViewBounds.getWidth();
96-
double relativeYMin = (yMin.get() - imageViewBounds.getMinY()) / imageViewBounds.getHeight();
97-
double relativeWidth = (xMax.get() - xMin.get()) / imageViewBounds.getWidth();
98-
double relativeHeight = (yMax.get() - yMin.get()) / imageViewBounds.getHeight();
99-
100-
return new Rectangle2D(relativeXMin, relativeYMin, relativeWidth, relativeHeight);
101-
}
102-
103-
@Override
104-
public BoundingShapeTreeItem toTreeItem() {
105-
return new BoundingPolygonTreeItem(this);
84+
return null;
10685
}
10786

10887
@Override
@@ -128,6 +107,11 @@ public boolean equals(Object obj) {
128107
return Objects.equals(getElements(), other.getElements());
129108
}
130109

110+
@Override
111+
public BoundingShapeTreeItem toTreeItem() {
112+
return new BoundingPolygonTreeItem(this);
113+
}
114+
131115
@Override
132116
public ToggleGroup getToggleGroup() {
133117
return boundingShapeViewData.getToggleGroup();
@@ -160,54 +144,17 @@ public BooleanProperty selectedProperty() {
160144

161145
public void addMoveTo(double x, double y) {
162146
getElements().add(new MoveTo(x, y));
163-
updateOutlineBoxFromCoordinates(x, y);
164147
}
165148

166149
public void addLineTo(double x, double y) {
167150
getElements().add(new LineTo(x, y));
168-
updateOutlineBoxFromCoordinates(x, y);
169151
}
170152

171153
void autoScaleWithBounds(ReadOnlyObjectProperty<Bounds> autoScaleBounds) {
172154
boundingShapeViewData.autoScaleBounds().bind(autoScaleBounds);
173155
addAutoScaleListener();
174156
}
175157

176-
177-
List<Double> getMinMaxScaledPoints(double width, double height) {
178-
final List<Double> points = new ArrayList<>((getElements().size() - 1) * 2);
179-
180-
for(PathElement element : getElements()) {
181-
if(element instanceof LineTo lineTo) {
182-
points.add((lineTo.getX() - xMin.get()) / (xMax.get() - xMin.get()) * width);
183-
points.add((lineTo.getY() - yMin.get()) / (yMax.get() - yMin.get()) * height);
184-
} else if(element instanceof MoveTo moveTo) {
185-
points.add((moveTo.getX() - xMin.get()) / (xMax.get() - xMin.get()) * width);
186-
points.add((moveTo.getY() - yMin.get()) / (yMax.get() - yMin.get()) * height);
187-
}
188-
}
189-
190-
return points;
191-
}
192-
193-
private void initializeFromBoundsInImage(double imageWidth, double imageHeight) {
194-
Bounds confinementBoundsValue = boundingShapeViewData.autoScaleBounds().getValue();
195-
196-
getElements().setAll(new MoveTo(pointsInImage.get(0) * confinementBoundsValue.getWidth() / imageWidth +
197-
confinementBoundsValue.getMinX(),
198-
pointsInImage.get(1) * confinementBoundsValue.getHeight() / imageHeight +
199-
confinementBoundsValue.getMinY()));
200-
201-
for(int i = 2; i < pointsInImage.size(); i += 2) {
202-
getElements().add(new LineTo(pointsInImage.get(i) * confinementBoundsValue.getWidth() / imageWidth +
203-
confinementBoundsValue.getMinX(),
204-
pointsInImage.get(i + 1) * confinementBoundsValue.getHeight() / imageHeight +
205-
confinementBoundsValue.getMinY()));
206-
}
207-
208-
getElements().add(new ClosePath());
209-
}
210-
211158
private void setUpInternalListeners() {
212159
fillProperty().bind(Bindings.when(selectedProperty())
213160
.then(Bindings.createObjectBinding(
@@ -224,17 +171,6 @@ private void setUpInternalListeners() {
224171
boundingShapeViewData.getHighlighted().set(false);
225172
}
226173
});
227-
228-
setOnMouseEntered(this::handleMouseEntered);
229-
setOnMouseExited(this::handleMouseExited);
230-
setOnMousePressed(this::handleMousePressed);
231-
232-
233-
boundingShapeViewData.getNodeGroup().viewOrderProperty().bind(
234-
Bindings.when(boundingShapeViewData.selectedProperty())
235-
.then(0)
236-
.otherwise(Bindings.min(xMax.subtract(xMin), yMax.subtract(yMin)))
237-
);
238174
}
239175

240176
private void addAutoScaleListener() {
@@ -251,63 +187,6 @@ private void addAutoScaleListener() {
251187
lineToElement.setY(newValue.getMinY() + (lineToElement.getY() - oldValue.getMinY()) * yScaleFactor);
252188
}
253189
}
254-
255-
updateOutlineBox();
256190
});
257191
}
258-
259-
private void updateOutlineBox() {
260-
double newXMin = Double.MAX_VALUE;
261-
double newYMin = Double.MAX_VALUE;
262-
double newXMax = 0;
263-
double newYMax = 0;
264-
265-
for(PathElement pathElement : getElements()) {
266-
if(pathElement instanceof LineTo lineToElement) {
267-
newXMin = Math.min(lineToElement.getX(), newXMin);
268-
newYMin = Math.min(lineToElement.getY(), newYMin);
269-
newXMax = Math.max(lineToElement.getX(), newXMax);
270-
newYMax = Math.max(lineToElement.getY(), newYMax);
271-
} else if(pathElement instanceof MoveTo moveToElement) {
272-
newXMin = Math.min(moveToElement.getX(), newXMin);
273-
newYMin = Math.min(moveToElement.getY(), newYMin);
274-
newXMax = Math.max(moveToElement.getX(), newXMax);
275-
newYMax = Math.max(moveToElement.getY(), newYMax);
276-
}
277-
}
278-
279-
xMin.set(newXMin);
280-
xMax.set(newXMax);
281-
yMin.set(newYMin);
282-
yMax.set(newYMax);
283-
}
284-
285-
private void updateOutlineBoxFromCoordinates(double x, double y) {
286-
xMin.set(Math.min(xMin.get(), x));
287-
xMax.set(Math.max(xMax.get(), x));
288-
yMin.set(Math.min(yMin.get(), y));
289-
yMax.set(Math.max(yMax.get(), y));
290-
}
291-
292-
private void handleMousePressed(MouseEvent event) {
293-
if(!event.isControlDown()) {
294-
boundingShapeViewData.getToggleGroup().selectToggle(this);
295-
296-
event.consume();
297-
}
298-
}
299-
300-
private void handleMouseExited(MouseEvent event) {
301-
if(!isSelected()) {
302-
boundingShapeViewData.setHighlighted(false);
303-
}
304-
}
305-
306-
private void handleMouseEntered(MouseEvent event) {
307-
if(!isSelected()) {
308-
boundingShapeViewData.setHighlighted(true);
309-
}
310-
311-
event.consume();
312-
}
313192
}

src/main/java/com/github/mfl28/boundingboxeditor/ui/WorkspaceSplitPaneView.java

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,10 @@ private void handlePopoverTimerFinished(ObjectTreeElementCell cell) {
507507
final Rectangle2D relativeOutline =
508508
((BoundingShapeViewable) cell.getItem()).getRelativeOutlineRectangle();
509509

510+
if(relativeOutline == null) {
511+
return;
512+
}
513+
510514
final Rectangle2D outline = new Rectangle2D(relativeOutline.getMinX() * currentImage.getWidth(),
511515
relativeOutline.getMinY() * currentImage.getHeight(),
512516
relativeOutline.getWidth() * currentImage.getWidth(),
@@ -536,20 +540,6 @@ private void handlePopoverTimerFinished(ObjectTreeElementCell cell) {
536540
polygon.getPoints().setAll(points);
537541

538542
imageView.setClip(polygon);
539-
} else if(cell.getItem() instanceof BoundingFreehandShapeView boundingFreehandShapeView) {
540-
final List<Double> points =
541-
boundingFreehandShapeView.getMinMaxScaledPoints(scaleWidth, scaleHeight);
542-
543-
final Path path = new Path();
544-
path.setFill(Color.WHITE);
545-
path.getElements().add(new MoveTo(points.get(0), points.get(1)));
546-
547-
for(int i = 2; i != points.size(); i += 2) {
548-
path.getElements().add(new LineTo(points.get(i), points.get(i + 1)));
549-
}
550-
551-
path.getElements().add(new ClosePath());
552-
imageView.setClip(path);
553543
}
554544

555545
cell.getPopOver().show(cell);

src/test/java/com/github/mfl28/boundingboxeditor/BoundingBoxEditorTestBase.java

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -142,24 +142,6 @@ protected void moveAndClickRelativeToImageView(FxRobot robot, MouseButton mouseb
142142
}
143143
}
144144

145-
protected void pressMoveReleaseRelativeToImageView(FxRobot robot, MouseButton mousebutton, boolean pressStart, boolean releaseEnd, Point2D... points) {
146-
robot.moveTo(getScreenPointFromImageViewRatios(points[0]));
147-
148-
if(pressStart) {
149-
robot.press(mousebutton);
150-
}
151-
152-
for(int i = 1; i < points.length - 1; ++i) {
153-
robot.moveTo(getScreenPointFromImageViewRatios(points[i]));
154-
}
155-
156-
robot.moveTo(getScreenPointFromImageViewRatios(points[points.length - 1]));
157-
158-
if(releaseEnd) {
159-
robot.release(mousebutton);
160-
}
161-
}
162-
163145
protected void enterNewCategory(FxRobot robot, String categoryName, TestInfo testinfo) {
164146
timeOutClickOn(robot, "#category-input-field", testinfo);
165147
WaitForAsyncUtils.waitForFxEvents();

src/test/java/com/github/mfl28/boundingboxeditor/ui/BoundingPolygonDrawingTests.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -430,14 +430,7 @@ void onFreehandDrawing_WhenImageFolderLoaded_ShouldCorrectlyCreatePolygons(FxRob
430430
verifyThat(boundingFreehandShapeView.getElements().get(boundingFreehandShapeView.getElements().size() - 1),
431431
Matchers.instanceOf(LineTo.class));
432432

433-
final Rectangle2D relativeOutlineRectangle = boundingFreehandShapeView.getRelativeOutlineRectangle();
434-
verifyThat(relativeOutlineRectangle.getMinX(), Matchers.allOf(Matchers.greaterThanOrEqualTo(0.0), Matchers.lessThanOrEqualTo(1.0)));
435-
verifyThat(relativeOutlineRectangle.getMaxX(), Matchers.allOf(Matchers.greaterThanOrEqualTo(0.0), Matchers.lessThanOrEqualTo(1.0)));
436-
verifyThat(relativeOutlineRectangle.getMinY(), Matchers.allOf(Matchers.greaterThanOrEqualTo(0.0), Matchers.lessThanOrEqualTo(1.0)));
437-
verifyThat(relativeOutlineRectangle.getMaxX(), Matchers.allOf(Matchers.greaterThanOrEqualTo(0.0), Matchers.lessThanOrEqualTo(1.0)));
438-
439-
final List<Double> minMaxPoints = boundingFreehandShapeView.getMinMaxScaledPoints(100, 100);
440-
verifyThat(minMaxPoints.stream().allMatch(value -> value >= 0.0 && value <= 100.0), Matchers.is(true));
433+
verifyThat(boundingFreehandShapeView.getRelativeOutlineRectangle(), Matchers.nullValue());
441434

442435
robot.moveTo(screenPoints.get(2)).moveTo(screenPoints.get(3)).release(MouseButton.PRIMARY);
443436

0 commit comments

Comments
 (0)