# FikoYT Web Dosya Formatları → fikatia-local Native Açma/Kaydetme SPEC'i

> **Amaç:** Web (`fikoyt-sistem`) tarafından üretilen `.FikoOp`, `.FikoApt` ve `.wrl` dosyalarını native fikatia-local (C++23 / OCCT / Vulkan) uygulamasında AÇMAK (ve gerekirse kaydetmek).
> **Kaynak dosyalar (web):** `fikoyt-sistem/src/service/fikoyt-ui/src/lib/fiko-three-js/IFikoThreeJS/`
> **Örnek veriler:** `D:/__sistem__/Downloads/Test/` (`Fikoperasyon.1/2/3.FikoOp`, `ust.1/2.FikoOp`, `Ust_Kalip_202510-UST-FORM-ON.FikoApt`, `Ust_Kalip.wrl`)
> **STEP (.stp):** native'de `geometri::stepYukleHiyerarsi` ile zaten açılıyor — kapsam dışı.

---

## 0. FORMATLARIN ÖZETİ (imza tablosu)

| Format | İmza (ilk baytlar) | Kodlama | İçerik | Web okuyucu/yazıcı |
|--------|--------------------|---------|--------|---------------------|
| **`.FikoOp`** | `1F 8B 08` (gzip) | **gzip → UTF-8 JSON** | Fikoperasyon: işleme ekseni + mesh çizimler + NC programları (takım yolu noktaları) + kamera | `FikoThreeCam/Fikoperasyon.ts` (`dosyayaKaydet`/`dosyadanYukle`/`toJSON`/`fromJson`) |
| **`.FikoApt`** | `24 24 20` (`$$ `) | **düz ASCII/UTF-8 metin** | CATIA APT/CL: GOTO hamle listesi + CUTTER/SPINDL/FEDRAT/TLAXIS | `FikoImporter.APTCAT.ts` (`parcala`) |
| **`.wrl`** | `23 56 52 4D 4C` (`#VRML`) | **düz metin VRML97 (V2.0 utf8)** | CATIA VRML mesh: IndexedFaceSet (yüzey) + IndexedLineSet (kenar) + Material | `FikoImporter.WRL.ts` (three.js `VRMLLoader`) |

**Gzip önemli:** `.FikoOp` ~4.25 MB dosya açıldığında ~53.5 MB JSON olur (**~12.6x**). Native tarafta streaming gzip decompress + streaming JSON parse ŞART (bellek).

---

## 1. `.FikoOp` FORMATI (Fikoperasyon)

### 1.1 Kodlama / açma adımları
1. Dosyayı oku, ilk 2 bayt `0x1F 0x8B` ise gzip'tir (değilse düz UTF-8 — eski/uncompressed uyumluluğu).
2. gzip decompress → UTF-8 string.
3. `JSON.parse` → aşağıdaki üst-düzey yapı.

**Web kaynağı:** `Fikoperasyon.ts:475-561` — `gzipSikistir` (CompressionStream), `gzipCoz` (DecompressionStream), `gzipMi` (imza kontrolü).

### 1.2 Üst-düzey şema (`FikoOperasyon.toJSON`)
```jsonc
{
  "type": "Fikoperasyon",
  "isim": "Fikoperasyon.1",
  "uuid": "94c41286-...",
  "eksen":     { /* FikoEksen — işleme ekseni, aşağıda §1.3 */ },
  "cizimler":  { /* FikoCizimler — mesh ağacı, §1.4 */ },
  "programlar":{ /* Fikogramlar — NC programları, §1.5 */ },
  "seciliKutukUuid": "..." | (yok),   // opsiyonel
  "konum":     { /* FikoKonum — kamera preset */ } | (yok),  // opsiyonel
  "userData":  { /* FikoParametreler/FikoArayuz/custom */ }, // opsiyonel
  "visible":   false,
  "matrix":    [16 float],            // TRS matrisi
  "kameraDurumu": { /* §1.6 */ }      // opsiyonel — export anındaki görünüm
}
```
> **NOT:** `Fikoperasyon.ts` sürümüne göre eski format da olabilir (`FikoImporter.FikoOpGL.ts`: `{ismi, cizim, programlar[].apt}`) — ama **örnek dosyalarımızın hepsi YENİ format** (`type/isim/eksen/cizimler/programlar`). Native başta sadece yeni formatı hedeflesin; eski format görülürse "desteklenmiyor" uyarısı.

