Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trying to implement my own logic on Gemini-viewer. But not working #142

Open
janardhanan305 opened this issue Oct 3, 2024 · 1 comment

Comments

@janardhanan305
Copy link

//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

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);
    }
});

}

// 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
};

@yanzexuan1
Copy link
Collaborator

You want to draw doors with canvas, It should not affected by gemini-viewer. I didn't try the code, what do you mean by not working?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants