当前位置: 首页 > 知识库问答 >
问题:

JavaFX多边形共享点

班玉堂
2023-03-14

我有一个类“Vertex”包含双x,y。另一个类“Face”包含一个“Vertex”对象列表。相邻面共享相同的顶点。

目前,我正在为每个脸创建一个javafx.scene.shape.多边形,并将它们全部添加到我的场景中,看起来像这样:截图

现在我计划修改多边形,类似于:JavaFX modify polygons

问题是多边形不会保存对顶点对象的引用,而是保存双值。当我改变一个点的位置时,相邻多边形中的同一点仍在原来的位置。我如何将这些点相互链接?以及如何将更改保存回我的“脸”对象

所要求的代码示例:pastebin.com/C3JHb2nM

共有2个答案

邵华皓
2023-03-14

创建顶点属性的x和y坐标。然后,您可以将侦听器添加到修改多边形点的属性中:

public class Vertex {

    public DoubleProperty xProperty() {
        ...
    }

    public DoubleProperty yProperty() {
        ...
    }

}
public class VertexListener implements InvalidationListerner {
    private final Vertex vertex;
    private final int firstIndex;
    private final List<Double> points;

    public VertexListener(Vertex vertex, Polygon polygon, int pointIndex) {
        this.firstIndex = 2 * pointIndex;
        this.vertex = vertex;
        this.points = polygon.getPoints();

        vertex.xProperty().addListener(this);
        vertex.yProperty().addListener(this);
    } 

    public void dispose() {
        vertex.xProperty().removeListener(this);
        vertex.yProperty().removeListener(this);
    }

    @Override
    public void invalidated(Observable observable) {
        double x = vertex.getX();
        double y = vertex.getY();
        points.set(firstIndex, x);
        points.set(firstIndex+1, y);
    }
}

这样,您只需要调整顶点中的属性值,侦听器就会添加所有事件面。。。

韩涵衍
2023-03-14

干得好。计算出的公共锚点位置,然后在移动一个锚点时调整所有公共锚点位置。

Anchor包含addCommon函数,该函数添加一个对其通用的锚。common变量存储所有公共锚点。然后,当调用handle时,所有常见的x和y位置也会改变。

另外,我建议你保留Faces中的共同点。我已经创建了一个简单的方法来计算所有在该类中共享顶点的Faces。但是遵循MVC准则,你需要一个模型来提供所有必要的数据来创建图形用户界面。我建议Mesh、Face和Vertex应该提供所有必要的信息来创建图形用户界面,而不是作为双向街道。基本上,锚不应该以任何方式改变你的模型。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.StrokeType;
import javafx.stage.Stage;

public class Main extends Application {

    public class Vertex {

        private double x, y;

        public Vertex(double x, double y) {
            this.x = x;
            this.y = y;
        }

        public Double[] getPoint() {
            return new Double[]{x, y};
        }
    }

    public class Face {

        private List<Vertex> verts;

        public Face(Vertex... verts) {
            this.verts = new ArrayList<>(Arrays.asList(verts));
        }

        public Polygon getPolygon() {
            Polygon polygon = new Polygon();
            polygon.setFill(Color.GRAY);
            polygon.setStroke(Color.BLACK);

            for (Vertex vertex : verts) {
                polygon.getPoints().addAll(vertex.getPoint());
            }
            return polygon;
        }

        public boolean containsVertex(Vertex ver) {
            for (Vertex v : this.verts) {
                if (v.x == ver.x && v.y == ver.y) {
                    return true;
                }
            }
            return false;
        }
    }

    public class Mesh {

        private List<Vertex> verts = new ArrayList<Vertex>();
        private List<Face> faces = new ArrayList<Face>();
        private Map<Vertex, List<Face>> commonVertices = new HashMap<>();

        public List<Polygon> getPolygons() {
            List<Polygon> polygons = new ArrayList<Polygon>();

            for (Face face : faces) {
                polygons.add(face.getPolygon());
            }
            return polygons;
        }