### 1.3 `eksen` — İşleme Ekseni (FikoEksen)
```jsonc
"eksen": {
  "type": "FikoEksen",
  "isim": "...İşleme Ekseni",
  "matrix": [16 float],       // yerleşim matrisi (örn. köşede 88.2 = ölçek)
  "xYon": {"x":1,"y":0,"z":0},
  "yYon": {"x":0,"y":1,"z":0},
  "zYon": {"x":0,"y":0,"z":1},
  "merkez": {"x":0,"y":0,"z":0},
  "visible": false
}
```
**Native karşılığı:** `PartOperasyon.eksenOrigin/eksenX/eksenY/eksenZ` (Machining Axis System). `merkez→eksenOrigin`, `xYon/yYon/zYon→eksenX/Y/Z`.

### 1.4 `cizimler` — Mesh Ağacı (FikoCizimler)
```
FikoCizimler
 └ children[]: FikoGrupCizim
     └ children[]: FikoCizimYalin   ← asıl mesh taşıyıcı
```
**`FikoCizimYalin` şeması (örnek dosyada):**
```jsonc
{
  "type": "FikoCizimYalin",
  "isim": "P2108_..._UNTERTEIL",
  "uuid": "...",
  "matrix": [16 float],            // yerel dönüşüm
  "yuzeyler": { /* THREE BufferGeometry.toJSON — YÜZEY mesh */ },
  "sinirlar": { /* BufferGeometry — KENAR çizgileri */ },
  "noktalar": { /* BufferGeometry — köşe noktaları */ },
  "konumlar": { "type":"FikoKonumlar", "liste":[] }
}
```
**Geometri iç yapısı (örnek dosyada — EN KOLAY hal):**
```jsonc
"yuzeyler": {
  "metadata": {"version":4.7, "type":"BufferGeometry", ...},
  "uuid": "...",
  "type": "BufferGeometry",
  "data": {
    "attributes": {
      "position": { "itemSize":3, "type":"Float32Array", "array":[x,y,z, x,y,z, ...] },
      "normal":   { "itemSize":3, "type":"Float32Array", "array":[...] },
      "color":    { "itemSize":3, "type":"Float32Array", "array":[r,g,b, ...] },
      "alpha":    { "itemSize":1, "type":"Float32Array", "array":[...] },
      "grup":     { "itemSize":3, "type":"Float32Array", "array":[...] }  // seçim/highlight
    },
    "boundingSphere": {...}
    // "index": {...}  ← örnek dosyada YOK (non-indexed üçgen soup)
  }
}
```
- **Koordinat birimi: mm** (float, ölçeklenmemiş). Örn `2315.699951171875`.
- **`position.array` düz JSON float listesi** — örnek dosyada base64 DEĞİL, `_bin` referansı DEĞİL. Native parse için trivial.
- `yuzeyler` = üçgen listesi (3'er vertex), `sinirlar`/`noktalar` = çizgi/nokta listesi.

> **⚠️ GOTCHA — geometri sıkıştırma varyantları:** `FikoCizimYalin.ts` içinde `geometryToCompact`/binary-buffer/base64/byteShuffle/deinterleaveXYZ + `flate` gzip **opsiyonel** kod yolları var (~%40 daha küçük dosya). Örnek dosyalarımız bu yolu KULLANMAMIŞ (düz array). Native parser: `position.array` bir **JSON dizisi** ise doğrudan oku; **string (base64)** ise veya `data._bin` alanı varsa → o dosya sıkıştırılmış geometri kullanmış demektir, ilk sürümde "bu FikoOp sıkıştırılmış geometri içeriyor, henüz desteklenmiyor" uyarısı ver. (Örnek verilerle test edildiğinde bu yola girilmez.)

**Native karşılığı:** Her `FikoCizimYalin` → bir sahne `Dugum`. `yuzeyler` → `MeshVeri{vertexler, indeksler}`, `sinirlar` → `KenarVeri`, `noktalar` → `NoktaVeri`. B-Rep gövde YOK (mesh-only import) — `sahne.ithalEkleHazir` mesh yollarıyla eklenir. `matrix` → dünya dönüşümü.

### 1.5 `programlar` — NC Programları (Fikogramlar → FikoAPTCAT → FikoTakimYolu)
```jsonc
"programlar": {
  "type": "Fikogramlar",
  "isim": "Nc Programlar",
  "children": [
    {
      "type": "FikoAPTCAT",
      "isim": "YENI-1005-UNTERTEIL-UST-ON",
      "tarihi": "2026-01-15T12:51:29.000Z",
      "programIsmi": "...",
      "kureMerkezi": false,          // "TOOL CENTER OUTPUT" bayrağı
      "operasyonIsmi": "...",
      "eksenKoord": {                // CATMAT matrisi (APT'den) — §1.5.1
        "x":[0,1,0], "y":[1,0,0], "z":[0,0,1], "o":[1423.5, ..., ...]
      },
      "takimYolu": { /* FikoTakimYolu — §1.5.2 */ }
    }
  ]
}
```
`type` `FikoAPTCAT` değilse (ör. düz `Fikogram`) → takım yolu içermeyen boş program; native'de basit isim düğümü olarak atla/oluştur.

#### 1.5.1 `eksenKoord` — takım yolu referans çerçevesi
- `x/y/z` = 3-eleman baz vektörler, `o` = origin (mm).
- Native (`FikoImporter.APTCAT.ts:296-297`): `takimYolu.position = o`, rotasyon = `makeBasis(x,y,z)`. **Noktalar bu çerçeveyle localToWorld'e çevrilir** (§1.5.2'de zaten dünya koordinatında saklı olabilir — aşağıya bak).

