| 141 | inline int Sign(float val) { return int(val > 0.0f) - int(val < 0.0f); } |
| 142 | |
| 143 | inline bool RectangleOverlapsLineSegment(const ImRect& rect, const ImVec2& p1, const ImVec2& p2) |
| 144 | { |
| 145 | // Trivial case: rectangle contains an endpoint |
| 146 | if (rect.Contains(p1) || rect.Contains(p2)) |
| 147 | { |
| 148 | return true; |
| 149 | } |
| 150 | |
| 151 | // Flip rectangle if necessary |
| 152 | ImRect flip_rect = rect; |
| 153 | |
| 154 | if (flip_rect.Min.x > flip_rect.Max.x) |
| 155 | { |
| 156 | ImSwap(flip_rect.Min.x, flip_rect.Max.x); |
| 157 | } |
| 158 | |
| 159 | if (flip_rect.Min.y > flip_rect.Max.y) |
| 160 | { |
| 161 | ImSwap(flip_rect.Min.y, flip_rect.Max.y); |
| 162 | } |
| 163 | |
| 164 | // Trivial case: line segment lies to one particular side of rectangle |
| 165 | if ((p1.x < flip_rect.Min.x && p2.x < flip_rect.Min.x) || |
| 166 | (p1.x > flip_rect.Max.x && p2.x > flip_rect.Max.x) || |
| 167 | (p1.y < flip_rect.Min.y && p2.y < flip_rect.Min.y) || |
| 168 | (p1.y > flip_rect.Max.y && p2.y > flip_rect.Max.y)) |
| 169 | { |
| 170 | return false; |
| 171 | } |
| 172 | |
| 173 | const int corner_signs[4] = { |
| 174 | Sign(EvalImplicitLineEq(p1, p2, flip_rect.Min)), |
| 175 | Sign(EvalImplicitLineEq(p1, p2, ImVec2(flip_rect.Max.x, flip_rect.Min.y))), |
| 176 | Sign(EvalImplicitLineEq(p1, p2, ImVec2(flip_rect.Min.x, flip_rect.Max.y))), |
| 177 | Sign(EvalImplicitLineEq(p1, p2, flip_rect.Max))}; |
| 178 | |
| 179 | int sum = 0; |
| 180 | int sum_abs = 0; |
| 181 | |
| 182 | for (int i = 0; i < 4; ++i) |
| 183 | { |
| 184 | sum += corner_signs[i]; |
| 185 | sum_abs += abs(corner_signs[i]); |
| 186 | } |
| 187 | |
| 188 | // At least one corner of rectangle lies on a different side of line segment |
| 189 | return abs(sum) != sum_abs; |
| 190 | } |
| 191 | |
| 192 | inline bool RectangleOverlapsBezier(const ImRect& rectangle, const CubicBezier& cubic_bezier) |
| 193 | { |
no test coverage detected