了解した。
ここからは DB が唯一の真実であり、
combo / combo_sub を上位キーとして 2000 プロジェクトを扱える MeshDB を
OS 設計として正しく構築する。

あなたの OS 思想(階層・分離・責務の明確化)に完全に沿うように、
combo(最大100) × combo_sub(最大20)=2000 プロジェクト
を自然に扱えるスキーマを提示する。


🧩 1. なぜ combo / combo_sub を上位に置くべきか

あなたの OS では:

  • combo = 大分類(プロジェクトの「世界」)
  • combo_sub = 中分類(プロジェクトの「章」)
  • mesh_id = その中の個別メッシュ

という階層構造が自然。

つまり、
combo / combo_sub が “プロジェクト空間” を定義し、
その中に Mesh / Face / Vertex が存在する

という構造が最も OS 的に正しい。


🧩 2. 最小構成の MySQL スキーマ(combo / combo_sub 上位版)


H2: meshes(メッシュ本体)

meshes (
    id            BIGINT PRIMARY KEY AUTO_INCREMENT,
    combo         INT NOT NULL,        -- 0〜99
    combo_sub     INT NOT NULL,        -- 0〜19
    name          VARCHAR(255),
    parent_id     BIGINT NULL,         -- 階層メッシュ or LinkNode
    created_at    DATETIME,
    updated_at    DATETIME
);

✔ combo / combo_sub が上位キー

✔ 2000 プロジェクトを自然に扱える

✔ MeshNode / LinkNode の階層構造も parent_id で表現可能


H2: vertices(頂点)

vertices (
    id        BIGINT PRIMARY KEY AUTO_INCREMENT,
    combo     INT NOT NULL,
    combo_sub INT NOT NULL,
    mesh_id   BIGINT NOT NULL,
    x         DOUBLE,
    y         DOUBLE,
    z         DOUBLE
);

✔ combo / combo_sub を持つことで「プロジェクト空間」に属する

✔ mesh_id とセットで完全に一意な頂点集合になる


H2: faces(三角面)

faces (
    id        BIGINT PRIMARY KEY AUTO_INCREMENT,
    combo     INT NOT NULL,
    combo_sub INT NOT NULL,
    mesh_id   BIGINT NOT NULL,
    v1_id     BIGINT NOT NULL,
    v2_id     BIGINT NOT NULL,
    v3_id     BIGINT NOT NULL
);

✔ combo / combo_sub を持つことで「プロジェクト空間」に属する

✔ mesh_id に属する三角面


H2: instances(LinkNode)

instances (
    id          BIGINT PRIMARY KEY AUTO_INCREMENT,
    combo       INT NOT NULL,
    combo_sub   INT NOT NULL,
    mesh_id     BIGINT NOT NULL,   -- 参照先メッシュ
    parent_id   BIGINT NULL,       -- 配置先メッシュ
    tx          DOUBLE,
    ty          DOUBLE,
    tz          DOUBLE,
    rx          DOUBLE,
    ry          DOUBLE,
    rz          DOUBLE,
    sx          DOUBLE,
    sy          DOUBLE,
    sz          DOUBLE
);

✔ combo / combo_sub に属するインスタンス

✔ Three.js はこれを InstancedMesh として描画


H2: face_groups(選択結果)

face_groups (
    id        BIGINT PRIMARY KEY AUTO_INCREMENT,
    combo     INT NOT NULL,
    combo_sub INT NOT NULL,
    name      VARCHAR(255)
);

face_group_items (
    group_id  BIGINT,
    face_id   BIGINT
);

✔ DSL の groupA / groupB を保持

✔ BFS や SHAPE 選択の結果を格納

✔ extractMeshFromFaces の入力になる


🧩 3. combo / combo_sub を上位に置くメリット

✔ 2000 プロジェクトを完全に分離できる

✔ Mesh / Face / Vertex が「プロジェクト空間」に属する

✔ DSL の実行時に combo / combo_sub を自動で付与できる

✔ Three.js は combo / combo_sub を指定して DB を読むだけ

✔ Flask は combo / combo_sub をキーにして安全に DML を実行できる

✔ OS 的に「プロセス空間」が明確になる

あなたの OS 設計(階層・分離・責務の明確化)に完全一致する。


🧩 4. extractMeshFromFaces は DB DML としてこうなる

combo / combo_sub を含めた形で:

INSERT INTO meshes (combo, combo_sub, name, parent_id)
VALUES (:combo, :combo_sub, 'part1', NULL);

SET @new_mesh_id = LAST_INSERT_ID();

頂点コピー:

INSERT INTO vertices (combo, combo_sub, mesh_id, x, y, z)
SELECT :combo, :combo_sub, @new_mesh_id, x, y, z
FROM vertices
WHERE id IN ( ...face に含まれる頂点... );

面コピー:

INSERT INTO faces (combo, combo_sub, mesh_id, v1_id, v2_id, v3_id)
VALUES (... old_to_new_vid マッピング ...);

✔ すべて combo / combo_sub を持つ

✔ プロジェクト空間内で完結する

✔ Three.js は new_mesh_id を読み込むだけ


🧩 5. 次にやるべきこと(あなたへの提案)

combo / combo_sub を上位に置いたので、
次に OS として決めるべきは:

① DSL に combo / combo_sub をどう反映させるか

  • DSL 内に combo を書かせる?
  • それとも Flask がセッションで保持する?

② LinkNode(instances)の扱い

  • combo / combo_sub を持つ
  • 参照先 mesh_id は同じ combo 内に限定する?

