getEnergyLevelColor: function() { var groundStateEnergy = this.model.getGroundState().getEnergyLevel(); var energy = this.model.getCurrentState().getEnergyLevel(); if (energy === groundStateEnergy) return '#000'; var deltaEnergy = energy - groundStateEnergy; var hex = WavelengthColors.nmToHex(PhysicsUtil.energyToWavelength(deltaEnergy)); return Colors.parseHex(hex); },
drawSquiggle: function(graphics, beam) { // Calculate all our rendering variables var wavelength = beam.get('wavelength') var color = Colors.parseHex(WavelengthColors.nmToHex(wavelength)); var beamEnergy = PhysicsUtil.wavelengthToEnergy(wavelength); var groundStateEnergy = this.simulation.getGroundState().getEnergyLevel(); var y0 = this.energyToY(groundStateEnergy); var y1 = this.energyToY(groundStateEnergy + beamEnergy); var length = y0 - y1; var amp = this.squiggleAmplitude; var intensity = beam.get('photonsPerSecond') / beam.get('maxPhotonsPerSecond'); var alpha = Math.sqrt(intensity); var arrowHeight = amp; // So that the tip of the arrow will just touch an energy level line when it is supposed to // match the line, we need to subtract 1 from the length of the squiggle var actualLength = length - 1; graphics.clear(); graphics.lineStyle(1, color, alpha); // Draw squiggle var phaseAngle = 0; var freqFactor = 15 * wavelength / 680; for (var i = 0; i <= actualLength - arrowHeight * 2; i++) { var k = Math.floor(Math.sin(phaseAngle + i * Math.PI * 2 / freqFactor) * amp / 2 + amp / 2); for (var j = 0; j < amp; j++) { if (j === k) { if (i === 0) graphics.moveTo(i + arrowHeight, k); else graphics.lineTo(i + arrowHeight, k); } } } // Draw arrows graphics.lineStyle(0, 0, 0); graphics.beginFill(color, alpha); var tailWidth = 2; var headWidth = amp * 1.2; graphics.drawArrow(arrowHeight, amp / 2, 0, amp / 2, tailWidth, headWidth, arrowHeight); graphics.drawArrow(actualLength - arrowHeight, amp / 2, actualLength, amp / 2, tailWidth, headWidth, arrowHeight); graphics.endFill(); },
getColor: function() { var deltaEnergy = this.middleState.getEnergyLevel() - this.groundState.getEnergyLevel(); var hex = WavelengthColors.nmToHex(PhysicsUtil.energyToWavelength(deltaEnergy)); return hex; },
drawSquiggle: function(ctx, x1, y1, x2, y2, wavelength) { // Distance between the 2 points var distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); var phi = Math.atan2(y2 - y1, x2 - x1); var period = this.wavelengthToPeriod(wavelength); // Save the context's state before transforming ctx.save(); // And transform so we can paint as though the squiggle is starting // on the origin and going to the right. ctx.translate(x1, y1); ctx.rotate(phi); // Color that corresponds to the wavelength var color; if (wavelength < WavelengthColors.MIN_WAVELENGTH) color = Constants.UV_COLOR; else if (wavelength > WavelengthColors.MAX_WAVELENGTH) color = Constants.IR_COLOR; else color = WavelengthColors.nmToHex(wavelength); /* * The arrow head is drawn only if the distance between the points is * large enough to fit both the arrow head and a minimum amount of squiggle. * If the distance isn't sufficient, then our squiggle will have no arrow head. */ var hasArrow = (distance > this.squiggleArrowHeadHeight + this.minSquiggleLength); if (hasArrow) { ctx.beginPath(); ctx.moveTo(distance, 0); ctx.lineTo(distance - this.squiggleArrowHeadHeight, this.squiggleArrowHeadWidth / 2); ctx.lineTo(distance - this.squiggleArrowHeadHeight, -this.squiggleArrowHeadWidth / 2); ctx.closePath(); ctx.fillStyle = color; ctx.fill(); } /* * The squiggle is a sinusoidal line, with period and amplitude. * If the 2 points are too close together, the sinusoidal nature of * the line won't be intelligible, so we simply draw a straight line. */ ctx.beginPath(); if (distance >= this.minSquiggleLength) { ctx.moveTo(0, 0); var maxX = (hasArrow) ? (distance - this.squiggleArrowHeadHeight) : distance; for (var x = 0; x < maxX; x++) { var angle = (x % period) * (2 * Math.PI / period); var y = this.squiggleAmplitude * Math.sin(angle); ctx.lineTo(x, y); } } else { // Use a straight line if the points are too close together ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); } ctx.lineWidth = this.squiggleLineWidth; ctx.strokeStyle = color; ctx.stroke(); // Reset the context's transform ctx.restore(); },
getColorFromWavelength: function(wavelength) { var key = '' + wavelength; if (this.colors[key] === undefined) this.colors[key] = Colors.parseHex(WavelengthColors.nmToHex(wavelength)); return this.colors[key]; },