#### 1.5.2 `FikoTakimYolu` — TAKIM YOLU (en kritik veri)
```jsonc
"takimYolu": {
  "type": "FikoTakimYolu",
  "isim": "....FikoTakimYolu",
  "uuid": "...",
  "children": [],
  "noktalar": [ /* delta-encoded nokta listesi — aşağıda */ ]
}
```
`noktalar` çok büyük olabilir (örn. **223970 nokta**). **DELTA/INHERIT ENCODING** kullanılır:

**Nokta[0] (tam):**
```jsonc
{
  "x": 41095486, "y": 53939609, "z": -21147269,   // INT: değer×100000 → mm
  "takim": { "type":"FikoGrup", "uuid":"...",
             "cap":3000000, "radius":1500000,       // INT: ×100000 → mm
             "boy":20000, "kesmeBoy":5000 },        // INT: ×100 → mm
  "ekBilgiler": { "ismi":"Roughing.13", "programIsmi":"..." },
  "hiz": 25000,            // ilerleme mm/dk (int, ölçeksiz)
  "devir": 4500,           // spindle rpm
  "tip": "linear",         // 'rapid'|'linear'|'cut'|'arc_cw'|'arc_ccw'|'dwell'|'tap'...
  "ty": [0, 0, -100000],   // takım YÖNÜ (TLAXIS) INT ×100000 → birim vektör
  "r": "#ff0000",          // renk (hex) — işleme/yaklaşma/uzaklaşma sınıfı
  "toplamSure": 1219563,   // INT ×100 → saniye (tüm noktalar aynı = toplam)
  "guncelSure": null       // INT ×100 → o noktadaki kümülatif süre (animasyon)
}
```
**Nokta[1+] (delta — sadece DEĞİŞEN alanlar):**
```jsonc
{ "x":41095486, "y":53939609, "z":-17157269, "r":"#ffff00", "guncelSure":10 }
```

**Ölçek çarpanları (`FikoVektorTakimYol3d.ts:98-112`, `FikoTakimYolu.ts:148`):**
| Alan | Çarpan | Native birim |
|------|--------|--------------|
| `x, y, z` | **÷100000** | mm |
| `ty[0..2]` (takım yönü) | **÷100000** | birim vektör |
| `takim.cap, takim.radius` | **÷100000** | mm |
| `takim.boy, takim.kesmeBoy` | **÷100** | mm |
| `guncelSure, toplamSure` | **÷100** | saniye |
| `i, j, k` (arc merkez ofset) | **÷100000** | mm |
| `hiz, devir` | ×1 (ham) | mm/dk, rpm |
| `r` | hex string | RGB renk |

> **⚠️ INT/FLOAT tespiti (eski uyumluluk):** Web decoder her alanda `Number.isInteger(v) && |v|>eşik` kontrolüyle int mi float mu ayırt eder (`FikoTakimYolu.ts:171`, `FikoVektorTakimYol3d.ts:157`). Native parser aynı kuralı uygulasın: **int + eşik-üstü ise ölçekle, değilse ham float kabul et.** Eşikler: koordinat >1000, cap/süre >100, ty >100.

