我的程序是这样的,您可以在其中放置 FRC 比赛中的现场绘图点,然后您可以看到使用这些点定义的路径。
程序的第一步是校准(找到真实距离比例的像素),我目前正在添加定义场的功能(场墙、障碍物等......)。我首先尝试定义字段边界。为此,我正在考虑在绘图上选择点,然后将它们添加到多边形中,然后从与字段图像大小相同的矩形中减去多边形。
问题是,在测试时,由于某种原因,它显示了我减去的形状偏移。我看过StackOverflow question然而,关于Shape.intersect
,它没有帮助。我已经检查了 AnchorPane
及其放置在其中的子项的所有布局位置、比例等,但它都返回 0 或 1。
下面是它返回的内容的图:
红色矩形是图像大小的矩形。
紫色是矩形和所选多边形之间的重叠部分。
灰色是 Shape.subtract()
结果。
我想要的是 Shape.substract
(灰色)在紫色顶部有一个空白点并且完美贴合。但正如您在该图像中看到的,紫色与灰色重叠。
这是我创建的用于重现该现象的测试环境:
Main.java
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
public Main() {
}
public static void main(String[] args) {
launch(args);
}
@Override
public final void start(Stage primaryStage) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("recreationFieldSelection.fxml"));
primaryStage.setTitle("Path Planner");
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
RecreationFieldSelection.java
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Path;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;
public class RecreationFieldSelection implements Initializable {
public AnchorPane pointPlacement;
public ImageView fieldImage;
public TextField distanceViewer;
public HBox infoPane;
private Polygon polygon = new Polygon();
private Color gray = Color.gray(.5, .6);
private Color blue = Color.rgb(0, 0, 255, .5);
private boolean now = true;
@Override
public void initialize(URL location, ResourceBundle resources) {
fieldImage.setFitHeight(1000);
fieldImage.setFitWidth(1000);
polygon.setFill(Color.TRANSPARENT);
polygon.setStroke(Color.RED);
polygon.setStrokeWidth(1);
pointPlacement.getChildren().add(polygon);
}
@FXML
public void handleMouseClicked(MouseEvent mouseEvent) {
outlineField(mouseEvent);
}
@FXML
private void outlineField(MouseEvent mouseEvent) {
polygon.getPoints().addAll(mouseEvent.getX(), mouseEvent.getY());
// If the polygon has 8 defining points
if (polygon.getPoints().size() / 2 >= 8 && now) {
now = false;
Rectangle rectangle = new Rectangle(fieldImage.getFitWidth(), fieldImage.getFitHeight());
rectangle.setFill(Color.color(1, 0, 0, .3));
Path subtract = (Path) Polygon.subtract(rectangle, polygon);
subtract.setFill(gray);
subtract.setStroke(gray);
subtract.setStrokeWidth(1);
polygon.setFill(blue);
pointPlacement.getChildren().addAll(subtract);
}
}
}
recreationFieldSelection.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns:fx="http://javafx.com/fxml/1" spacing="5.0" xmlns="http://javafx.com/javafx/8"
fx:controller="testing.RecreationFieldSelection">
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
</padding>
<ScrollPane VBox.vgrow="ALWAYS" prefViewportHeight="150.0" prefViewportWidth="200.0">
<AnchorPane fx:id="pointPlacement">
<ImageView onMouseClicked="#handleMouseClicked" pickOnBounds="true" preserveRatio="true" fx:id="fieldImage"/>
</AnchorPane>
</ScrollPane>
</VBox>
其余代码为here .
最佳答案
该问题是两个因素综合作用的结果:填充和节点层次结构;并且可能是一个错误。需要注意的重要一点来自 subtract
的文档:
Before the final operation the areas of the input shapes are transformed to the parent coordinate space of their respective topmost parent nodes.
这意味着进行减法时节点在层次结构中的位置很重要。如果节点位于具有填充的父级中,则在坐标转换期间会考虑到它,这会导致您看到的移位。
简单的解决方法是删除有问题的一侧的填充(取决于节点中的对齐方式),将移位的节点平移填充量(取消填充移位) ,或者在减去操作之后将多边形添加到层次结构中,其中添加减去
:
pointPlacement.getChildren().addAll(subtract, polygon);
为了进行更深入的分析,我创建了以下 MCVE:
public class Main2 extends Application {
private final double size = 400;
public static void main(String[] args) {
launch(args);
}
@Override
public final void start(Stage stage) throws IOException {
AnchorPane pane = new AnchorPane();
pane.setStyle("-fx-background-color: lightgray;");
VBox root = new VBox(pane);
VBox.setVgrow(pane, Priority.ALWAYS);
root.setPadding(new Insets(10, 10, 10, 10));
stage.setTitle("add none");
stage.setScene(new Scene(root));
stage.setWidth(size + 50);
stage.setHeight(size + 70);
draw(pane);
stage.show();
// stage.hide();
// draw(pane);
// stage.show();
}
private void draw(AnchorPane pane) {
Rectangle big = new Rectangle(size, size);
big.setFill(Color.RED.deriveColor(0, 1, 1, 0.3));
big.setStroke(Color.RED);
pane.getChildren().add(big);
Rectangle small = new Rectangle(size/2, size/2);
small.setFill(Color.BLUE.deriveColor(0, 1, 1, 0.3));
small.setStroke(Color.BLUE);
pane.getChildren().add(small);
Shape subtract = Shape.subtract(big, small);
subtract.setFill(Color.LIME.deriveColor(0, 1, 1, 0.3));
subtract.setStroke(Color.LIME);
// pane.getChildren().add(big);
// pane.getChildren().add(small);
pane.getChildren().add(subtract);
}
}
有几种情况需要注意:
关于java - 为什么 Shape.subtract() 生成的形状出现在错误的位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51599995/