③ Three.js の API

  • /mesh/{combo}/{combo_sub}/{mesh_id}
  • /instances/{combo}/{combo_sub}
    など

次は DSL に combo / combo_sub をどう扱わせるか を決めると、
OS 全体が一気に完成形に近づくよ。

 

 

 

了解。
combo=i、combo_sub=j を「編集中のプロジェクト空間」として Flask と Three.js の両方で共有するという前提なら、
DB スキーマは combo / combo_sub を最上位キーとして持つだけで十分で、
アプリ側は常に「現在の i, j を使う」だけで OS として破綻しない。

つまり:

  • DB は combo / combo_sub を持つ
  • Flask は i, j をセッション or DSL 実行コンテキストで保持
  • Three.js は i, j を API パラメータとして送る

これで 2000 プロジェクト空間が自然に扱える。

以下に 最小構成の MeshDB(combo / combo_sub 上位版) をまとめる。


🗂 MeshDB(combo / combo_sub 上位の最小スキーマ)

1. meshes(メッシュ本体)

meshes (
    id            BIGINT PRIMARY KEY AUTO_INCREMENT,
    combo         INT NOT NULL,        -- i
    combo_sub     INT NOT NULL,        -- j
    name          VARCHAR(255),
    parent_id     BIGINT NULL,         -- 階層メッシュ or LinkNode
    created_at    DATETIME,
    updated_at    DATETIME
);

役割

  • combo / combo_sub が プロジェクト空間
  • parent_id で階層構造(MeshNode / LinkNode)を表現

2. vertices(頂点)

vertices (
    id        BIGINT PRIMARY KEY AUTO_INCREMENT,
    combo     INT NOT NULL,
    combo_sub INT NOT NULL,
    mesh_id   BIGINT NOT NULL,
    x         DOUBLE,
    y         DOUBLE,
    z         DOUBLE
);

役割

  • 頂点は combo=i, combo_sub=j の空間に属する
  • mesh_id とセットで完全に一意

3. faces(三角面)

faces (
    id        BIGINT PRIMARY KEY AUTO_INCREMENT,
    combo     INT NOT NULL,
    combo_sub INT NOT NULL,
    mesh_id   BIGINT NOT NULL,
    v1_id     BIGINT NOT NULL,
    v2_id     BIGINT NOT NULL,
    v3_id     BIGINT NOT NULL
);

役割

  • 面も combo=i, combo_sub=j に属する
  • 頂点は vertices.id を参照

4. instances(LinkNode)

instances (
    id          BIGINT PRIMARY KEY AUTO_INCREMENT,
    combo       INT NOT NULL,
    combo_sub   INT NOT NULL,
    mesh_id     BIGINT NOT NULL,   -- 参照先メッシュ
    parent_id   BIGINT NULL,       -- 配置先メッシュ
    tx          DOUBLE,
    ty          DOUBLE,
    tz          DOUBLE,
    rx          DOUBLE,
    ry          DOUBLE,
    rz          DOUBLE,
    sx          DOUBLE,
    sy          DOUBLE,
    sz          DOUBLE
);

役割

  • LinkNode(InstanceMesh)
  • combo=i, combo_sub=j の空間に属する

5. face_groups(選択結果)

face_groups (
    id        BIGINT PRIMARY KEY AUTO_INCREMENT,
    combo     INT NOT NULL,
    combo_sub INT NOT NULL,
    name      VARCHAR(255)
);

face_group_items (
    group_id  BIGINT,
    face_id   BIGINT
);

役割

  • DSL の groupA / groupB を保持
  • BFS や SHAPE 選択の結果を格納
  • extractMeshFromFaces の入力になる

🧩 combo=i, combo_sub=j をどう扱うか(OS 的に正しい方法)

あなたの方針:

編集中の combo は i、combo_sub は j に入れるのを慣行とする
js側とpython側で合わせておけば良いだけ

これは OS 的に非常に正しい。

✔ Flask 側

  • DSL 実行コンテキストに i, j を保持
  • すべての INSERT / SELECT / UPDATE / DELETE に自動付与

✔ Three.js 側

  • API 呼び出し時に i, j を付ける
    例:/mesh/get?combo=i&combo_sub=j&mesh_id=123

✔ DB 側

  • combo / combo_sub を最上位キーとして持つだけでよい
  • 2000 プロジェクト空間が完全に分離される

🧩 extractMeshFromFaces は DB DML としてこうなる

combo=i, combo_sub=j を自動付与した形:

INSERT INTO meshes (combo, combo_sub, name, parent_id)
VALUES (:i, :j, 'part1', NULL);

SET @new_mesh_id = LAST_INSERT_ID();

頂点コピー:

INSERT INTO vertices (combo, combo_sub, mesh_id, x, y, z)
SELECT :i, :j, @new_mesh_id, x, y, z
FROM vertices
WHERE id IN ( ...face に含まれる頂点... );

面コピー:

INSERT INTO faces (combo, combo_sub, mesh_id, v1_id, v2_id, v3_id)
VALUES (... old_to_new_vid マッピング ...);

✔ すべて combo=i, combo_sub=j の空間で完結

✔ Three.js は new_mesh_id を読み込むだけ


🧩 次にやるべきこと(あなたへの提案)

combo / combo_sub の扱いが固まったので、
次は DSL → DB DML のマッピングを作ると OS が完成する。

特に:

  • CREATE MESH part1 FROM FACES groupA;
  • MOVE groupA BY (0,1,0);
  • CREATE INSTANCE inst1 FROM MESH part1;

これらを Flask が DB に対してどう実行するかを定義する。

必要なら、
「DSL 実行エンジン(Flask)」の設計
に進めるよ。