Initial commit
This commit is contained in:
commit
05c65aad4d
155 changed files with 93617 additions and 0 deletions
196
viewer/utils.js
Normal file
196
viewer/utils.js
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
import { core, setCore } from './core.js';
|
||||
|
||||
// Geometry helpers
|
||||
export function distanceBetweenPoints(pointA, pointB) {
|
||||
return Math.sqrt(
|
||||
Math.pow(pointB.x - pointA.x, 2) +
|
||||
Math.pow(pointB.y - pointA.y, 2) +
|
||||
Math.pow(pointB.z - pointA.z, 2)
|
||||
);
|
||||
}
|
||||
|
||||
export function distanceBetweenPointsVector(vector) {
|
||||
return Math.sqrt(
|
||||
Math.pow(vector.x, 2) +
|
||||
Math.pow(vector.y, 2) +
|
||||
Math.pow(vector.z, 2)
|
||||
);
|
||||
}
|
||||
|
||||
export function vectorBetweenPoints(pointA, pointB) {
|
||||
return {
|
||||
x: pointB.x - pointA.x,
|
||||
y: pointB.y - pointA.y,
|
||||
z: pointB.z - pointA.z
|
||||
};
|
||||
}
|
||||
|
||||
export function halfwayBetweenPoints(pointA, pointB) {
|
||||
return {
|
||||
x: (pointB.x + pointA.x) / 2,
|
||||
y: (pointB.y + pointA.y) / 2,
|
||||
z: (pointB.z + pointA.z) / 2
|
||||
};
|
||||
}
|
||||
|
||||
export function interpolateDistanceBetweenPoints(pointA, vector, length, scalar) {
|
||||
const _x = pointA.x + (scalar / Math.abs(length)) * vector.x;
|
||||
const _y = pointA.y + (scalar / Math.abs(length)) * vector.y;
|
||||
const _z = pointA.z + (scalar / Math.abs(length)) * vector.z;
|
||||
return { x: _x, y: _y, z: _z };
|
||||
}
|
||||
|
||||
export function detectColorFormat(color) {
|
||||
const hexRegex = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
|
||||
const rgbRegex = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/;
|
||||
if (hexRegex.test(color)) return "hex";
|
||||
if (rgbRegex.test(color)) return "rgb";
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
export function hexToRgb(hex) {
|
||||
hex = hex.replace(/^#/, "");
|
||||
if (hex.length === 3) {
|
||||
hex = hex.split("").map((char) => char + char).join("");
|
||||
}
|
||||
const bigint = parseInt(hex, 16);
|
||||
const r = (bigint >> 16) & 255;
|
||||
const g = (bigint >> 8) & 255;
|
||||
const b = bigint & 255;
|
||||
return `rgb(${r}, ${g}, ${b})`;
|
||||
}
|
||||
|
||||
// String helpers
|
||||
export function isValidUrl(urlString) {
|
||||
const urlPattern = new RegExp(
|
||||
"^(https?:\\/\\/)?" +
|
||||
"((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|" +
|
||||
"((\\d{1,3}\\.){3}\\d{1,3}))" +
|
||||
"(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*" +
|
||||
"(\\?[;&a-z\\d%_.~+=-]*)?" +
|
||||
"(\\#[-a-z\\d_]*)?$",
|
||||
"i"
|
||||
);
|
||||
return !!urlPattern.test(urlString);
|
||||
}
|
||||
|
||||
export function truncateString(str, n) {
|
||||
if (str.length === 0) return str;
|
||||
if (str.length > n) return str.substring(0, n) + "...";
|
||||
return str;
|
||||
}
|
||||
|
||||
// Path helpers
|
||||
export function getProxyPath(url, config) {
|
||||
const tempPath = decodeURIComponent(config.mainUrl);
|
||||
return tempPath.replace(core.fileObject.originalPath, encodeURIComponent(url));
|
||||
}
|
||||
|
||||
setCore("getProxyPath", getProxyPath);
|
||||
|
||||
export function normalizeColor(value) {
|
||||
if (value == null) return null;
|
||||
|
||||
//legacy: [[r,g,b]]
|
||||
if (Array.isArray(value) && Array.isArray(value[0])) {
|
||||
value = value[0];
|
||||
}
|
||||
|
||||
//already normalized
|
||||
if (
|
||||
typeof value === "object" &&
|
||||
value !== null &&
|
||||
typeof value.r === "number" &&
|
||||
typeof value.g === "number" &&
|
||||
typeof value.b === "number"
|
||||
) {
|
||||
return {
|
||||
r: value.r,
|
||||
g: value.g,
|
||||
b: value.b,
|
||||
a: value.a ?? 1
|
||||
};
|
||||
}
|
||||
|
||||
//[r, g, b, a?]
|
||||
if (Array.isArray(value)) {
|
||||
const [r, g, b, a = 1] = value;
|
||||
if (
|
||||
typeof r === "number" &&
|
||||
typeof g === "number" &&
|
||||
typeof b === "number"
|
||||
) {
|
||||
return { r, g, b, a };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//number (0xffffff or 16777215)
|
||||
if (typeof value === "number") {
|
||||
return {
|
||||
r: (value >> 16) & 255,
|
||||
g: (value >> 8) & 255,
|
||||
b: value & 255,
|
||||
a: 1
|
||||
};
|
||||
}
|
||||
|
||||
//string
|
||||
if (typeof value === "string") {
|
||||
return parseCssColor(value);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function parseCssColor(str) {
|
||||
if (typeof str !== "string") return null;
|
||||
|
||||
str = str.trim();
|
||||
|
||||
// 0xFFFFFF
|
||||
if (str.startsWith("0x")) {
|
||||
const n = parseInt(str, 16);
|
||||
return {
|
||||
r: (n >> 16) & 255,
|
||||
g: (n >> 8) & 255,
|
||||
b: n & 255,
|
||||
a: 1
|
||||
};
|
||||
}
|
||||
|
||||
// #RGB / #RRGGBB
|
||||
if (str.startsWith("#")) {
|
||||
let hex = str.slice(1);
|
||||
|
||||
if (hex.length === 3) {
|
||||
hex = hex.split("").map(c => c + c).join("");
|
||||
}
|
||||
|
||||
if (hex.length !== 6) return null;
|
||||
|
||||
return {
|
||||
r: parseInt(hex.slice(0, 2), 16),
|
||||
g: parseInt(hex.slice(2, 4), 16),
|
||||
b: parseInt(hex.slice(4, 6), 16),
|
||||
a: 1
|
||||
};
|
||||
}
|
||||
|
||||
// rgb / rgba
|
||||
const m = str.match(
|
||||
/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([\d.]+))?\s*\)/i
|
||||
);
|
||||
|
||||
if (m) {
|
||||
const [, r, g, b, a] = m;
|
||||
return {
|
||||
r: +r,
|
||||
g: +g,
|
||||
b: +b,
|
||||
a: a !== undefined ? +a : 1
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue