精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

圖形編輯器開發:基于相交策略選中圖形

開發 前端
我想要選中一個大矩形,就比較費勁,要畫一個比它還大的選區,可能還會把其他的矩形不小心放進去(那你別用選區,直接點選啊)。 不管怎樣,我選擇同時提供 “包含(Contain)” 和 "相交(Intersect)" 兩種模式,默認使用相交策略。

大家好,我是前端西瓜哥。

我開發的圖形編輯器,原本選中圖形是基于選區是否完全包含對應圖形來判斷其是否被選中,使用的是矩形包含判斷。

編輯器 github 地址:

https://github.com/F-star/suika

線上體驗:

https://blog.fstars.wang/app/suika/

但用著用著,我發現包含可能并不是一個好策略。

我想要選中一個大矩形,就比較費勁,要畫一個比它還大的選區,可能還會把其他的矩形不小心放進去(那你別用選區,直接點選啊)。

不管怎樣,我選擇同時提供 “包含(contain)” 和 "相交(intersect)" 兩種模式,默認使用相交策略。

包含選擇

包含策略很簡單,遍歷圖形,對比 selection 選區矩形和圖形的包圍盒,判斷是否為前者包含后者的關系。

如果是,就放到選中圖形集合中。

相比相交的實現,算法不復雜。

// 矩形 1 是否包含矩形 2
function isRectContain(rect1: IRect, rect2: IRect) {
  return (
    rect1.x <= rect2.x &&
    rect1.y <= rect2.y &&
    rect1.x + rect1.width >= rect2.x + rect2.width &&
    rect1.y + rect1.height >= rect2.y + rect2.height
  );
}

// 使用
for (const el of elements) {
  // getBBox 拿到的是 AABB 包圍盒
  if(isRectContain(selection, el.getBBox())) {
    selectSet.add(el);
  }
}

相交選擇

相交(也叫碰撞)的實現類似。

// 兩矩形是否相交
function isRectIntersect(rect1: IRect, rect2: IRect) {
  return (
    rect1.x <= rect2.x + rect2.width &&
    rect1.x + rect1.width >= rect2.x &&
    rect1.y <= rect2.y + rect2.height &&
    rect1.y + rect1.height >= rect2.y
  );
}

// 使用
for (const el of elements) {
  // getBBox 拿到的是 AABB 包圍盒
  if(isRectIntersect(selection, el.getBBox())) {
    selectSet.add(el);
  }
}

效果:

看起來不錯,但它這個相交檢測,很 “粗糙”。

因為上面實現,只做了大的 AABB 包圍盒的相交檢測,沒有做小的 OBB 包圍盒的相交檢測。

對于發生旋轉的圖形,selection 如果和包裹圖形的空白區域相交了,圖形也被選中。

這種事情,不要啊。

OBB 相交檢測

我們來實現更精準的 OBB 的相交檢測。

為此西瓜哥我調研(其實是瞎想)了幾個方案,并研究了算法實現。

方案 1:線段相交判斷

直接一點,判斷 selection 的邊和圖形的邊是否有相交的。

核心算法實現為:

type Point = [number, number];

function crossProduct(p1: Point, p2: Point, p3: Point): number {
  const x1 = p2[0] - p1[0];
  const y1 = p2[1] - p1[1];
  const x2 = p3[0] - p1[0];
  const y2 = p3[1] - p1[1];
  return x1 * y2 - x2 * y1;
}

function isSegmentIntersect(
  seg1: [Point, Point],
  seg2: [Point, Point],
): boolean {
  const [a, b] = seg1;
  const [c, d] = seg2;

  const d1 = crossProduct(a, b, c);
  const d2 = crossProduct(a, b, d);
  const d3 = crossProduct(c, d, a);
  const d4 = crossProduct(c, d, b);

  // 突然發現這里可以做一個短路計算優化
  return d1 * d2 < 0 && d3 * d4 < 0;
}

光是比較 1 對線段,就要進行如此多的計算。而我們要對比 4 * 4,共 16 組(當然這是最壞情況)。

感覺 8 太行,最后沒選擇該方案。

(理論上應該做性能測試對比各種實現的,還要考慮用戶使用選區的場景,是否會經常出現特定算法的最壞時間復雜度的情形,有空再做吧)

方案2:分離軸定理算法

這個算法挺有意思。

分離軸(Separating Axis Theorem,簡稱SAT),它的思想是:

如果能找到一條直線將兩個圖形分開,那說明這兩個圖形不相交。

