opentakeoff-mcp 0.9.47 → 0.9.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server-core.js +27 -17
- package/package.json +1 -1
package/dist/server-core.js
CHANGED
|
@@ -618,6 +618,7 @@ var ARC_CUSP_SPAN_MULT = 8;
|
|
|
618
618
|
var MASK_NODOOR_BIT = 8;
|
|
619
619
|
var DOOR_R_MIN_FT = 1.5;
|
|
620
620
|
var DOOR_R_MAX_FT = 4.5;
|
|
621
|
+
var DOOR_R_LEAF_MAX_FT = 7;
|
|
621
622
|
var CLUSTER_FIT_TOL_FRAC = 0.05;
|
|
622
623
|
var CLUSTER_FIT_TOL_PX = 1.5;
|
|
623
624
|
var HATCH_ANGLE_TOL = 2;
|
|
@@ -2065,9 +2066,10 @@ function wedgeRimPx(maskPxPerFt) {
|
|
|
2065
2066
|
if (!Number.isFinite(maskPxPerFt) || maskPxPerFt <= 0) return 3;
|
|
2066
2067
|
return Math.max(3, Math.round(WEDGE_RIM_FT * maskPxPerFt));
|
|
2067
2068
|
}
|
|
2068
|
-
function wedgeAllowance(fit, mppf, wedgeCapPx) {
|
|
2069
|
+
function wedgeAllowance(fit, mppf, wedgeCapPx, leafFound = false) {
|
|
2069
2070
|
if (fit.noDoorFrac > 0.5 && !fit.good) return 0;
|
|
2070
|
-
|
|
2071
|
+
const rMax = leafFound ? DOOR_R_LEAF_MAX_FT : DOOR_R_MAX_FT;
|
|
2072
|
+
if (fit.good && mppf > 0 && fit.r / mppf > rMax) return 0;
|
|
2071
2073
|
const rim = wedgeRimPx(mppf);
|
|
2072
2074
|
const bu = fit.good ? fit.buH : fit.bu, bn = fit.good ? fit.bnH : fit.bn;
|
|
2073
2075
|
let area = bu * bn;
|
|
@@ -2075,12 +2077,13 @@ function wedgeAllowance(fit, mppf, wedgeCapPx) {
|
|
|
2075
2077
|
area += 2 * rim * (bu + bn) + 4 * rim * rim;
|
|
2076
2078
|
return Math.min(2 * wedgeCapPx, Math.round(area * WEDGE_SLACK));
|
|
2077
2079
|
}
|
|
2078
|
-
function doorLikeness(fit, mppf) {
|
|
2080
|
+
function doorLikeness(fit, mppf, leafFound = false) {
|
|
2079
2081
|
let s = 1 - fit.noDoorFrac;
|
|
2080
2082
|
const swDeg = fit.sweep * 180 / Math.PI;
|
|
2081
2083
|
if (fit.good) {
|
|
2082
2084
|
s += 1;
|
|
2083
|
-
|
|
2085
|
+
const rMax = leafFound ? DOOR_R_LEAF_MAX_FT : DOOR_R_MAX_FT;
|
|
2086
|
+
if (mppf > 0 && fit.r / mppf >= DOOR_R_MIN_FT && fit.r / mppf <= rMax) s += 4;
|
|
2084
2087
|
if (swDeg >= 45 && swDeg <= 190) s += 2;
|
|
2085
2088
|
}
|
|
2086
2089
|
return s;
|
|
@@ -2211,19 +2214,21 @@ function floodRegionSealedInner(mo, ix, iy, sensitivity, radii, wedgeCapPx, minP
|
|
|
2211
2214
|
const { mw, mh } = mo;
|
|
2212
2215
|
let region = null;
|
|
2213
2216
|
let count = r1.count;
|
|
2214
|
-
let wedges = 0, ringWedges = 0;
|
|
2217
|
+
let wedges = 0, ringWedges = 0, refused = 0;
|
|
2215
2218
|
let hatchFiltered = !!r1.hatchFiltered;
|
|
2216
2219
|
let hatchTier = r1.hatchTier;
|
|
2217
2220
|
let sealedPx = r1.sealedPx, virtualFrac = r1.virtualFrac;
|
|
2218
2221
|
let minPassPxOut = r1.minPassPx, minPassDelta = r1.minPassDelta;
|
|
2219
|
-
const entry = (cl, pass, fit) => {
|
|
2222
|
+
const entry = (cl, pass, fit, leafFound = false) => {
|
|
2220
2223
|
const f = fit ?? arcClusterFit(cl, mw, mo.mask);
|
|
2221
2224
|
const ideal = 0.5 * f.r * f.r * f.sweep;
|
|
2225
|
+
const allow = wedgeAllowance(f, mo.mppf || 0, wedgeCapPx, leafFound);
|
|
2226
|
+
if (!allow && f.good && (mo.mppf || 0) > 0 && f.r / mo.mppf > (leafFound ? DOOR_R_LEAF_MAX_FT : DOOR_R_MAX_FT)) refused++;
|
|
2222
2227
|
return {
|
|
2223
2228
|
cl,
|
|
2224
2229
|
fit: f,
|
|
2225
|
-
allow
|
|
2226
|
-
rank: doorLikeness(f, mo.mppf || 0),
|
|
2230
|
+
allow,
|
|
2231
|
+
rank: doorLikeness(f, mo.mppf || 0, leafFound),
|
|
2227
2232
|
at: cl[0],
|
|
2228
2233
|
pass,
|
|
2229
2234
|
minGrow: pass === 2 ? Math.max(1, Math.round(LEAF_MIN_SECTOR_FRAC * ideal)) : 0
|
|
@@ -2232,15 +2237,16 @@ function floodRegionSealedInner(mo, ix, iy, sensitivity, radii, wedgeCapPx, minP
|
|
|
2232
2237
|
const ranked = [];
|
|
2233
2238
|
for (const cl of clusters) {
|
|
2234
2239
|
const fit = arcClusterFit(cl, mw, mo.mask);
|
|
2235
|
-
ranked.push(entry(cl, 0, fit));
|
|
2236
2240
|
const parts = splitMergedArcs(cl, mw, mo.mask, mo.mppf || 0);
|
|
2237
2241
|
const pieces = parts.length > 1 ? parts : [cl];
|
|
2238
|
-
|
|
2239
|
-
for (const p of pieces) {
|
|
2242
|
+
const leaves = pieces.map((p) => {
|
|
2240
2243
|
const pf = p === cl ? fit : arcClusterFit(p, mw, mo.mask);
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
+
return { p, pf, leaf: doorLeafCells(pf, p, mw, mh, mo.mask, mo.mppf || 0) };
|
|
2245
|
+
});
|
|
2246
|
+
const anyLeaf = leaves.some((l) => !!l.leaf);
|
|
2247
|
+
ranked.push(entry(cl, 0, fit, anyLeaf));
|
|
2248
|
+
if (parts.length > 1) for (const { p, pf, leaf } of leaves) ranked.push(entry(p, 1, pf, !!leaf));
|
|
2249
|
+
for (const { pf, leaf } of leaves) if (leaf) ranked.push({ ...entry(leaf, 2, pf, true), cl: leaf });
|
|
2244
2250
|
}
|
|
2245
2251
|
ranked.splice(0, ranked.length, ...ranked.filter((c) => c.allow >= 1).sort((a, b) => a.pass - b.pass || b.rank - a.rank || a.at - b.at));
|
|
2246
2252
|
let m2mask = null, m2dt = null;
|
|
@@ -2317,7 +2323,10 @@ function floodRegionSealedInner(mo, ix, iy, sensitivity, radii, wedgeCapPx, minP
|
|
|
2317
2323
|
if (r2.minPassPx && (!minPassPxOut || r2.minPassPx > minPassPxOut)) minPassPxOut = r2.minPassPx;
|
|
2318
2324
|
if (r2.minPassDelta != null && (minPassDelta == null || r2.minPassDelta > minPassDelta)) minPassDelta = r2.minPassDelta;
|
|
2319
2325
|
}
|
|
2320
|
-
if (!wedges || !region)
|
|
2326
|
+
if (!wedges || !region) {
|
|
2327
|
+
if (refused) r1.wedgesRefused = refused;
|
|
2328
|
+
return r1;
|
|
2329
|
+
}
|
|
2321
2330
|
const out = {
|
|
2322
2331
|
status: "ok",
|
|
2323
2332
|
region,
|
|
@@ -2334,7 +2343,8 @@ function floodRegionSealedInner(mo, ix, iy, sensitivity, radii, wedgeCapPx, minP
|
|
|
2334
2343
|
virtualFrac,
|
|
2335
2344
|
minPassPx: minPassPxOut,
|
|
2336
2345
|
minPassDelta,
|
|
2337
|
-
...ringWedges ? { ringWedges } : {}
|
|
2346
|
+
...ringWedges ? { ringWedges } : {},
|
|
2347
|
+
...refused ? { wedgesRefused: refused } : {}
|
|
2338
2348
|
};
|
|
2339
2349
|
const reg = region, reg1 = r1.region, mask = mo.mask;
|
|
2340
2350
|
const isDelta = (i) => reg[i] && !reg1[i];
|
|
@@ -11119,7 +11129,7 @@ function applyStagedTools(server, registered) {
|
|
|
11119
11129
|
// package.json
|
|
11120
11130
|
var package_default = {
|
|
11121
11131
|
name: "opentakeoff-mcp",
|
|
11122
|
-
version: "0.9.
|
|
11132
|
+
version: "0.9.48",
|
|
11123
11133
|
mcpName: "io.github.Kentucky-ai/opentakeoff",
|
|
11124
11134
|
type: "module",
|
|
11125
11135
|
description: "OpenTakeoff MCP server \u2014 drive the takeoff engine from your MCP client over stdio.",
|
package/package.json
CHANGED