如何修复makePoints函数以在WebGL中生成正弦波坐标点
makePoints Function for Arbitrary Direction Sine Waves Hey John, let's sort out this sine wave issue! Drawing a sine wave that follows any start-to-end direction is totally doable—let's break down what's likely going wrong with your makePoints function and fix it with a solid, tested implementation.
Common Pitfalls in Your Original Code (Likely Culprits)
Before jumping into the fix, here are the most common mistakes that cause wonky-looking points:
- Not normalizing the direction vector between start and end, leading to stretched/squashed waves
- Calculating the perpendicular direction incorrectly (so the wave doesn't sit perpendicular to your path)
- Not tying the sine wave's frequency to the length of your path (resulting in too many/few oscillations)
- Forgetting to map the sine offset to the path's coordinate system (so points are way off the line)
Fixed makePoints Implementation
Here's a robust version that handles arbitrary start/end directions, with explanations for each step:
function makePoints(start, end, amplitude, frequency) { // 1. Calculate core vectors for the path const dirX = end.x - start.x; const dirY = end.y - start.y; const pathLength = Math.sqrt(dirX * dirX + dirY * dirY); // 2. Normalize direction to a unit vector (so movement is consistent regardless of path length) const unitDirX = dirX / pathLength; const unitDirY = dirY / pathLength; // 3. Get perpendicular vector (this is where the sine wave will "wave" from the path) // Flip signs here (-unitDirY, unitDirX) for clockwise wave; use (unitDirY, -unitDirX) for counter-clockwise const perpX = -unitDirY; const perpY = unitDirX; const points = []; // 4. Determine number of points (more points = smoother wave; tied to path length + frequency) const totalPoints = Math.floor(pathLength * frequency) + 1; // 5. Generate each point along the wave for (let i = 0; i <= totalPoints; i++) { // Progress along the path from 0 (start) to 1 (end) const progress = i / totalPoints; // Base position along the straight line from start to end const baseX = start.x + dirX * progress; const baseY = start.y + dirY * progress; // Calculate sine offset: oscillates between -amplitude and amplitude const sineOffset = Math.sin(progress * Math.PI * 2 * frequency) * amplitude; // Add the offset to the base position using the perpendicular vector const finalX = baseX + perpX * sineOffset; const finalY = baseY + perpY * sineOffset; points.push({ x: finalX, y: finalY }); } return points; }
How to Use This Function
Call it with your start/end coordinates, desired wave height (amplitude), and how many full oscillations you want (frequency):
// Example: Wave from (50,50) to (300, 200), amplitude 20, 3 full waves const wavePoints = makePoints( { x: 50, y: 50 }, { x: 300, y: 200 }, 20, 3 );
Key Fixes Explained
- Normalized Direction: Ensures the wave's speed and spacing stay consistent no matter how long or angled your path is.
- Perpendicular Vector: Guarantees the wave sits perfectly perpendicular to your start-to-end line—flip the signs if you want the wave to curve the opposite way.
- Progress-Based Sine Calculation: Ties the sine wave's oscillations directly to how far along the path we are, so you get exactly the number of waves you specify with the
frequencyparameter. - Smooth Point Count: Generates enough points to make the wave look smooth without wasting unnecessary computation.
If you were seeing specific weird behavior (like points clustered or waves going the wrong way), let me know and we can tweak this further—but this should handle most arbitrary direction sine wave cases!
内容的提问来源于stack exchange,提问作者John Abraham

