🌐 English|한국어

고급 기능 안내서

이 안내서는 Modan2를 깊이 활용하는 사용자를 위한 고급 기능과 기법을 다룹니다.

성능 최적화

데이터베이스 최적화

Modan2는 데이터 저장에 SQLite를 사용합니다. 주기적으로 관리하면 성능이 향상됩니다.

데이터베이스 최적화:

# Using SQLite command line
sqlite3 ~/PaleoBytes/Modan2/Modan2.db "VACUUM;"

# Or using Python
import sqlite3
conn = sqlite3.connect('Modan2.db')
conn.execute('VACUUM')
conn.close()

이점:

  • 데이터베이스 파일 크기를 줄입니다

  • 쿼리 성능을 개선합니다

  • 사용하지 않는 공간을 회수합니다

최적화가 필요한 시점:

  • 데이터셋을 많이 삭제한 뒤

  • 데이터베이스 파일이 예상보다 클 때

  • 성능이 눈에 띄게 느려졌을 때

대용량 데이터셋 전략

객체가 1000개 이상인 데이터셋의 경우:

1. 계층적 구성:

Master Dataset (all objects)
├── Subset 1 (species A)
├── Subset 2 (species B)
└── Subset 3 (time period 1)

이점:

  • 하위 집합을 독립적으로 분석

  • 개별 분석 속도 향상

  • 체계적인 작업 흐름

2. 일괄 처리:

# Process multiple datasets programmatically
from MdModel import MdDataset, MdDatasetOps
from MdStatistics import PerformPCA

datasets = MdDataset.select()
for dataset in datasets:
    obj_count = len(dataset.get_object_list())
    if obj_count > 50:
        dataset_ops = MdDatasetOps()
        dataset_ops.read_from_dataset(dataset)
        pca = PerformPCA(dataset_ops)
        # Use pca results (pca.rotated_matrix, pca.eigen_value_percentages, etc.)

3. 메모리 관리:

  • 사용하지 않는 객체 뷰어를 닫으세요

  • 모든 분석을 열어 두지 마세요

  • 결과를 내보낸 뒤 탭을 닫으세요

성능 벤치마크

예상 성능 (Phase 7 검증 기준):

작업

객체 100개

객체 1000개

데이터셋 로드

< 50ms

277ms

PCA

< 10ms

60ms

CVA

< 5ms

2.5ms

MANOVA

< 10ms

28ms

객체 테이블

5ms

12.63ms

메모리 사용량:

  • 객체당 약 4KB (선형 증가)

  • 객체 1000개: 약 4MB

  • 객체 10000개: 약 40MB

확장성:

  • 객체 2000개까지 검증됨

  • 선형 O(n) 성능

  • 객체 100,000개 이상도 실사용 가능

고급 데이터 관리

계층적 데이터셋

상위-하위 관계 를 이용하면 데이터를 유연하게 구성할 수 있습니다:

하위 데이터셋 만들기:

  1. 트리에서 상위 데이터셋을 오른쪽 클릭합니다

  2. “Add child dataset”(하위 데이터셋 추가)를 선택합니다

  3. 새 데이터셋 대화상자를 평소처럼 채웁니다 — 상위 데이터셋은 미리 지정되어 있습니다

하위 데이터셋은 상위 아래에 중첩되는 새 빈 데이터셋입니다. 객체가 복사되어 들어오지는 않습니다. 연구를 하위 집합으로 나누어 직접 채워 넣을 때 사용하세요.

활용 사례:

예 1: 분류군별 하위 집합

All Specimens (parent)
├── Species A (child)
├── Species B (child)
└── Species C (child)

예 2: 시기별 구분

Complete Dataset (parent)
├── Pleistocene (child)
├── Holocene (child)
└── Modern (child)

일괄 작업

랜드마크 일괄 편집:

# Example: Apply transformation to all objects
from MdModel import MdDataset, MdObject
import numpy as np

dataset = MdDataset.get_by_id(dataset_id)
for obj in dataset.get_object_list():
    coords = obj.get_landmark_list()
    # Apply transformation
    coords = coords * 2.0  # Scale example
    obj.save_landmark_list(coords)

변수 일괄 편집:

  1. 데이터셋을 선택합니다

  2. 객체 테이블에서 셀을 직접 편집합니다

  3. Ctrl+C / Ctrl+V 로 스프레드시트와 복사/붙여넣기를 주고받습니다

일괄 가져오기:

