Skip to content

Commit d5d1818

Browse files
committed
frontend scripts and conf files
1 parent 668e03d commit d5d1818

9 files changed

Lines changed: 371 additions & 0 deletions

File tree

frontend/components.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"$schema": "https://ui.shadcn.com/schema.json",
3+
"style": "default",
4+
"rsc": true,
5+
"tsx": true,
6+
"tailwind": {
7+
"config": "tailwind.config.ts",
8+
"css": "src/app/globals.css",
9+
"baseColor": "slate",
10+
"cssVariables": true,
11+
"prefix": ""
12+
},
13+
"aliases": {
14+
"components": "@/components",
15+
"utils": "@/lib/utils"
16+
}
17+
}

frontend/next-env.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// <reference types="next" />
2+
/// <reference types="next/image-types/global" />
3+
4+
// NOTE: This file should not be edited
5+
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.

frontend/next.config.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
const isProd = process.env.NODE_ENV === 'production'
2+
const isStatic = process.env.STATIC_BUILD === 'true'
3+
const repoName = 'PCDiff'
4+
5+
module.exports = {
6+
assetPrefix: isProd && !isStatic ? `/${repoName}/` : '',
7+
basePath: isProd && !isStatic ? `/${repoName}` : '',
8+
repoName: isProd && !isStatic ? `/${repoName}` : '',
9+
output: 'export',
10+
images: {
11+
unoptimized: true,
12+
},
13+
webpack: (config, { isServer }) => {
14+
if (!isServer) {
15+
config.resolve.fallback.fs = false;
16+
config.resolve.fallback.module = false;
17+
}
18+
return config;
19+
},
20+
publicRuntimeConfig: {
21+
basePath: isProd && !isStatic ? `/${repoName}` : '',
22+
},
23+
async headers() {
24+
return [
25+
{
26+
source: '/data/:file*.json',
27+
headers: [
28+
{
29+
key: 'Content-Type',
30+
value: 'application/json',
31+
},
32+
],
33+
},
34+
]
35+
},
36+
}

frontend/package.json

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{
2+
"name": "pointcloud-diff-benchmark-test",
3+
"version": "1.1.0",
4+
"description": "A web application for visualizing and comparing point cloud data.",
5+
"author": "Leo Arnal--Anger",
6+
"private": true,
7+
"scripts": {
8+
"compress-img": "node scripts/compressor.js",
9+
"convert-pts": "node scripts/convertPtsToJson.js",
10+
"dev": "next dev",
11+
"build": "node scripts/convertPtsToJson.js && cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" STATIC_BUILD=false next build",
12+
"build-simple": "STATIC_BUILD=false next build && touch out/.nojekyll",
13+
"start": "next start",
14+
"lint": "next lint",
15+
"deploy": "node scripts/convertPtsToJson.js && cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" STATIC_BUILD=false next build && touch out/.nojekyll",
16+
"build-portable-simple": "STATIC_BUILD=true next build && node scripts/preparePortable.js",
17+
"build-portable": "node scripts/convertPtsToJson.js && cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" STATIC_BUILD=true next build && node scripts/preparePortable.js",
18+
"image-compression": "node scripts/compressor.js"
19+
},
20+
"dependencies": {
21+
"@radix-ui/react-accordion": "^1.2.0",
22+
"@radix-ui/react-dialog": "^1.1.1",
23+
"@radix-ui/react-dropdown-menu": "^2.0.6",
24+
"@radix-ui/react-label": "^2.1.0",
25+
"@radix-ui/react-menubar": "^1.0.4",
26+
"@radix-ui/react-scroll-area": "^1.0.5",
27+
"@radix-ui/react-select": "^2.0.0",
28+
"@radix-ui/react-separator": "^1.0.3",
29+
"@radix-ui/react-slider": "^1.1.2",
30+
"@radix-ui/react-slot": "^1.0.2",
31+
"@radix-ui/react-switch": "^1.1.0",
32+
"@radix-ui/react-tabs": "^1.0.4",
33+
"@radix-ui/react-tooltip": "^1.2.0",
34+
"@react-three/drei": "^9.106.0",
35+
"@react-three/fiber": "^8.16.8",
36+
"@types/styled-components": "^5.1.34",
37+
"@types/three": "^0.165.0",
38+
"class-variance-authority": "^0.7.0",
39+
"clsx": "^2.1.1",
40+
"d3": "^7.9.0",
41+
"lucide-react": "^0.378.0",
42+
"next": "^14.2.3",
43+
"next-themes": "^0.3.0",
44+
"react": "^18",
45+
"react-dom": "^18.3.1",
46+
"react-plotly.js": "^2.6.0",
47+
"react-resizable-panels": "^2.0.19",
48+
"sharp": "^0.33.5",
49+
"styled-components": "^6.1.11",
50+
"tailwind-merge": "^2.3.0",
51+
"tailwindcss-animate": "^1.0.7",
52+
"three": "^0.165.0"
53+
},
54+
"devDependencies": {
55+
"@types/d3": "^7.4.3",
56+
"@types/node": "^20",
57+
"@types/plotly.js": "^2.29.4",
58+
"@types/plotly.js-basic-dist": "^1.54.4",
59+
"@types/react": "^18",
60+
"@types/react-dom": "^18",
61+
"@types/react-plotly.js": "^2.6.3",
62+
"eslint": "^8",
63+
"eslint-config-next": "14.2.3",
64+
"postcss": "^8",
65+
"serve": "^14.2.3",
66+
"tailwindcss": "^3.4.1",
67+
"typescript": "^5"
68+
}
69+
}

