StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
253 lines
6.6 KiB
253 lines
6.6 KiB
import browser from "./browser.js";
|
|
import dom from "./domObjects.js";
|
|
import * as domUtils from "./domUtils.js";
|
|
import hypot from "./hypot.js";
|
|
import * as is from "./is.js";
|
|
import pointerExtend from "./pointerExtend.js";
|
|
export function copyCoords(dest, src) {
|
|
dest.page = dest.page || {};
|
|
dest.page.x = src.page.x;
|
|
dest.page.y = src.page.y;
|
|
dest.client = dest.client || {};
|
|
dest.client.x = src.client.x;
|
|
dest.client.y = src.client.y;
|
|
dest.timeStamp = src.timeStamp;
|
|
}
|
|
export function setCoordDeltas(targetObj, prev, cur) {
|
|
targetObj.page.x = cur.page.x - prev.page.x;
|
|
targetObj.page.y = cur.page.y - prev.page.y;
|
|
targetObj.client.x = cur.client.x - prev.client.x;
|
|
targetObj.client.y = cur.client.y - prev.client.y;
|
|
targetObj.timeStamp = cur.timeStamp - prev.timeStamp;
|
|
}
|
|
export function setCoordVelocity(targetObj, delta) {
|
|
const dt = Math.max(delta.timeStamp / 1000, 0.001);
|
|
targetObj.page.x = delta.page.x / dt;
|
|
targetObj.page.y = delta.page.y / dt;
|
|
targetObj.client.x = delta.client.x / dt;
|
|
targetObj.client.y = delta.client.y / dt;
|
|
targetObj.timeStamp = dt;
|
|
}
|
|
export function setZeroCoords(targetObj) {
|
|
targetObj.page.x = 0;
|
|
targetObj.page.y = 0;
|
|
targetObj.client.x = 0;
|
|
targetObj.client.y = 0;
|
|
}
|
|
export function isNativePointer(pointer) {
|
|
return pointer instanceof dom.Event || pointer instanceof dom.Touch;
|
|
} // Get specified X/Y coords for mouse or event.touches[0]
|
|
|
|
export function getXY(type, pointer, xy) {
|
|
xy = xy || {};
|
|
type = type || 'page';
|
|
xy.x = pointer[type + 'X'];
|
|
xy.y = pointer[type + 'Y'];
|
|
return xy;
|
|
}
|
|
export function getPageXY(pointer, page) {
|
|
page = page || {
|
|
x: 0,
|
|
y: 0
|
|
}; // Opera Mobile handles the viewport and scrolling oddly
|
|
|
|
if (browser.isOperaMobile && isNativePointer(pointer)) {
|
|
getXY('screen', pointer, page);
|
|
page.x += window.scrollX;
|
|
page.y += window.scrollY;
|
|
} else {
|
|
getXY('page', pointer, page);
|
|
}
|
|
|
|
return page;
|
|
}
|
|
export function getClientXY(pointer, client) {
|
|
client = client || {};
|
|
|
|
if (browser.isOperaMobile && isNativePointer(pointer)) {
|
|
// Opera Mobile handles the viewport and scrolling oddly
|
|
getXY('screen', pointer, client);
|
|
} else {
|
|
getXY('client', pointer, client);
|
|
}
|
|
|
|
return client;
|
|
}
|
|
export function getPointerId(pointer) {
|
|
return is.number(pointer.pointerId) ? pointer.pointerId : pointer.identifier;
|
|
}
|
|
export function setCoords(targetObj, pointers, timeStamp) {
|
|
const pointer = pointers.length > 1 ? pointerAverage(pointers) : pointers[0];
|
|
const tmpXY = {};
|
|
getPageXY(pointer, tmpXY);
|
|
targetObj.page.x = tmpXY.x;
|
|
targetObj.page.y = tmpXY.y;
|
|
getClientXY(pointer, tmpXY);
|
|
targetObj.client.x = tmpXY.x;
|
|
targetObj.client.y = tmpXY.y;
|
|
targetObj.timeStamp = timeStamp;
|
|
}
|
|
export function getTouchPair(event) {
|
|
const touches = []; // array of touches is supplied
|
|
|
|
if (is.array(event)) {
|
|
touches[0] = event[0];
|
|
touches[1] = event[1];
|
|
} // an event
|
|
else {
|
|
if (event.type === 'touchend') {
|
|
if (event.touches.length === 1) {
|
|
touches[0] = event.touches[0];
|
|
touches[1] = event.changedTouches[0];
|
|
} else if (event.touches.length === 0) {
|
|
touches[0] = event.changedTouches[0];
|
|
touches[1] = event.changedTouches[1];
|
|
}
|
|
} else {
|
|
touches[0] = event.touches[0];
|
|
touches[1] = event.touches[1];
|
|
}
|
|
}
|
|
|
|
return touches;
|
|
}
|
|
export function pointerAverage(pointers) {
|
|
const average = {
|
|
pageX: 0,
|
|
pageY: 0,
|
|
clientX: 0,
|
|
clientY: 0,
|
|
screenX: 0,
|
|
screenY: 0
|
|
};
|
|
|
|
for (const pointer of pointers) {
|
|
for (const prop in average) {
|
|
average[prop] += pointer[prop];
|
|
}
|
|
}
|
|
|
|
for (const prop in average) {
|
|
average[prop] /= pointers.length;
|
|
}
|
|
|
|
return average;
|
|
}
|
|
export function touchBBox(event) {
|
|
if (!event.length && !(event.touches && event.touches.length > 1)) {
|
|
return null;
|
|
}
|
|
|
|
const touches = getTouchPair(event);
|
|
const minX = Math.min(touches[0].pageX, touches[1].pageX);
|
|
const minY = Math.min(touches[0].pageY, touches[1].pageY);
|
|
const maxX = Math.max(touches[0].pageX, touches[1].pageX);
|
|
const maxY = Math.max(touches[0].pageY, touches[1].pageY);
|
|
return {
|
|
x: minX,
|
|
y: minY,
|
|
left: minX,
|
|
top: minY,
|
|
right: maxX,
|
|
bottom: maxY,
|
|
width: maxX - minX,
|
|
height: maxY - minY
|
|
};
|
|
}
|
|
export function touchDistance(event, deltaSource) {
|
|
const sourceX = deltaSource + 'X';
|
|
const sourceY = deltaSource + 'Y';
|
|
const touches = getTouchPair(event);
|
|
const dx = touches[0][sourceX] - touches[1][sourceX];
|
|
const dy = touches[0][sourceY] - touches[1][sourceY];
|
|
return hypot(dx, dy);
|
|
}
|
|
export function touchAngle(event, deltaSource) {
|
|
const sourceX = deltaSource + 'X';
|
|
const sourceY = deltaSource + 'Y';
|
|
const touches = getTouchPair(event);
|
|
const dx = touches[1][sourceX] - touches[0][sourceX];
|
|
const dy = touches[1][sourceY] - touches[0][sourceY];
|
|
const angle = 180 * Math.atan2(dy, dx) / Math.PI;
|
|
return angle;
|
|
}
|
|
export function getPointerType(pointer) {
|
|
return is.string(pointer.pointerType) ? pointer.pointerType : is.number(pointer.pointerType) ? [undefined, undefined, 'touch', 'pen', 'mouse'][pointer.pointerType] // if the PointerEvent API isn't available, then the "pointer" must
|
|
// be either a MouseEvent, TouchEvent, or Touch object
|
|
: /touch/.test(pointer.type) || pointer instanceof dom.Touch ? 'touch' : 'mouse';
|
|
} // [ event.target, event.currentTarget ]
|
|
|
|
export function getEventTargets(event) {
|
|
const path = is.func(event.composedPath) ? event.composedPath() : event.path;
|
|
return [domUtils.getActualElement(path ? path[0] : event.target), domUtils.getActualElement(event.currentTarget)];
|
|
}
|
|
export function newCoords() {
|
|
return {
|
|
page: {
|
|
x: 0,
|
|
y: 0
|
|
},
|
|
client: {
|
|
x: 0,
|
|
y: 0
|
|
},
|
|
timeStamp: 0
|
|
};
|
|
}
|
|
export function coordsToEvent(coords) {
|
|
const event = {
|
|
coords,
|
|
|
|
get page() {
|
|
return this.coords.page;
|
|
},
|
|
|
|
get client() {
|
|
return this.coords.client;
|
|
},
|
|
|
|
get timeStamp() {
|
|
return this.coords.timeStamp;
|
|
},
|
|
|
|
get pageX() {
|
|
return this.coords.page.x;
|
|
},
|
|
|
|
get pageY() {
|
|
return this.coords.page.y;
|
|
},
|
|
|
|
get clientX() {
|
|
return this.coords.client.x;
|
|
},
|
|
|
|
get clientY() {
|
|
return this.coords.client.y;
|
|
},
|
|
|
|
get pointerId() {
|
|
return this.coords.pointerId;
|
|
},
|
|
|
|
get target() {
|
|
return this.coords.target;
|
|
},
|
|
|
|
get type() {
|
|
return this.coords.type;
|
|
},
|
|
|
|
get pointerType() {
|
|
return this.coords.pointerType;
|
|
},
|
|
|
|
get buttons() {
|
|
return this.coords.buttons;
|
|
}
|
|
|
|
};
|
|
return event;
|
|
}
|
|
export { pointerExtend };
|
|
//# sourceMappingURL=pointerUtils.js.map
|