2017-09-13 30 views
0

我有一個類「頂點」,其中包含雙x,y。 另一個類「Face」包含「頂點」對象的列表。相鄰的面共享相同的頂點。JavaFX多邊形分享積分

目前我創建一個javafx.scene.shape.Polygon的每一張臉,他們都加到我的場景,它看起來像這樣: Screenshot

現在我打算修改多邊形,與此類似:JavaFX modify polygons

問題是多邊形不保存對我的頂點對象的引用,而是保存雙值。當我改變一個點的位置時,相鄰多邊形中的相同點仍舊在舊位置。我怎樣才能將這些點連接起來?還有如何將更改保存回我的「Face」對象?根據要求

代碼示例:pastebin.com/C3JHb2nM

+0

發表您的一些代碼請 – Steven

回答

0

你在這裏。計算出的共同錨點位置然後在移動時調整所有常見錨點位置。

Anchor包含addCommon函數,它添加了一個通用的錨點。 common變量存儲所有常用的錨點。然後當調用handle時,所有常見的x and y位置也會改變。

此外,我會建議你持有Faces的共同點。我創建了一個簡單的方法來計算所有在所述類中共享頂點的面。但是遵循MVC指南,您需要有一個提供所有必要數據來創建GUI的模型。我建議Mesh,Face和Vertex應該提供所有必要的信息來創建GUI,而不是作爲雙向街道。基本上,Anchor不應該以任何方式改變你的模型。

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; 
     } 
    } 
} 
0

使頂點屬性的xy座標。然後,您可以添加偵聽那些修改Polygon S的點屬性:

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); 
    } 
} 

這樣,你只需要在Vertex調整屬性值和聽衆將增加所有事件的面孔。 ..