如圖:

具體做法是做投影。(通過降維,將大問題拆分成小問題)

我們會對兩個凸多邊形做投影,投影到的線稱為 “分離軸”。

分離軸基本選擇的是兩個圖形的每條邊對應的法向量。當發現投影產生的兩條線段沒有相交,那找到了那條那條分割兩圖形的直線,證明兩個凸多邊形不相交。

否則繼續,如果都沒找到,說明相交。

下圖是以一個圖形的藍邊的法向量作為分離軸,進行投影的示意圖。

求投影會用到向量點乘的運算。

因為不是本文重點,具體實現細節就不講解了,可以考慮以后專門寫一篇文章。

矩形碰撞,特殊的分離軸定理碰撞

不知道你發現沒有,從分離軸線的角度去看,兩個沒有旋轉矩形的相交判斷,其實是一個特例。

我們在判斷選區矩形和圖形的 AABB 包圍盒是否相交時,其實就已經完成了 基于選區矩形對應的所有分離軸 的投影上是否相交的比較。

接下來我們只要再對圖形的邊對應的分離軸線投影,去對比就好了。

怎么做呢?

我們 “旋轉回來”,將圖形掰正,選區矩形產生了旋轉角度,計算選區矩形的 AABB 包圍盒,再進行矩形對比就好了。

這樣,圖形的分離軸的投影也對比完了,所有的分離軸都對比了,就能判斷出選區和圖形的 OBB 包圍盒是否碰撞了。

甚至都不用向量點乘。

OBB 相交判斷代碼實現

下面給出代碼實現。

// 使用相交策略,遍歷圖形是否和選區矩形相交。
for (const el of elements) {
  let isSelected = false; // 是否被選中到
 
  // 首先做 AABB 碰撞檢測
  // 絕大多數場景下,只有少數圖形和選區有相交
  if (!isRectIntersect(selection, el.getBBox())) {
    // 其實這里用 break; 在意圖上更明顯
    isSelected = false;
  } else {
    // 如果旋轉角度為 90 的倍數,
    // 則 OBB 等價于 AABB,前面已經判斷了,沒必要繼續算了
    if (el.rotation % HALF_PI == 0) {
      isSelected = true;
    } else {
      // OBB 碰撞檢測
      // 使用分離軸定理的特殊寫法
      const { x: cx, y: cy } = el.getCenter();
      const r = -el.rotation;
      const s1 = transformRotate(selection.x, selection.y, r, cx, cy);
      
      // 下面一大段代碼都是求選區旋轉后的 AABB
      const s2 = transformRotate(
        selection.x + selection.width,
        selection.y + selection.height,
        r,
        cx,
        cy,
      );
      const s3 = transformRotate(
        selection.x + selection.width,
        selection.y,
        r,
        cx,
        cy,
      );
      const s4 = transformRotate(
        selection.x,
        selection.y + selection.height,
        r,
        cx,
        cy,
      );

      const rotatedSelectionX = Math.min(s1.x, s2.x, s3.x, s4.x);
      const rotatedSelectionY = Math.min(s1.y, s2.y, s3.y, s4.y);
      const rotatedSelectionWidth =
        Math.max(s1.x, s2.x, s3.x, s4.x) - rotatedSelectionX;
      const rotatedSelectionHeight =
        Math.max(s1.y, s2.y, s3.y, s4.y) - rotatedSelectionY;

      // 這個就是選區矩形旋轉后的 AABB 包圍盒
      const rotatedSelection = {
        x: rotatedSelectionX,
        y: rotatedSelectionY,
        width: rotatedSelectionWidth,
        height: rotatedSelectionHeight,
      };

      // 對比它們(注意圖形不要再用 AABB 了)
      isSelected = isRectIntersect(rotatedSelection, {
        x: el.x,
        y: el.y,
        width: el.width,
        height: el.height,
      });
    }
  }

  // 更新選中圖形集合
  if (isSelected) {
    selectSet.add(el);
  }
}

看看效果,很完美。

結尾

矩形相交是分離軸定理相交算法的特殊情況。

責任編輯:姜華 來源: 前端西瓜哥
相關推薦

2023-10-19 10:12:34

圖形編輯器開發縮放圖形

2023-01-18 08:30:40

圖形編輯器元素

2023-09-07 08:24:35

圖形編輯器開發繪制圖形工具

2023-09-26 07:39:21

2023-09-11 09:02:31

圖形編輯器模塊間的通信

