Project 01 · Parametric CADProje 01 · Parametrik CAD

FORMTRACE

Show which parts of a design change when one dimension changes, and why.Bir ölçü değiştiğinde tasarımın hangi parçalarının neden değiştiğini göstermek.

StatusDurum
Working prototype, 2026Çalışan prototip, 2026
RunsÇalıştığı yer
In the browser; geometry in a Web WorkerTarayıcıda; geometri bir Web Worker'da
KernelÇekirdek
OpenCascade · replicad (WebAssembly)
My partBenim kısmım
Operation graph, cache, checks, explanations, revision diff, interfaceİşlem grafiği, önbellek, denetimler, açıklamalar, revizyon farkı, arayüz

The project in four partsDört bölümde proje

01

ProblemProblem

Change a wall from 2.4 to 1.8 mm and a fillet somewhere breaks. Most tools then say "command not done", or worse, accept a broken solid. They do not say which numbers collided, and the model you had is gone.

Bir duvarı 2,4 mm'den 1,8 mm'ye indirirsin, bir yerde bir kenar yuvarlatması bozulur. Çoğu araç "komut tamamlanamadı" der ya da daha kötüsü, bozuk bir katıyı kabul eder. Hangi sayıların çakıştığını söylemez; elindeki model de gider.

02

ConstraintsKısıtlar

  • No server: the kernel is 23 MB of WebAssembly and must not freeze the page.
  • A slider sends dozens of changes a second; an older result must never replace a newer one.
  • The kernel fails two ways: it throws, or it returns an invalid solid.
  • Exports must open in other CAD software.
  • Sunucu yok: çekirdek 23 MB WebAssembly ve sayfayı dondurmamalı.
  • Bir kaydırıcı saniyede onlarca değişiklik gönderir; eski bir sonuç yenisinin yerini asla almamalı.
  • Çekirdek iki şekilde başarısız olur: hata fırlatır ya da geçersiz bir katı döndürür.
  • Dışa aktarılan dosyalar başka CAD yazılımlarında açılmalı.
03

DecisionKarar

Model each part as a graph of operations. Each node gets a cache key from the parameters it reads, every solid the kernel returns is checked before it is kept, and the last valid model stays on screen when a step fails.

Her parçayı bir işlem grafiği olarak modelle. Her düğüm, okuduğu parametrelerden bir önbellek anahtarı alır; çekirdeğin döndürdüğü her katı saklanmadan önce denetlenir; bir adım başarısız olursa son geçerli model ekranda kalır.

04

SolutionÇözüm

Two part families, an electronics enclosure with its lid and an adjustable bracket, built from eight operation types. Changing a dimension recomputes only the nodes that depend on it. A failed step names the colliding numbers and offers the single change that fixes it.

İki parça ailesi: kapağıyla bir elektronik cihaz kasası ve ayarlı bir braket; sekiz işlem türünden kuruluyor. Bir ölçüyü değiştirmek yalnızca ona bağlı düğümleri yeniden hesaplar. Başarısız bir adım, çakışan sayıları söyler ve sorunu çözen tek değişikliği önerir.

Walkthrough · captured from the demo belowAdım adım · aşağıdaki gösterimden alınmış ekranlar

From drawing to revision differenceÇizimden revizyon farkına

Drawing view of the enclosure Kasanın çizim görünümü The enclosure as a solid with its operation history Kasa katı model olarak, işlem geçmişiyle Section through the box and the lid Gövde ve kapaktan geçen kesit Operation history after a rib spacing change, five recomputed Nervür aralığı değişince işlem geçmişi, beşi yeniden hesaplanmış Failure explanation with two suggested fixes İki düzeltme önerisiyle hata açıklaması Revision difference with added and removed volume Eklenen ve çıkarılan hacimle revizyon farkı

01Drawing: front, top and side views of the box and the lid, projected from the same model with the main dimensions.Çizim: gövdenin ve kapağın ön, üst ve yan görünüşleri, aynı modelden ana ölçüleriyle çıkarılıyor.

02Solid: sixteen operations build the box and the lid, and the kernel checks each result before it is kept.Katı: on altı işlem gövdeyi ve kapağı kuruyor; çekirdek her sonucu saklamadan önce denetliyor.

03Section: a plane cuts through the walls, the screw bosses and the lip of the lid.Kesit: bir düzlem duvarları, vida kulelerini ve kapağın dudağını kesiyor.