frontend/postcss.config.mjs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/** @type {import('postcss-load-config').Config} */
2+
const config = {
3+
plugins: {
4+
tailwindcss: {},
5+
},
6+
};
7+
8+
export default config;

frontend/scripts/compressor.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
const sharp = require('sharp');
4+
5+
// Chemin vers la racine du projet (un niveau au-dessus du dossier scripts)
6+
const projectRoot = path.join(__dirname, '..');
7+
8+
const sourceImageDirectory = path.join(projectRoot, 'public', 'images_compressed');
9+
const compressedImageDirectory = path.join(projectRoot, 'public', 'images_compressed_bis');
10+
11+
function ensureDirectoryExistence(filePath) {
12+
const dirname = path.dirname(filePath);
13+
if (fs.existsSync(dirname)) {
14+
return true;
15+
}
16+
ensureDirectoryExistence(dirname);
17+
fs.mkdirSync(dirname);
18+
}
19+
20+
function compressImage(sourcePath, destinationPath) {
21+
ensureDirectoryExistence(destinationPath);
22+
23+
return sharp(sourcePath)
24+
.resize(1920, 1080, { fit: 'inside', withoutEnlargement: true })
25+
.jpeg({ quality: 75 })
26+
.png({ quality: 75 })
27+
.toFile(destinationPath)
28+
.then(() => {
29+
console.log(`Compressed: ${sourcePath} -> ${destinationPath}`);
30+
})
31+
.catch(err => console.error(`Error compressing ${sourcePath}:`, err));
32+
}
33+
34+
function processDirectory(sourceDir, destDir) {
35+
if (!fs.existsSync(sourceDir)) {
36+
console.error(`Source directory does not exist: ${sourceDir}`);
37+
return;
38+
}
39+
40+
const items = fs.readdirSync(sourceDir);
41+
42+
for (const item of items) {
43+
const sourceItemPath = path.join(sourceDir, item);
44+
const destItemPath = path.join(destDir, item);
45+
const stat = fs.statSync(sourceItemPath);
46+
47+
if (stat.isDirectory()) {
48+
processDirectory(sourceItemPath, destItemPath);
49+
} else if (stat.isFile()) {
50+
const ext = path.extname(sourceItemPath).toLowerCase();
51+
if (['.jpg', '.jpeg', '.png'].includes(ext)) {
52+
compressImage(sourceItemPath, destItemPath);
53+
}
54+
}
55+
}
56+
}
57+
58+
console.log('Starting image compression...');
59+
console.log(`Source directory: ${sourceImageDirectory}`);
60+
console.log(`Destination directory: ${compressedImageDirectory}`);
61+
62+
if (!fs.existsSync(sourceImageDirectory)) {
63+
console.error(`Error: Source image directory does not exist: ${sourceImageDirectory}`);
64+
process.exit(1);
65+
}
66+
67+
processDirectory(sourceImageDirectory, compressedImageDirectory);
68+
console.log('Image compression complete. Compressed images are in the "images_compressed" folder.');
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
import { fileURLToPath } from 'url';
4+
5+
const __filename = fileURLToPath(import.meta.url);
6+
const __dirname = path.dirname(__filename);
7+
8+
const inputDir = path.join(__dirname, '../public/models');
9+
const outputDir = path.join(__dirname, '../public/data');
10+
11+
// Fonction récursive pour traiter les répertoires
12+
function processDirectory(currentInputDir, currentOutputDir) {
13+
if (!fs.existsSync(currentOutputDir)) {
14+
fs.mkdirSync(currentOutputDir, { recursive: true });
15+
}
16+
17+
fs.readdirSync(currentInputDir, { withFileTypes: true }).forEach(dirent => {
18+
const inputPath = path.join(currentInputDir, dirent.name);
19+
const outputPath = path.join(currentOutputDir, dirent.name);
20+
21+
if (dirent.isDirectory()) {
22+
// Si c'est un répertoire, on appelle récursivement la fonction
23+
processDirectory(inputPath, outputPath);
24+
} else {
25+
// Si c'est un fichier, on le traite
26+
if (path.extname(dirent.name) === '.pts' || path.extname(dirent.name) === '.obj') {
27+
const content = fs.readFileSync(inputPath, 'utf8');
28+
const points = content.split('\n')
29+
.filter(line => line.trim() !== '') // Supprime les lignes vides
30+
.map(line => line.split(' ').map(Number)) // Convertit chaque ligne en tableau de nombres
31+
.map(values => {
32+
// Applique la racine carrée à la colonne JetFitting (index 12) si elle existe
33+
if (inputPath.includes(`${path.sep}errors${path.sep}`) && values[12] !== undefined) {
34+
values[12] = Math.sqrt(values[12]);
35+
}
36+
return values;
37+
})
38+
.filter(values => {
39+
// Supprime les lignes où toutes les valeurs au-delà de la 4ème colonne sont égales à 0
40+
const beyondFourthColumn = values.slice(4);
41+
return !beyondFourthColumn.every(value => value === 0); // Garde les lignes où au moins une valeur est différente de 0
42+
});
43+
44+
// Remplace "selle" par "saddle" dans le nom du fichier de sortie JSON
45+
const jsonBaseName = path.basename(dirent.name, path.extname(dirent.name)).replace(/selle/g, 'saddle');
46+
const jsonOutputPath = path.join(
47+
path.dirname(outputPath),
48+
`${jsonBaseName}.json`
49+
);
50+
let outputContent = JSON.stringify(points);
51+
if (content.includes('selle')) {
52+
outputContent = outputContent.replace(/selle/g, 'saddle');
53+
}
54+
fs.writeFileSync(jsonOutputPath, outputContent);
55+
console.log(`Converti ${dirent.name} en JSON`);
56+
}
57+
}
58+
});
59+
}
60+
61+
// Démarrer le traitement à partir du répertoire racine
62+
processDirectory(inputDir, outputDir);

