Skip to content

Commit

Permalink
Merge branch 'gljames24-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
ricktu288 committed Apr 7, 2024
2 parents 76b103e + 308faf2 commit d65fd6d
Show file tree
Hide file tree
Showing 21 changed files with 541 additions and 5 deletions.
1 change: 1 addition & 0 deletions about.html
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ <h3><img src="icon128.png" alt="Icon" width="64" height="64"><br>
<li>Wei-Fang Sun (code, UI design)</li>
<li>Paul Falstad (code, gallery)</li>
<li>James Garrard (code, gallery)</li>
<li>digitalgreenery (code)</li>
<li>Scott Cheng (code)</li>
<li>Lo-Chen Cheng (de translations)</li>
<li>sadajun916 (ja translations)</li>
Expand Down
1 change: 1 addition & 0 deletions img/diffractiongrating.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions simulator/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,11 @@
<input type="radio" class="btn-check" name="toolsradio" autocomplete="off" id="tool_aperture">
<label class="btn shadow-none btn-primary dropdown-item" for="tool_aperture" data-text="tool_aperture" data-popover="tool_aperture_popover" data-image="aperture.svg" data-bs-placement="right" data-bs-offset="40,0"></label>
</li>
<li><hr class="dropdown-divider"></li>
<li>
<input type="radio" class="btn-check" name="toolsradio" autocomplete="off" id="tool_diffractiongrating">
<label class="btn shadow-none btn-primary dropdown-item" for="tool_diffractiongrating" data-text="tool_diffractiongrating" data-popover="tool_diffractiongrating_popover" data-image="diffractiongrating.svg" data-bs-placement="right" data-bs-offset="40,0"></label>
</li>
</ul>
</div>
<div class="dropdown">
Expand Down Expand Up @@ -712,6 +717,11 @@
<input type="radio" class="btn-check" name="toolsradio_mobile" autocomplete="off" id="tool_aperture_mobile">
<label class="btn btn-primary dropdown-item" for="tool_aperture_mobile" data-text="tool_aperture"></label>
</li>
<li><hr class="dropdown-divider"></li>
<li>
<input type="radio" class="btn-check" name="toolsradio_mobile" autocomplete="off" id="tool_diffractiongrating_mobile">
<label class="btn btn-primary dropdown-item" for="tool_diffractiongrating_mobile" data-text="tool_diffractiongrating"></label>
</li>
</ul>