        public Mesh() {
            verts.add(new Vertex(50, 50));
            verts.add(new Vertex(300, 50));
            verts.add(new Vertex(500, 50));
            verts.add(new Vertex(50, 300));
            verts.add(new Vertex(250, 300));
            verts.add(new Vertex(500, 300));
            verts.add(new Vertex(50, 600));
            verts.add(new Vertex(300, 700));
            verts.add(new Vertex(500, 700));

            faces.add(new Face(verts.get(0), verts.get(1), verts.get(4), verts.get(3)));
            faces.add(new Face(verts.get(4), verts.get(1), verts.get(2), verts.get(5)));
            faces.add(new Face(verts.get(3), verts.get(4), verts.get(7), verts.get(6)));
            faces.add(new Face(verts.get(7), verts.get(4), verts.get(5)));
            faces.add(new Face(verts.get(7), verts.get(5), verts.get(8)));

            findCommonVertices();
        }

        private void findCommonVertices() {
            for (Vertex ver : this.verts) {
                List<Face> share = new ArrayList<>();
                for (Face face : this.faces) {
                    if (face.containsVertex(ver)) {
                        share.add(face);
                    }
                }
                commonVertices.put(ver, share);
            }
        }

        public Map<Vertex, List<Face>> getCommonVertices() {
            return this.commonVertices;
        }

    }