04Dimension change: rib spacing from 50 to 40 mm. Only the five operations that depend on it run again; eleven come from the cache.Ölçü değişikliği: nervür aralığı 50'den 40 mm'ye. Yalnızca ona bağlı beş işlem yeniden çalışıyor; on biri önbellekten geliyor.

05A 1.8 mm wall breaks the rim fillet. The failing step, the reason and two fixes appear, and the last valid model stays on screen.1,8 mm'lik duvar kenar yuvarlatmasını bozuyor. Başarısız adım, nedeni ve iki düzeltme görünüyor; son geçerli model ekranda kalıyor.

06Revision difference A → B: added volume in green, removed volume in red, with the totals for each part.Revizyon farkı A → B: eklenen hacim yeşil, çıkarılan hacim kırmızı; her parçanın toplamlarıyla.

Working demonstrationÇalışan gösterim

Change a dimension. Break a fillet. Get it back.Bir ölçüyü değiştir. Bir yuvarlatmayı boz. Geri al.

Try this: set the wall to 1.8 mm. The rim fillet fails, the history shows which step and what depends on it, the last valid model stays, and one button fixes it. Then save two revisions and compare them.

Şunu dene: duvarı 1,8 mm yap. Ağız yuvarlatması başarısız olur; geçmiş hangi adımın, neye bağlı olarak bozulduğunu gösterir; son geçerli model ekranda kalır ve tek bir düğme düzeltir. Sonra iki revizyon kaydet ve karşılaştır.

Downloads the OpenCascade kernel: 23 MB, 7.3 MB when the server compresses it with gzip. Nothing is uploaded.OpenCascade çekirdeğini indirir: 23 MB; sunucu gzip ile sıkıştırırsa 7,3 MB. Hiçbir şey yüklenmez.

ValidationDoğrulama

What was checked, and howNeyin, nasıl denetlendiği

TestsTestler · 8/8

  1. graph: eight operation types, topological order, parameters reach only their dependentsgrafik: sekiz işlem türü, topolojik sıra, parametreler yalnızca kendine bağlı düğümlere ulaşıyor88 ms
  2. params: sanitize and the parameter file reject what they shouldparametreler: temizleme ve parametre dosyası reddetmesi gerekeni reddediyor1 ms
  3. engine: default models build, validate and come back from the cacheçekirdek: varsayılan modeller kuruluyor, doğrulanıyor ve önbellekten geri geliyor580 ms
  4. engine: a changed parameter recomputes exactly the nodes that depend on itçekirdek: değişen parametre tam olarak ona bağlı düğümleri yeniden hesaplıyor1401 ms
  5. engine: a seeded sweep of dimensions never accepts an invalid solidçekirdek: tohumlu ölçü taraması hiçbir geçersiz katıyı kabul etmiyor2849 ms
  6. failure: thinner walls break the rim fillet, the reason is explained, the fix restores the modelhata: incelen duvar ağız yuvarlatmasını bozuyor, neden açıklanıyor, düzeltme modeli geri getiriyor992 ms
  7. queue: rapid input builds only the newest request, results never go backwardskuyruk: hızlı girişte yalnızca en yeni istek hesaplanıyor, sonuçlar hiç geriye gitmiyor813 ms
  8. exports: STEP reopens with the same volume, STL is watertight, revision diff balancesdışa aktarım: STEP aynı hacimle açılıyor, STL kapalı, revizyon farkı dengede2046 ms

Node v24.20.0 · run 2026-10-08 · node --test lab/tests/formtrace.test.mjsNode v24.20.0 · 2026-10-08 tarihinde çalıştırıldı · node --test lab/tests/formtrace.test.mjs

MeasuredÖlçülen

ChangeDeğişiklikTimeSüreRecomputedYeniden hesaplanan
Enclosure, first buildKasa, ilk hesap510510 ms16 / 16
Same parameters againAynı parametreler tekrar0.10,1 ms0 / 16
widthgenişlik297297 ms16 / 16
heightyükseklik278278 ms14 / 16
pcbWidthkart genişliği181181 ms5 / 16
ribSpannervür aralığı165165 ms5 / 16
screwvida213213 ms8 / 16
Bracket, first buildBraket, ilk hesap5151 ms8 / 8

Node v24.20.0 on a Ryzen 5 9600X under Windows 11, 2026-10-08.Node v24.20.0, Ryzen 5 9600X, Windows 11, 2026-10-08. In Chrome 154.0.8037.98 (headless, ANGLE D3D11): kernel start 57 ms, first build 547 ms, width change 334 ms.Chrome 154.0.8037.98 (headless, ANGLE D3D11) içinde: çekirdek başlatma 57 ms, ilk hesap 547 ms, genişlik değişikliği 334 ms.