랜드마크 파일 여러 개를 한 번에 창으로 끌어다 놓거나, File → Import 에서 함께 선택하세요 — 각각이 데이터셋의 객체가 됩니다.

대규모 준랜드마크 곡선 작업

곡선은 데이터셋 수준에서 한 번만 정의하고(이름과 점 개수 N) 표본마다 추적하므로, 준랜드마크 개수는 구조적으로 데이터셋 전체에서 일관되게 유지됩니다.

  • 추적한 뒤에도 ``N`` 을 바꿀 수 있습니다. 곡선 표에서 N 을 수정하면 저장된 추적선을 다시 재표본화하므로, 다시 추적할 필요가 없습니다.

  • 클릭 수를 줄이세요. “Snap to curve”가 켜져 있으면(Curve 모드의 기본값) 추적선이 클릭 사이에서 이미지의 가장 강한 경계를 따라가므로, 깔끔한 윤곽선에 보통 점 몇 개면 충분합니다.

  • 곡선을 전체에서 제거합니다. 곡선 표의 행을 오른쪽 클릭 → “Delete Curve (all specimens)”.

  • 왕복 변환. CURVES= / POINTS= 블록은 TPS에서 읽고 TPS로 쓰며, JSON+ZIP 패키지는 곡선 구성과 추적한 모든 곡선을 함께 담습니다.

준랜드마크 곡선은 2D 전용 기능입니다. 분석에서는 곡선에서 유도된 점들을 일반 랜드마크처럼 다루며, 고정(해부학적) 랜드마크 뒤에 이어 붙입니다.

데이터베이스 직접 접근

고급 작업을 위해 데이터베이스에 직접 접근합니다:

from MdModel import MdDataset, MdObject, database

# Query datasets
datasets = MdDataset.select().where(
    MdDataset.dimension == 2
)

# Complex queries
from peewee import fn
large_datasets = MdDataset.select().where(
    fn.COUNT(MdObject.id) > 100
).join(MdObject)

# Bulk operations
with database.atomic():
    for obj in objects:
        obj.save()

고급 통계 분석

사용자 정의 분석 작업 흐름

한 번의 분석 실행은 항상 PCA, CVA, MANOVA를 함께 계산합니다. 아래의 탐색 작업은 그 뒤에 데이터 탐색(Data Exploration) 대화상자에서 이루어집니다.

회귀선 오버레이:

  1. 완료된 분석을 데이터 탐색 에서 엽니다

  2. “Show regression” 을 체크합니다

  3. Group by 로 그룹을 고르고, 회귀선을 All(전체 점), By group(그룹별), Select group(선택한 그룹) 중 어디에 적합시킬지 정합니다

형상 격자(Shape grid):

데이터 탐색에서 “Shape grid” 를 체크하면 플롯의 여러 위치에서 복원한 형상을 그려 주므로, 각 축을 따라 형상이 어떻게 변하는지 볼 수 있습니다.

중첩정렬 방식

Modan2는 분석 대화상자에서 고를 수 있는 세 가지 중첩정렬 방식을 제공합니다. 세 방식 모두 결측 랜드마크를 먼저 대치합니다(Missing Landmark Handling 참조).

프로크루스테스(일반화 프로크루스테스 분석):

  • 이동 + 회전 + 크기 조정

  • 중심 크기를 표준화하여 순수한 형상만 남김

  • 기본값이며, 특별한 이유가 없다면 이 방식이 적절합니다

북스틴(베이스라인 정합):

  • 데이터셋의 베이스라인 랜드마크를 표준 위치에 고정하여 각 형상을 북스틴 형상좌표로 다시 표현합니다

  • 2D: 베이스라인 양 끝점을 (-0.5, 0)과 (0.5, 0)으로; 3D는 3점 베이스라인을 사용

  • 데이터셋에 베이스라인이 정의되어 있어야 합니다

  • 비교의 기준이 될 해부학적 축이 뚜렷할 때 유용합니다

강건적합(RFTRA):

  • 랜드마크 쌍 관계의 반복 중앙값(repeated median)에 기반한 강건한 정렬

  • 몇 개의 이탈(이상치) 랜드마크가 프로크루스테스에서처럼 전체 정합을 끌어당기지 않습니다

  • 2D와 3D 모두 지원

방법 선택:

연구 목적

권장 방법

비고

순수 형상

프로크루스테스

기본값

해부학적 축을 기준으로 고정

북스틴

