Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Gauthier Quesnel
irritator
Commits
4f262e94
Commit
4f262e94
authored
Dec 11, 2020
by
Gauthier Quesnel
Browse files
gui: move init/obsveration in another pan
parent
956c203b
Pipeline
#23298
passed with stage
in 1 minute and 41 seconds
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
app/gui/node-editor.cpp
View file @
4f262e94
...
...
@@ -44,6 +44,8 @@ static auto automatic_layout_y_distance = 350.f;
static
auto
grid_layout_x_distance
=
250.
f
;
static
auto
grid_layout_y_distance
=
250.
f
;
static
bool
show_dynamics_inputs_in_editor
=
false
;
static
ImVec4
operator
*
(
const
ImVec4
&
lhs
,
const
float
rhs
)
noexcept
{
...
...
@@ -376,6 +378,13 @@ editor::free_group(cluster& group) noexcept
if
(
auto
*
mdl
=
sim
.
models
.
try_to_get
(
id
);
mdl
)
{
log_w
.
log
(
7
,
"delete model %"
PRIu64
"
\n
"
,
id
);
sim
.
deallocate
(
id
);
if
(
auto
*
out
=
plot_outs
.
try_to_get
(
observation_outputs
[
get_index
(
id
)].
plot_id
))
plot_outs
.
free
(
*
out
);
if
(
auto
*
out
=
file_outs
.
try_to_get
(
observation_outputs
[
get_index
(
id
)].
file_id
))
file_outs
.
free
(
*
out
);
}
}
else
{
auto
id
=
std
::
get
<
cluster_id
>
(
child
);
...
...
@@ -408,6 +417,13 @@ editor::free_children(const ImVector<int>& nodes) noexcept
log_w
.
log
(
7
,
"delete %"
PRIu64
"
\n
"
,
id
);
parent
(
id
,
undefined
<
cluster_id
>
());
sim
.
deallocate
(
id
);
if
(
auto
*
out
=
plot_outs
.
try_to_get
(
observation_outputs
[
get_index
(
id
)].
plot_id
))
plot_outs
.
free
(
*
out
);
if
(
auto
*
out
=
file_outs
.
try_to_get
(
observation_outputs
[
get_index
(
id
)].
file_id
))
file_outs
.
free
(
*
out
);
}
}
else
{
const
auto
id
=
std
::
get
<
cluster_id
>
(
child
.
first
);
...
...
@@ -941,12 +957,11 @@ editor::initialize(u32 id) noexcept
to_unsigned
(
kernel_message_cache
)));
irt_return_if_bad
(
clusters
.
init
(
sim
.
models
.
capacity
()));
irt_return_if_bad
(
top
.
init
(
to_unsigned
(
gui_node_cache
)));
irt_return_if_bad
(
plot_outs
.
init
(
to_unsigned
(
kernel_model_cache
)));
irt_return_if_bad
(
file_outs
.
init
(
to_unsigned
(
kernel_model_cache
)));
try
{
observation_outputs
.
resize
(
sim
.
models
.
capacity
());
observation_types
.
resize
(
sim
.
models
.
capacity
(),
observation_output
::
type
::
none
);
models_mapper
.
resize
(
sim
.
models
.
capacity
(),
undefined
<
cluster_id
>
());
clusters_mapper
.
resize
(
sim
.
models
.
capacity
(),
undefined
<
cluster_id
>
());
models_make_transition
.
resize
(
sim
.
models
.
capacity
(),
false
);
...
...
@@ -1993,48 +2008,6 @@ show_dynamics_inputs(time_func& dyn)
void
editor
::
show_model_dynamics
(
model
&
mdl
)
noexcept
{
ImGui
::
PushItemWidth
(
100.0
f
);
{
const
char
*
items
[]
=
{
"none"
,
"multiplot"
,
"file"
,
"both"
};
int
current_item
=
0
;
/* Default show none */
auto
*
obs
=
sim
.
observers
.
try_to_get
(
mdl
.
obs_id
);
if
(
obs
)
current_item
=
static_cast
<
int
>
(
observation_types
[
get_index
(
mdl
.
obs_id
)]);
if
(
ImGui
::
Combo
(
"observation"
,
&
current_item
,
items
,
IM_ARRAYSIZE
(
items
)))
{
if
(
current_item
==
0
)
{
if
(
obs
)
{
observation_types
[
get_index
(
mdl
.
obs_id
)]
=
observation_output
::
type
::
none
;
sim
.
observers
.
free
(
*
obs
);
mdl
.
obs_id
=
static_cast
<
observer_id
>
(
0
);
}
}
else
{
if
(
!
obs
)
{
auto
&
o
=
sim
.
observers
.
alloc
(
0.01
,
"TODO"
,
nullptr
);
sim
.
observe
(
mdl
,
o
);
}
observation_types
[
get_index
(
mdl
.
obs_id
)]
=
static_cast
<
observation_output
::
type
>
(
current_item
);
}
}
if
(
current_item
==
1
)
{
if
(
auto
*
o
=
sim
.
observers
.
try_to_get
(
mdl
.
obs_id
);
o
)
{
float
v
=
static_cast
<
float
>
(
o
->
time_step
);
if
(
ImGui
::
InputFloat
(
"freq."
,
&
v
,
0.001
f
,
0.1
f
,
"%.3f"
,
0
))
o
->
time_step
=
static_cast
<
double
>
(
v
);
}
}
}
ImGui
::
PopItemWidth
();
if
(
simulation_show_value
&&
st
!=
editor_status
::
editing
)
{
sim
.
dispatch
(
mdl
.
type
,
[
&
](
const
auto
&
d_array
)
{
const
auto
&
dyn
=
d_array
.
get
(
mdl
.
id
);
...
...
@@ -2049,7 +2022,9 @@ editor::show_model_dynamics(model& mdl) noexcept
auto
&
dyn
=
d_array
.
get
(
mdl
.
id
);
add_input_attribute
(
*
this
,
dyn
);
ImGui
::
PushItemWidth
(
120.0
f
);
show_dynamics_inputs
(
dyn
);
if
(
show_dynamics_inputs_in_editor
)
show_dynamics_inputs
(
dyn
);
ImGui
::
PopItemWidth
();
add_output_attribute
(
*
this
,
dyn
);
});
...
...
@@ -2263,7 +2238,7 @@ editor::show_editor() noexcept
windows_flags
|=
ImGuiWindowFlags_MenuBar
;
ImGui
::
SetNextWindowPos
(
ImVec2
(
500
,
50
),
ImGuiCond_FirstUseEver
);
ImGui
::
SetNextWindowSize
(
ImVec2
(
5
00
,
5
00
),
ImGuiCond_Once
);
ImGui
::
SetNextWindowSize
(
ImVec2
(
8
00
,
7
00
),
ImGuiCond_Once
);
if
(
!
ImGui
::
Begin
(
name
.
c_str
(),
&
show
,
windows_flags
))
{
ImGui
::
End
();
return
true
;
...
...
@@ -2301,6 +2276,9 @@ editor::show_editor() noexcept
ImGui
::
EndMenu
();
}
if
(
ImGui
::
BeginMenu
(
"Edition"
))
{
ImGui
::
MenuItem
(
"Show parameter in models"
,
nullptr
,
&
show_dynamics_inputs_in_editor
);
if
(
ImGui
::
MenuItem
(
"Clear"
))
clear
();
if
(
ImGui
::
MenuItem
(
"Grid Reorder"
))
...
...
@@ -2448,7 +2426,7 @@ editor::show_editor() noexcept
reader
r
(
is
);
auto
ret
=
r
(
sim
,
[
this
](
model_id
id
)
{
parent
(
id
,
undefined
<
cluster_id
>
());
imnodes
::
SetNodeEditorSpacePos
(
top
.
emplace_back
(
id
),
imnodes
::
EditorContextGetPanning
());
});
...
...
@@ -2488,9 +2466,9 @@ editor::show_editor() noexcept
"D -- duplicate selected nodes / "
"G -- group model"
);
ImGui
::
Columns
(
2
,
"
TODO column
"
);
ImGui
::
Columns
(
2
,
"
Edit
"
);
if
(
starting
)
{
ImGui
::
SetColumnWidth
(
0
,
40
0.
f
);
ImGui
::
SetColumnWidth
(
0
,
58
0.
f
);
starting
=
false
;
}
...
...
@@ -2528,7 +2506,8 @@ editor::show_editor() noexcept
auto
i
=
static_cast
<
int
>
(
dynamics_type
::
qss1_integrator
);
const
auto
e
=
static_cast
<
int
>
(
dynamics_type
::
qss1_wsum_4
);
for
(;
i
!=
e
;
++
i
)
add_popup_menuitem
(
*
this
,
static_cast
<
dynamics_type
>
(
i
),
&
new_model
);
add_popup_menuitem
(
*
this
,
static_cast
<
dynamics_type
>
(
i
),
&
new_model
);
ImGui
::
EndMenu
();
}
...
...
@@ -2537,7 +2516,8 @@ editor::show_editor() noexcept
const
auto
e
=
static_cast
<
int
>
(
dynamics_type
::
qss2_wsum_4
);
for
(;
i
!=
e
;
++
i
)
add_popup_menuitem
(
*
this
,
static_cast
<
dynamics_type
>
(
i
),
&
new_model
);
add_popup_menuitem
(
*
this
,
static_cast
<
dynamics_type
>
(
i
),
&
new_model
);
ImGui
::
EndMenu
();
}
...
...
@@ -2546,7 +2526,8 @@ editor::show_editor() noexcept
const
auto
e
=
static_cast
<
int
>
(
dynamics_type
::
qss3_wsum_4
);
for
(;
i
!=
e
;
++
i
)
add_popup_menuitem
(
*
this
,
static_cast
<
dynamics_type
>
(
i
),
&
new_model
);
add_popup_menuitem
(
*
this
,
static_cast
<
dynamics_type
>
(
i
),
&
new_model
);
ImGui
::
EndMenu
();
}
...
...
@@ -2668,7 +2649,109 @@ editor::show_editor() noexcept
}
ImGui
::
NextColumn
();
ImGui
::
Text
(
"Here node editor"
);
if
(
ImGui
::
CollapsingHeader
(
"Selected Models"
,
ImGuiTreeNodeFlags_CollapsingHeader
|
ImGuiTreeNodeFlags_DefaultOpen
)
&&
num_selected_nodes
)
{
selected_nodes
.
resize
(
num_selected_nodes
,
-
1
);
imnodes
::
GetSelectedNodes
(
selected_nodes
.
begin
());
for
(
int
i
=
0
,
e
=
selected_nodes
.
size
();
i
!=
e
;
++
i
)
{
const
auto
index
=
top
.
get_index
(
selected_nodes
[
i
]);
if
(
index
==
not_found
)
continue
;
const
auto
&
child
=
top
.
children
[
index
];
if
(
child
.
first
.
index
())
continue
;
const
auto
id
=
std
::
get
<
model_id
>
(
child
.
first
);
model
*
mdl
=
sim
.
models
.
try_to_get
(
id
);
if
(
!
mdl
)
continue
;
// TODO use the dynamic or model name.
const
auto
&
name
=
dynamics_type_names
[
static_cast
<
int
>
(
mdl
->
type
)];
if
(
ImGui
::
TreeNodeEx
(
name
,
ImGuiTreeNodeFlags_DefaultOpen
))
{
auto
&
out
=
observation_outputs
[
get_index
(
id
)];
auto
*
plot
=
plot_outs
.
try_to_get
(
out
.
plot_id
);
auto
*
file
=
file_outs
.
try_to_get
(
out
.
file_id
);
irt_assert
(
!
(
file
&&
plot
));
int
choose
=
plot
?
1
:
file
?
2
:
0
;
ImGui
::
RadioButton
(
"none"
,
&
choose
,
0
);
ImGui
::
SameLine
();
ImGui
::
RadioButton
(
"plot"
,
&
choose
,
1
);
ImGui
::
SameLine
();
ImGui
::
RadioButton
(
"file"
,
&
choose
,
2
);
if
(
choose
==
1
)
{
if
(
file
)
{
file_outs
.
free
(
*
file
);
sim
.
observers
.
free
(
mdl
->
obs_id
);
}
if
(
!
plot
)
{
plot_output
&
tf
=
plot_outs
.
alloc
(
"unamed"
);
plot
=
&
tf
;
out
.
plot_id
=
plot_outs
.
get_id
(
tf
);
auto
&
o
=
sim
.
observers
.
alloc
(
0.01
,
"unamed"
,
(
void
*
)
plot
);
o
.
initialize
=
&
observation_plot_output_initialize
;
o
.
observe
=
&
observation_plot_output_observe
;
o
.
free
=
&
observation_plot_output_free
;
sim
.
observe
(
*
mdl
,
o
);
}
ImGui
::
InputText
(
"name##plot"
,
plot
->
name
.
begin
(),
plot
->
name
.
size
());
}
else
if
(
choose
==
2
)
{
if
(
plot
)
{
plot_outs
.
free
(
*
plot
);
sim
.
observers
.
free
(
mdl
->
obs_id
);
}
if
(
!
file
)
{
file_output
&
tf
=
file_outs
.
alloc
(
"unamed"
);
file
=
&
tf
;
out
.
file_id
=
file_outs
.
get_id
(
tf
);
auto
&
o
=
sim
.
observers
.
alloc
(
0.01
,
"unamed"
,
(
void
*
)
file
);
o
.
initialize
=
&
observation_file_output_initialize
;
o
.
observe
=
&
observation_file_output_observe
;
o
.
free
=
&
observation_file_output_free
;
sim
.
observe
(
*
mdl
,
o
);
}
ImGui
::
InputText
(
"name##file"
,
file
->
name
.
begin
(),
file
->
name
.
size
());
}
else
{
if
(
plot
)
{
plot_outs
.
free
(
*
plot
);
sim
.
observers
.
free
(
mdl
->
obs_id
);
}
if
(
file
)
{
file_outs
.
free
(
*
file
);
sim
.
observers
.
free
(
mdl
->
obs_id
);
}
}
sim
.
dispatch
(
mdl
->
type
,
[](
auto
&
d_array
,
model
&
mdl
)
{
auto
&
dyn
=
d_array
.
get
(
mdl
.
id
);
show_dynamics_inputs
(
dyn
);
},
*
mdl
);
ImGui
::
TreePop
();
}
}
}
ImGui
::
End
();
...
...
@@ -2798,16 +2881,16 @@ show_plot_box(bool* show_plot)
if
(
auto
*
ed
=
make_combo_editor_name
(
current
);
ed
)
{
if
(
ImPlot
::
BeginPlot
(
"simulation"
,
"t"
,
"s"
))
{
ImPlot
::
PushStyleVar
(
ImPlotStyleVar_LineWeight
,
1.
f
);
for
(
const
auto
&
obs
:
ed
->
observation_outputs
)
{
if
(
obs
.
observation_type
==
observation_output
::
type
::
multiplot
&&
!
obs
.
xs
.
empty
())
{
ImPlot
::
PlotLine
(
obs
.
name
.
c_str
(),
obs
.
xs
.
data
(),
obs
.
ys
.
data
(),
static_cast
<
int
>
(
obs
.
xs
.
size
()));
}
plot_output
*
out
=
nullptr
;
while
(
ed
->
plot_outs
.
next
(
out
))
{
if
(
!
out
->
xs
.
empty
()
&&
!
out
->
ys
.
empty
())
ImPlot
::
PlotLine
(
out
->
name
.
c_str
(),
out
->
xs
.
data
(),
out
->
ys
.
data
(),
static_cast
<
int
>
(
out
->
xs
.
size
()));
}
ImPlot
::
PopStyleVar
(
1
);
ImPlot
::
EndPlot
();
}
...
...
app/gui/node-editor.hpp
View file @
4f262e94
...
...
@@ -214,30 +214,90 @@ struct window_logger
void
show
(
bool
*
is_show
);
};
struct
observation
_output
struct
plot
_output
{
enum
class
type
{
none
,
multiplot
,
file
,
both
};
plot_output
()
=
default
;
observation_output
()
=
default
;
observation_output
(
std
::
string_view
name_
)
plot_output
(
std
::
string_view
name_
)
:
name
(
name_
)
{}
std
::
ofstream
ofs
;
std
::
string
name
;
void
clear
()
{
name
.
clear
();
xs
.
clear
();
ys
.
clear
();
tl
=
0.0
;
min
=
-
1.
f
;
max
=
+
1.
f
;
}
std
::
vector
<
float
>
xs
;
std
::
vector
<
float
>
ys
;
small_string
<
24u
>
name
;
double
tl
=
0.0
;
float
min
=
-
1.
f
;
float
max
=
+
1.
f
;
type
observation_type
=
type
::
none
;
};
struct
file_output
{
file_output
()
=
default
;
file_output
(
std
::
string_view
name_
)
:
name
(
name_
)
{}
void
clear
()
{
ofs
.
close
();
name
.
clear
();
tl
=
0.0
;
}
std
::
ofstream
ofs
;
small_string
<
24u
>
name
;
double
tl
=
0.0
;
};
void
observation_plot_output_initialize
(
const
irt
::
observer
&
obs
,
const
irt
::
time
t
)
noexcept
;
void
observation_file_output_initialize
(
const
irt
::
observer
&
obs
,
const
irt
::
time
t
)
noexcept
;
void
observation_plot_output_observe
(
const
irt
::
observer
&
obs
,
const
irt
::
time
t
,
const
irt
::
message
&
msg
)
noexcept
;
void
observation_file_output_observe
(
const
irt
::
observer
&
obs
,
const
irt
::
time
t
,
const
irt
::
message
&
msg
)
noexcept
;
void
observation_plot_output_free
(
const
irt
::
observer
&
/*obs*/
,
const
irt
::
time
/*t*/
)
noexcept
;
void
observation_file_output_free
(
const
irt
::
observer
&
obs
,
const
irt
::
time
/*t*/
)
noexcept
;
enum
class
plot_output_id
:
u64
;
enum
class
file_output_id
:
u64
;
struct
observation_output
{
constexpr
observation_output
()
=
default
;
constexpr
void
clear
()
noexcept
{
plot_id
=
undefined
<
plot_output_id
>
();
file_id
=
undefined
<
file_output_id
>
();
}
plot_output_id
plot_id
=
undefined
<
plot_output_id
>
();
file_output_id
file_id
=
undefined
<
file_output_id
>
();
};
struct
editor
...
...
@@ -266,8 +326,10 @@ struct editor
bool
simulation_show_value
=
false
;
bool
stop
=
false
;
data_array
<
plot_output
,
plot_output_id
>
plot_outs
;
data_array
<
file_output
,
file_output_id
>
file_outs
;
std
::
vector
<
observation_output
>
observation_outputs
;
std
::
vector
<
observation_output
::
type
>
observation_types
;
std
::
filesystem
::
path
observation_directory
;
data_array
<
cluster
,
cluster_id
>
clusters
;
...
...
app/gui/simulation-editor.cpp
View file @
4f262e94
...
...
@@ -19,142 +19,144 @@
#include
<string>
#include
<fmt/format.h>
#include
<fmt/ostream.h>
#include
<irritator/core.hpp>
#include
<irritator/io.hpp>
namespace
irt
{
static
void
observation_output_initialize
(
const
irt
::
observer
&
obs
,
const
irt
::
time
t
)
noexcept
void
observation_plot_output_initialize
(
const
irt
::
observer
&
obs
,
const
irt
::
time
t
)
noexcept
{
// const auto diff = ed.simulation_end - ed.simulation_begin;
// const auto freq = diff / obs->time_step;
// const auto length = std::min((size_t)freq, (size_t)4096);
if
(
!
obs
.
user_data
)
return
;
auto
*
output
=
reinterpret_cast
<
observation_output
*>
(
obs
.
user_data
);
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
multiplot
,
observation_output
::
type
::
both
))
{
output
->
xs
.
clear
();
output
->
ys
.
clear
();
output
->
tl
=
t
;
output
->
min
=
-
1.
f
;
output
->
max
=
+
1.
f
;
}
auto
*
output
=
reinterpret_cast
<
plot_output
*>
(
obs
.
user_data
);
output
->
xs
.
clear
();
output
->
ys
.
clear
();
output
->
xs
.
reserve
(
4096u
);
output
->
ys
.
reserve
(
4096u
);
output
->
tl
=
t
;
output
->
min
=
-
1.
f
;
output
->
max
=
+
1.
f
;
}
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
file
,
observation_output
::
type
::
both
))
{
if
(
!
output
->
ofs
.
is_open
())
{
if
(
output
->
observation_type
==
observation_output
::
type
::
both
)
output
->
observation_type
=
observation_output
::
type
::
multiplot
;
else
output
->
observation_type
=
observation_output
::
type
::
none
;
}
else
output
->
ofs
<<
"t,"
<<
output
->
name
<<
'\n'
;
}
void
observation_file_output_initialize
(
const
irt
::
observer
&
obs
,
const
irt
::
time
t
)
noexcept
{
if
(
!
obs
.
user_data
)
return
;
auto
*
output
=
reinterpret_cast
<
file_output
*>
(
obs
.
user_data
);
output
->
tl
=
t
;
if
(
output
->
ofs
.
is_open
())
fmt
::
print
(
output
->
ofs
,
"t,{}
\n
"
,
output
->
name
.
c_str
());
}
static
void
observation_output_observe
(
const
irt
::
observer
&
obs
,
const
irt
::
time
t
,
const
irt
::
message
&
msg
)
noexcept
void
observation_
plot_
output_observe
(
const
irt
::
observer
&
obs
,
const
irt
::
time
t
,
const
irt
::
message
&
msg
)
noexcept
{
if
(
!
obs
.
user_data
)
return
;
auto
*
output
=
reinterpret_cast
<
observation
_output
*>
(
obs
.
user_data
);
auto
*
output
=
reinterpret_cast
<
plot
_output
*>
(
obs
.
user_data
);
const
auto
value
=
static_cast
<
float
>
(
msg
[
0
]);
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
multiplot
,
observation_output
::
type
::
both
))
{
output
->
min
=
std
::
min
(
output
->
min
,
value
);
output
->
max
=
std
::
max
(
output
->
max
,
value
);
for
(
double
to_fill
=
output
->
tl
;
to_fill
<
t
;
to_fill
+=
obs
.
time_step
)
{
output
->
ys
.
emplace_back
(
value
);
output
->
xs
.
emplace_back
(
static_cast
<
float
>
(
t
));
}
}
output
->
min
=
std
::
min
(
output
->
min
,
value
);
output
->
max
=
std
::
max
(
output
->
max
,
value
);
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
file
,
observation_output
::
type
::
both
))
{
output
->
ofs
<<
t
<<
','
<<
value
<<
'\n'
;
for
(
auto
to_fill
=
output
->
tl
;
to_fill
<
t
;
to_fill
+=
obs
.
time_step
)
{
output
->
ys
.
emplace_back
(
value
);
output
->
xs
.
emplace_back
(
static_cast
<
float
>
(
t
));
}
output
->
tl
=
t
;
}
static
void
observation_output_free
(
const
irt
::
observer
&
obs
,
const
irt
::
time
/*t*/
)
noexcept
void
observation_file_output_observe
(
const
irt
::
observer
&
obs
,
const
irt
::
time
t
,
const
irt
::
message
&
msg
)
noexcept
{
if
(
!
obs
.
user_data
)
return
;
auto
*
output
=
reinterpret_cast
<
observation_output
*>
(
obs
.
user_data
);
auto
*
output
=
reinterpret_cast
<
file_output
*>
(
obs
.
user_data
);
const
auto
value
=
static_cast
<
float
>
(
msg
[
0
]);
if
(
match
(
output
->
observation_type
,
observation_output
::
type
::
file
,
observation_output
::
type
::
both
))
{
output
->
ofs
.
close
();
}
fmt
::
print
(
output
->
ofs
,
"{},{}
\n
"
,
t
,
value
);
output
->
tl
=
t
;
}
static
void
initialize_observation
(
window_logger
&
log_w
,
irt
::
editor
&
ed
)
noexcept
{
ed
.
observation_outputs
.
clear
();
observer
*
obs
=
nullptr
;
while
(
ed
.
sim
.
observers
.
next
(
obs
))
{
auto
&
output
=
ed
.
observation_outputs
.
emplace_back
(
obs
->
name
.
sv
());
const
auto
type
=
ed
.
observation_types
[
get_index
(
ed
.
sim
.
observers
.
get_id
(
*
obs
))];
const
auto
diff
=
ed
.
simulation_end
-
ed
.
simulation_begin
;
const
auto
freq
=
diff
/
obs
->
time_step
;
const
auto
length
=
static_cast
<
size_t
>
(
freq
);
output
.
observation_type
=
type
;
if
(
match
(
type
,
observation_output
::
type
::
multiplot
,
observation_output
::
type
::
both
))
{
output
.
xs
.
clear
();
output
.
ys
.
clear
();
output
.
xs
.
reserve
(
length
);
output
.
ys
.
reserve
(
length
);
}
void
observation_plot_output_free
(
const
irt
::
observer
&
/*obs*/
,
const
irt
::
time
/*t*/
)
noexcept
{}
if
(
!
obs
->
name
.
empty
())
{
const
std
::
filesystem
::
path
obs_file_path
=
ed
.
observation_directory
/
obs
->
name
.
c_str
();
if
(
type
==
observation_output
::
type
::
file
||
type
==
observation_output
::
type
::
both
)
{
if
(
output
.
ofs
.
open
(
obs_file_path
);
!
output
.
ofs
.
is_open
())