Thirty changes in under a secondBir saniyenin altında otuz değişiklik

30 width changes arrived while the kernel was busy. 13 were merged before they started, 16 stopped at an operation boundary, 1 full build ran: revision 30, width 130 mm. No older result reached the screen.Çekirdek meşgulken 30 genişlik değişikliği geldi. 13 tanesi başlamadan birleştirildi, 16 tanesi bir işlem sınırında durduruldu, 1 tam hesap çalıştı: revizyon 30, genişlik 130 mm. Ekrana daha eski bir sonuç gelmedi.

The failure, recordedKaydedilen hata

Wall 2.4 → 1.8 mm with a 1 mm edge fillet:Duvar 2,4 → 1,8 mm, kenar yuvarlatma 1 mm:

  1. OpenCascade returned a solid, but its own check (BRepCheck) rejects it: the new faces cut into each other.OpenCascade bir katı döndürdü, ama kendi denetimi (BRepCheck) onu reddediyor: yeni yüzeyler birbirinin içine geçiyor.
  2. The rim is too narrow for this fillet. The rim is as wide as the wall, 1.8 mm. A 1 mm fillet rounds both its edges, so it needs at least 2 mm of rim.Ağız bu yuvarlatma için fazla dar. Ağız, duvar kadar geniş: 1.8 mm. 1 mm'lik yuvarlatma iki kenarı birden yuvarlar, bu yüzden en az 2 mm ağız ister.
  3. Blocked until fixed: joined, pilots, vents, mounts. The last valid model stays on screen.Düzelene kadar bekleyen: joined, pilots, vents, mounts. Son geçerli model ekranda kalır.
  4. Suggested fix: wall 2.2 mm → valid modelÖnerilen düzeltme: duvar 2,2 mm → geçerli model
  5. Suggested fix: rimFillet 0.8 mm → valid modelÖnerilen düzeltme: kenar yuvarlatma 0,8 mm → geçerli model

Revision difference, A → BRevizyon farkı, A → B

PartParçaABaddedeklenenremovedçıkarılan
BoxGövde58.1558,1565.3665,36+25.3025,30−18.0918,09
LidKapak20.0420,0423.3523,35+3.763,76−0.450,45

cm³. Width 120 → 140, rib spacing 50 → 40, board 70 → 90 mm. A + added − removed = B for both parts.cm³. Genişlik 120 → 140, nervür aralığı 50 → 40, kart 70 → 90 mm. Her iki parçada A + eklenen − çıkarılan = B.

Random dimensions, no invalid solid keptRastgele ölçüler, tutulan geçersiz katı yok

Seed 8102026, 30 random parameter sets per family. Enclosure: 5 valid, 25 rejected with a reason (lid-too-thin 9, board-fit 14, rim-too-narrow 2). Bracket: 29 valid, 1 rejected (slot-fit 1). Every kept solid passed BRepCheck.Tohum 8102026, aile başına 30 rastgele parametre seti. Kasa: 5 geçerli, 25 gerekçeyle reddedildi (lid-too-thin 9, board-fit 14, rim-too-narrow 2). Braket: 29 geçerli, 1 reddedildi (slot-fit 1). Tutulan her katı BRepCheck'ten geçti.

Real exports, opened in another programGerçek dışa aktarımlar, başka bir programda açıldı

