feat(rebar): 현장타설 말뚝 · 다주형 코핑 형상과 철근 계산
- 현장타설 기둥·말뚝 형상(cast-in-place-shape)과 주철근·횡철근·커플러 계산(rebar/cast-in-place, cast-layout) - 다주형 코핑 철근(multicol-coping), 기둥 높이 · 양단부 연장 - 철근표 요약 · 재료 수량 · 3D 뷰 연결과 삽도(cast-rebar-svg) - 검사 기준 갱신과 회귀 테스트, 검증 스크립트 보관 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3922b330d5
commit
2e0bfb6fc8
29 files changed
+1750
-71
No files matched your search
+16
-10
@@ -1,13 +1,14 @@
|
||||
import { buildAxis, copingSpan, fromAxis, kinkArc, nearKink, toAxis } from './axis';
|
||||
import { buildIntegratedBlocks, type IntegratedBlock } from './integrated-block';
|
||||
import { type BlockRebarSettings, DEFAULT_BLOCK_REBAR } from './rebar/bearing-block';
|
||||
import { type CopingRebarSettings, DEFAULT_COPING_REBAR, DEFAULT_TOP_SPLICE, type TopSpliceSettings } from './rebar/coping-settings';
|
||||
import { type CopingRebarSettings, copingDefaults, DEFAULT_TOP_SPLICE, type TopSpliceSettings } from './rebar/coping-settings';
|
||||
import { type ColumnRebarSettings, DEFAULT_COLUMN_REBAR } from './rebar/column-settings';
|
||||
import { type FootingRebarSettings, DEFAULT_FOOTING_REBAR } from './rebar/footing-settings';
|
||||
import { layoutText, resolveRowCounts, rowLayout, type PileGeometry } from './piles';
|
||||
import type { PierInput, Row, SolplatePlan } from './types';
|
||||
import { SOLPLATE_RULE_DEFAULT, solplatePlan } from './solplate-rule';
|
||||
import { type CopingGeom, P1_COPING_GEOM } from './coping-geom';
|
||||
import { castShape } from './cast-in-place-shape';
|
||||
|
||||
/** Dimensions in m. Sources: intent.PR sheet (P1 rules) and spec.md §3 defaults. */
|
||||
export const DIM = {
|
||||
@@ -15,7 +16,7 @@ export const DIM = {
|
||||
copingH1: 1.0,
|
||||
copingH2: 1.5,
|
||||
levelWidth: 2.1,
|
||||
/** Multi-column coping: underside between columns sits this far below Level, with 45° haunches of the same size (spec §4.5, Q3 추천안). */
|
||||
/** Multi-column coping: underside between columns sits this far above Level, with 45° haunches of the same size (spec §4.4, Q3). */
|
||||
haunch: 0.3,
|
||||
padThickness: 0.05,
|
||||
padSize: 1.0,
|
||||
@@ -207,6 +208,8 @@ export interface PierModel {
|
||||
blockHeightBack: number;
|
||||
frontBackDiffSpread: number;
|
||||
};
|
||||
/** Dedicated rebar source; never substitute footing-anchored column inputs. */
|
||||
castInput?: PierInput;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -343,7 +346,7 @@ export function buildPier(input: PierInput): PierModel {
|
||||
const levelEnd = Math.max(...colG) + levelW / 2;
|
||||
if (levelStart < 0 || levelEnd > L) throw new Error('코핑 길이가 Level 구간보다 짧습니다.');
|
||||
|
||||
// Underside from the right end to the left end. Between columns (2·3주형) it drops 300 below Level with 300 × 300 haunches (spec §4.5, Q3).
|
||||
// Underside from the right end to the left end. Between columns (2·3주형) it rises 300 above Level with 300 × 300 haunches (spec §4.4, Q3).
|
||||
const underside: [number, number][] = [[L, endBottom]];
|
||||
const levelZones = [...colG].sort((a, b) => b - a).map((s) => [s - levelW / 2, s + levelW / 2] as const);
|
||||
levelZones.forEach(([zoneStart, zoneEnd], k) => {
|
||||
@@ -352,8 +355,8 @@ export function buildPier(input: PierInput): PierModel {
|
||||
if (!next) return;
|
||||
const gap = zoneStart - next[1];
|
||||
if (gap <= 2 * DIM.haunch) throw new Error('기둥 사이 간격이 헌치(300 × 2)보다 좁아 코핑 하면을 만들 수 없습니다.');
|
||||
const lowerEl = levelBottom - DIM.haunch;
|
||||
underside.push([zoneStart - DIM.haunch, lowerEl], [next[1] + DIM.haunch, lowerEl], [next[1], levelBottom]);
|
||||
const raisedEl = levelBottom + DIM.haunch;
|
||||
underside.push([zoneStart - DIM.haunch, raisedEl], [next[1] + DIM.haunch, raisedEl], [next[1], levelBottom]);
|
||||
});
|
||||
|
||||
// Elevation outline in coping coordinates for one row of tops, closed by the shared underside.
|
||||
@@ -394,7 +397,9 @@ export function buildPier(input: PierInput): PierModel {
|
||||
}
|
||||
}
|
||||
|
||||
const footingTop = input.foundationType === '현장타설말뚝' ? input.footingBottomEl : input.footingBottomEl + fd.H;
|
||||
const cast = castShape(input);
|
||||
if (input.foundationType === '현장타설말뚝' && (!Number.isFinite(cast.pileTopEl) || cast.pileTopEl >= levelBottom || !Number.isFinite(input.pileLengthMm) || input.pileLengthMm <= 0)) throw new Error('현장타설말뚝은 지반고가 코핑 Level 하면보다 낮고 말뚝 길이가 양수여야 합니다.');
|
||||
const footingTop = input.foundationType === '현장타설말뚝' ? cast.pileTopEl : input.footingBottomEl + fd.H;
|
||||
const columns: ColumnModel[] = colG.map((g, i) => ({
|
||||
s: g - base[colK[i]],
|
||||
k: colK[i],
|
||||
@@ -407,11 +412,11 @@ export function buildPier(input: PierInput): PierModel {
|
||||
const blindings: BlindingModel[] = [];
|
||||
const piles: PileModel[] = [];
|
||||
const pileLength = input.pileLengthMm / 1000;
|
||||
const pileTip = input.footingBottomEl - pileLength;
|
||||
const pileTip = input.foundationType === '현장타설말뚝' ? cast.pileBottomEl : input.footingBottomEl - pileLength;
|
||||
|
||||
if (input.foundationType === '현장타설말뚝') {
|
||||
columns.forEach((c) => {
|
||||
piles.push({ s: c.s, k: c.k, n: 0, top: input.footingBottomEl, bottom: pileTip, diameter: colD });
|
||||
piles.push({ s: c.s, k: c.k, n: 0, top: cast.pileTopEl, bottom: pileTip, diameter: colD });
|
||||
});
|
||||
} else {
|
||||
for (const f of footingSets) {
|
||||
@@ -487,7 +492,7 @@ export function buildPier(input: PierInput): PierModel {
|
||||
blocks,
|
||||
integratedBlocks: buildIntegratedBlocks(blocks, input.bearingLayout === '일체'),
|
||||
blockRebar: { ...DEFAULT_BLOCK_REBAR, ...input.blockRebar },
|
||||
copingRebar: { ...DEFAULT_COPING_REBAR, ...input.copingRebar },
|
||||
copingRebar: { ...copingDefaults(columns.length), ...input.copingRebar },
|
||||
topSplice: { ...DEFAULT_TOP_SPLICE, ...input.topSplice },
|
||||
columnRebar: { ...DEFAULT_COLUMN_REBAR, ...input.columnRebar },
|
||||
footingRebar: { ...DEFAULT_FOOTING_REBAR, ...input.footingRebar },
|
||||
@@ -498,7 +503,7 @@ export function buildPier(input: PierInput): PierModel {
|
||||
groundEl: input.groundEl,
|
||||
derived: {
|
||||
columnHeight: levelBottom - columns[0].bottom,
|
||||
soilCover: input.groundEl - (input.foundationType === '현장타설말뚝' ? input.footingBottomEl : footingTop),
|
||||
soilCover: input.foundationType === '현장타설말뚝' ? 0 : input.groundEl - footingTop,
|
||||
pileCount: piles.length,
|
||||
pileLayout: input.foundationType === '말뚝기초' ? layoutText(resolveRowCounts(input.pileRows, pileGeometry(footings[0].length, fd.W)), pileGeometry(footings[0].length, fd.W)) : null,
|
||||
pileTipEl: piles.length ? pileTip : null,
|
||||
@@ -506,6 +511,7 @@ export function buildPier(input: PierInput): PierModel {
|
||||
blockHeightBack,
|
||||
frontBackDiffSpread,
|
||||
},
|
||||
...(input.foundationType === '현장타설말뚝' ? { castInput: { ...input } } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user