**Delta decode algoritması (native, `FikoTakimYolu.ts:150-255` referans):**
```
son* değişkenleri tut (sonTakim, sonEkBilgi, sonTy=[0,0,100000], sonHiz, sonDevir,
                        sonTip='linear', sonToplamSure, sonRenk=beyaz).
her nokta için:
  x/y/z HER ZAMAN var → ölçekle.
  alan JSON'da VARSA → decode + son*'u güncelle.
  alan YOKSA → son* değerini kullan.
  guncelSure genelde her noktada yazılır (animasyon için).
```

**Renk anlamı (`FikoImporter.APTCAT.ts:180-224`):**
| Renk | Anlam |
|------|-------|
| `chartreuse`/yeşil | işleme (kesme) |
| `#ffff00` sarı | yaklaşma (rapid, Z aşağı) |
| `#0000ff` mavi | uzaklaşma (rapid, Z yukarı) |
| `#ff0000` kırmızı | boşta geçiş (rapid, Z sabit) |

**Native karşılığı:** Her nokta → CAM `Hamle{tip, nokta(mm), ilerleme}`.
- `tip`: `rapid`→`HamleTip::Hizli`; `linear`/`cut`→`HamleTip::Kesme`; Z-dalma tespit edilirse `Dalma`.
- `nokta`: (x,y,z) mm.
- `ilerleme`: `hiz` (mm/dk).
- `takim` → `cam::Takim` (cap, koseYaricap=radius, boy).
- **EK ALANLAR** (`devir`, `ty` takım yönü, `r` renk, `guncelSure`): native `Hamle`'de yok. Bunlar için **import-özel zengin yol yapısı** öner (§2.2). Basit MVP: sadece `nokta+tip+ilerleme` al, gerisini görselleştirme için ayrı sakla.

### 1.6 `kameraDurumu` (opsiyonel)
```jsonc
{ "position":[3 float], "quaternion":[4], "up":[3], "zoom":f, "hedef":[3], "oran":f }
```
Native'de import sonrası kamerayı buraya kur (opsiyonel konfor). `zoom` viewport en-boy oranına (`oran`) göre yeniden ölçeklenir.

---

## 2. `.FikoApt` FORMATI (CATIA APT/CL)

### 2.1 Kodlama / yapı
- **Düz ASCII metin** (satır-tabanlı). Encoding: UTF-8, hatalıysa windows-1254 fallback (`FikoImporter.APTCAT.ts:41-44`).
- Örnek başlık:
```
$$ -----------------------------------------------------------------
$$     Generated on Thursday, 05 February 2026 22:12:47
$$     CATIA APT VERSION 1.0
$$ -----------------------------------------------------------------
$$ 202510-UST-FORM-ON            ← program ismi
$$  ON                           ← (TOOL CENTER OUTPUT bayrağı burada aranır)
$$ 202510-UST-FORM-ON
$$    -1.00000  0.00000  0.00000  1120.00000    ← eksen satırı 1 (CATMAT)
$$     0.00000 -1.00000  0.00000     0.00000    ← eksen satırı 2
$$     0.00000  0.00000  1.00000   -21.57288    ← eksen satırı 3
CATMAT/ 1120.0, 0.0, -21.57, -1.0, ...
PARTNO 202510-UST-FORM-ON
```

### 2.2 Komut sözlüğü (örnek dosyada görülenler + sayılar)
| Komut | Format | Anlam | Sayı (örnekte) |
|-------|--------|-------|----------------|
| `$$ ...` | yorum | header/operasyon adı işareti | çok |
| `$$ OPERATION NAME : X` | — | **operasyon ayırıcı** | — |
| `PARTNO ad` | — | parça no | 1 |
| `CATMAT/ ...` | 9+ sayı | eksen matrisi | 1 |
| `TLAXIS/ i,j,k` | 3 sayı | **takım ekseni yönü** | 1 |
| `CUTTER/ D,r,e,f,α,β,h` | 7 sayı (satır devamı `$`) | **kesici tanımı** | 1 |
| `LOADTL/n,ADJUST,m` | — | takım yükle | 1 |
| `SPINDL/ rpm,RPM,CLW` | — | **iğ devri** | 5 |
| `SPINDL/OFF` | — | iğ kapat | 1 |
| `FEDRAT/ v,MMPM` | — | **ilerleme hızı** (mm/dk) | ~7500 |
| `GOTO / x,y,z` | 3 sayı | **konum hamlesi** | **223970** |
| `PPRINT ...` | — | operatör mesajı | birkaç |
| `REWIND/0`, `END` | — | program sonu | 1 |

