2016-05-20 12 views
0

私は現在、パス描画algorythmの書き直しに取り組んでいます。 I パスを正しく描画する方法は?

は現在、私は持っている... 2D空間内のすべての与えられた点を通るなめらかなパスを取得するためのapache-コモンズ・数学のスプライン補間を使用しています:以来のことを、この背後にある考え方は
/** 
* Draws a route on a map. 
*/ 
public class MapRouteDrawer { 

    private static final SplineInterpolator splineInterpolator = new SplineInterpolator(); 

    /** 
    * Draws the route to the screen, does nothing if null. 
    */ 
    public static void drawRoute(final Graphics2D graphics, final RouteDescription routeDescription, final MapPanel view, final MapData mapData, final String movementLeftForCurrentUnits) { 
    if (routeDescription == null) { 
     return; 
    } 
    final Route route = routeDescription.getRoute(); 
    if (route == null) { 
     return; 
    } 

    final Point[] points = getRoutePoints(routeDescription, mapData); 
    final int xOffset = view.getXOffset(); 
    final int yOffset = view.getYOffset(); 
    final int jointsize = 10; 
    final int numTerritories = route.getAllTerritories().size(); 
    //set thickness and color of the future drawings 
    graphics.setStroke(new BasicStroke(3.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 
    graphics.setPaint(Color.red); 
    graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 

    if(Arrays.asList(points).contains(null)){//If the Array is null at some point 
     return; 
    } 

    if(numTerritories <= 1 || points.length <= 2){ 
     drawLineWithTranslate(graphics, new Line2D.Float(routeDescription.getStart(), routeDescription.getEnd()), xOffset, yOffset); 
     graphics.fillOval((routeDescription.getEnd().x - xOffset) - jointsize/2, (routeDescription.getEnd().y - yOffset) - jointsize/2, jointsize, jointsize); 
    } 
    else{ 
     drawCurvedPath(graphics, points, view); 
    } 
    } 

    } 

    private static double[] getIndex(Point[] points) { 
    final double[] index = new double[points.length]; 
    for(int i = 0; i < points.length; i++){ 
     index[i] = i; 
    } 
    return index; 
    } 

    private static void drawLineWithTranslate(Graphics2D graphics, Line2D line2D, double translateX, double translateY) { 
     final Line2D line = (Line2D) line2D; 
     final Point2D point1 = new Point2D.Double(line.getP1().getX() - translateX, line.getP1().getY() - translateY); 
     final Point2D point2 = new Point2D.Double(line.getP2().getX() - translateX, line.getP2().getY() - translateY); 
     graphics.draw(new Line2D.Double(point1, point2)); 
    } 

    private static Point[] getRoutePoints(RouteDescription routeDescription, MapData mapData){ 
    final List<Territory> territories = routeDescription.getRoute().getAllTerritories(); 
    final int numTerritories = territories.size(); 
    final Point[] points = new Point[numTerritories]; 
    for (int i = 0; i < numTerritories; i++) { 
     points[i] = mapData.getCenter(territories.get(i)); 
    } 
    if (routeDescription.getStart() != null) { 
     points[0] = routeDescription.getStart(); 
    } 
    if (routeDescription.getEnd() != null && numTerritories > 1) { 
     points[numTerritories - 1] = new Point(routeDescription.getEnd()); 
    } 
    return points; 
    } 

    private static double[] pointsXToDoubleArray(Point[] points){ 
    double[] result = new double[points.length]; 
    for(int i = 0; i < points.length; i++){ 
     result[i] = points[i].getX(); 
    } 
    return result; 
    } 
    private static double[] pointsYToDoubleArray(Point[] points){ 
    double[] result = new double[points.length]; 
    for(int i = 0; i < points.length; i++){ 
     result[i] = points[i].getY(); 
    } 
    return result; 
    } 

    private static double[] getCoords(PolynomialSplineFunction curve, float stepSize){ 
    final double[] coords = new double[(int) (curve.getN()/stepSize)]; 
    for(int i = 0; i < curve.getN()/stepSize; i++){ 
     coords[i] = curve.value(i * stepSize); 
    } 
    return coords; 
    } 

    private static void drawCurvedPath(Graphics2D graphics, Point[] points, MapPanel view){ 
    final double[] index = getIndex(points); 
    final float stepSize = 0.01f;//TODO calculating a step size that makes sense 
    final PolynomialSplineFunction xcurve = splineInterpolator.interpolate(index, pointsXToDoubleArray(points)); 
    final PolynomialSplineFunction ycurve = splineInterpolator.interpolate(index, pointsYToDoubleArray(points)); 
    final double[] xcoords = getCoords(xcurve, stepSize); 
    final double[] ycoords = getCoords(ycurve, stepSize); 

    for(int i = 1; i < xcoords.length; i++){ 
     //TODO maybe a line is not the best way to draw this... 
     drawLineWithTranslate(graphics, new Line2D.Double(xcoords[i-1], ycoords[i-1], xcoords[i], ycoords[i]), view.getXOffset(), view.getYOffset()); 
    } 
    } 
} 

ある

SplineInterpolatorは関数(例えばf(x)= y)のみを受け入れ、xは2つのdouble配列に分割してそれらを2回補間する必要があります...
最初にX値、次にY値。 ..
X値として「インデックス」と呼ばれる「ダミー配列」が取られ、最初の値は0、2番目の値は1番目の値、3番目の2というようになります。 3から2に、私は1ポイント0からのラインを描いています。このパスを描く1にするために
、2のように...考慮すべき2つのこと...


あります

  1. インデックスでステップサイズとして1を選択するのは意味がありますか?これは、Java doubleには64ビットしかないので、不正確さを招く可能性があり、私たちは静的な1ステップサイズで値をストレッチして圧迫しています。そしてもしそうなら、私はこれを最適化するために何を変えることができるでしょうか...
  2. そして、2番目の2倍の配列がどうすればより良い方法を描くことができますか?複数の線を描画しようとしても非常にうまく見えません - これはあまりにも大きなステップで補間された値を読み込んでいるためですか?

すべてのヘルプは非常に

EDIT理解される:「インデックス」アレイに対するステップサイズは、典型的にはつながらない、いわゆる均一なパラメータ化、そのまま1の選択 Path Zoomed in Whole Image

答えて

1

をデータポイントも比較的均一に分布していない限り、良い結果が得られます。私は次のように弦長パラメータ化又は求心パラメータ化のいずれかを使用してお勧めします:

t0 = 0.0 
t1 = d1/L 
t2 = t1 + d2/L 
t3 = t2 + d3/L 
............ 
t(n-1)= 1.0. 

場合弦長パラメータ化、使用E =上記式1.0の

d1=|P1-P0|^e, d2=|P2-P1|^e, d3=|P3-P2|^e and L = d1+d2+d3+.....d(n-1). 

。求心パラメトリゼーションの場合、e = 0.5を使用します。 e = 0.0を使用すると、単純に均一なパラメータ化が行われることに注意してください。データポイントの分布が非常に不均一な場合(ポイント間の距離が大きい場合や小さい場合など)、求心パラメトリゼーションはコード長のパラメータ化よりも良い結果をもたらすことがあります。

+0

私は描くために〜0.1ステップ程度使っていましたが、まだパスが予想通りに補間されていてもぎこちないようでした – RoiEX

+0

あなたのコードから、描画時にカーブの 'curve.getN()/ stepSize'それ。 'curve.getN()/ stepSize'の実際の数は何ですか? – fang

+0

これは、描画方法をループする頻度を示す数値です。すべてのstepSizeステップが表示されます。 – RoiEX

関連する問題