diff --git a/frontend/src/app/pages/particles/components/render-container/render-container.component.html b/frontend/src/app/pages/particles/components/render-container/render-container.component.html
index ecf727c..c358bae 100644
--- a/frontend/src/app/pages/particles/components/render-container/render-container.component.html
+++ b/frontend/src/app/pages/particles/components/render-container/render-container.component.html
@@ -35,6 +35,11 @@
[matTooltip]="gridVisible ? 'Hide grid' : 'Show grid'">
{{ gridVisible ? 'grid_off' : 'grid_on' }}
+
+
@if (isPlaneLocked) {
diff --git a/frontend/src/app/pages/particles/components/render-container/render-container.component.ts b/frontend/src/app/pages/particles/components/render-container/render-container.component.ts
index defaa73..6af34da 100644
--- a/frontend/src/app/pages/particles/components/render-container/render-container.component.ts
+++ b/frontend/src/app/pages/particles/components/render-container/render-container.component.ts
@@ -103,6 +103,15 @@ export class RenderContainerComponent implements AfterViewInit, OnDestroy {
this.intersectionPlaneService.setGridDensity(d);
}
+ // Grid snap proxies
+ public get gridSnapEnabled(): boolean {
+ return this.intersectionPlaneService.getGridSnapEnabled();
+ }
+
+ public set gridSnapEnabled(v: boolean) {
+ this.intersectionPlaneService.setGridSnapEnabled(v);
+ }
+
/**
* Toggle the plane locked state
*/
diff --git a/frontend/src/app/pages/particles/services/intersection-plane.service.ts b/frontend/src/app/pages/particles/services/intersection-plane.service.ts
index 8ef90c0..1f8d1cb 100644
--- a/frontend/src/app/pages/particles/services/intersection-plane.service.ts
+++ b/frontend/src/app/pages/particles/services/intersection-plane.service.ts
@@ -32,6 +32,7 @@ export class IntersectionPlaneService {
private gridHelper?: THREE.GridHelper;
private gridVisible: boolean = true;
private gridDensity: number = 4;
+ private gridSnapEnabled: boolean = true;
// Emits whenever plane position, orientation, or lock-affecting orientation updates change visuals
public readonly planeChanged$ = new Subject();
@@ -111,6 +112,14 @@ export class IntersectionPlaneService {
return this.gridDensity;
}
+ public setGridSnapEnabled(enabled: boolean): void {
+ this.gridSnapEnabled = enabled;
+ }
+
+ public getGridSnapEnabled(): boolean {
+ return this.gridSnapEnabled;
+ }
+
/**
* Creates the intersection plane and adds it to the scene
*/
diff --git a/frontend/src/app/pages/particles/services/particle-manager.service.ts b/frontend/src/app/pages/particles/services/particle-manager.service.ts
index ead536f..1aca2a4 100644
--- a/frontend/src/app/pages/particles/services/particle-manager.service.ts
+++ b/frontend/src/app/pages/particles/services/particle-manager.service.ts
@@ -57,9 +57,11 @@ export class ParticleManagerService {
const divisions = Math.max(1, Math.floor(planeSize * this.intersectionPlaneService.getGridDensity()));
const gridStepPlane = planeSize / divisions;
- x = Math.round(x / gridStepPlane) * gridStepPlane;
- y = Math.round(y / gridStepPlane) * gridStepPlane;
- z = Math.round(z / gridStepPlane) * gridStepPlane;
+ if (this.intersectionPlaneService.getGridSnapEnabled()) {
+ x = Math.round(x / gridStepPlane) * gridStepPlane;
+ y = Math.round(y / gridStepPlane) * gridStepPlane;
+ z = Math.round(z / gridStepPlane) * gridStepPlane;
+ }
// Create a visual representation of the particle
const particleGeometry = new THREE.SphereGeometry(0.03 * this.selectedSize, 16, 16);
const particleMaterial = new THREE.MeshBasicMaterial({color: this.selectedColor});