2024-01-08 08:30:05

光標圖形編輯器開發游標

2023-07-31 08:46:07

圖形編輯器圖形自動對齊

2023-10-10 16:04:30

圖形編輯器格式轉換

2023-10-08 08:11:40

圖形編輯器快捷鍵操作

2023-08-28 08:10:50

Hex圖形編輯器

2023-02-01 09:21:59

圖形編輯器標尺

2023-02-09 07:02:30

圖形編輯器修改圖形

2023-02-06 16:59:57

Canvas編輯器

2023-04-07 08:02:30

圖形編輯器對齊功能

2023-07-07 13:56:01

圖形編輯器畫布縮放

2024-01-03 08:43:17

圖形編輯器旋轉控制點縮放控制點

2023-02-02 14:07:00

圖形編輯器Canvas

2023-05-09 08:15:32

圖形編輯器撤銷重做功能

2023-04-10 08:45:44

圖形編輯器排列移動功能

2023-06-12 08:22:56

圖形編輯器工具
點贊
收藏

51CTO技術棧公眾號

欧美自拍大量在线观看| 日韩欧美自拍偷拍| 亚洲精品久久区二区三区蜜桃臀| 中文字幕精品无码亚| 在线中文字幕亚洲| 欧美精品一区二区三区在线| 18禁男女爽爽爽午夜网站免费| 国产高清免费av在线| 日本欧美一区二区三区乱码| 九九久久精品一区| 久久精品国产亚洲AV熟女| 久久99国产精品二区高清软件| 亚洲精品国久久99热| 久久久综合亚洲91久久98| 中文在线a天堂| 尤物在线精品| 日韩视频在线免费| 国产精品嫩草av| 一级片一区二区三区| 91精品秘密在线观看| 亚洲毛片在线看| 久久精品国产99久久99久久久| 麻豆mv在线看| 亚洲毛片av在线| 欧美高清性xxxxhd| 亚洲av无码乱码国产麻豆| 久久一二三四| 国产综合在线看| av资源在线免费观看| 巨人精品**| 91精选在线观看| 免费无码国产v片在线观看| 国产美女av在线| 久久久精品国产99久久精品芒果| 亚洲影院高清在线| 少妇一级淫片日本| 国产欧美在线| 欧美黄色免费网站| 免费国产羞羞网站美图| 成人在线免费小视频| 日韩精品视频免费| 成人做爰www看视频软件| 成人精品高清在线视频| 日韩欧美精品免费在线| 日本一本中文字幕| 国产在线二区| 中国av一区二区三区| 久久综合婷婷综合| 亚洲av成人无码久久精品老人 | 欧美视频官网| 最近中文字幕日韩精品| 波多野吉衣中文字幕| 色吊丝一区二区| 日韩精品视频在线播放| 日韩无码精品一区二区| youjizz亚洲| 亚洲精品在线一区二区| 少妇极品熟妇人妻无码| 一区二区日韩| 精品国产区一区| 乱码一区二区三区| h视频久久久| 亚洲电影在线观看| 国产精品久久久久久在线观看| 97se亚洲| 亚洲国产成人精品久久| 国产香蕉精品视频| 女同一区二区三区| 日韩高清有码在线| 91网站免费入口| 日韩情爱电影在线观看| 自拍偷拍亚洲在线| 国产精品免费人成网站酒店| 91av精品| 77777少妇光屁股久久一区| 综合激情网五月| 视频一区欧美精品| 成人欧美在线观看| 高清毛片aaaaaaaaa片| 91小视频在线观看| 神马影院我不卡午夜| 免费观看成人高潮| 亚洲精品成a人| 日韩a∨精品日韩在线观看| 欧美黄色网页| 日韩欧美在线视频观看| 国产又猛又黄的视频| www一区二区三区| 精品毛片乱码1区2区3区| 艳妇乳肉亭妇荡乳av| 激情综合网站| 久久精品中文字幕电影| 久久精品女人毛片国产| 日韩精品一卡二卡三卡四卡无卡| 成人欧美一区二区三区在线湿哒哒| www黄色网址| 久久这里只有精品视频网| 亚洲高清在线播放| 欧美xxx黑人xxx水蜜桃| 91黄色小视频| 伊人久久久久久久久| 九一亚洲精品| 欧美肥臀大乳一区二区免费视频| av网站中文字幕| 国产一区欧美一区| 欧美精品久久| 午夜羞羞小视频在线观看| 欧美性精品220| 国产999免费视频| 亚洲日产av中文字幕| 麻豆国产va免费精品高清在线| 日韩欧美三级视频| 久久99国产精品久久99果冻传媒| 久久99精品久久久久久久青青日本 | 三级影片在线看| 久久国产免费| 成人xxxxx色| 婷婷五月在线视频| 狠狠躁夜夜躁人人爽超碰91| 激情黄色小视频| 久久成人av| 97视频国产在线| 国产黄色av网站| 国产精品欧美一区二区三区| 欧美 日韩 国产 高清| 欧美电影在线观看一区| 中文字幕欧美专区| 中文字幕在线观看视频免费| 成人深夜在线观看| 青青草综合在线| 亚洲精品aa| 在线看日韩欧美| 一级黄色在线视频| 91丨九色丨黑人外教| 美女av免费观看| 成人动漫视频在线观看| 一道本无吗dⅴd在线播放一区| 日韩精品在线观看免费| 福利电影一区二区| 成人一区二区av| 欧美一级片网址| 久久精品视频网站| 一二区在线观看| 中文字幕欧美三区| 我要看一级黄色大片| 成人3d动漫在线观看| 国产成人91久久精品| 色噜噜狠狠狠综合欧洲色8| 欧美午夜精品理论片a级按摩| 精品国产一区在线| 91久久综合| 国产精品久久久久久久久久直播| 黄色网在线免费看| 91麻豆精品国产91久久久使用方法 | 久久露脸国产精品| 亚洲av少妇一区二区在线观看| 综合色中文字幕| 午夜免费福利网站| 亚洲一区色图| 97人摸人人澡人人人超一碰| av大大超碰在线| 日韩欧美中文字幕一区| 久久香蕉精品视频| 成人午夜视频免费看| 国产美女在线一区| 日韩精品免费一区二区三区竹菊| 91国产美女在线观看| 人成在线免费视频| 在线观看免费成人| 国产精品夜夜夜爽阿娇| 国产一区二区三区黄视频| av一区二区三区免费观看| www.国产精品一区| 日本韩国欧美精品大片卡二| 91se在线| 日韩西西人体444www| 日本特黄一级片| 国产色综合久久| 日韩a一级欧美一级| 亚洲电影在线| 先锋影音亚洲资源| 日韩中文字幕在线一区| 97久久国产精品| 国产三区四区在线观看| 欧美一区二区黄色| 久久国产视频播放| 国产精品国产自产拍高清av| 91人妻一区二区三区| 一本久久综合| 一本久道久久综合| 另类图片第一页| 国产精品十八以下禁看| 欧美韩日亚洲| 中文字幕亚洲欧美日韩在线不卡| 国产av无码专区亚洲a∨毛片| 亚洲va韩国va欧美va精品| 亚洲综合第一区| 成人视屏免费看| 美女网站色免费| 亚洲美女一区| 中文字幕人成一区| 亚洲伊人春色| 91黄在线观看| 久久精品国产福利| 91成人在线视频| gogogogo高清视频在线| 亚洲欧美www| 亚洲精品人妻无码| 欧美久久久一区| 毛片毛片女人毛片毛片| 一区二区激情视频| 免费看的黄色录像| 91麻豆精品在线观看| 性活交片大全免费看| 久久99久久精品欧美| 韩国一区二区av| 伊人精品在线| 成人黄色片免费| 亚洲精品国产首次亮相| 视频一区二区三| 天美av一区二区三区久久| 91在线在线观看| 亚洲一区二区三区久久久| 国产成人精品一区二区三区| 多野结衣av一区| 国内外成人免费激情在线视频网站 | 91美女在线观看| 国产女人18毛片水真多18| 国产成人精品一区二区三区网站观看 | 日韩欧美亚洲日产国| 亚洲色图美女| 久久精品99久久| 欧美五码在线| 精品国产一区二区三| 国产成人澳门| 92国产精品视频| 国产精品成人3p一区二区三区| 国产精品流白浆视频| 欧美日韩激情电影| 国产精品久久精品| 欧美羞羞视频| 国产精品三级网站| 久草综合在线| 成人写真福利网| 国产精一区二区| 91久久国产精品| 日韩一区二区三区精品| 97人人香蕉| 99精品国产一区二区三区2021| 99视频国产精品免费观看| 日韩精品三级| 国产精品国产三级欧美二区| 国产精品午夜av| 九九九久久久| 欧洲grand老妇人| 亚洲一区二区三区精品动漫| 日韩电影免费网址| 黄色一级片网址| 欧美日韩国产探花| 国内精品视频一区二区三区| 中文亚洲字幕| 久草福利视频在线| 久草中文综合在线| 国产伦理在线观看| 91年精品国产| 国精产品久拍自产在线网站| 亚洲免费色视频| 国产乡下妇女做爰毛片| 欧美性猛交xxxx黑人| 在线观看亚洲黄色| 欧美一级欧美一级在线播放| 日韩有码第一页| 亚洲欧美制服综合另类| www视频在线观看免费| 久久影院资源网| 超级白嫩亚洲国产第一| 国产精品网红直播| 成人偷拍自拍| 日韩欧美一区二区三区四区五区| 亚洲澳门在线| 国产a级一级片| 国产乱子轮精品视频| 国产精品一区二区入口九绯色| 亚洲国产精品传媒在线观看| 久久成人在线观看| 色香蕉久久蜜桃| xxxx18国产| 亚洲一区av在线播放| 99热国产在线| 日韩美女在线播放| 国产精品毛片无码| 久久精品中文字幕一区二区三区 | 中文一区二区完整视频在线观看 | av免费看在线| 欧美亚洲在线播放| 日本成人精品| 日本成人黄色| 国产主播一区| 午夜免费看毛片| 91视频国产观看| 日本妇女毛茸茸| 欧美综合一区二区三区| 黑人精品一区二区| 精品国产一区久久久| 三上悠亚一区二区| 国产精品yjizz| 91精品在线观看国产| 少妇高清精品毛片在线视频| 国产成人精品一区二| 多男操一女视频| 色嗨嗨av一区二区三区| 欧美熟妇另类久久久久久不卡 | 色就是色欧美| 中文精品视频| 日本一级大毛片a一| 综合久久一区二区三区| 波多野结衣在线观看一区| 亚洲精品美女久久久| 欧美性猛片xxxxx免费中国| 国产精品自拍网| 精品视频日韩| 波多野结衣家庭教师视频| 不卡一二三区首页| 久久久香蕉视频| 欧美一区二区三区人| 黄色的网站在线观看| 国产日韩欧美一二三区| 国产精品一在线观看| 国产女女做受ⅹxx高潮| 99re成人精品视频| 日韩三级小视频| 精品福利一二区| 不卡一本毛片| 国产视频精品网| 亚洲激情成人| 这里只有精品在线观看视频| 亚洲国产精品久久不卡毛片| 不卡的日韩av| 欧美激情aaaa| xxxxxhd亚洲人hd| 91好吊色国产欧美日韩在线| 成人h动漫精品一区二区| 日本少妇xxxx动漫| 亚洲电影av在线| 午夜欧美激情| 亚洲国内高清视频| 日韩av女优在线观看| 亚洲级视频在线观看免费1级| av免费不卡国产观看| 久中文字幕一区| 日韩福利视频网| www.日本高清视频| 欧美精三区欧美精三区| 九七久久人人| 99re国产| 99精品国产在热久久| 最新中文字幕视频| 欧美性高清videossexo| 青青青青在线| 成人免费在线看片| 亚洲美女一区| 呻吟揉丰满对白91乃国产区| 欧美精品1区2区3区| 男男gaygays亚洲| 精品视频第一区| 免费欧美在线视频| 国产精品国产精品88| 亚洲成人网av| 成人在线视频播放| 裸体裸乳免费看| 99精品久久久久久| 中文字幕精品一区二区精| 久久色免费在线视频| 国产精品对白久久久久粗| 99蜜桃臀久久久欧美精品网站| 国产精品女上位| 高h震动喷水双性1v1| 国产精品美女免费看| 国产精品99免费看| 亚洲一区二区三区蜜桃| 日韩一区二区在线看片| 国产.精品.日韩.另类.中文.在线.播放| 日本天堂在线播放| 色综合色狠狠综合色| 香蕉视频在线看| 国产91精品入口17c| 美女诱惑一区| 国产盗摄x88av| 亚洲另类xxxx| 国产一区二区av在线| 欧美日韩国产精品激情在线播放| 国产精品午夜免费| 日批视频在线播放| 国产精品一区二区3区| 亚洲午夜一级| 色撸撸在线视频| 国产综合一区二区| 国产这里有精品| 一本一本久久a久久精品综合小说 一本一本久久a久久精品牛牛影视 | 小早川怜子影音先锋在线观看|