데이터셋 베이스라인 필요

신뢰하기 어려운 랜드마크가 일부 있음

강건적합

이상치 랜드마크에 강함

결측 랜드마크 처리

Modan2는 분석 중에 정렬과 대치를 번갈아 수행하는 EM 방식 루프로 결측 랜드마크를 자동으로 채웁니다:

  1. 빈 자리를 그대로 둔 채 모든 표본을 정렬합니다 — 평균 형상은 빈 자리를 무시하며, 각 표본은 실제로 가진 랜드마크만으로 정렬합니다.

  2. 결측이 있는 각 표본에 대해, 현재 평균 형상을 그 표본의 관측된 랜드마크에 상사변환(회전, 크기, 이동)으로 정합한 뒤, 정합된 평균 형상에서 결측 위치를 읽어옵니다.

  3. 채워 넣은 값으로 다시 정렬한 다음, 원래의 빈 자리를 다시 열어 개선된 평균 형상으로부터 재추정합니다.

  4. 3단계를 몇 번 반복합니다. 정렬이 수렴하면서 추정값이 개선되며, 이전 추정값에 다시 맞추는 일은 없습니다.

대치된 값은 분석용 작업 사본에만 존재하며 데이터베이스에 다시 기록되지 않습니다. 객체 대화상자의 “추정값 보기”(Show Estimated)와 “Show Expected” 미리보기도 같은 형상 정합을 사용합니다.

권장 사항:

  • 결측 데이터를 전체 랜드마크의 10% 미만으로 유지하세요

  • 완전한(또는 거의 완전한) 표본을 충분히 확보하세요

  • 어떤 랜드마크가 결측이었는지 기록하세요

  • 민감도 분석(해당 표본을 포함/제외한 결과 비교)

3D 시각화 기법

고급 3D 조작

탐색:

  • 왼쪽 버튼 드래그: 중심을 기준으로 회전

  • 가운데 버튼 드래그: 이동(팬)

  • 오른쪽 버튼 드래그 또는 스크롤 휠: 확대/축소

표시 토글 (뷰어 옆의 체크박스):

  • 3D Model: 메시를 표시

  • Rotate: 모델을 계속 회전

  • Wireframe / Polygon / Baseline: 데이터셋의 랜드마크 연결선, 채워진 폴리곤, 베이스라인을 표시

랜드마크 시각화

사용자 지정Edit → Preferences 에서 2D와 3D를 각각 설정합니다:

  • 랜드마크 크기: 작게 / 중간 / 크게

  • 와이어프레임 두께: 얇게 / 중간 / 굵게

  • 인덱스(레이블) 크기: 작게 / 중간 / 크게

  • 뷰어의 배경 색상

랜드마크 레이블:

  • Show 체크박스로 레이블을 켜고 끕니다

  • Index / Name 라디오 버튼으로 레이블을 랜드마크 번호로 할지 데이터셋 전체 이름으로 할지 정합니다

와이어프레임 표시:

  • 데이터셋 대화상자의 와이어프레임 탭에서 연결을 정의합니다

모델 가져오기 및 처리

지원하는 3D 형식:

  • OBJ: Wavefront 형식 (가장 널리 쓰임)

  • PLY: Polygon File Format

  • STL: Stereolithography

모델 전처리:

성능을 높이려면 모델을 미리 다듬으세요:

  1. 폴리곤 수 줄이기 (MeshLab/Blender):

    Original: 1,000,000 polygons
    Decimated: 100,000 polygons
    Quality: Still excellent
    Performance: 10x faster
    
  2. 모델 중심 맞추기:

    • 모델이 원점에 중심을 둠

    • 랜드마크 배치가 쉬워짐

  3. 적절한 크기로 조정:

    • 좌표 범위를 적당하게

    • 너무 크거나 작지 않게

모델 일괄 처리:

# Example: Decimate models with Trimesh
import trimesh

mesh = trimesh.load('model.obj')
# Reduce to 10% of original faces
simplified = mesh.simplify_quadratic_decimation(
    len(mesh.faces) // 10
)
simplified.export('model_simplified.obj')

외부 도구와의 연동

R 연동

R에서 분석할 수 있도록 데이터를 내보냅니다:

랜드마크 내보내기:

# Modan2: Export as Morphologika or TPS

# R: Import with geomorph
library(geomorph)
data <- readland.tps("export.tps", specID = "ID")

# Or Morphologika
data <- read.morphologika("export.txt")

