Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d4d8828
add /OpenEMSH/GlobalParams parser
thomaslepoix Dec 8, 2025
6965386
add Polygon Primitive parser
thomaslepoix Dec 9, 2025
7bfe07c
add Board::material for BackgroundMaterial
thomaslepoix Dec 10, 2025
e666fb5
add --read-oemsh-params
thomaslepoix Dec 14, 2025
f1240ad
add Logger
thomaslepoix Dec 17, 2025
09ce3c0
add warning for unsupported Primitives
thomaslepoix Dec 18, 2025
1382a35
add error when no /openEMS path in CSX file
thomaslepoix Dec 28, 2025
c42bfc3
add --integrate-old-mesh
thomaslepoix Jan 22, 2026
12f3979
add --add-fixed-meshline and /OpenEMSH/FixedMeshlines path in CSX file
thomaslepoix Jan 22, 2026
dab9812
fix --add-fixed-meshline
thomaslepoix Jan 25, 2026
d5c75e1
refactor : rm res_factor definitely but keep MLP::d=dmax/2 for now
thomaslepoix Jan 25, 2026
b3a26e1
fix : add handling for ONELINE policies in ConflictColinearEdges & Co…
thomaslepoix Jan 25, 2026
4bfe1bc
set default lmin to 2
thomaslepoix Jan 25, 2026
a9e9e3d
add Sphere Primitive parser
thomaslepoix Jan 26, 2026
6a684d0
add Cylinder Primitive parser (orthogonal only)
thomaslepoix Jan 26, 2026
23cb4f8
add warning for unsupported Transformation
thomaslepoix Jan 26, 2026
406f034
fix : only mesh ONELINE MeshlinePolicy when enabled
thomaslepoix Jan 27, 2026
b49b0df
add Point Primitive parser
thomaslepoix Jan 27, 2026
9d8d287
add Curve Primitive parser
thomaslepoix Jan 27, 2026
8b10f4e
add MultiBox Primitive parser
thomaslepoix Jan 27, 2026
cba9990
parse Material subclasses (Dispersive, Debye, Lorentz, Disc) like Mat…
thomaslepoix Jan 27, 2026
8be064f
fix : set infinite priority for Curve & Point Primitives
thomaslepoix Jan 27, 2026
d3ee5a2
fix : avoid exceptions in openemsh target : std::stod() -> std::from_…
thomaslepoix Jan 28, 2026
7912d2c
add Polygon & unsupported Wire Primitives to test/shapes.csx
thomaslepoix Jan 28, 2026
042baca
add Material::Type::PORT with infinite priority
thomaslepoix Jan 28, 2026
bb7f116
fix Transformation detection & add warning for unsupported Properties…
thomaslepoix Jan 28, 2026
0f1bfb7
refactor : fix some badsmells
thomaslepoix Jan 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ target_sources( openemsh
"${CMAKE_CURRENT_SOURCE_DIR}/utils/entity.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/utils/tree_node.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/utils/state_management.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/utils/logger.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/utils/progress.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/domain/geometrics/space.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/domain/geometrics/relation.cpp"
Expand Down Expand Up @@ -84,6 +85,7 @@ add_executable( openemsh_bin WIN32 )
target_sources( openemsh_bin
PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/ui/cli/cli.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ui/cli/logger.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ui/cli/progress.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ui/qt/utils/nodegraph/highlightable.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ui/qt/utils/nodegraph/port.cpp"
Expand Down Expand Up @@ -132,6 +134,7 @@ target_sources( openemsh_bin
"${CMAKE_CURRENT_SOURCE_DIR}/ui/qt/about_dialog.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ui/qt/icons.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ui/qt/main_window.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ui/qt/logger.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ui/qt/progress.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ui/qt/style.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ui/qt/resources.qrc"
Expand Down
16 changes: 11 additions & 5 deletions src/domain/board.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
///*****************************************************************************

#include <algorithm>
#include <limits>
#include <set>
#include <utility>

Expand Down Expand Up @@ -65,10 +66,16 @@ shared_ptr<Board> Board::Builder::build(Params&& params) {
return make_shared<Board>(
std::move(polygons),
std::move(fixed_meshline_policy_creators),
std::move(material),
std::move(params),
Caretaker::singleton().get_history_root());
}

//******************************************************************************
void Board::Builder::set_background_material(shared_ptr<Material> background) {
material = background;
}

// TODO should be in meshline manager?
//******************************************************************************
void Board::Builder::add_fixed_meshline_policy(Axis const axis, Coord const coord) {
Expand Down Expand Up @@ -146,12 +153,14 @@ Board::Board(PlaneSpace<vector<shared_ptr<Polygon>>>&& polygons, Params&& params
Board::Board(
PlaneSpace<std::vector<std::shared_ptr<Polygon>>>&& polygons,
AxisSpace<std::vector<std::function<void (Board*, Timepoint*)>>>&& fixed_meshline_policy_creators,
shared_ptr<Material>&& background,
Params&& params,
Timepoint* t)
: Originator(t, BoardState(std::move(polygons)))
, global_params(make_shared<GlobalParams>(std::move(params), t))
, conflict_manager(make_shared<ConflictManager>(t))
, line_policy_manager(make_shared<MeshlinePolicyManager>(global_params.get(), t))
, material(background)
, fixed_meshline_policy_creators(std::move(fixed_meshline_policy_creators)) {

conflict_manager->init(line_policy_manager.get());
Expand Down Expand Up @@ -196,8 +205,7 @@ pair<shared_ptr<Material>, remove_const_t<decltype(Polygon::priority)>> Board::f
if(!materials.empty())
return materials.back();
else
// TODO if no material return Board::background_material
return {};
return { material, std::numeric_limits<remove_const_t<decltype(Polygon::priority)>>::min() };
}

//******************************************************************************
Expand Down Expand Up @@ -661,9 +669,7 @@ void Board::detect_individual_edges() {

//******************************************************************************
void Board::add_fixed_meshline_policies() {
#warning TODO
// for(auto const& axis : AllAxis)
for(auto const& axis : { X, Y })
for(auto const& axis : AllAxis)
add_fixed_meshline_policies(axis);
}

Expand Down
5 changes: 5 additions & 0 deletions src/domain/board.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "utils/state_management.hpp"
#include "conflict_manager.hpp"
#include "global.hpp"
#include "material.hpp"
#include "meshline_policy_manager.hpp"
//#include "meshline_policy.hpp"
//#include "range.hpp"
Expand Down Expand Up @@ -59,6 +60,7 @@ class Board
class Builder {
public:

void set_background_material(std::shared_ptr<Material> background);
void add_fixed_meshline_policy(Axis axis, Coord coord);
void add_polygon(Plane plane, std::shared_ptr<Material> const& material, std::string const& name, std::size_t priority, Polygon::RangeZ const& z_placement, std::initializer_list<Point> points);
void add_polygon(Plane plane, std::shared_ptr<Material> const& material, std::string const& name, std::size_t priority, Polygon::RangeZ const& z_placement, std::vector<std::unique_ptr<Point const>>&& points);
Expand All @@ -67,16 +69,19 @@ class Board
[[nodiscard]] std::shared_ptr<Board> build(Params&& params = Params());

private:
std::shared_ptr<Material> material;
PlaneSpace<std::vector<std::shared_ptr<Polygon>>> polygons;
AxisSpace<std::vector<std::function<void (Board*, Timepoint*)>>> fixed_meshline_policy_creators;
};

std::shared_ptr<Material> material;
AxisSpace<std::vector<std::function<void (Board*, Timepoint*)>>> const fixed_meshline_policy_creators; // Meant to delay MeshlinePolicies creation at Step time instead of Parse time.

Board(PlaneSpace<std::vector<std::shared_ptr<Polygon>>>&& polygons, Params&& params, Timepoint* t);
Board(
PlaneSpace<std::vector<std::shared_ptr<Polygon>>>&& polygons,
AxisSpace<std::vector<std::function<void (Board*, Timepoint*)>>>&& fixed_meshline_policy_creators,
std::shared_ptr<Material>&& background,
Params&& params,
Timepoint* t);

Expand Down
17 changes: 14 additions & 3 deletions src/domain/conflicts/conflict_colinear_edges.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ void ConflictColinearEdges::append(Edge* edge, Timepoint* t) {
void ConflictColinearEdges::auto_solve(MeshlinePolicyManager& line_policy_manager) {
size_t normal_min = 0;
size_t normal_max = 0;
bool must_be_oneline = false;

auto const& s = get_current_state();

Expand All @@ -49,15 +50,21 @@ void ConflictColinearEdges::auto_solve(MeshlinePolicyManager& line_policy_manage
case Normal::YMIN:
case Normal::ZMIN:
++normal_min;
break;
continue;
case Normal::XMAX:
case Normal::YMAX:
case Normal::ZMAX:
++normal_max;
continue;
case Normal::NONE:
must_be_oneline = true;
break;
default:
break;
::unreachable();
}

if(must_be_oneline)
break;
}

optional<Coord> const coord = domain::coord(s.edges.front()->p0(), s.edges.front()->axis);
Expand All @@ -78,7 +85,11 @@ void ConflictColinearEdges::auto_solve(MeshlinePolicyManager& line_policy_manage
};

if(coord) {
if(normal_min && normal_max) {
if(must_be_oneline) {
add_policy(
MeshlinePolicy::Policy::ONELINE,
MeshlinePolicy::Normal::NONE);
} else if(normal_min && normal_max) {
add_policy(
MeshlinePolicy::Policy::HALFS,
MeshlinePolicy::Normal::NONE);
Expand Down
35 changes: 16 additions & 19 deletions src/domain/conflicts/conflict_too_close_meshline_policies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,52 +36,49 @@ void ConflictTooCloseMeshlinePolicies::auto_solve(MeshlinePolicyManager& line_po
if(a->axis != b->axis)
return;

auto [policy, normal] = [&]() -> tuple<optional<MeshlinePolicy::Policy>, optional<MeshlinePolicy::Normal>> {
auto [policy, normal, coord] = [&]() -> tuple<optional<MeshlinePolicy::Policy>, optional<MeshlinePolicy::Normal>, optional<Coord>> {
auto const& state_a = a->get_current_state();
auto const& state_b = b->get_current_state();

if(state_a.policy == MeshlinePolicy::Policy::THIRDS && state_b.policy == MeshlinePolicy::Policy::THIRDS) {
if(state_a.policy == MeshlinePolicy::Policy::ONELINE && state_b.policy == MeshlinePolicy::Policy::ONELINE) {
return { MeshlinePolicy::Policy::ONELINE, MeshlinePolicy::Normal::NONE, mid(a->coord, b->coord) };
} else if(state_a.policy == MeshlinePolicy::Policy::ONELINE && state_b.policy != MeshlinePolicy::Policy::ONELINE) {
return { MeshlinePolicy::Policy::ONELINE, MeshlinePolicy::Normal::NONE, a->coord };
} else if(state_a.policy != MeshlinePolicy::Policy::ONELINE && state_b.policy == MeshlinePolicy::Policy::ONELINE) {
return { MeshlinePolicy::Policy::ONELINE, MeshlinePolicy::Normal::NONE, b->coord };
} else if(state_a.policy == MeshlinePolicy::Policy::THIRDS && state_b.policy == MeshlinePolicy::Policy::THIRDS) {
if(state_a.normal != state_b.normal) {
return { MeshlinePolicy::Policy::HALFS, MeshlinePolicy::Normal::NONE };
return { MeshlinePolicy::Policy::HALFS, MeshlinePolicy::Normal::NONE, mid(a->coord, b->coord) };
} else if(state_a.normal == MeshlinePolicy::Normal::MIN
&& state_b.normal == MeshlinePolicy::Normal::MIN) {
return { MeshlinePolicy::Policy::THIRDS, MeshlinePolicy::Normal::MIN };
return { MeshlinePolicy::Policy::THIRDS, MeshlinePolicy::Normal::MIN, mid(a->coord, b->coord) };
} else if(state_a.normal == MeshlinePolicy::Normal::MAX
&& state_b.normal == MeshlinePolicy::Normal::MAX) {
return { MeshlinePolicy::Policy::THIRDS, MeshlinePolicy::Normal::MAX };
return { MeshlinePolicy::Policy::THIRDS, MeshlinePolicy::Normal::MAX, mid(a->coord, b->coord) };
}
} else if((state_a.policy == MeshlinePolicy::Policy::HALFS && state_b.policy == MeshlinePolicy::Policy::HALFS)
|| (state_a.policy == MeshlinePolicy::Policy::HALFS && state_b.policy == MeshlinePolicy::Policy::THIRDS)
|| (state_a.policy == MeshlinePolicy::Policy::THIRDS && state_b.policy == MeshlinePolicy::Policy::HALFS)) {
return { MeshlinePolicy::Policy::HALFS, MeshlinePolicy::Normal::NONE };
} //else if(ONE and *) { // TODO }
// TODO should not have been created ?
// TODO only one, remove other?
// TODO one and one : merge
return { MeshlinePolicy::Policy::HALFS, MeshlinePolicy::Normal::NONE, mid(a->coord, b->coord) };
}

return { nullopt, nullopt };
return { nullopt, nullopt, nullopt };
} ();

if(policy && normal) {
if(policy && normal && coord) {
auto [t, state] = make_next_state();
state.meshline_policy = line_policy_manager.add_meshline_policy(
{ this },
axis,
policy.value(),
normal.value(),
mid(a->coord, b->coord),
coord.value(),
true,
t);
state.solution = state.meshline_policy;
state.is_solved = true;
set_state(t, state);
}

// TODO detect axis
// TODO detect 2 vs 3 rule (vs 1 rule?)
// TODO detect normal
// TODO create MLP

}

// TODO Interval class : just mesh() from adjacent / neibourgh
Expand Down
29 changes: 24 additions & 5 deletions src/domain/geometrics/polygon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
/// @author Thomas Lepoix <thomas.lepoix@protonmail.ch>
///*****************************************************************************

#include <cmath>
#include <numbers>

#include "utils/unreachable.hpp"
#include "edge.hpp"
#include "point.hpp"
Expand Down Expand Up @@ -50,8 +53,8 @@ vector<shared_ptr<Edge>> detect_edges(vector<unique_ptr<Point const>> const& poi
edges.push_back(make_shared<Edge>(plane, prev, point.get(), t));
prev = point.get();
}
edges.shrink_to_fit();

edges.shrink_to_fit();
return edges;
}

Expand Down Expand Up @@ -204,10 +207,26 @@ relation::PolygonPoint Polygon::relation_to(Point const& point) const noexcept {
/// Check if two Z ranges overlap or just touch each other.
///*****************************************************************************
bool does_overlap(Polygon::RangeZ const& a, Polygon::RangeZ const& b) noexcept {
return (b.min >= a.min && b.min <= a.max)
|| (b.max >= a.min && b.max <= a.max)
|| (a.min >= b.min && a.min <= b.max)
|| (a.max >= b.min && a.max <= b.max);
return min(a.max, b.max) >= max(a.min, b.min);
}

/// Points on axes guaranteed. CCW oriented.
///*****************************************************************************
vector<unique_ptr<Point const>> circle_to_points(Point const& center, double radius, size_t n_slices_per_quarter) {
if(!n_slices_per_quarter)
n_slices_per_quarter = 1;

double const angle = (numbers::pi/2) / n_slices_per_quarter;
size_t const n = n_slices_per_quarter * 4;

vector<unique_ptr<Point const>> points;
for(size_t i = 0; i < n; ++i) {
double a = angle * i;
points.emplace_back(make_unique<Point const>(center.x + radius * cos(a), center.y + radius * sin(a)));
}

points.shrink_to_fit();
return points;
}

} // namespace domain
3 changes: 3 additions & 0 deletions src/domain/geometrics/polygon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,7 @@ std::vector<std::shared_ptr<Edge>> detect_edges(std::vector<std::unique_ptr<Poin
//******************************************************************************
bool does_overlap(Polygon::RangeZ const& a, Polygon::RangeZ const& b) noexcept;

//******************************************************************************
std::vector<std::unique_ptr<Point const>> circle_to_points(Point const& center, double radius, std::size_t n_slices_per_quarter = 9);

} // namespace domain
7 changes: 6 additions & 1 deletion src/domain/global.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
#pragma once

#include <cstddef>
#include <utility>
#include <vector>

#include "geometrics/space.hpp"
#include "utils/state_management.hpp"

namespace domain {
Expand All @@ -17,12 +20,14 @@ struct Params {
bool has_grid_already = false; // TODO would better fit in infra layer?
double proximity_limit = 1; // TODO must be linked to initial d
double smoothness = 2;
std::size_t lmin = 10;
std::size_t lmin = 2;
double dmax = 2.5;

std::size_t diagonal_lmin = 2;
double diagonal_dmax = 0.2;
double consecutive_diagonal_minimal_angle = 20; // Limite between acute / obtuse angles.

std::vector<std::pair<Axis, double>> input_fixed_meshlines;
};

//******************************************************************************
Expand Down
11 changes: 11 additions & 0 deletions src/domain/material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,33 @@ Material::Material(Type type, string const& name, optional<Color> const& fill_co
//******************************************************************************
strong_ordering Material::operator<=>(Material const& other) const noexcept {
switch(type) {
case Type::PORT:
switch(other.type) {
case Type::PORT: return strong_ordering::equivalent;
case Type::CONDUCTOR: return strong_ordering::greater;
case Type::DIELECTRIC: return strong_ordering::greater;
case Type::AIR: return strong_ordering::greater;
default: ::unreachable();
}
case Type::CONDUCTOR:
switch(other.type) {
case Type::PORT: return strong_ordering::less;
case Type::CONDUCTOR: return strong_ordering::equivalent;
case Type::DIELECTRIC: return strong_ordering::greater;
case Type::AIR: return strong_ordering::greater;
default: ::unreachable();
}
case Type::DIELECTRIC:
switch(other.type) {
case Type::PORT: return strong_ordering::less;
case Type::CONDUCTOR: return strong_ordering::less;
case Type::DIELECTRIC: return strong_ordering::equivalent;
case Type::AIR: return strong_ordering::greater;
default: ::unreachable();
}
case Type::AIR:
switch(other.type) {
case Type::PORT: return strong_ordering::less;
case Type::CONDUCTOR: return strong_ordering::less;
case Type::DIELECTRIC: return strong_ordering::less;
case Type::AIR: return strong_ordering::equivalent;
Expand Down
1 change: 1 addition & 0 deletions src/domain/material.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class Material {

enum class Type {
// DUMP,
PORT,
// PEC,
CONDUCTOR,
DIELECTRIC,
Expand Down
9 changes: 4 additions & 5 deletions src/domain/mesh/meshline_policy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,12 @@ MeshlinePolicy::MeshlinePolicy(
Coord const coord,
Timepoint* t,
vector<IMeshLineOrigin*> const& origins,
bool const is_enabled,
double const res_factor)
bool const is_enabled)
: Originator(t, {
.policy = policy,
.normal = normal,
.is_enabled = is_enabled,
.res_factor = res_factor,
.d = global_params->get_current_state().dmax / res_factor,
.d = global_params->get_current_state().dmax / 2, // TODO this seems to help while center of intervals is buggy
.origins = origins
})
, axis(axis)
Expand All @@ -40,7 +38,8 @@ MeshlinePolicy::MeshlinePolicy(

//******************************************************************************
optional<Meshline> MeshlinePolicy::mesh() {
if(get_current_state().policy == Policy::ONELINE)
auto const& state = get_current_state();
if(state.is_enabled && state.policy == Policy::ONELINE)
return Meshline(coord, this);
else
return nullopt;
Expand Down
Loading
Loading