UNPKG

@bitbybit-dev/occt

Version:

Bit By Bit Developers CAD algorithms using OpenCascade Technology kernel. Run in Node and in Browser.

252 lines (251 loc) 10.4 kB
import { Base } from "./inputs/inputs"; export class ShapesHelperService { starLines(innerRadius, outerRadius, numRays, half, offsetOuterEdges) { let lines = []; const angle_step = (2 * Math.PI) / numRays; for (let i = 0; i < numRays; i++) { const angle_i = i * angle_step; const offset = offsetOuterEdges ? offsetOuterEdges : 0; const outer_point = [ outerRadius * Math.cos(angle_i), offset, outerRadius * Math.sin(angle_i) ]; const inner_point = [ innerRadius * Math.cos(angle_i + angle_step / 2), 0, innerRadius * Math.sin(angle_i + angle_step / 2) ]; const next_outer_point = [ outerRadius * Math.cos(angle_i + angle_step), offset, outerRadius * Math.sin(angle_i + angle_step) ]; lines.push({ start: outer_point, end: inner_point }); lines.push({ start: inner_point, end: next_outer_point }); } if (half) { lines = lines.slice(0, lines.length / 2); } return lines; } parallelogram(width, height, angle, center) { const radians = (angle * Math.PI) / 180; let x1, y1, x2, y2, x3, y3, x4, y4; if (center) { x1 = -width / 2; y1 = -height / 2; x2 = width / 2; y2 = -height / 2; x3 = width / 2; y3 = height / 2; x4 = -width / 2; y4 = height / 2; } else { x1 = 0; y1 = 0; x2 = width; y2 = 0; x3 = width; y3 = height; x4 = 0; y4 = height; } const shift = height * Math.tan(radians) / 2; x1 += shift; x2 += shift; x3 -= shift; x4 -= shift; const pt1 = [x1, 0, y1]; const pt2 = [x2, 0, y2]; const pt3 = [x3, 0, y3]; const pt4 = [x4, 0, y4]; const line1 = { start: pt1, end: pt2 }; const line2 = { start: pt2, end: pt3 }; const line3 = { start: pt3, end: pt4 }; const line4 = { start: pt4, end: pt1 }; return [line1, line2, line3, line4]; } ngon(n, radius, center) { const angle = (2 * Math.PI) / n; const edges = []; for (let i = 0; i < n; i++) { const start = [center[0] + radius * Math.cos(i * angle), 0, center[1] + radius * Math.sin(i * angle)]; const end = [center[0] + radius * Math.cos((i + 1) * angle), 0, center[1] + radius * Math.sin((i + 1) * angle)]; edges.push({ start, end }); } return edges; } polygonL(widthFirst, lengthFirst, widthSecond, lengthSecond) { return [ [0, 0, 0], [lengthFirst, 0, 0], [lengthFirst, 0, -widthFirst], [-widthSecond, 0, -widthFirst], [-widthSecond, 0, lengthSecond], [0, 0, lengthSecond], ]; } polygonLInverted(widthFirst, lengthFirst, widthSecond, lengthSecond) { if (widthFirst >= lengthSecond) { widthFirst = lengthSecond - 1e-6; console.warn("width first is bigger than length second, to make it work, width second is set to length first - 1e-6"); } if (widthSecond >= lengthFirst) { widthSecond = lengthFirst - 1e-6; console.warn("width second is bigger than length first, to make it work, width second is set to length first - 1e-6"); } return [ [0, 0, 0], [lengthFirst, 0, 0], [lengthFirst, 0, widthFirst], [widthSecond, 0, widthFirst], [widthSecond, 0, lengthSecond], [0, 0, lengthSecond], ]; } polygonLMiddle(widthFirst, lengthFirst, widthSecond, lengthSecond) { if (widthFirst >= lengthSecond) { widthFirst = lengthSecond - 1e-6; console.warn("width first is bigger than length second, to make it work, width second is set to length first - 1e-6"); } if (widthSecond >= lengthFirst) { widthSecond = lengthFirst - 1e-6; console.warn("width second is bigger than length first, to make it work, width second is set to length first - 1e-6"); } return [ [widthSecond / 2, 0, widthFirst / 2], [widthSecond / 2, 0, lengthSecond], [-widthSecond / 2, 0, lengthSecond], [-widthSecond / 2, 0, -widthFirst / 2], [lengthFirst, 0, -widthFirst / 2], [lengthFirst, 0, widthFirst / 2], ]; } beamIProfile(width, height, webThickness, flangeThickness, alignment) { // Create I-beam profile centered at origin const halfWidth = width / 2; const halfHeight = height / 2; const halfWeb = webThickness / 2; // Points for I-beam (clockwise from top-left) const points = [ [-halfWidth, 0, halfHeight], [halfWidth, 0, halfHeight], [halfWidth, 0, halfHeight - flangeThickness], [halfWeb, 0, halfHeight - flangeThickness], [halfWeb, 0, -halfHeight + flangeThickness], [halfWidth, 0, -halfHeight + flangeThickness], [halfWidth, 0, -halfHeight], [-halfWidth, 0, -halfHeight], [-halfWidth, 0, -halfHeight + flangeThickness], [-halfWeb, 0, -halfHeight + flangeThickness], [-halfWeb, 0, halfHeight - flangeThickness], [-halfWidth, 0, halfHeight - flangeThickness], ]; return this.applyBeamAlignment(points, width, height, alignment); } beamHProfile(width, height, webThickness, flangeThickness, alignment) { // H-beam is I-beam rotated 90 degrees (width and height swapped) // Create H-beam profile centered at origin (rotated I-beam) const halfWidth = width / 2; const halfHeight = height / 2; const halfWeb = webThickness / 2; // Points for H-beam (I-beam rotated 90 degrees, clockwise from top-left) const points = [ [-halfWidth, 0, halfHeight], [-halfWidth + flangeThickness, 0, halfHeight], [-halfWidth + flangeThickness, 0, halfWeb], [halfWidth - flangeThickness, 0, halfWeb], [halfWidth - flangeThickness, 0, halfHeight], [halfWidth, 0, halfHeight], [halfWidth, 0, -halfHeight], [halfWidth - flangeThickness, 0, -halfHeight], [halfWidth - flangeThickness, 0, -halfWeb], [-halfWidth + flangeThickness, 0, -halfWeb], [-halfWidth + flangeThickness, 0, -halfHeight], [-halfWidth, 0, -halfHeight], ]; return this.applyBeamAlignment(points, width, height, alignment); } beamTProfile(width, height, webThickness, flangeThickness, alignment) { // Create T-beam profile centered at origin const halfWidth = width / 2; const halfHeight = height / 2; const halfWeb = webThickness / 2; // Points for T-beam (clockwise from top-left) const points = [ [-halfWidth, 0, halfHeight], [halfWidth, 0, halfHeight], [halfWidth, 0, halfHeight - flangeThickness], [halfWeb, 0, halfHeight - flangeThickness], [halfWeb, 0, -halfHeight], [-halfWeb, 0, -halfHeight], [-halfWeb, 0, halfHeight - flangeThickness], [-halfWidth, 0, halfHeight - flangeThickness], ]; return this.applyBeamAlignment(points, width, height, alignment); } beamUProfile(width, height, webThickness, flangeThickness, flangeWidth, alignment) { // Create U-beam profile centered at origin (opening upward - rotated 180 degrees from previous) const halfWidth = width / 2; const halfHeight = height / 2; // Points for U-beam (clockwise from top-left outside, opening upward) const points = [ [-halfWidth, 0, halfHeight], [-halfWidth + flangeThickness, 0, halfHeight], [-halfWidth + flangeThickness, 0, -halfHeight + flangeWidth], [halfWidth - webThickness, 0, -halfHeight + flangeWidth], [halfWidth - webThickness, 0, halfHeight], [halfWidth, 0, halfHeight], [halfWidth, 0, -halfHeight], [-halfWidth, 0, -halfHeight], ]; return this.applyBeamAlignment(points, width, height, alignment); } applyBeamAlignment(points, width, height, alignment) { // Alignment logic: the specified corner/edge of the shape is placed at the origin // For example, topLeft means the top-left corner of the shape is at (0,0) let offsetX = 0; let offsetZ = 0; switch (alignment) { case Base.basicAlignmentEnum.topLeft: offsetX = width / 2; offsetZ = -height / 2; break; case Base.basicAlignmentEnum.topMid: offsetX = 0; offsetZ = -height / 2; break; case Base.basicAlignmentEnum.topRight: offsetX = -width / 2; offsetZ = -height / 2; break; case Base.basicAlignmentEnum.midLeft: offsetX = width / 2; offsetZ = 0; break; case Base.basicAlignmentEnum.midMid: offsetX = 0; offsetZ = 0; break; case Base.basicAlignmentEnum.midRight: offsetX = -width / 2; offsetZ = 0; break; case Base.basicAlignmentEnum.bottomLeft: offsetX = width / 2; offsetZ = height / 2; break; case Base.basicAlignmentEnum.bottomMid: offsetX = 0; offsetZ = height / 2; break; case Base.basicAlignmentEnum.bottomRight: offsetX = -width / 2; offsetZ = height / 2; break; } return points.map(pt => [pt[0] + offsetX, pt[1], pt[2] + offsetZ]); } }