# Perform analysis in geomorph
gpa <- gpagen(data)
pca <- gm.prcomp(gpa$coords)

R 결과 가져오기:

  1. R 결과를 CSV로 저장

  2. Modan2에 변수로 가져오기

  3. 데이터 탐색에서 시각화

Python/NumPy 연동

프로그램으로 데이터에 접근합니다:

from MdModel import MdDataset, MdObject
import numpy as np

# Load dataset
dataset = MdDataset.get_by_id(1)
objects = dataset.get_object_list()

# Extract landmark coordinates
coords = []
for obj in objects:
    landmarks = obj.get_landmark_list()
    coords.append(landmarks)

# Convert to NumPy array
data = np.array(coords)  # Shape: (n_objects, n_landmarks, n_dims)

# Perform custom analysis
from scipy.spatial.distance import pdist, squareform
from sklearn.decomposition import PCA

# Flatten for PCA
flat_data = data.reshape(len(objects), -1)

# Custom PCA
pca = PCA(n_components=10)
scores = pca.fit_transform(flat_data)

# Save results back to Modan2
# (Add as variables to objects)

MorphoJ 호환성

MorphoJ용으로 내보내기:

  1. Morphologika 형식으로 내보내기

  2. MorphoJ에서 열기

  3. 추가 분석 수행

  4. 결과 비교

MorphoJ에서 가져오기:

  1. MorphoJ에서 Morphologika 형식으로 내보내기

  2. Modan2로 가져오기

  3. 작업 계속 진행

스크립팅과 자동화

Python API

스크립트에서 Modan2 모듈을 사용합니다:

#!/usr/bin/env python
"""
Example: Batch PCA analysis
"""
from MdModel import MdDataset, MdDatasetOps
from MdStatistics import PerformPCA
import json

# Get all 2D datasets with sufficient objects
datasets = MdDataset.select().where(MdDataset.dimension == 2)

results = []
for dataset in datasets:
    # Check object count
    obj_count = len(dataset.get_object_list())
    if obj_count < 50:
        continue

    print(f"Processing {dataset.dataset_name}...")

    # Create dataset ops and perform PCA
    dataset_ops = MdDatasetOps()
    dataset_ops.read_from_dataset(dataset)

    pca = PerformPCA(dataset_ops)
    if pca is None:
        continue

    # Save results
    results.append({
        'dataset': dataset.dataset_name,
        'n_components': len(pca.eigen_value_percentages),
        'variance_ratios': pca.eigen_value_percentages[:5]  # First 5 PCs
    })

# Export summary
with open('pca_summary.json', 'w') as f:
    json.dump(results, f, indent=2)

print(f"Processed {len(results)} datasets")

데이터베이스 쿼리

고급 데이터베이스 작업:

from MdModel import MdDataset, MdObject, MdAnalysis
from peewee import fn

# Find datasets with most objects
top_datasets = (MdDataset
    .select(MdDataset, fn.COUNT(MdObject.id).alias('count'))
    .join(MdObject)
    .group_by(MdDataset)
    .order_by(fn.COUNT(MdObject.id).desc())
    .limit(10))

# Find objects with missing landmarks
incomplete_objects = (MdObject
    .select()
    .where(MdObject.missing_landmarks.is_null(False)))

# Get all PCA analyses
pca_analyses = (MdAnalysis
    .select()
    .where(MdAnalysis.analysis_type == 'PCA'))

# Complex join query
results = (MdDataset
    .select(MdDataset.name, fn.AVG(MdObject.size).alias('mean_size'))
    .join(MdObject)
    .group_by(MdDataset)
    .having(fn.COUNT(MdObject.id) > 30))

일괄 내보내기

여러 데이터셋을 한 번에 내보냅니다:

#!/usr/bin/env python
"""
Export all datasets as JSON+ZIP
"""
from MdModel import MdDataset
from MdUtils import create_zip_package
import os

output_dir = "exports"
os.makedirs(output_dir, exist_ok=True)

datasets = MdDataset.select()
for dataset in datasets:
    filename = f"{dataset.dataset_name.replace(' ', '_')}.zip"
    filepath = os.path.join(output_dir, filename)

    print(f"Exporting {dataset.dataset_name}...")
    create_zip_package(
        dataset.id,
        filepath,
        include_files=True
    )

print(f"Exported {len(datasets)} datasets to {output_dir}")

사용자 정의 시각화

Matplotlib 연동

Modan2 데이터로 사용자 정의 플롯을 만듭니다:

import matplotlib.pyplot as plt
from MdModel import MdDataset, MdDatasetOps
from MdStatistics import PerformPCA
import numpy as np

# Load dataset and run PCA
dataset = MdDataset.get_by_id(1)
dataset_ops = MdDatasetOps()
dataset_ops.read_from_dataset(dataset)

pca = PerformPCA(dataset_ops)
if pca is None:
    print("PCA failed")
    exit(1)

# Extract PC scores and variance
scores = np.array(pca.rotated_matrix)
variance = [v * 100 for v in pca.eigen_value_percentages]  # Convert to percentages

# Create custom scatter plot
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

# PC1 vs PC2
ax1.scatter(scores[:, 0], scores[:, 1], alpha=0.6)
ax1.set_xlabel(f'PC1 ({variance[0]:.1f}%)')
ax1.set_ylabel(f'PC2 ({variance[1]:.1f}%)')
ax1.set_title('PCA Scores')
ax1.grid(True, alpha=0.3)

# Scree plot
n_components = min(10, len(variance))  # Show first 10 components
ax2.bar(range(1, n_components+1), variance[:n_components])
ax2.set_xlabel('Component')
ax2.set_ylabel('Variance Explained (%)')
ax2.set_title('Scree Plot')

plt.tight_layout()
plt.savefig('pca_custom.png', dpi=300)
plt.show()

형상 변형 격자

주성분 축을 따라 형상이 어떻게 변하는지 시각화합니다:

import matplotlib.pyplot as plt
import numpy as np
from MdModel import MdDataset, MdDatasetOps
from MdStatistics import PerformPCA

# Load dataset and run PCA
dataset = MdDataset.get_by_id(1)
dataset_ops = MdDatasetOps()
dataset_ops.read_from_dataset(dataset)

pca = PerformPCA(dataset_ops)
if pca is None:
    print("PCA failed")
    exit(1)

# Calculate mean shape (already centered in PCA)
n_landmarks = len(dataset_ops.object_list[0].landmark_list)
dimension = dataset.dimension

# Get PC1 loadings (rotation matrix column 0)
pc1_loadings = pca.rotation_matrix[:, 0]

# Reconstruct shapes at -2SD, mean (0), +2SD along PC1
sd = np.sqrt(pca.raw_eigen_values[0])
shapes = []
for multiplier in [-2, 0, 2]:
    # Apply PC1 loadings scaled by SD
    shape_vector = pc1_loadings * multiplier * sd
    # Reshape to landmarks
    shape = shape_vector.reshape(n_landmarks, dimension)
    shapes.append(shape)

# Plot deformation
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
wireframe = dataset.unpack_wireframe()

for ax, shape, title in zip(
    axes,
    shapes,
    ['PC1 -2SD', 'Mean', 'PC1 +2SD']
):
    ax.scatter(shape[:, 0], shape[:, 1], c='red', s=50, zorder=2)
    # Add wireframe if defined
    if wireframe:
        for connection in wireframe:
            idx1, idx2 = connection
            ax.plot([shape[idx1, 0], shape[idx2, 0]],
                   [shape[idx1, 1], shape[idx2, 1]], 'b-', alpha=0.6)
    ax.set_title(title)
    ax.set_aspect('equal')
    ax.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('shape_deformation.png', dpi=300)

설정과 구성

설정 파일 형식

Modan2는 설정을 JSON 파일에 보관하며, 애플리케이션을 종료할 때 기록합니다.

위치 — 운영체제의 표준 설정 폴더입니다:

플랫폼

위치

Windows

%LOCALAPPDATA%\PaleoBytes\Modan2\preferences.json

macOS

~/Library/Application Support/PaleoBytes/Modan2/preferences.json

Linux

~/.config/PaleoBytes/Modan2/preferences.json

이것은 데이터(~/PaleoBytes/Modan2/ — 데이터베이스, 이미지, 3D 모델, 로그, 백업)와 별개입니다. 설정은 애플리케이션이 다시 만들 수 있지만 데이터는 그럴 수 없으므로 둘을 따로 둡니다.

위치가 바뀌면 설정은 자동으로 새 위치로 복사되므로 업그레이드로 잃는 일이 없습니다. 이전 버전은 ~/PaleoBytes/Modan2/preferences.json 에, 그 전에는 ~/.modan2/config.json 에 두었습니다. 그 파일들은 그대로 남으며 업그레이드가 끝나면 삭제해도 됩니다.

