Skip to content

Commit 3650398

Browse files
committed
Add custom surface tools (#123, #131, #132, #250)
1 parent d26deb1 commit 3650398

17 files changed

Lines changed: 1410 additions & 9 deletions

File tree

locales/en/main.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,24 @@
168168
"description": "A freehand drawing tool.",
169169
"instruction": "Drag to draw."
170170
},
171+
"CustomSurface": {
172+
"title": "Custom Surface",
173+
"description": "A custom line-segment surface where the angles (θ) and brightnesses (P) of the outgoing rays (when a ray is incident on it) are defined by custom equations."
174+
},
175+
"CustomArcSurface": {
176+
"title": "Custom Arc Surface",
177+
"description": "A custom surface with shape of a circular arc."
178+
},
171179
"moveView": {
172180
"title": "Move view",
173181
"description": "Drag to move the view. (Mouse right button drag has the same function.)"
174182
},
175183
"modules": {
176184
"import": "Import Modules…",
177185
"remove": "Remove module"
186+
},
187+
"moreTools": {
188+
"title": "More Tools…"
178189
}
179190
},
180191
"view": {

locales/en/simulator.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,30 @@
312312
},
313313
"CustomGlass": {
314314
"curveGenerationError": "Curve generation error: f(x) > g(x) at x = {{x}}"
315+
},
316+
"BaseCustomSurface": {
317+
"info": {
318+
"angles": "{{theta_0}} and {{theta_j}} are the angles of the incident and jth outgoing rays, respectively, in radians and relative to the normal direction.",
319+
"brightnesses": "{{P_0}} and {{P_j}} are the brightnesses of the incident and jth outgoing rays, respectively, in the same unit as the detector tool.",
320+
"previousFormulas": "A formula can refer to the result of previous formulas. If a formula gives an invalid value, that outgoing ray is ignored and its brightness is treated as 0.",
321+
"otherParams": "Other parameters of the incident rays that can be used are {{lambda}} (wavelength in nm) and {{p}} (0 for s-polarized, 1 for p-polarized). They remain the same for the outgoing rays.",
322+
"coating": "This object can act as a coating of glass objects by overlapping with their surfaces. In this case, the refraction itself also needs to be handled by the formulas of this object. The refractive indices of the material attached to the same and opposite sides of the incident ray can be referred to as {{n_0}} and {{n_1}}, respectively. If this object is inside a glass object, the values are relative to it.",
323+
"twoSides": "If you want the two sides of this surface to have different formulas, you can overlap two single-sided surfaces with opposite orientations.",
324+
"module": "To have custom parameters, complicated formulas, or a large number of outgoing rays, you can create a custom module. See Tools -> Other -> Import Modules -> Make custom modules for more information."
325+
},
326+
"twoSided": "Two-sided",
327+
"addOutgoingRay": "Add outgoing ray",
328+
"removeOutgoingRay": "Remove outgoing ray"
329+
},
330+
"CustomSurface": {
331+
"info": {
332+
"incidentPos": "The position of the incident point can be referred to as {{t}}, which interpolates linearly from -1 to 1 between the two endpoints of the line-segment."
333+
}
334+
},
335+
"CustomArcSurface": {
336+
"info": {
337+
"incidentPos": "The position of the incident point can be referred to as {{t}}, which interpolates uniformly (with respect to angle) from -1 to 1 between the two endpoints of the arc."
338+
}
315339
}
316340
},
317341
"saveModal": {
@@ -469,6 +493,9 @@
469493
"handleArrow": {
470494
"title": "Handle arrow"
471495
},
496+
"customSurface": {
497+
"title": "Custom surface style"
498+
},
472499
"import": {
473500
"title": "Import",
474501
"description": "Import theme from a scene JSON file.",

locales/zh-CN/main.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,24 @@
168168
"description": "手绘工具。",
169169
"instruction": "拖曳以绘图。"
170170
},
171+
"CustomSurface": {
172+
"title": "自定义表面",
173+
"description": "当光线入射时,出射光线的角度 (θ) 和亮度 (P) 由自定义方程决定的线段形表面。"
174+
},
175+
"CustomArcSurface": {
176+
"title": "自定义弧形表面",
177+
"description": "形状为圆弧的自定义表面。"
178+
},
171179
"moveView": {
172180
"title": "移动画面",
173181
"description": "拖曳以移动视窗。(滑鼠右键拖曳也有相同的功能。)"
174182
},
175183
"modules": {
176184
"import": "导入模块…",
177185
"remove": "移除模块"
186+
},
187+
"moreTools": {
188+
"title": "更多工具…"
178189
}
179190
},
180191
"view": {

locales/zh-CN/simulator.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,30 @@
312312
},
313313
"CustomGlass": {
314314
"curveGenerationError": "曲线生成错误:x = {{x}} 时 f(x) > g(x)"
315+
},
316+
"BaseCustomSurface": {
317+
"info": {
318+
"angles": "{{theta_0}} 和 {{theta_j}} 分别是入射光线和第 j 条出射光线的角度,以弧度为单位,相对于法线方向。",
319+
"brightnesses": "{{P_0}} 和 {{P_j}} 分别是入射光线和第 j 条出射光线的亮度,单位与探测器工具相同。",
320+
"previousFormulas": "公式可以引用先前公式的结果。如果公式给出无效值,该出射光线将被忽略,且亮度视为 0。",
321+
"otherParams": "其他可用的入射光线参数为 {{lambda}}(波长,单位为 nm)和 {{p}}(0 表示 s 偏振,1 表示 p 偏振)。出射光线将保持相同的参数。",
322+
"coating": "此物件可与透光物表面重叠来作为涂层。在这种情况下,折射本身也需要包含在此物件的公式中。公式中可用 {{n_0}} 和 {{n_1}} 来分别代表与入射光线同侧和对侧相接的材料折射率。如果此物件位于一个透光物内部,则这些值相对于该透光物。",
323+
"twoSides": "如需让表面的两侧以不同公式定义,可重叠两个方向相反的单面表面。",
324+
"module": "如需自定义参数、使用复杂的公式或定义大量出射光线,可使用自定义模块。更多信息请参见工具->其他->导入模块->创建自定义模块。"
325+
},
326+
"twoSided": "双面",
327+
"addOutgoingRay": "添加出射光线",
328+
"removeOutgoingRay": "移除出射光线"
329+
},
330+
"CustomSurface": {
331+
"info": {
332+
"incidentPos": "公式中可用 {{t}} 代表入射点的位置,在线段两端点之间从 -1 到 1 线性插值。"
333+
}
334+
},
335+
"CustomArcSurface": {
336+
"info": {
337+
"incidentPos": "公式中可用 {{t}} 代表入射点的位置,在圆弧两端点之间从 -1 到 1 均匀插值(相对于角度)。"
338+
}
315339
}
316340
},
317341
"saveModal": {
@@ -469,6 +493,9 @@
469493
"handleArrow": {
470494
"title": "控制杆箭头"
471495
},
496+
"customSurface": {
497+
"title": "自定义表面样式"
498+
},
472499
"import": {
473500
"title": "导入",
474501
"description": "从场景 JSON 文件导入主题。",

locales/zh-TW/main.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,24 @@
168168
"description": "手繪工具。",
169169
"instruction": "拖曳以繪圖。"
170170
},
171+
"CustomSurface": {
172+
"title": "自訂表面",
173+
"description": "當光線入射時,出射光線的角度 (θ) 和亮度 (P) 由自訂方程式決定的線段形表面。"
174+
},
175+
"CustomArcSurface": {
176+
"title": "自訂弧形表面",
177+
"description": "形狀為圓弧的自訂表面。"
178+
},
171179
"moveView": {
172180
"title": "移動畫面",
173181
"description": "拖曳以移動視窗。(滑鼠右鍵拖曳也有相同的功能。)"
174182
},
175183
"modules": {
176184
"import": "匯入模組…",
177185
"remove": "移除模組"
186+
},
187+
"moreTools": {
188+
"title": "更多工具…"
178189
}
179190
},
180191
"view": {

locales/zh-TW/simulator.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,30 @@
312312
},
313313
"CustomGlass": {
314314
"curveGenerationError": "曲線生成錯誤:x = {{x}} 時 f(x) > g(x)"
315+
},
316+
"BaseCustomSurface": {
317+
"info": {
318+
"angles": "{{theta_0}} 和 {{theta_j}} 分別是入射光線和第 j 條出射光線的角度,以弳度為單位,相對於法線方向。",
319+
"brightnesses": "{{P_0}} 和 {{P_j}} 分別是入射光線和第 j 條出射光線的亮度,單位與探測器工具相同。",
320+
"previousFormulas": "公式可以引用先前公式的結果。如果公式給出無效值,該出射光線將被忽略,且亮度視為 0。",
321+
"otherParams": "其他可用的入射光參數為 {{lambda}}(波長,單位為 nm)及 {{p}}(0 表示 s 偏振,1 表示 p 偏振)。出射光線將保持相同的參數。",
322+
"coating": "此物件可與透光物表面重疊來作為塗層。在這種情況下,折射本身也須包含於此物件的公式中。公式中可用 {{n_0}} 和 {{n_1}} 來分別代表與入射光的同側和對側相接的材料折射率。如果此物件位於一透光物內部,則這些值相對於該透光物。",
323+
"twoSides": "如需讓表面的兩側以不同公式定義,可重疊兩個方向相反的單面表面。",
324+
"module": "如需自訂參數、使用複雜的公式或定義大量出射光線,可使用自訂模組。更多資訊請參見工具->其他->匯入模組->建立自訂模組。"
325+
},
326+
"twoSided": "雙面",
327+
"addOutgoingRay": "新增出射光線",
328+
"removeOutgoingRay": "移除出射光線"
329+
},
330+
"CustomSurface": {
331+
"info": {
332+
"incidentPos": "公式中可用 {{t}} 代表入射點的位置,在線段兩端點之間從 -1 到 1 線性插值。"
333+
}
334+
},
335+
"CustomArcSurface": {
336+
"info": {
337+
"incidentPos": "公式中可用 {{t}} 代表入射點的位置,在圓弧兩端點之間從 -1 到 1 均勻插值(相對於角度)。"
338+
}
315339
}
316340
},
317341
"saveModal": {
@@ -469,6 +493,9 @@
469493
"handleArrow": {
470494
"title": "控制桿箭頭"
471495
},
496+
"customSurface": {
497+
"title": "自訂表面樣式"
498+
},
472499
"import": {
473500
"title": "匯入",
474501
"description": "從場景 JSON 檔案匯入佈景主題。",

src/app/components/App.vue

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,17 @@ export default {
8282
.popover {
8383
padding-bottom:10px;
8484
}
85+
8586
.popover-body {
8687
padding-bottom:0px;
88+
max-height: 80vh;
89+
overflow-y: auto;
90+
overflow-x: hidden;
8791
}
8892
93+
.popover-body ul {
94+
padding-left: 10px;
95+
}
8996
9097
#main-flex-wrapper {
9198
position: fixed;
@@ -116,6 +123,10 @@ export default {
116123
border-radius: 0;
117124
}
118125
126+
.dropdown-menu>li>div>ul>li>.btn {
127+
border-radius: 0;
128+
}
129+
119130
.mobile-dropdown>ul {
120131
list-style-type: none;
121132
padding-left: 0;
@@ -125,6 +136,10 @@ export default {
125136
border-radius: 0;
126137
}
127138
139+
.mobile-dropdown>ul>li>div>ul>li>.btn {
140+
border-radius: 0;
141+
}
142+
128143
.modal-backdrop {
129144
background-color: rgba(0, 0, 0, 0.3);
130145
z-index: 1040;

src/app/components/theme/ThemeOptionsList.vue

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,14 @@
339339
@update="updateHandleArrow"
340340
/>
341341
</div>
342+
343+
<div class="theme-option-row">
344+
<StrokeControl
345+
:label="$t('simulator:themeModal.customSurface.title')"
346+
:strokeOptions="customSurfaceOptions"
347+
@update="updateCustomSurface"
348+
/>
349+
</div>
342350
</div>
343351
</template>
344352

@@ -423,6 +431,7 @@ export default {
423431
const decorationOptions = computed(() => themeStore.getThemeObject('decoration'))
424432
const handlePointOptions = computed(() => themeStore.getThemeObject('handlePoint'))
425433
const handleArrowOptions = computed(() => themeStore.getThemeObject('handleArrow'))
434+
const customSurfaceOptions = computed(() => themeStore.getThemeObject('customSurface'))
426435
427436
// All theme options update functions
428437
const updateBackground = (newBackground) => themeStore.setThemeObject('background', newBackground)
@@ -465,6 +474,7 @@ export default {
465474
const updateDecoration = (newDecoration) => themeStore.setThemeObject('decoration', newDecoration)
466475
const updateHandlePoint = (newHandlePoint) => themeStore.setThemeObject('handlePoint', newHandlePoint)
467476
const updateHandleArrow = (newHandleArrow) => themeStore.setThemeObject('handleArrow', newHandleArrow)
477+
const updateCustomSurface = (newCustomSurface) => themeStore.setThemeObject('customSurface', newCustomSurface)
468478
469479
return {
470480
// Theme options
@@ -508,6 +518,7 @@ export default {
508518
decorationOptions,
509519
handlePointOptions,
510520
handleArrowOptions,
521+
customSurfaceOptions,
511522
// Update functions
512523
updateBackground,
513524
updateRay,
@@ -548,7 +559,8 @@ export default {
548559
updateRulerText,
549560
updateDecoration,
550561
updateHandlePoint,
551-
updateHandleArrow
562+
updateHandleArrow,
563+
updateCustomSurface
552564
}
553565
}
554566
}

src/app/components/toolbar/Toolbar.vue

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,23 @@ export default {
151151
} else if (input.name == 'toolsradio_mobile') {
152152
app.resetDropdownButtons();
153153
154-
// Get the associated mobile trigger button
155-
let groupId = input.parentElement.parentElement.id.replace('mobile-dropdown-', '');
156-
let toggle = document.getElementById(`mobile-dropdown-trigger-${groupId}`);
157-
if (toggle != null) {
158-
// Style the button to indicate selection.
159-
toggle.classList.add('selected');
154+
// Get the associated mobile trigger button by searching up the DOM tree
155+
let element = input;
156+
let groupId = null;
157+
while (element && element.parentElement) {
158+
element = element.parentElement;
159+
if (element.id && element.id.startsWith('mobile-dropdown-')) {
160+
groupId = element.id.replace('mobile-dropdown-', '');
161+
break;
162+
}
163+
}
164+
165+
if (groupId) {
166+
let toggle = document.getElementById(`mobile-dropdown-trigger-${groupId}`);
167+
if (toggle != null) {
168+
// Style the button to indicate selection.
169+
toggle.classList.add('selected');
170+
}
160171
}
161172
}
162173
}

src/app/components/toolbar/ToolsList.vue

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,23 @@
265265
:layout="layout"
266266
/>
267267
<li><hr class="dropdown-divider"></li>
268+
<MoreToolsCollapsible :layout="layout">
269+
<ToolItem
270+
id="CustomSurface"
271+
:title="$t('main:tools.CustomSurface.title') + '<sup>Beta</sup>'"
272+
:popoverContent="$t('main:meta.parentheses', {main: $t('main:tools.CustomSurface.description'), sub: $t('main:tools.common.lineInstruction')})"
273+
:verticalOffset="0"
274+
:layout="layout"
275+
/>
276+
<ToolItem
277+
id="CustomArcSurface"
278+
:title="$t('main:tools.CustomArcSurface.title') + '<sup>Beta</sup>'"
279+
:popoverContent="$t('main:meta.parentheses', {main: $t('main:tools.CustomArcSurface.description'), sub: $t('main:tools.ArcMirror.instruction')})"
280+
:verticalOffset="0"
281+
:layout="layout"
282+
/>
283+
<li><hr class="dropdown-divider"></li>
284+
</MoreToolsCollapsible>
268285
<ModuleTools :layout="layout" />
269286
</ToolsCategory>
270287
</template>
@@ -278,13 +295,15 @@
278295
import ToolsCategory from './ToolsCategory.vue'
279296
import ToolItem from './controls/ToolItem.vue'
280297
import ModuleTools from './ModuleTools.vue'
298+
import MoreToolsCollapsible from './controls/MoreToolsCollapsible.vue'
281299
282300
export default {
283301
name: 'ToolsList',
284302
components: {
285303
ToolsCategory,
286304
ToolItem,
287-
ModuleTools
305+
ModuleTools,
306+
MoreToolsCollapsible
288307
},
289308
props: {
290309
layout: {

0 commit comments

Comments
 (0)