<ul id="mobile-dropdown-more" style="display:none">
Expand Down Expand Up @@ -1272,6 +1282,7 @@ <h5 class="modal-title" id="staticBackdropLabel" data-text="language"></h5>
<script src="js/objs/blackline.js"></script>
<script src="js/objs/blackcircle.js"></script>
<script src="js/objs/aperture.js"></script>
<script src="js/objs/diffractiongrating.js"></script>
<script src="js/objs/ruler.js"></script>
<script src="js/objs/protractor.js"></script>
<script src="js/objs/power.js"></script>
Expand Down
1 change: 1 addition & 0 deletions simulator/js/objs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
| Blocker -> Line Blocker | `blackline` |
| Blocker -> Circle Blocker | `blackcircle` |
| Blocker -> Aperture | `aperture` |
| Blocker -> Diffraction Grating | `diffractiongrating` |
| Other -> Ruler | `ruler` |
| Other -> Protractor | `protractor` |
| Other -> Detector | `power` |
Expand Down
2 changes: 1 addition & 1 deletion simulator/js/objs/beamsplitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ objTypes['beamsplitter'] = {

// Create the obj
create: function(mouse) {
return {type: 'beamsplitter', p1: mouse, p2: mouse, p: .5, isDichroic: false, isDichroicFilter: false};
return {type: 'beamsplitter', p1: mouse, p2: mouse, p: .5};
},

dichroicSettings: objTypes['mirror'].dichroicSettings,
Expand Down
2 changes: 1 addition & 1 deletion simulator/js/objs/blackline.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ objTypes['blackline'] = {
dichroicSettings(obj,elem);
},

//Describes how the ray
//Describes how the ray hits the object
rayIntersection: function(blackline, ray) {
if (wavelengthInteraction(blackline,ray)) {
return objTypes['lineobj'].rayIntersection(blackline, ray);
Expand Down
131 changes: 131 additions & 0 deletions simulator/js/objs/diffractiongrating.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Blocker -> Diffraction Grating
objTypes['diffractiongrating'] = {

// Create the obj
create: function(mouse) {
return {type: 'diffractiongrating', p1: mouse, p2: mouse, line_density: 1000, slit_ratio: 0.5, mirrored: false};
},

// Use the prototype lineobj
c_mousedown: objTypes['lineobj'].c_mousedown,
c_mousemove: objTypes['lineobj'].c_mousemove,
c_mouseup: objTypes['lineobj'].c_mouseup,
move: objTypes['lineobj'].move,
clicked: objTypes['lineobj'].clicked,
dragging: objTypes['lineobj'].dragging,

// Draw the obj on canvas
draw: function(obj, ctx, aboveLight) {
if (obj.mirrored) {
ctx.strokeStyle = getMouseStyle(obj, 'rgb(168,168,168)');
ctx.beginPath();
ctx.moveTo(obj.p1.x, obj.p1.y);
ctx.lineTo(obj.p2.x, obj.p2.y);
ctx.stroke();
}
ctx.strokeStyle = getMouseStyle(obj, 'rgb(124,62,18)');
ctx.lineWidth = 2;
ctx.lineCap = 'butt';
ctx.beginPath();
ctx.setLineDash([4*(1-obj.slit_ratio),4*obj.slit_ratio]);
ctx.moveTo(obj.p1.x, obj.p1.y);
ctx.lineTo(obj.p2.x, obj.p2.y);
ctx.stroke();
ctx.setLineDash([]);
ctx.lineWidth = 1;
},

// Show the property box
p_box: function(obj, elem) {
createNumberAttr(getMsg('lines/mm'), 1, 2500, 5, obj.line_density, function(obj, value) {
obj.line_density = value;
}, elem);

if (createAdvancedOptions(obj.slit_ratio != 0.5 || obj.mirrored)) {
createNumberAttr(getMsg('slit_ratio'), 0, 1, 0.001, obj.slit_ratio, function(obj, value) {
obj.slit_ratio = value;
}, elem);
createBooleanAttr(getMsg('mirrored'), obj.mirrored, function(obj, value) {
obj.mirrored = value;
}, elem);
}

if (mode == 'images' || mode == 'observer') {
var note = document.createElement('span');
note.innerHTML = getMsg('image_detection_warning');
note.id = "image_detection_warning";
note.style.marginLeft = "0.2em";
note.style.marginRight = "0.2em";
note.style.color = "white";
elem.appendChild(note);
}

if (!colorMode) {
var note = document.createElement('span');
note.innerHTML = getMsg('non_color_mode_warning');
note.id = "non_color_mode_warning";
note.style.marginLeft = "0.2em";
note.style.marginRight = "0.2em";
note.style.color = "white";
elem.appendChild(note);
}
},

//Describes how the ray intersects the grating
rayIntersection: function(obj, ray) {
return objTypes['lineobj'].rayIntersection(obj, ray);
},

// When the obj is shot by a ray
shot: function(diffractiongrating, ray, rayIndex, rp) {
const mm_in_nm = 1/1000000;
var rx = ray.p1.x - rp.x;
var ry = ray.p1.y - rp.y;
var mx = diffractiongrating.p2.x - diffractiongrating.p1.x;
var my = diffractiongrating.p2.y - diffractiongrating.p1.y;
ray.exist = false;

var wavelength = (ray.wavelength || GREEN_WAVELENGTH) * mm_in_nm;
var interval = 1/diffractiongrating.line_density;
var slit_width = interval * diffractiongrating.slit_ratio;

//Find which side the incoming ray is hitting the diffraction line segment
var crossProduct = rx * my - ry * mx;
var left_point = crossProduct > 0? diffractiongrating.p1 : diffractiongrating.p2;

//If mirrored, reflect the rays rather than pass them
var mirror = diffractiongrating.mirrored? -1 : 1;

//Find angles
var theta_left = Math.PI - Math.atan2(left_point.y - rp.y,left_point.x - rp.x);
var theta_i = Math.PI - Math.atan2(ry,rx);
var incidence_angle = Math.PI/2 - (theta_left < theta_i? theta_left + 2 * Math.PI - theta_i : theta_left - theta_i);

var m_min = -Math.floor(interval/wavelength*(1-Math.sin(incidence_angle)));
var m_max = -Math.ceil(interval/wavelength*(-1-Math.sin(incidence_angle)));

for (var m = m_min; m <= m_max; m++) {
var diffracted_angle = Math.asin(Math.sin(incidence_angle) - m * wavelength / interval);

var rot_c = Math.cos(mirror * (-Math.PI/2 - diffracted_angle));
var rot_s = Math.sin(mirror * (-Math.PI/2 - diffracted_angle));
var diffracted_ray = graphs.ray(rp, graphs.point(rp.x + (left_point.x-rp.x) * rot_c - (left_point.y-rp.y) * rot_s, rp.y + (left_point.x-rp.x) * rot_s + (left_point.y-rp.y) * rot_c));

var phase_diff = 2 * Math.PI * slit_width / wavelength * (Math.sin(incidence_angle) - Math.sin(diffracted_angle))
var sinc_arg = (phase_diff == 0)? 1 : Math.sin(phase_diff/2) / (phase_diff/2);
var intensity = slit_width*slit_width/(interval*interval) * Math.pow(sinc_arg, 2);

if (m==0) {
console.log(intensity)
}
diffracted_ray.wavelength = ray.wavelength;
diffracted_ray.brightness_s = ray.brightness_s * intensity;
diffracted_ray.brightness_p = ray.brightness_p * intensity;

// There is currently no good way to make image detection work here. So just set gap to true to disable image detection for the diffracted rays.
diffracted_ray.gap = true;

addRay(diffracted_ray);
}
},
};
6 changes: 3 additions & 3 deletions simulator/js/simulator.js
Original file line number Diff line number Diff line change
Expand Up @@ -690,9 +690,9 @@ function dichroicSettings(obj, elem){
//Optical filter wavelength interaction check
//Checks to see if the wavelength of the ray interacts
function wavelengthInteraction(obj, ray){
var dichroicEnabled = colorMode && obj.isDichroic && obj.wavelength;
var rayHueMatchesMirror = Math.abs(obj.wavelength - ray.wavelength) <= (obj.bandwidth || 0);
return !dichroicEnabled || (rayHueMatchesMirror != obj.isDichroicFilter);
var dichroicEnabled = colorMode && obj.isDichroic && obj.wavelength;
var rayHueMatchesMirror = Math.abs(obj.wavelength - ray.wavelength) <= (obj.bandwidth || 0);
return !dichroicEnabled || (rayHueMatchesMirror != obj.isDichroicFilter);
}


Expand Down
32 changes: 32 additions & 0 deletions simulator/locales/de.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ locales["de"] = {
"toolname_blackcircle": {
"message": "Kreisförmiger Absorber"
},
"toolname_diffractiongrating": {
"incomplete": true,
"message": "Diffraction Grating<sup>Beta</sup>"
},
"toolname_ruler": {
"message": "Lineal"
},
Expand Down Expand Up @@ -248,6 +252,10 @@ locales["de"] = {
"tool_blackcircle": {
"message": "Kreisförmiger Absorber"
},
"tool_diffractiongrating": {
"incomplete": true,
"message": "Diffraction Grating<sup>Beta</sup>"
},
"tool_ruler": {
"message": "Lineal"
},
Expand Down Expand Up @@ -375,6 +383,18 @@ locales["de"] = {
"emissionangle": {
"message": "Emissionswinkel (°)"
},
"mirrored": {
"incomplete": true,
"message": "Mirrored"
},
"lines/mm": {
"incomplete": true,
"message": "Lines/mm"
},
"slit_ratio": {
"incomplete": true,
"message": "Slit width / line spacing"
},
"symmetric": {
"message": "symmetrisch"
},
Expand Down Expand Up @@ -543,6 +563,14 @@ locales["de"] = {
"incomplete": true,
"message": "⚠️ Image detection may not work with divergent/random beams."
},
"image_detection_warning": {
"incomplete": true,
"message": "⚠️ This tool does not support image detection."
},
"non_color_mode_warning": {
"incomplete": true,
"message": "⚠️ This tool only works when \"Simulate Color\" is on."
},
"brightness_note_popover": {
"incomplete": true,
"message": "<p>Only effective if 'Ray Density' is high enough.</p><p>To control the numbers of rays emitted, please adjust the global 'Ray Density' slider instead.</p>"
Expand Down Expand Up @@ -704,6 +732,10 @@ locales["de"] = {
"tool_blackcircle_popover": {
"message": "Ein kreisförmiger Absorber. (Ziehen oder Klicken zum Erzeugen.)"
},
"tool_diffractiongrating_popover": {
"incomplete": true,
"message": "A diffraction grating that splits light at an angle depending on wavelength. Warning: The intensities of diffracted rays may not be accurate. (Drag or click to create.)"
},
"tool_ruler_popover": {
"message": "Ein Lineal von einem Nullpunkt bis zu einem anderen Punkt. Die Skala ist in Pixeln angegeben. (Ziehen oder Klicken zum Erzeugen.)"
},
Expand Down
24 changes: 24 additions & 0 deletions simulator/locales/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ locales["en"] = {
"toolname_blackcircle": {
"message": "Circle Blocker"
},
"toolname_diffractiongrating": {
"message": "Diffraction Grating<sup>Beta</sup>"
},
"toolname_ruler": {
"message": "Ruler"
},
Expand Down Expand Up @@ -237,6 +240,9 @@ locales["en"] = {
"tool_blackcircle": {
"message": "Circle Blocker"
},
"tool_diffractiongrating": {
"message": "Diffraction Grating<sup>Beta</sup>"
},
"tool_ruler": {
"message": "Ruler"
},
Expand Down Expand Up @@ -357,6 +363,15 @@ locales["en"] = {
"emissionangle": {
"message": "Emission Angle (°)"
},
"mirrored": {
"message": "Mirrored"
},
"lines/mm": {
"message": "Lines/mm"
},
"slit_ratio": {
"message": "Slit width / line spacing"
},
"symmetric": {
"message": "Symmetric"
},
Expand Down Expand Up @@ -486,6 +501,12 @@ locales["en"] = {
"beam_warning": {
"message": "⚠️ Image detection may not work with divergent/random beams."
},
"image_detection_warning": {
"message": "⚠️ This tool does not support image detection."
},
"non_color_mode_warning": {
"message": "⚠️ This tool only works when \"Simulate Color\" is on."
},
"brightness_note_popover": {
"message": "<p>Only effective if 'Ray Density' is high enough.</p><p>To control the numbers of rays emitted, please adjust the global 'Ray Density' slider instead.</p>"
},
Expand Down Expand Up @@ -636,6 +657,9 @@ locales["en"] = {
"tool_blackcircle_popover": {
"message": "A circle light blocker which absorbs the incident rays. (Drag or click to create.)"
},
"tool_diffractiongrating_popover": {
"message": "A diffraction grating that splits light at an angle depending on wavelength. Warning: The intensities of diffracted rays may not be accurate. (Drag or click to create.)"
},
"tool_ruler_popover": {
"message": "A ruler from a point for zero and another point. The scale is in pixels. (Drag or click to create.)"
},
Expand Down
Loading

0 comments on commit d65fd6d

Please sign in to comment.