> **NOT:** Bu dosyada `RAPID`, `CIRCLE/GOFWD` (yay), `CYCLE` (sabit döngü), `GODLTA` **YOK** — sadece `GOTO`+`FEDRAT`+`SPINDL`. Native parser bunlarla başlasın; `CIRCLE/CYCLE/RAPID` gelecekte eklenebilir (sözdizimi hazır bırak).

### 2.3 Parse algoritması (`FikoImporter.APTCAT.ts:96-260` referans)
1. İlk 4 satırdan tarih (`Generated on ...` → Date), `programIsmi`, `kureMerkezi` (`TOOL CENTER OUTPUT` içeriyor mu), `operasyonIsmi`.
2. 3 eksen satırı → `eksenKoord{x,y,z,o}` (her sayı `[-+]?\d*\.\d+|\d+` regex ile).
3. `$$ OPERATION NAME :` ile operasyonlara böl.
4. Her operasyonda satır satır: `CUTTER/`→takım, `TLAXIS/`→takım yönü, `SPINDL`→devir, `FEDRAT`→ilerleme, `GOTO`→nokta (son takım/devir/ilerleme/yön miras alınır).
5. **Rapid tespiti:** dosyadaki max FEDRAT bulunur; `FEDRAT ≥ max*0.95` ise o GOTO rapid sayılır → Z değişimine göre yaklaşma(sarı)/uzaklaşma(mavi)/boşta(kırmızı); değilse işleme(yeşil).
6. **Süre:** ardışık nokta mesafesi / (hız/60) → kümülatif `guncelSure`, toplam `toplamSure`.
7. Noktalar `eksenKoord` çerçevesiyle **localToWorld** yapılır (dünya koordinatına).

**CUTTER 7 param (APT standardı):** `D`(çap), `r`(köşe R), `e`, `f`, `α`, `β`, `h`(boy). Web sadece `D=olcu[0]`, `r=olcu[1]`, `kesmeBoy=olcu[son]` alır, boy=200 sabit (`FikoImporter.APTCAT.ts:282`).

### 2.4 Native karşılığı
`.FikoApt` parse çıktısı **`.FikoOp`'un `programlar.children[0].takimYolu`'na birebir eşdeğerdir** (ust.1.FikoOp'un 223970 noktası, Ust_Kalip .FikoApt'ın 223970 GOTO'suyla birebir aynı — dosyalar aynı işin iki formatı). Dolayısıyla:
- `.FikoApt` → `FikoTakimYolu`-benzeri hamle listesi → CAM `TakimYolu{hamleler}` + `SimProgram` hamleleri.
- Eksen → `PartOperasyon` machining axis.
- CUTTER → `cam::Takim`.
- SPINDL → `PartOperasyon.spindle*` / hamle metadata; FEDRAT → `Hamle.ilerleme`.

---

## 3. `.wrl` FORMATI (VRML97 mesh)

### 3.1 Kodlama / yapı
- **Düz metin VRML V2.0 utf8.** İmza: `#VRML V2.0 utf8`.
- CATIA export: `WorldInfo` + `NavigationInfo` + `Background` + `Viewpoint` + `Transform > Group > Shape`.
- Node sayıları (Ust_Kalip.wrl, 12.7 MB): **4152 IndexedFaceSet** (yüzey mesh), **10354 IndexedLineSet** (kenar), 7 Material, 14508 Shape/Coordinate/Appearance.
```
geometry IndexedFaceSet {
  coord Coordinate { point [ x y z, x y z, ... ] }
  coordIndex [ i0 i1 i2 -1, ... ]     ← -1 ile yüz ayrımı
}
```

### 3.2 Web okuyucu
`FikoImporter.WRL.ts` — three.js `VRMLLoader` (`three/examples/jsm/loaders/VRMLLoader`). Sahneyi traverse eder: `Mesh`→yüzey, `LineSegments`→kenar, `Points`→nokta. Her geometri klonlanır, `color/alpha/grup` attribute'leri material'dan üretilir, sonra merge edilir (GPU/WASM/three.js fallback).

### 3.3 Native karşılığı — İKİ SEÇENEK
| Seçenek | Yöntem | Değerlendirme |
|---------|--------|---------------|
| **A) OCCT `VrmlData_Scene`** | OCCT'nin `VrmlData` modülü VRML97 okur → `TopoDS_Shape` | ✅ B-Rep değil, mesh shell döner; kütüphane zaten linkli. ⚠️ VrmlData VRML2 desteği kısıtlı/eski olabilir, IndexedLineSet'i atlar. |
| **B) Basit VRML97 IndexedFaceSet parser** (ÖNERİLEN) | Elle: `Coordinate point[]` + `coordIndex[]` (-1 ayraç) oku → `MeshVeri`; `IndexedLineSet` → `KenarVeri`; `Material diffuseColor` → renk | ✅ Tam kontrol, kenarları da alır (web davranışıyla birebir), CATIA çıktısı düzenli/tahmin edilebilir. Tek iş: tokenizer + node tarama. Bağımlılık yok. |

