我的程序是一个程序,您可以在其中放置FRC比赛中的工程图的点,然后可以查看使用这些点定义的路径。
程序的第一步是进行校准(将像素确定为实际距离比例),并且我目前正在添加定义场(场墙,障碍物等)的功能。我首先尝试定义场边界。为此,我正在考虑选择图形上的点,然后将其添加到多边形中,然后从与场图像大小相同的矩形中减去该多边形。
问题是,进行测试时,由于某种原因,它会显示我减去的形状偏移。我看过关于Shape.intersect
的{{3}},但这无济于事。我已经检查了AnchorPane
及其放置在其中的所有子元素的所有布局位置,比例等,但是它们都返回0或1s。
以下是返回的图片:
红色矩形是作为图像大小的矩形。
紫色是矩形和所选多边形之间的重叠。
灰色是Shape.subtract()
的结果。
我想要的是Shape.substract
(灰色)在紫色顶部有一个空白点,非常合适。但是正如您在这张图片中看到的,紫色与灰色重叠。
这就是我想要的样子: StackOverflow question
这是我为重现此现象而创建的测试环境:
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>
答案 0 :(得分:2)
问题是两个因素共同作用的结果:填充和节点层次结构;可能是一个错误。需要注意的重点是来自subtract
的文档:
在最终操作之前,将输入形状的区域转换为它们各自最顶层父节点的父坐标空间。
这意味着在进行减法时,节点在层次结构中的位置很重要。如果节点位于带填充的父对象中,则在坐标转换期间会将其考虑在内,这将导致您看到的偏移。
您的简单解决方法是删除有问题的边上的填充(取决于节点中的对齐方式),将移位后的节点平移填充量(取消填充移位) ,或在添加subtract
的减法运算之后将多边形添加到层次结构中:
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);
}
}
有几种情况需要注意: