| 5 | | class dist { |
|---|
| 6 | | vec2f line_start, line_end, d, v; |
|---|
| 7 | | this(vec2f ls, vec2f le) { |
|---|
| 8 | | line_start = ls; |
|---|
| 9 | | line_end = le; |
|---|
| 10 | | d = line_end - line_start; |
|---|
| 11 | | v = vec2f(d.y, -d.x).normalized(); |
|---|
| | 5 | bool _polygons_overlap_4(vec2f[4] poly_1, vec2f[4] poly_2) { |
|---|
| | 6 | int next_1(int i) { if (i == poly_1.length - 1) return 0; else return i+1; } |
|---|
| | 7 | foreach (i, pt; poly_1) { |
|---|
| | 8 | auto pt2 = poly_1[next_1(i)]; |
|---|
| | 9 | auto d = pt2 - pt, perp = vec2f(d.y, -d.x); |
|---|
| | 10 | bool check(vec2f v) { return perp.dot(v) > 0; } |
|---|
| | 11 | bool side = check(poly_1[next_1(next_1(i))] - pt); // check which side poly_1 is on |
|---|
| | 12 | bool separating = true; |
|---|
| | 13 | foreach (other_pt; poly_2) { |
|---|
| | 14 | // if any point of the other polygon is on the _same_ side, this is not a separating line. Abort. |
|---|
| | 15 | if (check(other_pt - pt) == side) { |
|---|
| | 16 | separating = false; |
|---|
| | 17 | break; |
|---|
| | 18 | } |
|---|
| | 19 | } |
|---|
| | 20 | if (separating) return false; |
|---|
| | 21 | } |
|---|
| | 22 | return true; // no separating side found; see http://gpwiki.org/index.php/Polygon_Collision |
|---|
| | 23 | } |
|---|
| | 24 | |
|---|
| | 25 | bool polygons_overlap_4(vec2f[4] poly_1, vec2f[4] poly_2) { |
|---|
| | 26 | return _polygons_overlap_4(poly_1, poly_2) && _polygons_overlap_4(poly_2, poly_1); |
|---|
| | 27 | } |
|---|
| | 28 | |
|---|
| | 29 | class FatLine { |
|---|
| | 30 | vec2f[] pts, ds, vs; |
|---|
| | 31 | float width; |
|---|
| | 32 | this(vec2f[] pts, float w) { |
|---|
| | 33 | width = w; |
|---|
| | 34 | this.pts = pts.dup; |
|---|
| | 35 | for (int i = 0; i < pts.length - 1; ++i) { |
|---|
| | 36 | auto d = pts[i+1] - pts[i], v = vec2f(d.y, -d.x).normalized(); |
|---|
| | 37 | ds ~= d; vs ~= v; |
|---|
| | 38 | } |
|---|
| | 39 | } |
|---|
| | 40 | bool overlap(vec2f tl, vec2f br) { |
|---|
| | 41 | auto tr = vec2f(br.x, tl.y), bl = vec2f(tl.x, br.y); |
|---|
| | 42 | auto square = [tl, tr, br, bl]; |
|---|
| | 43 | for (int i = 0; i < pts.length - 1; ++i) { |
|---|
| | 44 | // construct polygon for line |
|---|
| | 45 | auto line_start = pts[i], line_end = pts[i+1]; |
|---|
| | 46 | auto d = line_end - line_start, d_norm = d.normalized(), d_extend = d_norm * width; |
|---|
| | 47 | auto offs = vec2f(d_norm.y, -d_norm.x) * width; |
|---|
| | 48 | auto start_extend = line_start - d_extend, end_extend = line_end + d_extend; |
|---|
| | 49 | auto line = [start_extend + offs, start_extend - offs, end_extend - offs, end_extend + offs]; |
|---|
| | 50 | if (polygons_overlap_4(line, square)) return true; |
|---|
| | 51 | } |
|---|
| | 52 | return false; |
|---|
| 14 | | auto start_diff = pt - line_start, end_diff = pt - line_end; |
|---|
| 15 | | auto dist2 = d.dot(start_diff) > 0, dist3 = d.dot(end_diff) < 0; |
|---|
| 16 | | if (dist2 && dist3) return v.dot(start_diff); |
|---|
| 17 | | else { |
|---|
| 18 | | auto d1 = start_diff.lensq(), d2 = end_diff.lensq(); |
|---|
| 19 | | return sqrt(min(d1, d2)); |
|---|
| | 55 | auto smallest_sqr = float.infinity, smallest = float.nan; |
|---|
| | 56 | vec2f start_diff, end_diff = pt - pts[0]; |
|---|
| | 57 | for (int i = 0; i < pts.length - 1; ++i) { |
|---|
| | 58 | start_diff = end_diff; end_diff = pt - pts[i+1]; |
|---|
| | 59 | auto dist2 = ds[i].dot(start_diff) > 0, dist3 = ds[i].dot(end_diff) < 0; |
|---|
| | 60 | if (dist2 && dist3) { |
|---|
| | 61 | auto whee = vs[i].dot(start_diff), whee_sq = whee * whee; |
|---|
| | 62 | if (whee_sq < smallest_sqr) { |
|---|
| | 63 | smallest_sqr = whee_sq; |
|---|
| | 64 | smallest = abs(whee); |
|---|
| | 65 | } |
|---|
| | 66 | } else { |
|---|
| | 67 | auto d1 = start_diff.lensq(), d2 = end_diff.lensq(); |
|---|
| | 68 | if (smallest_sqr > d1) { smallest_sqr = d1; smallest = float.nan; } |
|---|
| | 69 | if (smallest_sqr > d2) { smallest_sqr = d2; smallest = float.nan; } |
|---|
| | 70 | } |
|---|
| 51 | | if (mouse.clicked) change_first = !change_first; |
|---|
| 52 | | if (change_first) start = vec2f(mouse.pos.x, mouse.pos.y); |
|---|
| 53 | | else end = vec2f(mouse.pos.x, mouse.pos.y); |
|---|
| 54 | | df = new dist(start, end); |
|---|
| | 96 | if (mouse.clicked) current ~= vec2f(mouse.pos.x, mouse.pos.y); |
|---|
| | 97 | df = new FatLine(current, df.width); |
|---|
| | 98 | } |
|---|
| | 99 | void jiggle() { |
|---|
| | 100 | foreach (ref v; current) v += vec2f(randf() - .5f, randf() - .5f); |
|---|
| | 101 | df = new FatLine(current, df.width); |
|---|
| 57 | | if (abs(d) > 5) return Black.blend(White, 0.1); |
|---|
| 58 | | else if (abs(d) > 4) return Black.blend(White, 0.1).blend(White, 5f - abs(d)); |
|---|
| | 104 | if (abs(d) > df.width) return Black.blend(White, 0.1); |
|---|
| | 105 | else if (abs(d) > df.width - 2) return Black.blend(White, 0.1).blend(White, (df.width - abs(d)) / 2f); |
|---|
| | 106 | else if (abs(d) > df.width - 4) return White.blend(Black, (df.width - 2 - abs(d)) / 2f); |
|---|
| | 107 | else if (abs(d) > df.width - 6) return Black.blend(White, (df.width - 4 - abs(d)) / 2f); |
|---|