Examples and demos for gemini-viewer sdk, which is a WebGL based BIM model viewer, built on three.js. It is used to view dwg/dxf, gltf, obj, ifc models, etc.
195
stars
42
forks
source link
Trying to implement my own logic on Gemini-viewer. But not working #142
//Here below following code i have implemented logic to draw a logic for doordrawing on 2D layers
//How should i integrate the my code in DXFviewer
// do i need to add integrate a code with DXFViwer logic?
// we are setting up grid and min/max length constants
const gridSize = 10; // Grid size is assigned
const MIN_LENGTH = 80; // Minimum door length in pixels (equivalent to mm)
const MAX_LENGTH = 120; // Maximum door length in pixels (equivalent to mm);
let isDrawing = false; // State to check if we're drawing
let selectedPoint = null; // To know which point is selected for dragging
let draggingLine = null; // To check if the line is being dragged
let dragStartPos = null; // Starting position when dragging
let currentDoor = null; // Storing the current door being drawn
let doors = []; // Array to store all doors
// This function will resizes the canvas whenever the window is resized
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
// Here we are adding event listener to resize the canvas whenever the window is resized
window.addEventListener('resize', resizeCanvas);
resizeCanvas(); // Initializing the canvas size on load
// This function will snaps the mouse pointer to the nearest grid point for precision
function snapToGrid(x, y) {
return {
x: Math.round(x / gridSize) gridSize,
y: Math.round(y / gridSize) gridSize
};
}
// This function to calculate the distance between two points (for line length calculation)
function calculateDistance(x1, y1, x2, y2) {
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}
//This will be having history of door states (can be used for undo functionality)
function saveHistory() {
// If needed, we can implement undo functionality by saving history
}
// When mouse is pressed, this function starts the door drawing process
function handleMouseDown(e) {
const pos = snapToGrid(e.offsetX, e.offsetY); // Snap mouse position to grid
let pointClicked = false; // Flag to check if any point (start/end) was clicked
// Check if we're clicking on an existing door's start or end points
doors.forEach((door, index) => {
const start = door.start;
const end = door.end;
// If clicked on the start or end point of a door, mark that point as selected
if (calculateDistance(pos.x, pos.y, start.x, start.y) < gridSize) {
selectedPoint = { type: 'start', index };
pointClicked = true;
} else if (calculateDistance(pos.x, pos.y, end.x, end.y) < gridSize) {
selectedPoint = { type: 'end', index };
pointClicked = true;
}
// Check if clicked on the door line itself (for dragging)
const distanceToLine = Math.abs(
(end.y - start.y) * pos.x - (end.x - start.x) * pos.y + end.x * start.y - end.y * start.x
) / calculateDistance(start.x, start.y, end.x, end.y);
const isWithinBounds = pos.x >= Math.min(start.x, end.x) &&
pos.x <= Math.max(start.x, end.x) &&
pos.y >= Math.min(start.y, end.y) &&
pos.y <= Math.max(start.y, end.y);
if (!pointClicked && distanceToLine < 5 && isWithinBounds) {
draggingLine = index; // Mark the line for dragging
dragStartPos = pos; // Store initial drag position
pointClicked = true;
}
});
// If no existing door point was clicked, start drawing a new door
if (!pointClicked) {
isDrawing = true;
currentDoor = {
start: pos, // Start position of the new door
end: null // End will be set as we move the mouse
};
doors.push(currentDoor); // Add this door to the list
}
}
// Handle mouse movement while drawing or dragging a door
function handleMouseMove(e) {
const pos = snapToGrid(e.offsetX, e.offsetY); // Snap position to grid for precision
if (selectedPoint) {
// We are dragging one of the points (start or end)
const door = doors[selectedPoint.index]; // Get the door being updated
const fixedPoint = selectedPoint.type === 'start' ? door.end : door.start; // The other end remains fixed
const distance = calculateDistance(fixedPoint.x, fixedPoint.y, pos.x, pos.y); // Calculate new distance
const clampedDistance = Math.max(MIN_LENGTH, Math.min(distance, MAX_LENGTH)); // Clamp the distance within allowed limits
const angle = Math.atan2(pos.y - fixedPoint.y, pos.x - fixedPoint.x); // Get the angle of movement
// Update the selected point (start or end) with new position
if (selectedPoint.type === 'start') {
door.start = {
x: fixedPoint.x + Math.cos(angle) * clampedDistance,
y: fixedPoint.y + Math.sin(angle) * clampedDistance
};
} else {
door.end = {
x: fixedPoint.x + Math.cos(angle) * clampedDistance,
y: fixedPoint.y + Math.sin(angle) * clampedDistance
};
}
redrawCanvas(); // Redraw canvas to reflect changes
} else if (draggingLine !== null && dragStartPos) {
// If we're dragging the entire line, calculate the delta and update both start and end points
const dx = pos.x - dragStartPos.x;
const dy = pos.y - dragStartPos.y;
const door = doors[draggingLine];
door.start.x += dx;
door.start.y += dy;
door.end.x += dx;
door.end.y += dy;
dragStartPos = pos; // Update drag start position for continuous dragging
redrawCanvas(); // Redraw to update changes
} else if (isDrawing) {
// If we're still in the drawing phase (mouse is down), update the end point
const distance = calculateDistance(currentDoor.start.x, currentDoor.start.y, pos.x, pos.y);
const clampedDistance = Math.max(MIN_LENGTH, Math.min(distance, MAX_LENGTH));
const angle = Math.atan2(pos.y - currentDoor.start.y, pos.x - currentDoor.start.x);
currentDoor.end = {
x: currentDoor.start.x + Math.cos(angle) * clampedDistance,
y: currentDoor.start.y + Math.sin(angle) * clampedDistance
};
redrawCanvas(); // Redraw canvas with the new door line
}
}
// Once the mouse is released, finalize the door drawing or dragging process
function handleMouseUp() {
if (isDrawing) {
isDrawing = false; // Stop the drawing process
if (!currentDoor.end || calculateDistance(currentDoor.start.x, currentDoor.start.y, currentDoor.end.x, currentDoor.end.y) < 10) {
doors.pop(); // Remove the door if it's too short
}
currentDoor = null; // Clear current door
saveHistory(); // Save the state for potential undo functionality
}
if (selectedPoint || draggingLine !== null) {
saveHistory(); // Save after dragging or point movement
}
// Reset the state
selectedPoint = null;
draggingLine = null;
dragStartPos = null;
}
// Draw a dashed line (used for the vertical dashed line)
function drawDashedLine(x1, y1, x2, y2) {
ctx.setLineDash([5, 5]); // Define dash pattern
ctx.beginPath(); // Start the line drawing
ctx.moveTo(x1, y1); // Move to start point
ctx.lineTo(x2, y2); // Draw line to end point
ctx.stroke(); // Render the line
ctx.setLineDash([]); // Reset line style to solid
}
// Draw the quarter-circle arc for the door
function drawDottedArc(cx, cy, radius, startAngle, endAngle) {
ctx.setLineDash([5, 5]); // Create dashed arc pattern
ctx.beginPath();
ctx.arc(cx, cy, radius, startAngle, endAngle); // Draw arc
ctx.stroke(); // Render arc
ctx.setLineDash([]); // Reset line style to solid
}
// Function to calculate perpendicular points for vertical line and arc
function calculatePerpendicular(door) {
const { start, end } = door;
// Calculate angle of the door line
const angle = Math.atan2(end.y - start.y, end.x - start.x);
// Calculate perpendicular angle (90 degrees offset)
const perpendicularAngle = angle + Math.PI / 2;
// Calculate door length for vertical and arc
const length = calculateDistance(start.x, start.y, end.x, end.y);
// Calculate vertical line end point
const verticalEndX = end.x + Math.cos(perpendicularAngle) * length;
const verticalEndY = end.y + Math.sin(perpendicularAngle) * length;
return { verticalEndX, verticalEndY, length, perpendicularAngle };
}
// Redraw the canvas including all doors and grid
function redrawCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear the entire canvas
// Draw the grid on the canvas
for (let x = 0; x < canvas.width; x += gridSize) {
for (let y = 0; y < canvas.height; y += gridSize) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.moveTo(0, y);
ctx.lineTo(canvas.width, y);
ctx.strokeStyle = '#ddd';
ctx.lineWidth = 0.5;
ctx.stroke();
}
}
// Draw all doors with their associated lines and arcs
doors.forEach(door => {
if (door.start && door.end) {
// Draw the main solid line for the door
ctx.beginPath();
ctx.moveTo(door.start.x, door.start.y);
ctx.lineTo(door.end.x, door.end.y);
ctx.strokeStyle = 'green';
ctx.lineWidth = 4;
ctx.stroke();
// Show the door length in the middle of the line
const midX = (door.start.x + door.end.x) / 2;
const midY = (door.start.y + door.end.y) / 2;
const length = calculateDistance(door.start.x, door.start.y, door.end.x, door.end.y).toFixed(0);
ctx.fillStyle = 'green';
ctx.font = '20px Arial';
ctx.fillText(`${length *10} mm`, midX, midY); // Display the length
// Calculate perpendicular points for vertical line and arc
const { verticalEndX, verticalEndY, length: doorLength, perpendicularAngle } = calculatePerpendicular(door);
// Draw vertical dashed line at the end of the door
drawDashedLine(door.end.x, door.end.y, verticalEndX, verticalEndY);
// Draw the quarter-circle arc at the end of the door
drawDottedArc(door.end.x, door.end.y, doorLength, perpendicularAngle, perpendicularAngle + Math.PI / 2);
}
});
//Here below following code i have implemented logic to draw a logic for doordrawing on 2D layers //How should i integrate the my code in DXFviewer // do i need to add integrate a code with DXFViwer logic?
// script.js
const canvas = document.getElementById('drawingCanvas'); const ctx = canvas.getContext('2d');
// we are setting up grid and min/max length constants const gridSize = 10; // Grid size is assigned const MIN_LENGTH = 80; // Minimum door length in pixels (equivalent to mm) const MAX_LENGTH = 120; // Maximum door length in pixels (equivalent to mm);
let isDrawing = false; // State to check if we're drawing let selectedPoint = null; // To know which point is selected for dragging let draggingLine = null; // To check if the line is being dragged let dragStartPos = null; // Starting position when dragging let currentDoor = null; // Storing the current door being drawn let doors = []; // Array to store all doors
// This function will resizes the canvas whenever the window is resized function resizeCanvas() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }
// Here we are adding event listener to resize the canvas whenever the window is resized window.addEventListener('resize', resizeCanvas); resizeCanvas(); // Initializing the canvas size on load
// This function will snaps the mouse pointer to the nearest grid point for precision function snapToGrid(x, y) { return { x: Math.round(x / gridSize) gridSize, y: Math.round(y / gridSize) gridSize }; }
// This function to calculate the distance between two points (for line length calculation) function calculateDistance(x1, y1, x2, y2) { return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); }
//This will be having history of door states (can be used for undo functionality) function saveHistory() { // If needed, we can implement undo functionality by saving history }
// When mouse is pressed, this function starts the door drawing process function handleMouseDown(e) { const pos = snapToGrid(e.offsetX, e.offsetY); // Snap mouse position to grid
}
// Handle mouse movement while drawing or dragging a door function handleMouseMove(e) { const pos = snapToGrid(e.offsetX, e.offsetY); // Snap position to grid for precision
}
// Once the mouse is released, finalize the door drawing or dragging process function handleMouseUp() { if (isDrawing) { isDrawing = false; // Stop the drawing process if (!currentDoor.end || calculateDistance(currentDoor.start.x, currentDoor.start.y, currentDoor.end.x, currentDoor.end.y) < 10) { doors.pop(); // Remove the door if it's too short } currentDoor = null; // Clear current door saveHistory(); // Save the state for potential undo functionality }
}
// Draw a dashed line (used for the vertical dashed line) function drawDashedLine(x1, y1, x2, y2) { ctx.setLineDash([5, 5]); // Define dash pattern ctx.beginPath(); // Start the line drawing ctx.moveTo(x1, y1); // Move to start point ctx.lineTo(x2, y2); // Draw line to end point ctx.stroke(); // Render the line ctx.setLineDash([]); // Reset line style to solid }
// Draw the quarter-circle arc for the door function drawDottedArc(cx, cy, radius, startAngle, endAngle) { ctx.setLineDash([5, 5]); // Create dashed arc pattern ctx.beginPath(); ctx.arc(cx, cy, radius, startAngle, endAngle); // Draw arc ctx.stroke(); // Render arc ctx.setLineDash([]); // Reset line style to solid }
// Function to calculate perpendicular points for vertical line and arc function calculatePerpendicular(door) { const { start, end } = door;
}
// Redraw the canvas including all doors and grid function redrawCanvas() { ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear the entire canvas
}
// Add event listeners for mouse actions canvas.addEventListener('mousedown', handleMouseDown); canvas.addEventListener('mousemove', handleMouseMove); canvas.addEventListener('mouseup', handleMouseUp);
// Initial drawing of the canvas and grid redrawCanvas();
// At the bottom of DoorDrawingLogic.js, make sure you export it:
export { resizeCanvas, snapToGrid, calculateDistance, saveHistory, handleMouseDown, handleMouseMove, handleMouseUp, drawDashedLine, drawDottedArc, calculatePerpendicular, redrawCanvas };