精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

在线观看免费小视频| www.国产在线视频| 国产又粗又黄又爽的视频| 天天综合国产| 亚洲国产精品999| 麻豆传传媒久久久爱| 黄色网址在线免费| 91免费精品国自产拍在线不卡| 国产精品美女久久久久久免费| 欧洲猛交xxxx乱大交3| 在线看成人短视频| 日韩一区二区三区三四区视频在线观看| 青青草国产免费| lutube成人福利在线观看| 国产传媒欧美日韩成人| 热草久综合在线| 激情四射综合网| 日韩精品欧美| 亚洲成人网久久久| 奇米视频7777| 偷拍视频一区二区三区| 亚洲免费伊人电影| 日本一区二区三区在线视频| 国产成人自拍一区| 精品一区二区三区av| 91高清免费在线观看| 国产探花在线播放| 久久影视一区| 亚洲午夜色婷婷在线| 国产免费a级片| 亚洲国产91视频| 一本在线高清不卡dvd| www.国产二区| 久做在线视频免费观看| 国产精品私人影院| 欧美日韩免费精品| 完全免费av在线播放| 999福利在线视频| 亚洲人精品一区| 五月天亚洲综合| 国产色a在线| 久久综合久久鬼色中文字| 国产精品一区二区三区四区五区| 国产精品区在线观看| 日本女人一区二区三区| 国产成人中文字幕| 久久久成人免费视频| 99精品国产在热久久| 欧美激情videos| 免费一级肉体全黄毛片| 欧美日本一区| 欧美大肥婆大肥bbbbb| 东方av正在进入| 亚洲91视频| 久热爱精品视频线路一| 污软件在线观看| 91成人观看| 欧美日韩国产成人| 久久免费精彩视频| 国产精品成人一区二区网站软件| 久热精品在线视频| 欧美丰满熟妇bbbbbb| 亚洲综合色网| 久久久久久国产精品| 国产亚洲精品久久久久久无几年桃 | 精品奇米国产一区二区三区| 免费国偷自产拍精品视频| 麻豆国产一区| 亚洲精品成人久久| 人妻丰满熟妇av无码久久洗澡 | 日韩精品中文字幕在线观看| 国产中文字幕一区二区| 九九视频免费观看视频精品| 中文字幕精品网| www.99re7| 激情五月***国产精品| 97视频免费在线看| 久久亚洲精品石原莉奈| 久久精品国产成人一区二区三区| 91久久久在线| 天天插天天干天天操| 久久久久成人黄色影片| 亚洲免费不卡| 欧美女同一区| 日本韩国一区二区三区视频| 中文字幕国产高清| 麻豆一区一区三区四区| 亚洲午夜av久久乱码| 黄色录像一级片| 国产欧美综合一区二区三区| 国产精品午夜国产小视频| 国产黄色av片| 久久久久久久免费视频了| 亚洲一区二区三区精品视频 | 一区二区理论电影在线观看| 免费在线观看亚洲视频| 亚洲二区av| 精品视频在线播放免| 91精品少妇一区二区三区蜜桃臀| 一区视频在线| 国产美女91呻吟求| 丰满人妻一区二区三区免费| 亚洲国产高清aⅴ视频| 国产免费内射又粗又爽密桃视频| 成人性生交大片免费观看网站| 欧美精品久久久久久久久老牛影院| 日韩无码精品一区二区| 99精品小视频| 日韩av电影在线免费播放| av中文字幕免费| 久久精品综合网| 91国在线高清视频| 123成人网| 日韩精品亚洲精品| 麻豆chinese极品少妇| 日韩国产欧美在线视频| 91成人理论电影| 大片免费播放在线视频| 午夜精品久久久久久久久久久| 亚洲 欧美 另类人妖| 少妇高潮一区二区三区| 欧美第一黄网免费网站| 国产毛片毛片毛片毛片毛片| 国产色婷婷亚洲99精品小说| 欧洲精品一区二区三区久久| 99精品视频在线免费播放| 在线一区二区日韩| 天堂中文在线网| 99热这里都是精品| 日韩国产成人无码av毛片| 精品国产黄a∨片高清在线| 亚洲美女激情视频| 日本三级片在线观看| 国产高清在线精品| 成人手机视频在线| 欧美性生活一级| 在线播放日韩专区| 精品国产乱子伦| 久久蜜臀中文字幕| 91九色在线观看视频| 国产精品一线| 97免费在线视频| 日批免费在线观看| 亚洲一卡二卡三卡四卡| 久久久久久久久久影视| 国产精品v日韩精品v欧美精品网站| 亚洲a在线观看| 黄色av免费在线| 欧美一级高清片| 欧美日韩一级大片| 国产高清亚洲一区| 91网站在线观看免费| 亚洲精品在线播放| 久久久久免费精品国产| 日韩一区免费视频| 精品久久久久久久久国产字幕| 国产一卡二卡三卡四卡| 一区二区日本视频| 欧美日韩国产综合视频在线| 欧美日韩免费看片| 在线一区二区日韩| 国产精品美女一区| **欧美大码日韩| av在线天堂网| 国产亚洲精品自拍| 欧美一区二区三区电影在线观看 | 日本中文字幕在线视频| 欧美人与性动xxxx| www.av视频| 成人午夜电影网站| 国产成人在线免费看| 精品免费av| 91人成网站www| 黄色成人在线网| 日韩精品中文字幕在线| 久久久久久av无码免费看大片| 亚洲色图制服丝袜| 亚洲av成人片无码| 视频在线观看91| 中文字幕久精品免| 国产一区福利| 国产成人精品视频| 成人影院在线看| 亚洲国产成人久久综合一区| 区一区二在线观看| 亚洲人妖av一区二区| jlzzjizz在线播放观看| 欧美a级理论片| 精品久久久久久无码中文野结衣| 妖精视频一区二区三区| 成人欧美在线视频| 欧美少妇精品| 久久精品视频va| 色播色播色播色播色播在线| 欧美精品黑人性xxxx| 日本在线视频中文字幕| 欧美激情一区二区| 国产av一区二区三区传媒| 日韩av电影一区| www.在线观看av| 青青草91久久久久久久久| http;//www.99re视频| 日韩欧美精品电影| 色综合视频一区中文字幕| 九色在线播放| 精品国产一区二区三区忘忧草| 免费精品一区二区| 亚洲动漫第一页| 蜜桃av免费观看| 91在线精品一区二区| 九一精品久久久| 久久先锋影音| 自拍日韩亚洲一区在线| 99久久亚洲精品| 日本福利一区二区三区| 国产精东传媒成人av电影| 成人黄色大片在线免费观看| 手机av在线| 欧美激情在线观看| 搞黄网站在线观看| 日韩一级裸体免费视频| 国产三级电影在线| 精品无人区太爽高潮在线播放 | 成人免费高清视频| 中文字幕日韩综合| 日韩精品三区四区| 欧美亚洲日本一区二区三区| 一区在线视频| 欧美日韩视频免费| 亚洲国产老妈| 一区二区在线观| 精品一区在线| 久久国产一区| 猫咪成人在线观看| 国产欧美日本在线| 高潮按摩久久久久久av免费| 亚洲www视频| 国产999精品在线观看| 国产精品一久久香蕉国产线看观看| 自拍在线观看| 国产91在线视频| 免费电影日韩网站| 热99在线视频| 成人做爰免费视频免费看| 国产精品99久久久久久久久久久久| 91吃瓜在线观看| 97视频在线观看免费高清完整版在线观看| 怡红院在线播放| 欧美成人精品h版在线观看| 成人福利片网站| 色综合视频网站| 18video性欧美19sex高清| 国语对白做受69| 欲香欲色天天天综合和网| 5566日本婷婷色中文字幕97| 高潮一区二区| 国产精品久久久久久久久久久久| 高清电影一区| 成人在线小视频| 日韩精品成人| 国产精品swag| 色愁久久久久久| 日本一区二区三区在线视频| 日韩精品一区二区久久| 吴梦梦av在线| 狠狠综合久久| www一区二区www免费| 天堂在线一区二区| a在线观看免费视频| 国产一区二区免费视频| av免费观看不卡| 久久久久久久久久看片| 天堂网av2018| 一区二区三区免费观看| 亚洲 欧美 视频| 欧洲亚洲精品在线| 国产女人高潮的av毛片| 精品国产一区二区三区忘忧草 | 久久精品国产99国产精品澳门| www在线免费观看视频| 久久欧美在线电影| 日本免费久久| 91亚洲va在线va天堂va国| 澳门成人av| 青娱乐国产91| 欧美在线亚洲综合一区| 欧美三级一级片| 可以看av的网站久久看| 日韩av福利在线观看| 91网站在线观看视频| 男女全黄做爰文章| 亚洲国产aⅴ天堂久久| 在线观看国产区| 精品日韩99亚洲| av影片在线看| 97国产精品视频| 亚洲精品三区| 九色91在线视频| 亚洲影视一区| 91香蕉视频污版| 成人av在线资源网站| 亚洲欧美综合7777色婷婷| 欧美日韩中文字幕在线| 国产精品毛片久久久久久久av| 亚洲精品一二区| 性欧美猛交videos| 国产精品福利网站| 国产一区二区三区亚洲| 中文字幕在线乱| 日韩高清一级片| 亚洲av成人片色在线观看高潮| 成人免费在线观看入口| 日本中文字幕久久| 精品国产一区二区三区忘忧草 | 深夜福利在线观看直播| 欧美成aaa人片在线观看蜜臀| 欧美成a人片在线观看久| 国产chinese精品一区二区| 日韩国产一区| 四季av一区二区| 91污片在线观看| 久久久精品视频免费| 日韩午夜在线观看视频| 欧美三级黄网| 国产精品高潮呻吟视频| 亚洲成a人片77777在线播放 | 日韩欧美激情一区二区| 在线视频精品| 成年女人免费视频| 一区二区三区日本| 国产成人久久精品77777综合 | 欧美视频小说| 99精品热6080yy久久| 国产精品欧美性爱| 亚洲卡通欧美制服中文| 国产精品乱码一区二区| 最新日韩中文字幕| 国产精品99| 水蜜桃一区二区| 日本人妖一区二区| 国产黄片一区二区三区| 色综合久久六月婷婷中文字幕| 色猫av在线| 国产999精品| 精品视频亚洲| 国产又粗又长又大的视频| 久久久精品国产免费观看同学| 国产成人一级片| 国产亚洲激情视频在线| 国精品产品一区| 伊人情人网综合| 国产精品一区专区| 中文字幕影音先锋| 日韩精品一区二区三区视频| 国产理论电影在线| 国产一区二区免费电影| 国产日本精品| av手机在线播放| 51精品秘密在线观看| av激情在线| 国产日韩欧美一区二区| 性xx色xx综合久久久xx| 国产一二三四五区| 欧美日韩黄色一区二区| av片在线观看网站| 成人免费看片网址| 日韩图片一区| 欧美性猛交xxxx乱| 欧美美女直播网站| 伊人在我在线看导航| 狠狠综合久久av| 日本少妇一区二区| 五月天丁香激情| 亚洲免费一在线| 亚洲精品自拍| 国产精品国产对白熟妇| 久久女同性恋中文字幕| 国产精品久久久久久久久久久久久久久久| 久热精品视频在线观看| 欧洲亚洲一区二区三区| 91看片在线免费观看| 一区二区三区久久久| 瑟瑟在线观看| 亚洲综合大片69999| 一本一本久久| 女人18毛片毛片毛片毛片区二| 欧美成人精品福利| 午夜日韩成人影院| 50度灰在线观看| 国产午夜精品福利| 性中国xxx极品hd| 国产成人精品在线播放| 欧美日本不卡| 中文字幕av久久爽一区| 精品日韩在线一区| 免费视频观看成人| 黄色免费福利视频| 中文字幕在线观看不卡| 深夜福利视频一区| av在线不卡一区|