frontend/tailwind.config.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import type { Config } from "tailwindcss"
2+
3+
const config = {
4+
darkMode: ["class"],
5+
content: [
6+
'./pages/**/*.{ts,tsx}',
7+
'./components/**/*.{ts,tsx}',
8+
'./app/**/*.{ts,tsx}',
9+
'./src/**/*.{ts,tsx}',
10+
],
11+
prefix: "",
12+
theme: {
13+
container: {
14+
center: true,
15+
padding: "2rem",
16+
screens: {
17+
"2xl": "1400px",
18+
},
19+
},
20+
extend: {
21+
colors: {
22+
border: "hsl(var(--border))",
23+
input: "hsl(var(--input))",
24+
ring: "hsl(var(--ring))",
25+
background: "hsl(var(--background))",
26+
foreground: "hsl(var(--foreground))",
27+
primary: {
28+
DEFAULT: "hsl(var(--primary))",
29+
foreground: "hsl(var(--primary-foreground))",
30+
},
31+
secondary: {
32+
DEFAULT: "hsl(var(--secondary))",
33+
foreground: "hsl(var(--secondary-foreground))",
34+
},
35+
destructive: {
36+
DEFAULT: "hsl(var(--destructive))",
37+
foreground: "hsl(var(--destructive-foreground))",
38+
},
39+
muted: {
40+
DEFAULT: "hsl(var(--muted))",
41+
foreground: "hsl(var(--muted-foreground))",
42+
},
43+
accent: {
44+
DEFAULT: "hsl(var(--accent))",
45+
foreground: "hsl(var(--accent-foreground))",
46+
},
47+
popover: {
48+
DEFAULT: "hsl(var(--popover))",
49+
foreground: "hsl(var(--popover-foreground))",
50+
},
51+
card: {
52+
DEFAULT: "hsl(var(--card))",
53+
foreground: "hsl(var(--card-foreground))",
54+
},
55+
},
56+
borderRadius: {
57+
lg: "var(--radius)",
58+
md: "calc(var(--radius) - 2px)",
59+
sm: "calc(var(--radius) - 4px)",
60+
},
61+
keyframes: {
62+
"accordion-down": {
63+
from: { height: "0" },
64+
to: { height: "var(--radix-accordion-content-height)" },
65+
},
66+
"accordion-up": {
67+
from: { height: "var(--radix-accordion-content-height)" },
68+
to: { height: "0" },
69+
},
70+
},
71+
animation: {
72+
"accordion-down": "accordion-down 0.2s ease-out",
73+
"accordion-up": "accordion-up 0.2s ease-out",
74+
},
75+
},
76+
},
77+
plugins: [require("tailwindcss-animate")],
78+
} satisfies Config
79+
80+
export default config

frontend/tsconfig.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"compilerOptions": {
3+
"lib": ["dom", "dom.iterable", "esnext"],
4+
"allowJs": true,
5+
"skipLibCheck": true,
6+
"strict": true,
7+
"noEmit": true,
8+
"esModuleInterop": true,
9+
"module": "esnext",
10+
"moduleResolution": "bundler",
11+
"resolveJsonModule": true,
12+
"isolatedModules": true,
13+
"jsx": "preserve",
14+
"incremental": true,
15+
"plugins": [
16+
{
17+
"name": "next"
18+
}
19+
],
20+
"paths": {
21+
"@/*": ["./src/*"]
22+
}
23+
},
24+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
25+
"exclude": ["node_modules"]
26+
}

0 commit comments

Comments
 (0)