    @Override
    public void start(Stage stage) {
        Group root = new Group();
        Scene scene = new Scene(root, 1024, 768);
        stage.setScene(scene);

        Group g = new Group();
        Mesh mesh = new Mesh();
        List<Polygon> polygons = mesh.getPolygons();

        g.getChildren().addAll(polygons);

        List<Anchor> anchors = new ArrayList<>();
        for (Polygon p : polygons) {
            ObservableList<Anchor> temp = createControlAnchorsFor(p.getPoints());
            g.getChildren().addAll(temp);
            for (Anchor kk : temp) {
                anchors.add(kk);
            }
        }

        for (int i = 0; i < anchors.size(); i++) {
            List<Anchor> common = new ArrayList<>();
            for (int j = 0; j < anchors.size(); j++) {
                if (i != j) {
                    if (anchors.get(i).x.doubleValue() == anchors.get(j).x.doubleValue() && anchors.get(i).y.doubleValue() == anchors.get(j).y.doubleValue()) {
                        anchors.get(i).addCommon(anchors.get(j));
                        System.out.println("COMMON " + i + "  " + j);
                    }
                }
            }
           // anchors.get(i).setCommon(common);
        }

        scene.setRoot(g);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

    // Everything below was copied from here: https://gist.github.com/jewelsea/5375786
    // @return a list of anchors which can be dragged around to modify points in the format [x1, y1, x2, y2...]
    private ObservableList<Anchor> createControlAnchorsFor(final ObservableList<Double> points) {
        ObservableList<Anchor> anchors = FXCollections.observableArrayList();

        for (int i = 0; i < points.size(); i += 2) {
            final int idx = i;

            DoubleProperty xProperty = new SimpleDoubleProperty(points.get(i));
            DoubleProperty yProperty = new SimpleDoubleProperty(points.get(i + 1));

            xProperty.addListener(new ChangeListener<Number>() {
                @Override
                public void changed(ObservableValue<? extends Number> ov, Number oldX, Number x) {
                    points.set(idx, (double) x);
                }
            });

            yProperty.addListener(new ChangeListener<Number>() {
                @Override
                public void changed(ObservableValue<? extends Number> ov, Number oldY, Number y) {
                    points.set(idx + 1, (double) y);
                }
            });

            anchors.add(new Anchor(Color.GOLD, xProperty, yProperty));
        }

        return anchors;
    }

    // a draggable anchor displayed around a point.
    class Anchor extends Circle {

        private final DoubleProperty x, y;
        List<Anchor> common = new ArrayList<>();

        public void setCommon(List<Anchor> common) {
            this.common = common;
        }

        public void addCommon(Anchor com) {
            common.add(com);
            enableDrag();
        }

        Anchor(Color color, DoubleProperty x, DoubleProperty y) {
            super(x.get(), y.get(), 10);
            setFill(color.deriveColor(1, 1, 1, 0.5));
            setStroke(color);
            setStrokeWidth(2);
            setStrokeType(StrokeType.OUTSIDE);

            this.x = x;
            this.y = y;

            x.bind(centerXProperty());
            y.bind(centerYProperty());
               enableDrag();
        }

        // make a node movable by dragging it around with the mouse.
        private void enableDrag() {
            final Delta dragDelta = new Delta();
            setOnMousePressed(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent mouseEvent) {
                    // record a delta distance for the drag and drop operation.
                    dragDelta.x = getCenterX() - mouseEvent.getX();
                    dragDelta.y = getCenterY() - mouseEvent.getY();
                    getScene().setCursor(Cursor.MOVE);
                }
            });
            setOnMouseReleased(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent mouseEvent) {
                    getScene().setCursor(Cursor.HAND);
                }
            });
            setOnMouseDragged(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent mouseEvent) {
                    double newX = mouseEvent.getX() + dragDelta.x;
                    if (newX > 0 && newX < getScene().getWidth()) {
                        setCenterX(newX);
                        if (common != null) {
                            for (Anchor an : common) {
                                an.setCenterX(newX);
                                System.out.println("CALLED");
                            }
                        }
                    }
                    double newY = mouseEvent.getY() + dragDelta.y;
                    if (newY > 0 && newY < getScene().getHeight()) {
                        setCenterY(newY);
                        if (common != null) {
                            for (Anchor an : common) {
                                an.setCenterY(newY);
                            }
                        }
                    }
                }
            });
            setOnMouseEntered(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent mouseEvent) {
                    if (!mouseEvent.isPrimaryButtonDown()) {
                        getScene().setCursor(Cursor.HAND);
                    }
                }
            });
            setOnMouseExited(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent mouseEvent) {
                    if (!mouseEvent.isPrimaryButtonDown()) {
                        getScene().setCursor(Cursor.DEFAULT);
                    }
                }
            });
        }

        // records relative x and y co-ordinates.
        private class Delta {

            double x, y;
        }
    }
}
 类似资料:
  • 主要内容:JavaFX多边形折线JavaFX多边形折线 多边形,一个简单的示例代码如下所示 - 上面的代码生成以下结果。 折线示例,一个简单的示例代码如下所示 - 上面的代码生成以下结果。

  • 有没有办法在JavaFX中修改多边形?例如,如果我有一个三角形,我按下然后从该三角形拖动一个点,三角形将用该点的新坐标进行修改。

  • 我目前正在使用JavaFX研究不同形状之间的边界相交。我想检测两个多边形在它们的点上的碰撞,而不是在它们的边界上(即2个多边形)。 请参阅图1:不期望的行为,以及图2:期望的行为。 是否有任何现有的算法可以帮助我或使用任何库?提前感谢:) 在这里找到我的解决方案: 输出: 它似乎工作正常,我将使用Path对象进行测试以替换多边形objets。

  • 返回顶点的输入数组,并且附有一些其他方法,如下面所描述 polygon.area() 返回此多边形的标定区域。如果顶点是逆时针顺序,面积为正,否则为负。 polygon.centroid() 返回一个表示此多边形的质心的两元素数组。 polygon.clip(subject) 对这个多边形剪切主题多边形。换句话说,返回一个多边形表示这个多边形和主题多边形的交集。假定剪切的多边形是逆时针方向以及凸多

  • 基础示例 <vuep template="#example"></vuep> <script v-pre type="text/x-template" id="example"> <template> <div class="amap-page-container"> <el-amap vid="amap" :zoom="zoom" :amap-manager="ama

  • SVG 多边形 - <polygon> 实例 1 <polygon> 标签用来创建含有不少于三个边的图形。 多边形是由直线组成,其形状是"封闭"的(所有的线条 连接起来)。 polygon来自希腊。 "Poly" 意味 "many" , "gon" 意味 "angle". 下面是SVG代码: <svg xmlns="http://www.w3.org/2000/svg" version="1.1"