# BREP Loop, Shell, and Solid Extraction Implementation

## Overview

This document describes the complete implementation of Loop, Shell, and Solid extraction for the FikoBrep system in fikoyt-zorro.com.

## Implementation Date
2025-02-15

## Files Modified

1. `d:\__sistem__\Masaustu\FikoYT.Yeni.Cag\fikoyt-zorro.com\src\service\fikoyt-ui\src\lib\fiko-three-js\IFikoThreeJS\FikoBrep\FikoBrep.ts`
2. `d:\__sistem__\Masaustu\FikoYT.Yeni.Cag\fikoyt-zorro.com\src\service\fikoyt-ui\src\lib\fiko-three-js\IFikoThreeJS\FikoBrep\FikoBrepWasmAnalyzer.ts`

## What Was Implemented

### 1. Loop Extraction (`extractLoops()`)

**Purpose:** Extract boundary loops for each face by ordering edges into continuous paths.

**Algorithm:**
- For each face, find all edges that belong to it
- Order edges into continuous paths using vertex matching (end-to-start)
- Determine loop orientation (CCW = outer, CW = hole) using signed area calculation
- Create BrepLoop objects with ordered edge and vertex lists

**Key Features:**
- **Edge Ordering:** `orderEdgesIntoLoops()` method chains edges by matching vertices
- **Loop Orientation:** `isLoopCounterClockwise()` uses shoelace formula on 2D projection
- **Multiple Loops per Face:** Supports outer loops + inner holes

**Code Structure:**
```typescript
private extractLoops(brep: BrepBody): void {
  brep.faces.forEach(face => {
    const loops = this.orderEdgesIntoLoops(faceEdges, brep);
    loops.forEach(loopEdges => {
      const isOuter = this.isLoopCounterClockwise(loopVertices, face.normal, brep);
      // Create BrepLoop
    });
  });
}
```

### 2. Shell Extraction (`extractShells()`)

**Purpose:** Group connected faces into shells using face adjacency analysis.

**Algorithm:**
- Build face adjacency graph (faces sharing edges are neighbors)
- Use DFS (Depth-First Search) to find connected components
- Each connected component = one shell
- Check closure: all edges must have exactly 2 faces for watertight shell
- Calculate volume for closed shells using signed volume formula

**Key Features:**
- **Graph-Based:** Uses adjacency map instead of just group attributes
- **Connected Components:** DFS traversal finds all shells
- **Closure Detection:** `isShellClosed()` validates watertight property
- **Volume Calculation:** `calculateShellVolume()` uses tetrahedron formula

**Code Structure:**
```typescript
private extractShells(brep: BrepBody, gruplar: Map<number, Set<number>>): void {
  // Build adjacency graph
  brep.edges.forEach(edge => {
    if (edge.faces.length === 2) {
      adjacencyMap.get(f0).add(f1);
      adjacencyMap.get(f1).add(f0);
    }
  });

  // DFS to find connected components
  const visited = new Set<string>();
  for (const faceId of brep.faces.keys()) {
    const component = dfsTraversal(faceId);
    // Create shell from component
  }
}
```

**Volume Formula:**
```
V = Σ (v0 · (v1 × v2)) / 6
```
Where each triangle contributes to the signed volume.

### 3. Solid Extraction (`extractSolids()`)

**Purpose:** Create solid bodies from closed shells, detecting outer shell and inner voids.

**Algorithm:**
- Filter only closed shells (watertight)
- Sort shells by bounding box size (largest = outer shell)
- For each outer shell, find inner shells (voids) using containment test
- Calculate net volume: outer volume - void volumes
- Compute center of mass using volume-weighted average

**Key Features:**
- **Void Detection:** `isShellContainedIn()` uses bounding box + size comparison
- **Volume Subtraction:** Net volume = outer - sum(voids)
- **Center of Mass:** `calculateSolidCenterOfMass()` weighted by volume

**Code Structure:**
```typescript
private extractSolids(brep: BrepBody): void {
  const closedShells = shells.filter(s => s.isClosed);
  const sortedShells = closedShells.sort(byBoundingBoxSize);

  for (const outerShell of sortedShells) {
    const voids = findContainedShells(outerShell);
    const volume = outerShell.volume - sum(void.volumes);
    const centerOfMass = calculateWeightedCenter();
    // Create BrepSolid
  }
}
```

**Containment Test:**
1. Bounding box must be fully contained
2. Inner shell must be significantly smaller (< 80% of outer)
3. Center distance check: `distance + innerSize/2 < outerSize/2`

**Center of Mass Formula:**
```
COM = (Vouter * COMouter - Σ(Vvoid * COMvoid)) / Vtotal
```

## Data Flow

```
Mesh Geometry
    ↓
extractVertices() → BrepVertex[]
    ↓
extractEdges() → BrepEdge[] (with face adjacency)
    ↓
extractFaces() → BrepFace[] (triangles)
    ↓
extractLoops() → BrepLoop[] (ordered edge paths)
    ↓                         ↓
extractShells() → BrepShell[] (connected components)
    ↓                         ↓
    ↓                    isShellClosed()
    ↓                    calculateShellVolume()
    ↓
extractSolids() → BrepSolid[] (outer + voids)
    ↓                         ↓
    ↓                    calculateSolidCenterOfMass()
    ↓
Complete BrepBody
```

