Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/dorrington/ray-optics int…
Browse files Browse the repository at this point in the history
…o dorrington-master
  • Loading branch information
ricktu288 committed Jun 3, 2023
2 parents 28afef4 + 6502cce commit 175f651
Show file tree
Hide file tree
Showing 12 changed files with 535 additions and 33 deletions.
105 changes: 88 additions & 17 deletions simulator/js/objs/parallel.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
// Beam
objTypes['parallel'] = {

tmp_randomNumbers: [],

//建立物件 Create the obj
create: function(mouse) {
return {type: 'parallel', p1: mouse, p2: mouse, p: 0.5};
return {type: 'parallel', p1: mouse, p2: mouse, p: 0.5, divergence: 0.0, lambert: false, random: false};
},

p_box: objTypes['laser'].p_box,
//顯示屬性方塊 Show the property box
p_box: function(obj, elem) {
createNumberAttr(getMsg('brightness'), 0, 1, 0.01, obj.p || 1, function(obj, value) {
obj.p = value;
}, elem);
if (colorMode) {
createNumberAttr(getMsg('wavelength'), UV_WAVELENGTH, INFRARED_WAVELENGTH, 1, obj.wavelength || GREEN_WAVELENGTH, function(obj, value) {
obj.wavelength = value;
}, elem);
}
createNumberAttr(getMsg('emissionangle'), 0, 180, 1, obj.divergence, function(obj, value) {
obj.divergence = value;
}, elem);
createBooleanAttr(getMsg('lambertian'), obj.lambert, function(obj, value) {
obj.lambert = value;
}, elem);
createBooleanAttr(getMsg('random'), obj.random, function(obj, value) {
obj.random = value;
}, elem);
},

//使用lineobj原型 Use the prototype lineobj
c_mousedown: objTypes['lineobj'].c_mousedown,
Expand Down Expand Up @@ -39,31 +60,81 @@ objTypes['parallel'] = {
ctx.lineCap = 'butt';
},

initRandom: function (obj) {
if (obj.tmp_randomNumbers == undefined || !obj.random){
this.clearRandom(obj);
}
},

clearRandom: function (obj) {
obj.tmp_randomNumbers = [];
},

getRandom: function (obj, i) {
for(j=obj.tmp_randomNumbers.length; j<=i; j++) {
obj.tmp_randomNumbers.push(Math.random());
}
return obj.tmp_randomNumbers[i];
},

newRay: function(obj, x, y, normal, angle, gap, brightness_factor=1.0) {
var ray1 = graphs.ray(graphs.point(x, y), graphs.point(x + Math.sin(normal+angle), y + Math.cos(normal+angle)));
ray1.brightness_s = Math.min(obj.p / getRayDensity() * brightness_factor, 1) * 0.5;
ray1.brightness_p = Math.min(obj.p / getRayDensity() * brightness_factor, 1) * 0.5;
if (obj.lambert) {
lambert = Math.cos(angle)
ray1.brightness_s *= lambert;
ray1.brightness_p *= lambert;
}
ray1.isNew = true;
if (colorMode) {
ray1.wavelength = obj.wavelength || GREEN_WAVELENGTH;
}
ray1.gap = gap;
addRay(ray1);
},

//射出光線 Shoot rays
shoot: function(obj) {
var n = graphs.length_segment(obj) * getRayDensity();
var stepX = (obj.p2.x - obj.p1.x) / n;
var stepY = (obj.p2.y - obj.p1.y) / n;
var rayp2_x = obj.p1.x + obj.p2.y - obj.p1.y;
var rayp2_y = obj.p1.y - obj.p2.x + obj.p1.x;
var s = Math.PI * 2 / parseInt(getRayDensity() * 500);
var sizeX = (obj.p2.x - obj.p1.x);
var sizeY = (obj.p2.y - obj.p1.y);
var normal = Math.atan2(stepX, stepY) + Math.PI / 2.0;
var halfAngle = obj.divergence / 180.0 * Math.PI * 0.5;
var numnAngledRays = 1.0 + Math.floor(halfAngle/s) * 2.0;
var rayBrightness = 1.0 / numnAngledRays;
this.initRandom(obj);


for (var i = 0.5; i <= n; i++)
{
var ray1 = graphs.ray(graphs.point(obj.p1.x + i * stepX, obj.p1.y + i * stepY), graphs.point(rayp2_x + i * stepX, rayp2_y + i * stepY));
ray1.brightness_s = Math.min(obj.p / getRayDensity(), 1) * 0.5;
ray1.brightness_p = Math.min(obj.p / getRayDensity(), 1) * 0.5;
ray1.isNew = true;
if (colorMode) {
ray1.wavelength = obj.wavelength || GREEN_WAVELENGTH;
}
if (i == 0)
if (!obj.random) {
for (var i = 0.5; i <= n; i++)
{
ray1.gap = true;
var x = obj.p1.x + i * stepX;
var y = obj.p1.y + i * stepY;
this.newRay(obj, x, y, normal, 0.0, i==0, rayBrightness);
for (var angle = s; angle < halfAngle; angle += s)
{
this.newRay(obj, x, y, normal, angle, i==0, rayBrightness);
this.newRay(obj, x, y, normal, -angle, i==0, rayBrightness);
}
}
} else {
for (var i = 0; i < n*numnAngledRays; i++){
position = this.getRandom(obj, i*2);
angle = this.getRandom(obj, i*2+1);
this.newRay(
obj,
obj.p1.x + position * sizeX,
obj.p1.y + position * sizeY,
normal,
(angle*2-1) * halfAngle,
i==0,
rayBrightness);
}
addRay(ray1);
}

}

};
114 changes: 102 additions & 12 deletions simulator/js/objs/text.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,69 @@
// Text
// Originally contributed by Paul Falstad (pfalstad)

// generic list of web safe fonts
fonts = [
'Serif',
'Arial',
'Helvetica',
'Times New Roman',
'Georgia',
'Courier New',
'Verdana',
'Tahoma',
'Trebuchet MS',
'Impact',
'Lucida Sans'
];

fontStyles = [
'Normal',
'Bold',
'Italic',
'Bold Italic',
'Oblique',
'Bold Oblique'
]

fontAlignmants = {
'left': "Left",
'center': "Centre",
'right': "Right"
}

objTypes['text'] = {

//建立物件 Create the obj
create: function(mouse) {
return {type: 'text', x: mouse.x, y: mouse.y, p: 'text here'};
return {type: 'text', x: mouse.x, y: mouse.y, p: 'text here', fontSize: 24, fontName: 'Serif', fontStyle: 'Normal', fontAlignmant: 'Left', fontSmallCaps: false, fontAngle: 0};
},

//顯示屬性方塊 Show the property box
p_box: function(obj, elem) {
createStringAttr('', obj.p, function(obj, value) {
// createStringAttr('', obj.p, function(obj, value) {
// obj.p = value;
// }, elem);
createTextAttr('', obj.p, function(obj, value) {
obj.p = value;
}, elem);
createNumberAttr(getMsg('fontsize'), 6, 96, 1, obj.fontSize, function(obj, value) {
obj.fontSize = value;
}, elem);
createDropdownAttr(getMsg('fontname'), obj.fontName, fonts, function(obj, value) {
obj.fontName = value;
}, elem);
createDropdownAttr(getMsg('fontstyle'), obj.fontStyle, fontStyles, function(obj, value) {
obj.fontStyle = value;
}, elem);
createDropdownAttr(getMsg('fontalignment'), obj.fontAlignmant, fontAlignmants, function(obj, value) {
obj.fontAlignmant = value;
}, elem);
createBooleanAttr(getMsg('smallcaps'), obj.fontSmallCaps, function(obj, value) {
obj.fontSmallCaps = value;
}, elem);
createNumberAttr(getMsg('angle'), 0, 360, 1, obj.fontAngle, function(obj, value) {
obj.fontAngle = value;
}, elem);
},

//建立物件過程滑鼠按下 Mousedown when the obj is being constructed by the user
Expand All @@ -36,12 +88,37 @@ objTypes['text'] = {

//將物件畫到Canvas上 Draw the obj on canvas
draw: function(obj, canvas) {
ctx.fillStyle = getMouseStyle(obj, 'white');
ctx.textAlign = 'left';
ctx.textBaseline = 'bottom';
ctx.font = '24px serif';
ctx.fillText(obj.p, obj.x, obj.y);
obj.tmp_width = ctx.measureText(obj.p).width;
ctx.fillStyle = getMouseStyle(obj, 'white');
ctx.textAlign = obj.fontAlignmant;
ctx.textBaseline = 'bottom';

fontName = '';
if (obj.fontStyle != 'Normal') fontName += obj.fontStyle + ' ';
if (obj.fontSmallCaps) fontName += 'small-caps '
fontName += obj.fontSize + 'px ' + obj.fontName;
ctx.font = fontName;

ctx.save();
ctx.translate(obj.x, obj.y);
ctx.rotate(-obj.fontAngle/180*Math.PI);
y_offset = 0;
obj.tmp_left = 0;
obj.tmp_right = 0;
obj.tmp_up = 0;
obj.tmp_down = 0;
obj.p.split('\n').forEach(line => {
ctx.fillText(line, 0, y_offset);
lineDimensions = ctx.measureText(line);
obj.tmp_left = Math.max(obj.tmp_left, lineDimensions.actualBoundingBoxLeft);
obj.tmp_right = Math.max(obj.tmp_right, lineDimensions.actualBoundingBoxRight);
obj.tmp_up = Math.max(obj.tmp_up, lineDimensions.actualBoundingBoxAscent - y_offset);
obj.tmp_down = Math.max(obj.tmp_down, -lineDimensions.actualBoundingBoxDescent + y_offset);
y_offset += lineDimensions.fontBoundingBoxAscent + lineDimensions.fontBoundingBoxDescent;
});
ctx.restore();
// precompute triganometry for faster calculations in 'clicked' function
obj.tmp_sin_angle = Math.sin(obj.fontAngle/180*Math.PI);
obj.tmp_cos_angle = Math.cos(obj.fontAngle/180*Math.PI);
},

//平移物件 Move the object
Expand All @@ -54,10 +131,16 @@ objTypes['text'] = {
//繪圖區被按下時(判斷物件被按下的部分) When the drawing area is clicked (test which part of the obj is clicked)
clicked: function(obj, mouse_nogrid, mouse, draggingPart) {

if (mouse_nogrid.x >= obj.x && mouse_nogrid.x <= obj.x+obj.tmp_width &&
mouse_nogrid.y <= obj.y && mouse_nogrid.y >= obj.y-24) {
// translate and rotate the mouse point into the text's reference frame for easy comparison
relativeMouseX = mouse_nogrid.x - obj.x
relativeMouseY = mouse_nogrid.y - obj.y
rotatedMouseX = relativeMouseX * obj.tmp_cos_angle - relativeMouseY * obj.tmp_sin_angle;
rotatedMouseY = relativeMouseY * obj.tmp_cos_angle + relativeMouseX * obj.tmp_sin_angle;
if (rotatedMouseX >= -obj.tmp_left && rotatedMouseX <= obj.tmp_right &&
rotatedMouseY <= obj.tmp_down && rotatedMouseY >= -obj.tmp_up) {
draggingPart.part = 0;
draggingPart.mouse0 = graphs.point(mouse_nogrid.x, mouse_nogrid.y);
draggingPart.mouse0snapped = document.getElementById('grid').checked ? graphs.point(Math.round(draggingPart.mouse0.x / gridSize) * gridSize, Math.round(draggingPart.mouse0.y / gridSize) * gridSize) : draggingPart.mouse0;
draggingPart.targetPoint_ = graphs.point(obj.x, obj.y); // Avoid setting 'targetPoint' (otherwise the xybox will appear and move the text to incorrect coordinates).
draggingPart.snapData = {};
return true;
Expand All @@ -77,8 +160,15 @@ objTypes['text'] = {
draggingPart.snapData = {}; //放開shift時解除原先之拖曳方向鎖定 Unlock the dragging direction when the user release the shift key
}

obj.x = mouse_snapped.x + draggingPart.targetPoint_.x - draggingPart.mouse0.x;
obj.y = mouse_snapped.y + draggingPart.targetPoint_.y - draggingPart.mouse0.y;
// 'mouse' current mouse position, snapped to grid
// 'draggingPart.targetPoint_' object placement position (bottom left)
// 'draggingPart.mouse0' is coordiates of where the drag started, not snapped
// 'draggingPart.mouse0snapped' is coordiates of where the drag started, snapped to grid
// 'mouse_snapped' is restriced to horzontal or vertical when shift held, snapped to grid

// new location = current location (snapped) + object placement location - where drag started (snapped)
obj.x = mouse_snapped.x + draggingPart.targetPoint_.x - draggingPart.mouse0snapped.x;
obj.y = mouse_snapped.y + draggingPart.targetPoint_.y - draggingPart.mouse0snapped.y;
},

};
61 changes: 61 additions & 0 deletions simulator/js/parameterBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,37 @@ function createStringAttr(label, value, func, elem) {
};
}

function createTextAttr(label, value, func, elem) {
var p_name = document.createElement('span');
p_name.innerHTML = '&nbsp;' + label + '&nbsp;';
elem.appendChild(p_name);
var objAttr_text = document.createElement('textarea');
objAttr_text.value = value;
objAttr_text.cols = 25;
objAttr_text.rows = 1;
elem.appendChild(objAttr_text);
objAttr_text.oninput = function()
{
// if user starts adding more than one line, auto expand the text area
if (objAttr_text.value.split('\n').length > 1 && objAttr_text.rows==1) {
objAttr_text.rows = 3;
}
setAttr(function(obj) {
func(obj, objAttr_text.value);
});
};
cancelMousedownEvent_(objAttr_text);
objAttr_text.onkeydown = function(e)
{
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
};
objAttr_text.onclick = function(e)
{
this.select();
};
}

function createBooleanAttr(label, value, func, elem) {
var label_elem = document.createElement('label');
label_elem.style.marginLeft = '0.2em';
Expand Down Expand Up @@ -146,6 +177,36 @@ function createEquationAttr(label, value, func, elem) {
}, 1);
}

function createDropdownAttr(label, value, options, func, elem) {
var p_name = document.createElement('span');
p_name.innerHTML = '&nbsp;' + label + '&nbsp;';
elem.appendChild(p_name);

isArray = Array.isArray(options);
var dropdown = document.createElement('select');
for (key in options) {
var option = document.createElement('option');
option.value = isArray ? options[key] : key;
option.textContent = options[key];
if (option.value == value) option.selected = true;
dropdown.appendChild(option);
}

elem.appendChild(dropdown);
dropdown.onchange = function()
{
setAttr(function(obj) {
func(obj, dropdown.value);
});
createUndoPoint();
};
cancelMousedownEvent_(dropdown);
dropdown.onclick = function(e)
{
this.select();
};
}

function hasSameAttrType(obj1, obj2)
{
return obj1.type==obj2.type;
Expand Down
32 changes: 32 additions & 0 deletions simulator/locales/de.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,38 @@ locales["de"] = {
"refractiveindex": {
"message": "Brechungsindex:"
},
"random": {
"incomplete": true,
"message": "Random emission"
},
"lambertian": {
"incomplete": true,
"message": "Lambertian emission"
},
"fontsize": {
"incomplete": true,
"message": "Font Size (px)"
},
"fontname": {
"incomplete": true,
"message": "Font"
},
"fontstyle": {
"incomplete": true,
"message": "Style"
},
"fontalignment": {
"incomplete": true,
"message": "Alignment"
},
"smallcaps": {
"incomplete": true,
"message": "Small Caps"
},
"angle": {
"incomplete": true,
"message": "Angle (°)"
},
"refractiveindex_note": {
"message": "(relativ, wenn Glaskörper überlappen)"
},
Expand Down
Loading

0 comments on commit 175f651

Please sign in to comment.