(hole, outerNode)
| 1896 | |
| 1897 | // David Eberly's algorithm for finding a bridge between hole and outer polygon |
| 1898 | function findHoleBridge(hole, outerNode) { |
| 1899 | var p = outerNode, |
| 1900 | hx = hole.x, |
| 1901 | hy = hole.y, |
| 1902 | qx = -Infinity, |
| 1903 | m; |
| 1904 | |
| 1905 | // find a segment intersected by a ray from the hole's leftmost point to the left; |
| 1906 | // segment's endpoint with lesser x will be potential connection point |
| 1907 | do { |
| 1908 | if (hy <= p.y && hy >= p.next.y) { |
| 1909 | var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y); |
| 1910 | if (x <= hx && x > qx) { |
| 1911 | qx = x; |
| 1912 | if (x === hx) { |
| 1913 | if (hy === p.y) return p; |
| 1914 | if (hy === p.next.y) return p.next; |
| 1915 | } |
| 1916 | m = p.x < p.next.x ? p : p.next; |
| 1917 | } |
| 1918 | } |
| 1919 | p = p.next; |
| 1920 | } while (p !== outerNode); |
| 1921 | |
| 1922 | if (!m) return null; |
| 1923 | |
| 1924 | if (hx === qx) return m.prev; // hole touches outer segment; pick lower endpoint |
| 1925 | |
| 1926 | // look for points inside the triangle of hole point, segment intersection and endpoint; |
| 1927 | // if there are no points found, we have a valid connection; |
| 1928 | // otherwise choose the point of the minimum angle with the ray as connection point |
| 1929 | |
| 1930 | var stop = m, |
| 1931 | mx = m.x, |
| 1932 | my = m.y, |
| 1933 | tanMin = Infinity, |
| 1934 | tan; |
| 1935 | |
| 1936 | p = m.next; |
| 1937 | |
| 1938 | while (p !== stop) { |
| 1939 | if (hx >= p.x && p.x >= mx && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) { |
| 1940 | |
| 1941 | tan = Math.abs(hy - p.y) / (hx - p.x); // tangential |
| 1942 | |
| 1943 | if ((tan < tanMin || tan === tanMin && p.x > m.x) && locallyInside(p, hole)) { |
| 1944 | m = p; |
| 1945 | tanMin = tan; |
| 1946 | } |
| 1947 | } |
| 1948 | |
| 1949 | p = p.next; |
| 1950 | } |
| 1951 | |
| 1952 | return m; |
| 1953 | } |
| 1954 | |
| 1955 | // interlink polygon nodes in z-order |
no test coverage detected