tldraw چطور bounding box شکلها رو حساب میکنه
خلاصهٔ کاملتر
تو این مقاله از وبلاگ tldraw، نویسنده توضیح میده که روی یه بوم بینهایت هر تعاملی یه سؤال مکانی میسازه: روی چی کلیک شد؟ کدوم شکلها الان دیده میشن؟ جواب همهی اینا bounding box هست، یعنی کوچیکترین مستطیلی که شکل رو کامل در بر میگیره. نکتهی مهم اینه که این مستطیل axis-aligned هست، یعنی لبههاش همیشه افقی و عمودی میمونن، حتی اگه خود شکل چرخیده باشه.
دلیلش سرعته. برای اینکه بفهمی دو تا جعبه با هم برخورد دارن یا نه، فقط چهار تا مقایسهی ساده بین لبههاشون لازمه:
static Collides(A: Box, B: Box) {
return !(A.maxX < B.minX || A.minX > B.maxX || A.maxY < B.minY || A.minY > B.maxY)
}حالا اگه شکل بچرخه چی؟ اگه گوشههای یه مستطیل ۱۰۰ در ۵۰ رو ۴۵ درجه بچرخونی، لبههاش دیگه با محورها همراستا نیستن. برای تست برخورد با این گوشهها باید از قضیهی separating axis (یعنی تست با تصویر کردن روی محورها با ضرب داخلی) استفاده کنی که گرونتره. راهحل tldraw اینه که گوشههای چرخیده رو به فضای صفحه میبره و با تابع Box.FromPoints کمترین و بیشترین x و y رو پیدا میکنه. نتیجه یه جعبهی صاف حدوداً ۱۰۶ در ۱۰۶ هست که از جعبهی اصلی بزرگتره.
شکلها تو tldraw میتونن داخل frameها باشن که خودشون هم ممکنه چرخیده باشن. هر transform (جابهجایی، چرخش، مقیاس) یه ماتریسه. تابع getShapePageTransform بهصورت بازگشتی transform والد رو با transform محلی شکل ترکیب میکنه (با Mat.Compose)، پس هر عمقی از تودرتویی درست حساب میشه.
یه جای جالب جعبهی انتخابه. وقتی چند تا شکل رو با هم میچرخونی، جعبهی انتخاب هم باهاشون میچرخه. نویسنده میگه tldraw دو نوع bounds داره: برای viewport culling (یعنی نکشیدن چیزهایی که بیرون صفحهان) فقط جعبهی صاف، ولی برای UI انتخاب یه جعبهی چرخیده. این کار باعث میشه بتونی شکلها رو در جهت واقعیشون resize کنی و کجوکوله نشن. برای ساختنش گوشهها رو برعکس میچرخونن، جعبهی صاف میگیرن و دوباره برش میگردونن. اگه شکلها زاویههای متفاوت داشته باشن، برمیگرده به همون جعبهی صاف.
به گفتهی نویسنده، همهی این جعبهها تقریبیان. جعبهی یه شکل چرخیده همیشه از خود شکل بزرگتره، پس گاهی شکلی چک میشه که واقعاً کلیک نخورده. ولی این خطاها رو میشه ارزون تو یه مرحلهی دوم فیلتر کرد و حساب دقیق هندسه فقط وقتی لازمه انجام میشه، مثلاً hit-test از نزدیک.
نکات کلیدی:
- تست برخورد دو جعبهی axis-aligned فقط با چهار مقایسه انجام میشه.
- برای شکل چرخیده، گوشهها به فضای صفحه میرن و Box.FromPoints یه جعبهی صاف جدید دورشون میسازه.
- یه مستطیل ۱۰۰ در ۵۰ بعد از چرخش ۴۵ درجه، جعبهای حدود ۱۰۶ در ۱۰۶ میگیره.
- transform شکلهای تودرتو با Mat.Compose و بهصورت بازگشتی از والدها حساب میشه.
- جعبهی انتخاب فقط وقتی میچرخه که همهی شکلها زاویهی یکسان داشته باشن.