**Öneri: B (basit parser).** CATIA WRL çıktısı çok düzenli (Transform→Group→Shape→IndexedFaceSet/IndexedLineSet). Parser:
1. Tokenize (whitespace + `{}[],`).
2. `Shape` bloğu: `appearance Material diffuseColor r g b` → renk.
3. `IndexedFaceSet`: `coord Coordinate point[...]` → vertex, `coordIndex[... -1 ...]` → üçgen (poligon ise fan-triangulate).
4. `IndexedLineSet`: aynı mantık → çizgi segmentleri (`KenarVeri`).
5. Sonuç → `MeshVeri{vertexler,indeksler}` + `KenarVeri`, `sahne.ithalEkleHazir` ile ekle (B-Rep yok).

**Birim: mm** (CATIA VRML mm export'lar; koordinatlar ~metre değil, model ölçeğine bağlı — örnekte model AABB'sine bakılarak doğrulanmalı).

---

## 4. NATIVE EŞLEME TABLOSU (özet)

| Web alanı | Native alan | Dönüşüm |
|-----------|-------------|---------|
| FikoOp `eksen.merkez/xYon/yYon/zYon` | `PartOperasyon.eksenOrigin/eksenX/Y/Z` | doğrudan (mm) |
| FikoAPTCAT `eksenKoord{x,y,z,o}` | `PartOperasyon` axis + takım yolu çerçevesi | `o`=origin, `x/y/z`=baz |
| FikoAPTCAT `programIsmi/tarihi/operasyonIsmi` | `PartOperasyon.ad` + metadata | metin |
| takimYolu `noktalar[].x/y/z` (÷100000) | `Hamle.nokta` | int×100000 → mm |
| nokta `tip` | `Hamle.tip` | rapid→Hizli, linear/cut→Kesme, Z-dalma→Dalma |
| nokta `hiz` | `Hamle.ilerleme` | mm/dk |
| nokta `takim{cap,radius,boy,kesmeBoy}` | `cam::Takim{cap,koseYaricap,boy}` | cap/radius ÷100000, boy ÷100 |
| nokta `devir` | (import-özel meta) | rpm |
| nokta `ty` (÷100000) | takım ekseni yönü (5-eksen) | birim vektör |
| nokta `r` (hex) | görselleştirme rengi | RGB |
| nokta `guncelSure/toplamSure` (÷100) | simülasyon zaman ekseni | saniye |
| FikoCizimYalin `yuzeyler` | `MeshVeri{vertexler,indeksler}` | düz float array (mm) |
| FikoCizimYalin `sinirlar` | `KenarVeri` | çizgi listesi |
| FikoCizimYalin `matrix` | `Dugum` dünya dönüşümü | 16-float |
| CUTTER (APT) `D,r,...,h` | `cam::Takim{cap,koseYaricap,...,boy}` | mm |
| VRML IndexedFaceSet | `MeshVeri` | coordIndex fan-triangulate |
| VRML IndexedLineSet | `KenarVeri` | çizgi segment |

**⚠️ Native `Hamle` yetersizliği:** `Hamle{tip,nokta,ilerleme}` web noktasındaki `devir/ty/renk/guncelSure`'yi taşımaz. **Öneri:** import edilen FikoOp/FikoApt yolları için `motor/cam` içine **zengin import yolu** yapısı ekle (§2.2 tarzı), veya en azından `Hamle`'ye `f64 devir=0; Vec3d takimEkseni{0,0,1}; f32 renk[3]; f64 sure=0;` **enum/struct SONUNA additive** alanlar (undo u8 kararlılığı bozulmaz). MVP'de bunlar atlanabilir, sadece geometrik yol (nokta+tip+ilerleme) alınır.

---

## 5. UYGULAMA PLANI

### 5.1 Konum ve fonksiyon imzaları
Yeni modül: **`motor/io/`** (veya `motor/cam/` içine `cam_io.{hpp,cpp}` — mevcut modül tercihi). Öneri: `motor/cam/include/fiko/cam/web_io.hpp`:

```cpp
namespace fiko::cam {

// FikoOp: gzip→JSON→Fikoperasyon. Mesh çizimler + NC yolları + eksen döner.
struct FikoOpSonuc {
  std::string ad;
  PartOperasyon operasyon;                 // eksen + program metadata
  std::vector<TakimYolu> yollar;           // programlar.children[].takimYolu
  std::vector<Takim> takimlar;             // benzersiz takımlar
  std::vector<HazirCizim> cizimler;        // mesh (yuzey/kenar/nokta + matrix)
};
struct HazirCizim { std::string ad; MeshVeri yuzey; KenarVeri kenar; NoktaVeri nokta; Mat4d matris; };

// yol: .FikoOp dosyası. ilerle: worker ilerleme (STEP importla aynı kalıp).
FikoOpSonuc fikoOpYukle(const std::string& yol, const IlerlemeGeri& ilerle = {});

// FikoApt: düz APT metni → tek takım yolu + eksen + takım.
struct FikoAptSonuc { PartOperasyon operasyon; TakimYolu yol; Takim takim; std::string programAdi; };
FikoAptSonuc fikoAptYukle(const std::string& yol, const IlerlemeGeri& ilerle = {});

// WRL: VRML97 mesh → yüzey + kenar (B-Rep yok).
struct WrlSonuc { std::string ad; std::vector<HazirCizim> parcalar; };
WrlSonuc wrlYukle(const std::string& yol, const IlerlemeGeri& ilerle = {});

}  // namespace fiko::cam
```

**⚠️ BAĞIMLILIK DURUMU (kontrol edildi):** `ucuncu_taraf/` şu an sadece `imgui/ lua/ opencamlib/ vma/` içeriyor — **gzip kütüphanesi YOK, JSON kütüphanesi YOK.** İki eksik eklenmeli:
- **Gzip:** `ucuncu_taraf/miniz/` (tek dosya `miniz.c/.h`, MIT) ekle — `tinfl`/`mz_inflate` ile gzip decompress. (OCCT sistemde linkliyse `zlib` transitif gelebilir ama ona bel bağlama; miniz temiz.)
- **JSON:** `ucuncu_taraf/simdjson/` (tek header `simdjson.h`, Apache-2) ekle — 53 MB JSON için **simdjson On-Demand** ideal (streaming, düşük bellek, çok hızlı). Alternatif: nlohmann/json (daha yavaş, DOM tümünü belleğe alır → 53 MB için riskli).
`fikoOpYukle`: miniz ile decompress → simdjson On-Demand ile `noktalar[]` üzerinde streaming iterasyon (tüm diziyi std::vector'a materialize etmeden delta-decode).

### 5.2 Dosya menüsü entegrasyonu (`uygulama/fikocad/main.cpp`)
STEP import kalıbını (main.cpp:383-465) birebir taklit et:
- `dosyaSec` filtresine ekle: `L"FikoOp (*.FikoOp)\0*.FikoOp\0APT (*.FikoApt;*.apt)\0*.FikoApt;*.apt\0VRML (*.wrl)\0*.wrl\0..."`.
- 3 yeni komut (`komut("Dosya", "FikoOp Aç...", ...)` vb.), her biri `cekirdek.gorevler().kuyrukla(...)`:
  - **WORKER:** `fikoOpYukle/fikoAptYukle/wrlYukle` (saf CPU — gzip+parse+mesh).
  - **FINALIZE (main-thread):** `sahne.grupEkle` + `sahne.ithalEkleHazir(...)` (mesh), takım yolları → CAM sistemine ekle (`cam_sistemi`), eksen → PartOperasyon.
- **Makro+plugin+olay (zorunlu ilke):** `FikoOpYuklendi/FikoAptYuklendi/WrlYuklendi` olayını `olay.hpp` enum SONUNA; `fiko.cam.fikoOpYukle` Lua API. (bkz. `fikatia-mimari-ilke-makro-plugin-olay.md`)

### 5.3 Test stratejisi (9 MB dosyayı repoya koymadan)
**Sorun:** Gerçek Test dosyaları 4-12 MB — repoya konmaz. **Çözüm:**

1. **Küçük fixture üret** (offline, bir kez): Test klasöründeki gerçek dosyalardan **küçük örnek** türet ve `motor/cam/test/veri/` altına koy (~birkaç KB):
   - `.FikoApt`: gerçek dosyanın ilk ~200 satırını (header + 1 operasyon + ~50 GOTO) al → `mini.FikoApt`.
   - `.FikoOp`: gerçek dosyayı aç, `noktalar`'ı ilk ~100'e kır, `cizimler` mesh'ini 1 küçük küpe indir, tekrar gzip'le → `mini.FikoOp`. (Python script ile — geliştirici üretir, repoya commit'ler.)
   - `.wrl`: elle yazılmış minimal VRML (1 IndexedFaceSet küp + 1 IndexedLineSet) → `mini.wrl`.
2. **Otomatik testler** (`motor/cam/test/test_web_io.cpp`, mevcut test kalıbı):
   - `fikoAptYukle("veri/mini.FikoApt")` → GOTO sayısı, eksen, CUTTER doğrula.
   - `fikoOpYukle("veri/mini.FikoOp")` → program/nokta sayısı, ilk nokta koordinatı (÷100000 mm), mesh vertex sayısı, delta-decode doğruluğu (2. nokta miras alanları).
   - `wrlYukle("veri/mini.wrl")` → yüzey üçgen + kenar segment sayısı.
   - Test dosya yolu: `FIKO_TEST_VERI_DIZINI` CMake define veya çalışma dizinine göre rölatif (`veri/`).
3. **Opsiyonel büyük-dosya smoke testi** (CI-dışı, elle): `FIKO_BUYUK_TEST=1` env varsa `D:/__sistem__/Downloads/Test/` gerçek dosyalarını dener (repoda değil, sadece geliştirici makinesinde). Bellek/hız profili için.

**Fixture üretme scripti** (geliştirici çalıştırır, `motor/cam/test/veri/uret.py`):
```python
import gzip, json
d = json.load(gzip.open("Fikoperasyon.1.FikoOp"))
for pr in d["programlar"]["children"]:
    if pr.get("takimYolu"): pr["takimYolu"]["noktalar"] = pr["takimYolu"]["noktalar"][:100]
# cizimler mesh'ini de küçült (isteğe bağlı)
json.dump(d, gzip.open("mini.FikoOp","wt",encoding="utf-8"))
```

---

## 6. KAYDETME (native → FikoOp yazma) — GEREKLİ Mİ?

**Kısa cevap: MVP'de HAYIR, sonra ÖNERİLİR (çift yönlü uyumluluk).**

- **İlk aşama:** Sadece AÇMA yeterli (web'de üretilmiş dosyaları native'de görüntüle/işle).
- **Çift yönlü senaryo:** Native'de düzenlenen operasyonu web'e geri göndermek istenirse `.FikoOp` yazma gerekir. Yazma = `Fikoperasyon.ts:toJSON` şemasının tersine mühendisliği:
  - Aynı üst-düzey yapı (`type/isim/eksen/cizimler/programlar/matrix/kameraDurumu`).
  - Takım yolu: **delta-encode** (§1.5.2 tersi) + INT ölçekleme (×100000/×100).
  - Mesh: `BufferGeometry.toJSON` düz float array formatı (base64/compact YOK — web hepsini okur).
  - gzip'le, `.FikoOp` uzantısı.
- **Öneri:** `fikoOpYaz(const FikoOpSonuc&, yol)` imzasını `web_io.hpp`'ye şimdiden ekle ama gövdeyi 2. aşamaya bırak. Web'in okuyabilmesi için delta-encoding + INT ölçek + BufferGeometry.toJSON şemasına **birebir** uy (aksi halde web `fromJson` bozulur).
- **APT yazma:** Native zaten `motor/cam/gkod.hpp` (G-code) üretiyor; APT çıktısı ayrı iş, düşük öncelik.

---

## 7. ÖNCELİK SIRASI (implementasyon ajanı için)
1. **`.FikoApt`** (en basit — düz metin, gzip yok, mesh yok). `fikoAptYukle` + test + menü.
2. **`.wrl`** (basit VRML parser — mesh import, CAM yok). `wrlYukle` + test + menü.
3. **`.FikoOp`** (gzip + büyük JSON + delta-decode + mesh + yollar — en karmaşık). Gzip/JSON bağımlılığı çöz, `fikoOpYukle` + test + menü.
4. Zengin hamle yapısı (devir/ty/renk/süre) — görselleştirme/simülasyon için.
5. (Opsiyonel) `.FikoOp` yazma — çift yönlü.
