@ -1,3 +1,7 @@
@@ -1,3 +1,7 @@
function round _to _pow2 ( value , multiple ) {
return ( value + multiple - 1 ) & - multiple ;
}
function screen _to _canvas ( state , p ) {
// should be called with coordinates obtained from MouseEvent.clientX/clientY * window.devicePixelRatio
const xc = ( p . x - state . canvas . offset . x ) / state . canvas . zoom ;
@ -6,36 +10,39 @@ function screen_to_canvas(state, p) {
@@ -6,36 +10,39 @@ function screen_to_canvas(state, p) {
return { 'x' : xc , 'y' : yc } ;
}
function rdp _find _max ( zoom , point s, start , end ) {
function rdp _find _max ( state , zoom , stroke , start , end ) {
const EPS = 1.0 / zoom ;
// const EPS = 10.0;
let result = - 1 ;
let max _dist = 0 ;
const a = points [ start ] ;
const b = points [ end ] ;
const ax = state . coordinates . data [ stroke . coords _from + start * 2 + 0 ] ;
const ay = state . coordinates . data [ stroke . coords _from + start * 2 + 1 ] ;
const bx = state . coordinates . data [ stroke . coords _from + end * 2 + 0 ] ;
const by = state . coordinates . data [ stroke . coords _from + end * 2 + 1 ] ;
const dx = b . x - a . x ;
const dy = b . y - a . y ;
const dx = bx - ax ;
const dy = by - ay ;
const dist _ab = Math . sqrt ( dx * dx + dy * dy ) ;
const sin _theta = dy / dist _ab ;
const cos _theta = dx / dist _ab ;
for ( let i = start ; i < end ; ++ i ) {
const p = points [ i ] ;
const px = state . coordinates . data [ stroke . coords _from + i * 2 + 0 ] ;
const py = state . coordinates . data [ stroke . coords _from + i * 2 + 1 ] ;
const ox = p . x - a . x ;
const oy = p . y - a . y ;
const ox = px - ax ;
const oy = py - ay ;
const rx = cos _theta * ox + sin _theta * oy ;
const ry = - sin _theta * ox + cos _theta * oy ;
const x = rx + a . x ;
const y = ry + a . y ;
const x = rx + ax ;
const y = ry + ay ;
const dist = Math . abs ( y - a . y ) ;
const dist = Math . abs ( y - ay ) ;
if ( dist > EPS && dist > max _dist ) {
result = i ;
@ -46,45 +53,37 @@ function rdp_find_max(zoom, points, start, end) {
@@ -46,45 +53,37 @@ function rdp_find_max(zoom, points, start, end) {
return result ;
}
function process _rdp _r ( zoom , mask , point s, start , end ) {
function process _rdp _indices _ r ( state , zoom , mask , stroke , start , end ) {
let result = 0 ;
const max = rdp _find _max ( zoom , point s, start , end ) ;
const max = rdp _find _max ( state , zoom , stroke , start , end ) ;
if ( max !== - 1 ) {
mask [ max ] = 1 ;
result += 1 ;
result += process _rdp _r ( zoom , mask , point s, start , max ) ;
result += process _rdp _r ( zoom , mask , point s, max , end ) ;
result += process _rdp _indices _ r ( state , zoom , mask , stroke , start , max ) ;
result += process _rdp _indices _ r ( state , zoom , mask , stroke , max , end ) ;
}
return result ;
}
function process _rdp ( state , zoom , points ) {
if ( state . rdp _mask . length < points . length ) {
state . rdp _mask = new Uint8Array ( points . length ) ;
function process _rdp _indices ( state , zoom , stroke ) {
const point _count = ( stroke . coords _to - stroke . coords _from ) / 2 ;
if ( state . rdp _mask . length < point _count ) {
state . rdp _mask = new Uint8Array ( point _count ) ;
}
state . rdp _mask . fill ( 0 , 0 , points . length ) ;
state . rdp _mask . fill ( 0 , 0 , point _count ) ;
const mask = state . rdp _mask ;
const npoints = process _rdp _r ( zoom , mask , point s, 0 , points . length - 1 ) ;
const npoints = 2 + process _rdp _indices _ r ( state , zoom , mask , stroke , 0 , point _count - 1 ) ; // 2 is for the first and last vertex, which do not get included by the recursive functions, but should always be there at any lod level
mask [ 0 ] = 1 ;
mask [ points . length - 1 ] = 1 ;
const result = new Array ( npoints ) ;
let j = 0 ;
for ( let i = 0 ; i < points . length ; ++ i ) {
if ( mask [ i ] === 1 ) {
result [ j ] = points [ i ] ;
++ j ;
}
}
mask [ point _count - 1 ] = 1 ;
return result ;
return npoints ;
}
function process _ewmv ( points , round = false ) {
@ -103,9 +102,9 @@ function process_ewmv(points, round = false) {
@@ -103,9 +102,9 @@ function process_ewmv(points, round = false) {
return result ;
}
function process _stroke ( state , zoom , point s) {
function process _stroke ( state , zoom , stroke ) {
// const result0 = process_ewmv(points);
const result1 = process _rdp ( state , zoom , point s, true ) ;
const result1 = process _rdp _indices ( state , zoom , stroke , true ) ;
return result1 ;
}
@ -202,20 +201,23 @@ function segment_interesects_quad(a, b, quad_topleft, quad_bottomright, quad_top
@@ -202,20 +201,23 @@ function segment_interesects_quad(a, b, quad_topleft, quad_bottomright, quad_top
return false ;
}
function stroke _bbox ( stroke ) {
function stroke _bbox ( state , st roke ) {
const radius = stroke . width / 2 ;
let min _x = stroke . points [ 0 ] . x - radius ;
let max _x = stroke . points [ 0 ] . x + radius ;
let min _y = stroke . points [ 0 ] . y - radius ;
let max _y = stroke . points [ 0 ] . y + radius ;
let min _x = state . coordinates . data [ stroke . coords _from + 0 ] - radius ;
let max _x = state . coordinates . data [ stroke . coords _from + 0 ] + radius ;
let min _y = state . coordinates . data [ stroke . coords _from + 1 ] - radius ;
let max _y = state . coordinates . data [ stroke . coords _from + 1 ] + radius ;
for ( const p of stroke . points ) {
min _x = Math . min ( min _x , p . x - radius ) ;
min _y = Math . min ( min _y , p . y - radius ) ;
max _x = Math . max ( max _x , p . x + radius ) ;
max _y = Math . max ( max _y , p . y + radius ) ;
for ( let i = stroke . coords _from + 2 ; i < stroke . coords _to ; i += 2 ) {
const px = state . coordinates . data [ i + 0 ] ;
const py = state . coordinates . data [ i + 1 ] ;
min _x = Math . min ( min _x , px - radius ) ;
min _y = Math . min ( min _y , py - radius ) ;
max _x = Math . max ( max _x , px + radius ) ;
max _y = Math . max ( max _y , py + radius ) ;
}
return { 'x1' : min _x , 'y1' : min _y , 'x2' : max _x , 'y2' : max _y , 'cx' : ( max _x + min _x ) / 2 , 'cy' : ( max _y + min _y ) / 2 } ;
@ -246,6 +248,10 @@ function quad_union(a, b) {
@@ -246,6 +248,10 @@ function quad_union(a, b) {
} ;
}
function box _area ( box ) {
return ( box . x2 - box . x1 ) * ( box . y2 - box . y1 ) ;
}
function segments _onscreen ( state , context , do _clip ) {
// TODO: handle stroke width