enclosure-rev-b.step623 kB623 kBFreeCAD 1.0.2: 2 solids, valid yes, closed yes, volume 88,701.7 mm³ (FORMTRACE: 88,701.7)FreeCAD 1.0.2: 2 katı, geçerli evet, kapalı evet, hacim 88.701,7 mm³ (FORMTRACE: 88.701,7)SHA-256 d91aaea0922d92ff8950a3bca71cd70ad81dcb3f770ca33a19555296a4542336enclosure-rev-b-box.stl258 kB258 kBFreeCAD 1.0.2: 5,160 facets, closed yes, non-manifold edges none, self-intersections noneFreeCAD 1.0.2: 5.160 yüzey, kapalı evet, manifold olmayan kenar yok, kendi kendini kesme yokSHA-256 c39c559d922834cf20509731bfa2e6b946901d1bf907b692969e129abde01da4enclosure-rev-b-lid.stl112 kB112 kBFreeCAD 1.0.2: 2,248 facets, closed yes, non-manifold edges none, self-intersections noneFreeCAD 1.0.2: 2.248 yüzey, kapalı evet, manifold olmayan kenar yok, kendi kendini kesme yokSHA-256 6a94609c524e9177a4ed8752e5912b76ff1e5dc68165cb9b33b967767aa926a6bracket.step99 kB99 kBFreeCAD 1.0.2: 1 solid, valid yes, closed yes, volume 17,383.7 mm³ (FORMTRACE: 17,383.7)FreeCAD 1.0.2: 1 katı, geçerli evet, kapalı evet, hacim 17.383,7 mm³ (FORMTRACE: 17.383,7)SHA-256 2d72fc4697303868b98b937e8feae1e6ec6e2af7f5d6dae4ca0f650f6d77845dbracket-bracket.stl22 kB22 kBFreeCAD 1.0.2: 444 facets, closed yes, non-manifold edges none, self-intersections noneFreeCAD 1.0.2: 444 yüzey, kapalı evet, manifold olmayan kenar yok, kendi kendini kesme yokSHA-256 7f5fe1cbd86ffd70545fbe7f4e41dd3615e00034e6ec2c2d03712207678a363denclosure.formtrace.json751 bytes751 baytSHA-256 7ad0a4664605bde14e740bf8e7ae508e77169029dfa5807361f937b13f140adfbracket.formtrace.json232 bytes232 baytSHA-256 b8be417e68027145d6905593cefab1a3cf7b05c1b55765c70fd921cf9cd06125

Decision notesKarar notları

Constraint, method, resultKısıt, yöntem, sonuç

Check every solidHer katıyı denetle

ConstraintKısıt
For a 1.5 mm fillet on a 2.4 mm rim, OpenCascade returned a solid with more volume than before. It looked fine.2,4 mm'lik ağızda 1,5 mm yuvarlatma için OpenCascade, öncekinden fazla hacimli bir katı döndürdü. Sorunsuz görünüyordu.
MethodYöntem
Every solid passes BRepCheck and a volume check before it enters the cache; a rejected one fails its node with a reason.Her katı, önbelleğe girmeden önce BRepCheck ve hacim denetiminden geçer; reddedilen katı, düğümünü gerekçesiyle başarısız sayar.
ResultSonuç
Seeded sweep of 60 random parameter sets: 34 valid, 26 rejected with a named reason, and no invalid solid kept.60 rastgele parametre setiyle tohumlu tarama: 34 geçerli, 26'sı adı konmuş bir gerekçeyle reddedildi; hiçbir geçersiz katı tutulmadı.

Newest request winsEn yeni istek kazanır

ConstraintKısıt
A kernel operation cannot be interrupted, and a slider produces far more requests than the kernel can finish.Bir çekirdek işlemi yarıda kesilemez ve bir kaydırıcı, çekirdeğin bitirebileceğinden çok daha fazla istek üretir.
MethodYöntem
The worker checks for a newer request between operations and stops; the page ignores any result older than the one on screen.Worker, işlemler arasında daha yeni bir istek olup olmadığına bakar ve durur; sayfa, ekrandakinden eski her sonucu yok sayar.
ResultSonuç
30 width changes in under a second: 1 full build ran, 13 merged before starting, 16 stopped between operations, and the screen never went backwards.Bir saniyenin altında 30 genişlik değişikliği: 1 tam hesap çalıştı, 13'ü başlamadan birleştirildi, 16'sı işlemler arasında durdu; ekran hiç geriye gitmedi.

Relations, not coordinatesKoordinat değil ilişki

ConstraintKısıt
With rounded corners, a lid boss placed by fixed offsets pokes through the wall when the corner radius grows.Yuvarlatılmış köşelerde sabit ofsetle konan kapak burcu, köşe yarıçapı büyüyünce duvardan dışarı taşar.
MethodYöntem
Bosses sit tangent to the inner corner arc, 0.6 mm into the wall; rib count follows the free wall length; lid holes reuse the boss positions.Burçlar iç köşe yayına teğet ve duvara 0,6 mm gömülü durur; nervür sayısı serbest duvar boyuna göre değişir; kapak delikleri burç konumlarını kullanır.
ResultSonuç
In the sweep, the checks named board and fit conflicts before the kernel ran (14 board-fit), and every kept solid passed BRepCheck.Taramada denetimler kart ve geçme çakışmalarını çekirdek çalışmadan adlandırdı (14 kart sığmama); tutulan her katı BRepCheck'ten geçti.

