Генерація каталогу мініатюр
Створення візуальних каталогів CAD-деталей з автоматично згенерованими мініатюрами.
Огляд процесу
Бібліотека CAD
Колекція деталей
Обробка
Трансляція у SVF2
Витяг мініатюр
Витяг метаданих
Генерація каталогу
Створення сітки мініатюр
Побудова індексної сторінки
Генерація даних пошуку
Вихід каталогу
HTML-галерея
JSON-індекс
PDF-каталог
Вхід→Обробка→Генерація→Вихід
Підхід через CLI
Крок 1: Генерація мініатюр для всіх деталей
mkdir -p ./catalog/thumbnails
raps object list cad-library --output json | jq -r '.[].key' | while read key; do
URN=$(raps object urn cad-library "$key" --output plain)
# Check if translation exists and is complete
STATUS=$(raps translate manifest "$URN" 2>/dev/null | jq -r '.status // "none"')
if [ "$STATUS" = "success" ]; then
# Generate safe filename
SAFE_NAME=$(echo "$key" | tr '/' '_' | sed 's/\.[^.]*$//')
# Download thumbnail
raps derivative thumbnail "$URN" --output "./catalog/thumbnails/${SAFE_NAME}.png"
echo "Generated: ${SAFE_NAME}.png"
else
echo "Skipping (not translated): $key"
fi
done
Крок 2: Витяг метаданих деталей
echo "[]" > ./catalog/parts.json
raps object list cad-library --output json | jq -r '.[].key' | while read key; do
URN=$(raps object urn cad-library "$key" --output plain)
STATUS=$(raps translate manifest "$URN" 2>/dev/null | jq -r '.status // "none"')
if [ "$STATUS" = "success" ]; then
SAFE_NAME=$(echo "$key" | tr '/' '_' | sed 's/\.[^.]*$//')
# Get properties
PROPS=$(raps derivative properties "$URN" --output json 2>/dev/null | jq '.[0].properties // {}')
# Add to catalog
jq --arg key "$key" \
--arg name "$SAFE_NAME" \
--argjson props "$PROPS" \
'. += [{key: $key, name: $name, thumbnail: ($name + ".png"), properties: $props}]' \
./catalog/parts.json > ./catalog/parts.tmp.json
mv ./catalog/parts.tmp.json ./catalog/parts.json
fi
done
Крок 3: Генерація HTML-каталогу
cat > ./catalog/index.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>Parts Catalog</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 20px; }
.part { border: 1px solid #ddd; padding: 10px; text-align: center; border-radius: 8px; }
.part img { max-width: 100%; height: 150px; object-fit: contain; }
.part h3 { font-size: 14px; margin: 10px 0 5px; }
.part p { font-size: 12px; color: #666; margin: 0; }
.search { margin-bottom: 20px; padding: 10px; width: 100%; font-size: 16px; }
</style>
</head>
<body>
<h1>Parts Catalog</h1>
<input type="text" class="search" placeholder="Search parts..." onkeyup="filterParts(this.value)">
<div class="grid" id="catalog"></div>
<script>
let parts = [];
fetch('parts.json')
.then(r => r.json())
.then(data => {
parts = data;
renderParts(parts);
});
function renderParts(data) {
const grid = document.getElementById('catalog');
grid.innerHTML = data.map(p => `
<div class="part">
<img src="thumbnails/${p.thumbnail}" alt="${p.name}">
<h3>${p.name}</h3>
<p>${p.properties['Part Number'] || ''}</p>
<p>${p.properties['Material'] || ''}</p>
</div>
`).join('');
}
function filterParts(query) {
const filtered = parts.filter(p =>
p.name.toLowerCase().includes(query.toLowerCase()) ||
JSON.stringify(p.properties).toLowerCase().includes(query.toLowerCase())
);
renderParts(filtered);
}
</script>
</body>
</html>
EOF
echo "Catalog generated at ./catalog/index.html"
CI/CD-конвеєр
# .github/workflows/catalog-generation.yml
name: Parts Catalog Generation
on:
schedule:
- cron: '0 2 * * *' # Daily at 2 AM
workflow_dispatch:
jobs:
generate-catalog:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install RAPS
run: cargo install raps
- name: Generate thumbnails
env:
APS_CLIENT_ID: ${{ secrets.APS_CLIENT_ID }}
APS_CLIENT_SECRET: ${{ secrets.APS_CLIENT_SECRET }}
run: |
mkdir -p ./catalog/thumbnails
raps object list cad-library --output json | jq -r '.[].key' | while read key; do
URN=$(raps object urn cad-library "$key" --output plain)
STATUS=$(raps translate manifest "$URN" 2>/dev/null | jq -r '.status // "none"')
if [ "$STATUS" = "success" ]; then
SAFE_NAME=$(echo "$key" | tr '/' '_' | sed 's/\.[^.]*$//')
raps derivative thumbnail "$URN" --output "./catalog/thumbnails/${SAFE_NAME}.png" 2>/dev/null || true
fi
done
- name: Generate metadata
env:
APS_CLIENT_ID: ${{ secrets.APS_CLIENT_ID }}
APS_CLIENT_SECRET: ${{ secrets.APS_CLIENT_SECRET }}
run: |
echo "[]" > ./catalog/parts.json
raps object list cad-library --output json | jq -r '.[].key' | while read key; do
URN=$(raps object urn cad-library "$key" --output plain)
STATUS=$(raps translate manifest "$URN" 2>/dev/null | jq -r '.status // "none"')
if [ "$STATUS" = "success" ]; then
SAFE_NAME=$(echo "$key" | tr '/' '_' | sed 's/\.[^.]*$//')
PROPS=$(raps derivative properties "$URN" --output json 2>/dev/null | jq '.[0].properties // {}' || echo '{}')
jq --arg key "$key" --arg name "$SAFE_NAME" --argjson props "$PROPS" \
'. += [{key: $key, name: $name, thumbnail: ($name + ".png"), properties: $props}]' \
./catalog/parts.json > ./catalog/parts.tmp.json
mv ./catalog/parts.tmp.json ./catalog/parts.json
fi
done
- name: Generate HTML
run: |
# Generate index.html (see CLI section for template)
cat > ./catalog/index.html << 'HTMLEOF'
<!-- HTML template here -->
HTMLEOF
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./catalog
Потік конвеєра
Розклад/Ручний
Щоденно о 2:00
→
Генерація
Перелік усіх деталей
Генерація мініатюр
Витяг метаданих
Побудова HTML
→
Розгортання
GitHub Pages
Інтеграція з MCP
Генерація каталогу
User: "Create a visual catalog of all parts in the CAD library"
Користувач
AI-асистент
RAPS MCP
APS Cloud
Користувач
Створити каталог деталей
AI
aps_object_list(bucket=“cad-library”)
MCP
Перелік об’єктів
APS
Список об’єктів
цикл: Для кожної деталі
AI
aps_derivative_thumbnail(urn)
MCP
Отримання мініатюри
APS
PNG-дані
AI
aps_derivative_properties(urn)
MCP
Отримання властивостей
APS
Properties JSON
AI
Генерація HTML-каталогу
AI
Каталог готовий з посиланням
Відповідь AI:
Згенеровано каталог деталей з 45 елементами:
Статистика каталогу:
- Всього деталей: 45
- З мініатюрами: 43
- З метаданими: 45
Категорії:
- Кронштейни: 12
- Корпуси: 8
- Вали: 10
- Шестерні: 15
Пошук у каталозі
User: "Find all aluminum parts in the catalog"
Відповідь AI:
Знайдено 18 алюмінієвих деталей:
Деталь Матеріал Вага bracket-a Aluminum 6061 0.45 кг housing-main Aluminum 7075 2.3 кг cover-plate Aluminum 6061 0.12 кг … … …
Розширені можливості
Організація за категоріями
# Organize by part type
cat ./catalog/parts.json | jq '
group_by(.properties["Part Type"] // "Uncategorized") |
map({
category: .[0].properties["Part Type"] // "Uncategorized",
count: length,
parts: .
})'
Генерація PDF-каталогу
# Using wkhtmltopdf
wkhtmltopdf \
--enable-local-file-access \
--print-media-type \
./catalog/index.html \
./catalog/parts-catalog.pdf
Інкрементальні оновлення
# Only update changed parts
LAST_RUN=$(cat .catalog-last-run 2>/dev/null || echo "1970-01-01")
raps object list cad-library --output json | \
jq --arg since "$LAST_RUN" '.[] | select(.lastModified > $since)' | \
jq -r '.key' | while read key; do
echo "Updating: $key"
# Generate thumbnail and metadata for this part
done
date -Iseconds > .catalog-last-run