## Interface Compliance

All implementations fully comply with the existing interfaces:

### BrepLoop Interface
```typescript
interface BrepLoop {
    id: string;
    edges: string[];     // ✓ Ordered edge list
    isOuter: boolean;    // ✓ CCW/CW determination
    vertices: string[];  // ✓ Ordered vertex list
}
```

### BrepShell Interface
```typescript
interface BrepShell {
    id: string;
    faces: string[];         // ✓ Connected face group
    isClosed: boolean;       // ✓ Watertight check
    volume?: number;         // ✓ Signed volume calculation
    boundingBox: THREE.Box3; // ✓ From vertex positions
}
```

### BrepSolid Interface
```typescript
interface BrepSolid {
    id: string;
    outerShell: string;      // ✓ Largest shell
    voids: string[];         // ✓ Contained inner shells
    volume: number;          // ✓ Outer - voids
    centerOfMass: THREE.Vector3; // ✓ Volume-weighted
    boundingBox: THREE.Box3; // ✓ From outer shell
}
```

## Performance Characteristics

### Loop Extraction
- **Time Complexity:** O(E × F) where E = edges, F = faces
- **Space Complexity:** O(L) where L = total loops
- **Optimizations:**
  - Visited set prevents duplicate traversal
  - Early termination when loop closes

### Shell Extraction
- **Time Complexity:** O(F + E) for DFS traversal
- **Space Complexity:** O(F) for visited set and adjacency map
- **Optimizations:**
  - Adjacency map built once
  - Linear DFS traversal per component

### Solid Extraction
- **Time Complexity:** O(S²) where S = shell count (usually small)
- **Space Complexity:** O(S) for shell sorting and tracking
- **Optimizations:**
  - Early bounding box rejection
  - Size-based sorting reduces containment tests

## Usage Example

```typescript
import { FikoBrep } from './FikoBrep';

const fikoBrep = new FikoBrep();
const meshGeom = getBufferGeometry();

const result = await fikoBrep.meshtenBrepOlustur(meshGeom, {
  tolerance: 1e-6,
  recognizeSurfaces: true
});

// Access extracted topology
console.log(`Loops: ${result.brep.loops.size}`);
console.log(`Shells: ${result.brep.shells.size}`);
console.log(`Solids: ${result.brep.solids.size}`);

// Check watertight
result.brep.shells.forEach(shell => {
  console.log(`Shell ${shell.id}: ${shell.isClosed ? 'closed' : 'open'}`);
  if (shell.volume) {
    console.log(`  Volume: ${shell.volume.toFixed(6)}`);
  }
});

// Solid information
result.brep.solids.forEach(solid => {
  console.log(`Solid ${solid.id}:`);
  console.log(`  Volume: ${solid.volume.toFixed(6)}`);
  console.log(`  Center of Mass: ${solid.centerOfMass.toArray()}`);
  console.log(`  Voids: ${solid.voids.length}`);
});
```

## Integration with Analysis Pipeline

The extraction methods are automatically called in the analysis pipeline:

```typescript
// FikoBrepWasmAnalyzer.ts line 68-75
// 5. Loop extraction
this.extractLoops(brep);

// 6. Shell extraction (grup bazlı)
this.extractShells(brep, gruplar);

// 7. Solid extraction
this.extractSolids(brep);
```

## Testing Recommendations

1. **Simple Cube:** Single outer loop per face, one shell, one solid
2. **Cube with Hole:** Outer + inner loops on some faces, one shell, one solid with void
3. **Multiple Objects:** Multiple shells → multiple solids
4. **Open Mesh:** Shells with `isClosed = false`, no solids
5. **Complex STEP File:** Real-world CAD model with multiple features

## Known Limitations

1. **Loop Ordering:** Assumes manifold edges (max 2 faces per edge)
2. **Void Detection:** Uses bounding box approximation, not ray casting
3. **Center of Mass:** Simplified calculation using shell centers, not true volumetric integration
4. **Non-Manifold Geometry:** May produce unexpected results if mesh has non-manifold edges

## Future Enhancements

1. **Advanced Loop Detection:** Support non-manifold and T-junctions
2. **Precise Void Detection:** Implement point-in-solid ray casting
3. **Accurate Center of Mass:** Volumetric integration using tetrahedral mesh
4. **NURBS Support:** Extend loop ordering to parametric curve boundaries
5. **Parallel Processing:** WASM acceleration for shell/solid extraction

## References

- **Signed Volume Formula:** Mirtich, "Fast and Accurate Computation of Polyhedral Mass Properties" (1996)
- **Shoelace Formula:** Gauss's area formula for polygons
- **Connected Components:** Tarjan's DFS algorithm
- **BREP Topology:** ISO 10303-42 (STEP AP242)

## Conclusion

This implementation provides a complete, working BREP topology extraction system that:
- ✓ Orders edges into continuous loops
- ✓ Detects loop orientation (outer vs holes)
- ✓ Groups faces into shells using adjacency
- ✓ Validates watertight closure
- ✓ Calculates shell volumes
- ✓ Detects solid voids
- ✓ Computes center of mass

All methods are functional (not stubs) and integrate seamlessly with the existing FikoBrep analysis pipeline.