이 파일의 내용은 모두 환경 설정(Preferences) 대화상자와 세션 간에 기억되는 창 위치·크기가 기록하므로, 설정을 바꾸는 정상적인 방법은 UI를 이용하는 것입니다. Modan2를 기본값으로 되돌리려면 종료한 뒤 이 파일을 삭제하세요. 다음 실행 시 다시 만들어집니다.

# Backup (Linux; adjust the path for your platform, see the table above)
cp ~/.config/PaleoBytes/Modan2/preferences.json{,.backup}

# Restore
cp ~/.config/PaleoBytes/Modan2/preferences.json{.backup,}

명령줄 옵션

애플리케이션은 시작할 때 몇 가지 옵션을 받습니다:

  • --db <경로> — 기본 데이터베이스 대신 특정 데이터베이스를 엽니다

  • --config <경로> — 다른 설정 파일을 사용합니다

  • --lang <en|ko> — 지정한 언어로 시작합니다

  • --debug — 상세 로깅

  • --no-splash — 스플래시 화면을 건너뜁니다

  • --version — 버전을 출력하고 종료합니다

참고

Modan2는 환경 변수로 설정하지 않습니다. 이 옵션들(또는 환경 설정 대화상자)을 사용하세요.

팁과 요령

키보드 단축키

메인 창:

  • Ctrl+N: 새 데이터셋

  • Ctrl+Shift+N: 새 객체

  • Ctrl+Shift+O: 객체 편집

  • Ctrl+S: 변경사항 저장

  • Ctrl+I: 가져오기

  • Ctrl+E: 내보내기

  • Ctrl+G: 분석

  • Ctrl+P: 객체 미리보기 켜기/끄기

  • Ctrl+W: 종료

  • F1: 정보

객체 대화상자 (Curve 모드):

  • Enter / 더블클릭: 현재 추적 확정

  • Esc / 오른쪽 클릭: 현재 추적 취소

표:

  • Ctrl+C / Ctrl+V: 셀 복사·붙여넣기 (예: 스프레드시트와 주고받기)

작업 흐름 최적화

효율적인 데이터 입력:

  1. 템플릿 데이터셋:

    • 구조를 완전히 갖춘 데이터셋을 만들어 두세요

    • 새 연구마다 복제해서 사용하세요

    • 변수와 와이어프레임을 미리 정의해 두세요

  2. 키보드 이동:

    • Tab으로 입력란 이동

    • Enter로 확정

    • Esc로 취소

  3. 일괄 작업:

    • 여러 객체 선택

    • 표에서 변수 편집

    • 스프레드시트에서 복사/붙여넣기

분석 작업 흐름:

Quick exploration:
1. Import data
2. Quick PCA (no grouping)
3. Identify outliers
4. Refine dataset

Publication workflow:
1. Clean data
2. Document variables
3. Multiple analyses
4. Export high-quality figures
5. Export data for R/Python

숨은 기능

더블클릭 동작:

  • 데이터셋 더블클릭: 펼치기/접기

  • 객체 더블클릭: 객체 대화상자 열기

  • 분석 더블클릭: 결과 열기

오른쪽 클릭 상황 메뉴:

  • 트리에서 데이터셋 오른쪽 클릭: 하위 데이터셋·객체·분석 추가, 데이터 탐색, 새로 고침

  • 2D 뷰어에서 랜드마크 오른쪽 클릭: 삭제

  • 곡선의 점 오른쪽 클릭 (Curve 모드): Delete Point / Delete Curve

  • 곡선 표의 행 오른쪽 클릭: Delete Curve (all specimens)

드래그 앤 드롭:

  • TPS 파일을 창으로 끌어다 놓기: 가져오기

  • 이미지를 객체로 끌어다 놓기: 첨부

  • 3D 모델을 객체로 끌어다 놓기: 첨부

더 많은 자료

문서:

  • 설치 안내서: 자세한 설치 방법

  • 사용자 안내서: 기본 사용법

  • 문제 해결 안내서: 문제 해결

  • FAQ: 자주 묻는 질문

커뮤니티:

  • GitHub Discussions: 질문하기

  • GitHub Issues: 버그 신고

개발:

  • 개발자 안내서: 아키텍처

  • CONTRIBUTING.md: 기여 안내

  • GitHub 저장소: 소스 코드

연락처: