flex+BlazeDS關于軍標的實現思路和演算法

來源:互聯網
上載者:User

轉:http://bbs.esrichina-bj.cn/esri/viewthread.php?tid=57166

本帖最後由 _daniel 於 2009-11-12 22:26 編輯

前幾天說要傳軍標的演算法思想呢,結果有事耽誤了,現在我把我軍標思想給說一下。
首先利用的技術:前端as語言繪製軍標(其實就是個多邊形),把多邊形的點組成 XML字串《這裡也可以傳對象,但是在後台java段也要有相同的對應對象》通過BlazeDS的 RemoteObject方式傳到後台。
後台可以通過java儲存到資料庫中,這個最好是儲存為Clob欄位。
下面我把關鍵代碼給大家分享一下。。

//處理按一下滑鼠事件
  public function map_mouseClickHandler(event:MouseEvent):void
  {
   map.mapNavigationEnabled=false;
   //確定點擊的地圖點的座標,然後放到數組中
   var m_point:MapPoint=map.toMapFromStage(event.stageX, event.stageY);
   if (m_firstpoints == null)
   {
    m_firstpoints=new Array();
   }
   m_firstpoints.push(m_point);
  }
  //處理滑鼠雙擊事件
  public function map_mouseDoubleClickHandler(event:MouseEvent):void
  {
   m_gbjGeometry=new Polyline();
   //定義軍標的多邊形
   if (m_firstpoints.length <= 2)
   {
    m_firstpoints.splice(0);
    Alert.show("請最少點擊三個點才能完成對軍標的畫法", "Error INFO");
    return;
   }
   //根據貝茲路徑演算法來畫線和面
   drawBezierCurve();
   //形成graphic
   full_polygon_graphic=new Graphic(full_gbjpolygon, gbjSymbol);
   full_polygon_graphic.toolTip="gbj";
   full_gbjpolygon.spatialReference=map.spatialReference;
   graphicsLayer.add(full_polygon_graphic);
   map.removeEventListener(MouseEvent.CLICK, map_mouseClickHandler);
   map.removeEventListener(MouseEvent.DOUBLE_CLICK, map_mouseDoubleClickHandler);
   m_firstpoints.splice(0);
   this.dispatchEvent(new DrawEvent("drawEnd", full_polygon_graphic));
  }

/**
   *這個是貝茲路徑演算法函數用於畫軍標
   *
   */
  private function drawBezierCurve():void
  {
   //主要演算法思想是:由中軸線的兩點確定一條直線,做直線的垂線,並取垂線上一定距離的點,作成上邊曲線和下邊曲線
   if ((m_gbjGeometry.paths != null) && (m_gbjGeometry.paths.length > 0))
   {
    m_gbjGeometry.removePath(0);
   }
   //判斷點擊點的季偶性,得到軍標的多邊形
   var jishu:Boolean=true;
   if (m_firstpoints.length % 2 == 0)
   {
    jishu=false;
   }
   clogger.logger.info("你點擊的個數是不是奇數:"+jishu);
   var curvepoints:Array=getzz_geometry(m_firstpoints, jishu);

   var dgbj_geometry:Array=getdbx_geometry(curvepoints);
   full_gbjpolygon=new Polygon(dgbj_geometry);
  }
  /**
   * 這個函數就是用來求中軸線的,中軸線上的所有點
   * @param clickarray
   * @param jishu
   * @return
   *
   */
  private function getzz_geometry(clickarray:Array, jishu:Boolean):Array
  {
   //首先定義中軸曲線的點座標
   var curvepoints:Array=new Array();
   //數組長度
   var array_length:Number=clickarray.length;
   if (jishu)
   {
    clogger.logger.info("你點擊的次數是奇數個:並且他大於等於三,是:" + clickarray.length + "個");
    for (var i:int=0; i < clickarray.length - 2; i=i + 2)
    {
     for (var j:Number=0; j <= 1; j=j + 0.1)
     {
      if (i != 0 && j == 0)
       continue;
      var pos_x:Number=Math.pow((1 - j), 2) * clickarray.x + 2 * j * (1 - j) * clickarray[i + 1].x + Math.pow(j, 2) * clickarray[i + 2].x;
      var pos_y:Number=Math.pow((1 - j), 2) * clickarray.y + 2 * j * (1 - j) * clickarray[i + 1].y + Math.pow(j, 2) * clickarray[i + 2].y;
      var m_point:MapPoint=new MapPoint(pos_x, pos_y);
      curvepoints.push(m_point);
     }
    }
   }
   //下面的是偶數時後,前面那些點還是用三個點來確定,後面四個點用三次貝茲路徑來搞定。
   if (!jishu)
   {
    //判斷點擊的點是不是大於6個,如果是六個的話,首先是先用二次方貝茲曲線算出前三個來。
    if (clickarray.length >= 6)
    {
     clogger.logger.info("你點擊的次數是偶數個:並且他大於等於6,是:" + clickarray.length + "個");
     for (var i:int=0; i < clickarray.length - 5; i=i + 2)
     {
      for (var j:Number=0; j <= 1; j=j + 0.1)
      {
       if (i != 0 && j == 0)
        continue;
       var pos_x:Number=Math.pow((1 - j), 2) * clickarray.x + 2 * j * (1 - j) * clickarray[i + 1].x + Math.pow(j, 2) * clickarray[i + 2].x;
       var pos_y:Number=Math.pow((1 - j), 2) * clickarray.y + 2 * j * (1 - j) * clickarray[i + 1].y + Math.pow(j, 2) * clickarray[i + 2].y;
       var m_point:MapPoint=new MapPoint(pos_x, pos_y);
       //中軸線的點數
       curvepoints.push(m_point);
      }
     }
     //這最後四個點用三次貝茲路徑來確定
     var p_1:MapPoint=clickarray[array_length - 4];
     var p_2:MapPoint=clickarray[array_length - 3];
     var p_3:MapPoint=clickarray[array_length - 2];
     var p_4:MapPoint=clickarray[array_length - 1];
     for (var k:Number=0; k < 1; k=k + 0.1)
     {
      if (k == 0)
       continue;
      var pos_x:Number=p_1.x * Math.pow((1 - k), 3) + 3 * p_2.x * k * Math.pow((1 - k), 2) + 3 * p_3.x * Math.pow(k, 2) * (1 - k) + p_4.x * Math.pow(k, 3);
      var pos_y:Number=p_1.y * Math.pow((1 - k), 3) + 3 * p_2.y * k * Math.pow((1 - k), 2) + 3 * p_3.y * Math.pow(k, 2) * (1 - k) + p_4.y * Math.pow(k, 3);
      var m_point:MapPoint=new MapPoint(pos_x, pos_y);
      //中心軸的添加
      curvepoints.push(m_point);
     }
    }
    //如果僅僅就四個點的話,下面是求只有四個點的公式
    else
    {
     clogger.logger.info("你點擊的次數是4個,他是:" + clickarray.length + "個");
     var p_1:MapPoint=clickarray[0];
     var p_2:MapPoint=clickarray[1];
     var p_3:MapPoint=clickarray[2];
     var p_4:MapPoint=clickarray[3];
     for (var k:Number=0; k < 1; k=k + 0.1)
     {
      var pos_x:Number=p_1.x * Math.pow((1 - k), 3) + 3 * p_2.x * k * Math.pow((1 - k), 2) + 3 * p_3.x * Math.pow(k, 2) * (1 - k) + p_4.x * Math.pow(k, 3);
      var pos_y:Number=p_1.y * Math.pow((1 - k), 3) + 3 * p_2.y * k * Math.pow((1 - k), 2) + 3 * p_3.y * Math.pow(k, 2) * (1 - k) + p_4.y * Math.pow(k, 3);
      var m_point:MapPoint=new MapPoint(pos_x, pos_y);
      //中心軸的添加
      curvepoints.push(m_point);
     }
    }
   }
   clogger.logger.info("這個中軸線上的所有的點的個數是:" + curvepoints.length);
   return curvepoints;
  }

  /**
   * 這個函數是用來求多邊行的各個點的
   * 他利用的原理就是求垂線的距離
   * @return
   *
   */
  private function getdbx_geometry(curvepoints:Array):Array
  {
   //定義上邊曲線的點座標數組(當確定軍標多邊形的時候我是從這個數組開始的)
   var topcurepoints:Array=new Array();
   //定義下邊曲線的點座標數組
   var bottomcurepoints:Array=new Array();
   //定義左上測的直線
   var left_top_points:Array=new Array();
   //定義左下側的直線
   var left_bottom_points:Array=new Array();
   //定義右上方邊的數組
   var right_top_points:Array=new Array();
   //定義中軸線離上下兩邊的距離
   var dis:Number=(8 - map.level) * (8 - map.level) * 40;
   //大的架構肯定是從0--1
   var c_length:Number=curvepoints.length;
   for (var u:Number=0; u < curvepoints.length; u++)
   {
    if (u == 0)
    {
     continue;
    }
    else
    {
     var m_point:MapPoint=curvepoints;
     var pos_x:Number=m_point.x;
     var pos_y:Number=m_point.y;
     //先求上一點的座標
     var pre_point:MapPoint=curvepoints[u - 1];
     //進行計算取的上下邊的點
     var pre_pos_x:Number=pre_point.x;
     var pre_pos_y:Number=pre_point.y;
     var slope:Number=(pos_y - pre_pos_y) / (pos_x - pre_pos_x);
     //上邊點確定
     var bb:Number=dis * (1 - u / c_length * 0.9);
     var cos_number:Number=Math.cos(Math.atan(slope) - Math.PI / 2);
     var sin_number:Number=Math.sin(Math.atan(slope) - Math.PI / 2);
     var top_pos_x:Number=0.0;
     var top_pos_y:Number=0.0;
     //下面分四種情況畫線。
     if (pre_pos_x <= pos_x && pre_pos_y <= pos_y)
     {
      top_pos_x=pre_pos_x - ((bb * cos_number) < 0 ? (-bb * cos_number) : (bb * cos_number));
      top_pos_y=pre_pos_y + ((bb * sin_number) < 0 ? (-bb * sin_number) : (bb * sin_number));
     }
     else if (pre_pos_x <= pos_x && pre_pos_y > pos_y)
     {
      top_pos_x=pre_pos_x + ((bb * cos_number) < 0 ? (-bb * cos_number) : (bb * cos_number));
      top_pos_y=pre_pos_y + ((bb * sin_number) < 0 ? (-bb * sin_number) : (bb * sin_number));
     }
     else if (pre_pos_x >= pos_x && pre_pos_y >= pos_y)
     {
      top_pos_x=pre_pos_x + ((bb * cos_number) < 0 ? (-bb * cos_number) : (bb * cos_number));
      top_pos_y=pre_pos_y - ((bb * sin_number) < 0 ? (-bb * sin_number) : (bb * sin_number));
     }
     else if (pre_pos_x >= pos_x && pre_pos_y <= pos_y)
     {
      top_pos_x=pre_pos_x - ((bb * cos_number) < 0 ? (-bb * cos_number) : (bb * cos_number));
      top_pos_y=pre_pos_y - ((bb * sin_number) < 0 ? (-bb * sin_number) : (bb * sin_number));
     }
     var top_point:MapPoint=new MapPoint(top_pos_x, top_pos_y);
     clogger.logger.info("上半部分是:" + top_pos_x + "yy:" + top_pos_y);
     topcurepoints.push(top_point);
     //下面來確定下邊的曲線
     var bottom_pos_x:Number;
     var bottom_pos_y:Number;
     if (pre_pos_x <= pos_x && pre_pos_y <= pos_y)
     {
      bottom_pos_x=pre_pos_x + ((bb * cos_number) < 0 ? (-bb * cos_number) : (bb * cos_number));
      bottom_pos_y=pre_pos_y - ((bb * sin_number) < 0 ? (-bb * sin_number) : (bb * sin_number));
     }
     else if (pre_pos_x <= pos_x && pre_pos_y > pos_y)
     {
      bottom_pos_x=pre_pos_x - ((bb * cos_number) < 0 ? (-bb * cos_number) : (bb * cos_number));
      bottom_pos_y=pre_pos_y - ((bb * sin_number) < 0 ? (-bb * sin_number) : (bb * sin_number));
     }
     else if (pre_pos_x >= pos_x && pre_pos_y >= pos_y)
     {
      bottom_pos_x=pre_pos_x - ((bb * cos_number) < 0 ? (-bb * cos_number) : (bb * cos_number));
      bottom_pos_y=pre_pos_y + ((bb * sin_number) < 0 ? (-bb * sin_number) : (bb * sin_number));
     }
     else if (pre_pos_x >= pos_x && pre_pos_y <= pos_y)
     {
      bottom_pos_x=pre_pos_x + ((bb * cos_number) < 0 ? (-bb * cos_number) : (bb * cos_number));
      bottom_pos_y=pre_pos_y + ((bb * sin_number) < 0 ? (-bb * sin_number) : (bb * sin_number));
     }
     var bottom_point:MapPoint=new MapPoint(bottom_pos_x, bottom_pos_y);
     bottomcurepoints.push(bottom_point);
    }
   }
   /*
    **下面是添加軍標箭頭的程式,因為現在已經得到上下邊界的曲線了。
    **
    */
   var end_curvepoint:MapPoint=curvepoints[curvepoints.length - 1];
   var end_top_point:MapPoint=topcurepoints[topcurepoints.length - 1];
   var end_top_point2:MapPoint=topcurepoints[topcurepoints.length - 2];
   //求箭頭上方的點
   var x2:Number=end_curvepoint.x;
   var y2:Number=end_curvepoint.y;
   var pos_x:Number=end_top_point.x;
   var pos_y:Number=end_top_point.y;
   var pre_pos_x:Number=end_top_point2.x;
   var pre_pos_y:Number=end_top_point2.y;
   var end_slope:Number=(pre_pos_y - pos_y) / (pre_pos_x - pos_x);
   var b:Number=dis;
   var end_point_x:Number;
   var end_point_y:Number;
   var cos_number:Number=Math.cos(Math.atan(end_slope) - Math.PI / 2);
   var sin_number:Number=Math.sin(Math.atan(end_slope) - Math.PI / 2);
   //下面分四種情況畫線。
   if (pre_pos_x <= pos_x && pre_pos_y <= pos_y)
   {
    end_point_x=pre_pos_x - ((b * cos_number) < 0 ? (-b * cos_number) : (b * cos_number));
    end_point_y=pre_pos_y + ((b * sin_number) < 0 ? (-b * sin_number) : (b * sin_number));
   }
   else if (pre_pos_x <= pos_x && pre_pos_y > pos_y)
   {
    end_point_x=pre_pos_x + ((b * cos_number) < 0 ? (-b * cos_number) : (b * cos_number));
    end_point_y=pre_pos_y + ((b * sin_number) < 0 ? (-b * sin_number) : (b * sin_number));
   }
   else if (pre_pos_x >= pos_x && pre_pos_y >= pos_y)
   {
    end_point_x=pre_pos_x + ((b * cos_number) < 0 ? (-b * cos_number) : (b * cos_number));
    end_point_y=pre_pos_y - ((b * sin_number) < 0 ? (-b * sin_number) : (b * sin_number));
   }
   else if (pre_pos_x >= pos_x && pre_pos_y <= pos_y)
   {
    end_point_x=pre_pos_x - ((b * cos_number) < 0 ? (-b * cos_number) : (b * cos_number));
    end_point_y=pre_pos_y - ((b * sin_number) < 0 ? (-b * sin_number) : (b * sin_number));
   }
   //建立第三個點,然後建立三角形
   clogger.logger.info("右上面的點的橫座標點x:" + end_point_x + "----------右上方點的縱座標的y:" + end_point_y);
   //得到右上方的點
   var end_right_point:MapPoint=new MapPoint(end_point_x, end_point_y);
   topcurepoints.push(end_right_point);
   //最右邊,箭頭頂點的座標是
   clogger.logger.info("頂點的橫座標是x:" + end_curvepoint.x + "---------頂點的縱座標y:" + end_curvepoint.y);
   topcurepoints.push(end_curvepoint);
   //下邊線
   var end_bottom_point:MapPoint=bottomcurepoints[bottomcurepoints.length - 1];
   var end_bottom_point2:MapPoint=bottomcurepoints[bottomcurepoints.length - 2];
   //求箭頭下方向的點
   var bx1:Number=end_bottom_point.x;
   var by1:Number=end_bottom_point.y;
   var bx0:Number=end_bottom_point2.x;
   var by0:Number=end_bottom_point2.y;
   var bend_slope:Number=(by1 - by0) / (bx1 - bx0);
   var bend_point_x:Number;
   var bend_point_y:Number;
   var bend_cos_number:Number=Math.cos(Math.atan(bend_slope) - Math.PI / 2);
   var bend_sin_number:Number=Math.sin(Math.atan(bend_slope) - Math.PI / 2);
   if (bx0 <= bx1 && by0 <= by1)
   {
    bend_point_x=bx0 + ((b * bend_cos_number) < 0 ? (-b * bend_cos_number) : (b * bend_cos_number));
    bend_point_y=by0 - ((b * bend_sin_number) < 0 ? (-b * bend_sin_number) : (b * bend_sin_number));
   }
   else if (bx0 <= bx1 && by0 > by1)
   {
    bend_point_x=bx0 - ((b * bend_cos_number) < 0 ? (-b * bend_cos_number) : (b * bend_cos_number));
    bend_point_y=by0 - ((b * bend_sin_number) < 0 ? (-b * bend_sin_number) : (b * bend_sin_number));
   }
   else if (bx0 >= bx1 && by0 >= by1)
   {
    bend_point_x=bx0 - ((b * bend_cos_number) < 0 ? (-b * bend_cos_number) : (b * bend_cos_number));
    bend_point_y=by0 + ((b * bend_sin_number) < 0 ? (-b * bend_sin_number) : (b * bend_sin_number));
   }
   else if (bx0 >= bx1 && by0 <= by1)
   {
    bend_point_x=bx0 + ((b * bend_cos_number) < 0 ? (-b * bend_cos_number) : (b * bend_cos_number));
    bend_point_y=by0 + ((b * bend_sin_number) < 0 ? (-b * bend_sin_number) : (b * bend_sin_number));
   }
   clogger.logger.info("下方的點的橫座標x為:" + bend_point_x + "-------下方的點的縱座標y為:" + bend_point_y);
   //得到右下方的點
   var bend_right_point:MapPoint=new MapPoint(bend_point_x, bend_point_y);
   topcurepoints.push(bend_right_point);
   for (var k:Number=bottomcurepoints.length - 1; k >= 0; k--)
   {
    //  這個是下半部分
    clogger.logger.info("由此開始下半部分:" + bottomcurepoints[k].x + "yyyyy:" + bottomcurepoints[k].y);
    topcurepoints.push(bottomcurepoints[k]);
   }
   //添加尾部的部分,至此完成對軍標多邊行的演算法,
   topcurepoints.push(curvepoints[1]);
   topcurepoints.push(topcurepoints[0]);
   clogger.logger.info("軍標上的點的個數是" + topcurepoints.length);
   var rings:Array=new Array();
   rings.push(topcurepoints);
   return rings;
  }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.