STL from the triangulationSTL'i üçgenlemeden yaz

ConstraintKısıt
One export path skipped a face on a model ("null triangulation"), which leaves a hole in a print file.Bir dışa aktarma yolu, bir modelde bir yüzeyi atladı ("null triangulation"); bu, baskı dosyasında delik bırakır.
MethodYöntem
STL is written from the kernel's mesh and checked: after welding, every edge must belong to exactly two triangles.STL, çekirdeğin ağından yazılır ve denetlenir: noktalar birleştirildikten sonra her kenar tam iki üçgene ait olmalı.
ResultSonuç
FreeCAD 1.0.2 opened every exported STL as closed, with no non-manifold edges and no self-intersections.FreeCAD 1.0.2, dışa aktarılan her STL'i kapalı açtı; manifold olmayan kenar ve kendi kendini kesme yok.

Load the kernel on requestÇekirdeği istenince yükle

ConstraintKısıt
23 MB, 7.3 MB with gzip, is too much to load just because someone opened the page.23 MB (gzip ile 7,3 MB), biri sayfayı açtı diye yüklenmek için fazla.
MethodYöntem
The page loads without it. The button fetches it with visible progress and hands the bytes to the worker once.Sayfa çekirdek olmadan açılır. Düğme onu görünür bir ilerlemeyle indirir ve baytları worker'a bir kez verir.
ResultSonuç
The page opens without it. In Chrome on the test PC the first model appeared 865 ms after the click: download, a 57 ms kernel start and a 547 ms first build.Sayfa onsuz açılıyor. Test bilgisayarında Chrome'da ilk model tıklamadan 865 ms sonra geldi: indirme, 57 ms çekirdek başlatma ve 547 ms ilk hesap.

Strict parameter filesKatı parametre dosyaları

ConstraintKısıt
A parameter file comes from outside and can be malformed, huge or crafted.Parametre dosyası dışarıdan gelir; bozuk, çok büyük ya da kötü niyetle hazırlanmış olabilir.
MethodYöntem
32,768-byte limit, known keys only, finite numbers inside each range, format and version checked; the worker checks again.32.768 baytlık sınır, yalnızca bilinen anahtarlar, her aralığın içinde sonlu sayılar, biçim ve sürüm denetimi; worker bir kez daha denetler.
ResultSonuç
A crafted file with unknown keys, huge numbers and script text was refused with a reason; nothing from it reached the page.Bilinmeyen anahtarlar, dev sayılar ve betik metni içeren hazırlanmış bir dosya gerekçesiyle reddedildi; içinden hiçbir şey sayfaya ulaşmadı.

Built on, and what I addedÜzerine kurulduğu altyapı ve benim eklediklerim

Built onAltyapı

  • OpenCascadeB-rep geometry: extrusions, shells, fillets, booleans, STEP. LGPL-2.1, unmodified build.B-rep geometri: uzatma, kabuk, yuvarlatma, boolean işlemleri, STEP. LGPL-2.1, değiştirilmemiş derleme.
  • replicad 1.1.0JavaScript API over OpenCascade and its WebAssembly build. MIT.OpenCascade üzerinde JavaScript API'si ve WebAssembly derlemesi. MIT.
  • three.js 0.186Display: lights, section plane, edges. MIT.Görüntüleme: ışıklar, kesit düzlemi, kenarlar. MIT.

Added in FORMTRACEFORMTRACE'te eklenenler

  • Graph and cacheGrafik ve önbellekOperation graph, cache keys from read parameters, partial recompute, LRU cleanup.İşlem grafiği, okunan parametrelerden önbellek anahtarı, kısmi yeniden hesap, LRU temizliği.
  • ReliabilityGüvenilirlikWorker queue with coalescing and cancellation, stale-result guard, 20 s watchdog.Birleştirme ve iptal destekli worker kuyruğu, eski sonuç koruması, 20 sn bekçi.
  • ExplanationsAçıklamalarValidity checks, domain checks, reasons in two languages, one-click fixes.Geçerlilik ve alan denetimleri, iki dilde gerekçeler, tek tıkla düzeltmeler.
  • Revisions and filesRevizyonlar ve dosyalarAdded and removed volume between revisions, checked STL writer, parameter file format.Revizyonlar arası eklenen ve çıkarılan hacim, denetimli STL yazıcı, parametre dosyası biçimi.