This commit is contained in:
Matthias Koefferlein 2025-04-19 16:14:15 +02:00
parent 8a122c8a7d
commit dfe67178dc
3 changed files with 158 additions and 33 deletions

View File

@ -26,6 +26,50 @@
namespace pex namespace pex
{ {
// -----------------------------------------------------------------------------
std::string
RNode::to_string () const
{
std::string res;
switch (type) {
default:
res += "$" + tl::to_string (port_index);
break;
case VertexPort:
res += "V" + tl::to_string (port_index);
break;
case PolygonPort:
res += "P" + tl::to_string (port_index);
break;
}
return res;
}
// -----------------------------------------------------------------------------
std::string
RElement::to_string () const
{
std::string res = "R ";
if (a ()) {
res += a ()->to_string ();
} else {
res += "(nil)";
}
res += " ";
if (b ()) {
res += b ()->to_string ();
} else {
res += "(nil)";
}
res += " ";
res += tl::sprintf ("%.6g", resistance ());
return res;
}
// -----------------------------------------------------------------------------
RNetwork::RNetwork () RNetwork::RNetwork ()
{ {
// .. nothing yet .. // .. nothing yet ..
@ -36,10 +80,23 @@ RNetwork::~RNetwork ()
clear (); clear ();
} }
std::string
RNetwork::to_string () const
{
std::string res;
for (auto e = m_elements.begin (); e != m_elements.end (); ++e) {
if (! res.empty ()) {
res += "\n";
}
res += e->to_string ();
}
return res;
}
void void
RNetwork::clear () RNetwork::clear ()
{ {
m_elements.clear (); // must come before m_nodes m_elements.clear (); // must happen before m_nodes
m_nodes.clear (); m_nodes.clear ();
m_elements_by_nodes.clear (); m_elements_by_nodes.clear ();
m_nodes_by_type.clear (); m_nodes_by_type.clear ();
@ -51,7 +108,7 @@ std::map<std::pair<RNode::node_type, unsigned int>, RNode *> m_nodes;
RNode * RNode *
RNetwork::create_node (RNode::node_type type, unsigned int port_index) RNetwork::create_node (RNode::node_type type, unsigned int port_index)
{ {
if (type != RNode::INTERNAL) { if (type != RNode::Internal) {
auto i = m_nodes_by_type.find (std::make_pair (type, port_index)); auto i = m_nodes_by_type.find (std::make_pair (type, port_index));
if (i != m_nodes_by_type.end ()) { if (i != m_nodes_by_type.end ()) {
@ -60,7 +117,7 @@ RNetwork::create_node (RNode::node_type type, unsigned int port_index)
} else { } else {
RNode *new_node = new RNode (type, db::DBox (), port_index); RNode *new_node = new RNode (this, type, db::DBox (), port_index);
m_nodes.push_back (new_node); m_nodes.push_back (new_node);
m_nodes_by_type.insert (std::make_pair (std::make_pair (type, port_index), new_node)); m_nodes_by_type.insert (std::make_pair (std::make_pair (type, port_index), new_node));
@ -69,7 +126,7 @@ RNetwork::create_node (RNode::node_type type, unsigned int port_index)
} else { } else {
RNode *new_node = new RNode (type, db::DBox (), port_index); RNode *new_node = new RNode (this, type, db::DBox (), port_index);
m_nodes.push_back (new_node); m_nodes.push_back (new_node);
return new_node; return new_node;
@ -87,13 +144,15 @@ RNetwork::create_element (double conductivity, RNode *a, RNode *b)
} else { } else {
RElement *element = new RElement (conductivity, a, b); RElement *element = new RElement (this, conductivity, a, b);
a->elements.push_back (element); m_elements.push_back (element);
element->m_ia = --a->elements.end ();
b->elements.push_back (element);
element->m_ia = --b->elements.end ();
m_elements_by_nodes.insert (std::make_pair (std::make_pair (a, b), element)); m_elements_by_nodes.insert (std::make_pair (std::make_pair (a, b), element));
a->m_elements.push_back (element);
element->m_ia = --a->m_elements.end ();
b->m_elements.push_back (element);
element->m_ib = --b->m_elements.end ();
return element; return element;
} }
@ -102,9 +161,9 @@ RNetwork::create_element (double conductivity, RNode *a, RNode *b)
void void
RNetwork::remove_node (RNode *node) RNetwork::remove_node (RNode *node)
{ {
tl_assert (node->type == RNode::INTERNAL); tl_assert (node->type == RNode::Internal);
while (! node->elements.empty ()) { while (! node->m_elements.empty ()) {
remove_element (const_cast<RElement *> (node->elements.front ())); delete const_cast<RElement *> (node->m_elements.front ());
} }
delete node; delete node;
} }
@ -112,19 +171,20 @@ RNetwork::remove_node (RNode *node)
void void
RNetwork::remove_element (RElement *element) RNetwork::remove_element (RElement *element)
{ {
RNode *a = const_cast<RNode *> (element->a); RNode *a = const_cast<RNode *> (element->a ());
RNode *b = const_cast<RNode *> (element->b); RNode *b = const_cast<RNode *> (element->b ());
delete element; delete element;
if (a && a->type == RNode::INTERNAL && a->elements.empty ()) { if (a && a->type == RNode::Internal && a->m_elements.empty ()) {
delete a; delete a;
} }
if (b && b->type == RNode::INTERNAL && b->elements.empty ()) { if (b && b->type == RNode::Internal && b->m_elements.empty ()) {
delete b; delete b;
} }
} }
// -----------------------------------------------------------------------------
RExtractor::RExtractor () RExtractor::RExtractor ()
{ {

View File

@ -39,28 +39,36 @@ namespace pex
class RElement; class RElement;
class RNode; class RNode;
class RNetwork;
struct PEX_PUBLIC RNode struct PEX_PUBLIC RNode
: public tl::list_node<RNode> : public tl::list_node<RNode>
{ {
public: public:
enum node_type { enum node_type {
INTERNAL, Internal,
VERTEX_PORT, VertexPort,
POLYGON_PORT PolygonPort
}; };
node_type type; node_type type;
db::DBox location; db::DBox location;
unsigned int port_index; unsigned int port_index;
mutable std::list<const RElement *> elements;
const std::list<const RElement *> &elements () const
{
return m_elements;
}
std::string to_string () const;
protected: protected:
friend class RNetwork; friend class RNetwork;
friend class RElement;
friend class tl::list_impl<RNode, false>; friend class tl::list_impl<RNode, false>;
RNode (node_type _type, const db::DBox &_location, unsigned int _port_index) RNode (RNetwork *network, node_type _type, const db::DBox &_location, unsigned int _port_index)
: type (_type), location (_location), port_index (_port_index) : type (_type), location (_location), port_index (_port_index), mp_network (network)
{ } { }
~RNode () { } ~RNode () { }
@ -68,39 +76,48 @@ protected:
private: private:
RNode (const RNode &other); RNode (const RNode &other);
RNode &operator= (const RNode &other); RNode &operator= (const RNode &other);
RNetwork *mp_network;
mutable std::list<const RElement *> m_elements;
}; };
struct PEX_PUBLIC RElement struct PEX_PUBLIC RElement
: public tl::list_node<RElement> : public tl::list_node<RElement>
{ {
double conductivity; double conductivity;
const RNode *a, *b;
const RNode *a () const { return mp_a; }
const RNode *b () const { return mp_b; }
double resistance () const double resistance () const
{ {
return 1.0 / conductivity; return 1.0 / conductivity;
} }
std::string to_string () const;
protected: protected:
friend class RNetwork; friend class RNetwork;
friend class tl::list_impl<RElement, false>; friend class tl::list_impl<RElement, false>;
RElement (double _conductivity, const RNode *_a, const RNode *_b) RElement (RNetwork *network, double _conductivity, const RNode *a, const RNode *b)
: conductivity (_conductivity), a (_a), b (_b) : conductivity (_conductivity), mp_network (network), mp_a (a), mp_b (b)
{ } { }
~RElement () ~RElement ()
{ {
if (a) { if (mp_a) {
a->elements.erase (m_ia); mp_a->m_elements.erase (m_ia);
} }
if (b) { if (mp_b) {
b->elements.erase (m_ib); mp_b->m_elements.erase (m_ib);
} }
a = b = 0; mp_a = mp_b = 0;
} }
std::list<const RElement *>::iterator m_ia, m_ib; std::list<const RElement *>::iterator m_ia, m_ib;
RNetwork *mp_network;
const RNode *mp_a, *mp_b;
private: private:
RElement (const RElement &other); RElement (const RElement &other);
@ -108,6 +125,7 @@ private:
}; };
class PEX_PUBLIC RNetwork class PEX_PUBLIC RNetwork
: public tl::Object
{ {
public: public:
RNetwork (); RNetwork ();
@ -119,6 +137,8 @@ public:
void remove_node (RNode *node); void remove_node (RNode *node);
void clear (); void clear ();
std::string to_string () const;
private: private:
tl::list<RNode, false> m_nodes; tl::list<RNode, false> m_nodes;
tl::list<RElement, false> m_elements; tl::list<RElement, false> m_elements;

View File

@ -24,8 +24,53 @@
#include "pexRExtractor.h" #include "pexRExtractor.h"
#include "tlUnitTest.h" #include "tlUnitTest.h"
TEST(1) TEST(network_basic)
{ {
// @@@ pex::RNetwork rn;
EXPECT_EQ (rn.to_string (), "");
pex::RNode *n1 = rn.create_node (pex::RNode::Internal, 1);
pex::RNode *n2 = rn.create_node (pex::RNode::Internal, 2);
/* pex::RElement *e12 = */ rn.create_element (0.5, n1, n2);
EXPECT_EQ (rn.to_string (),
"R $1 $2 2"
);
pex::RNode *n3 = rn.create_node (pex::RNode::Internal, 3);
/* pex::RElement *e13 = */ rn.create_element (0.25, n1, n3);
pex::RElement *e23 = rn.create_element (1.0, n2, n3);
EXPECT_EQ (rn.to_string (),
"R $1 $2 2\n"
"R $1 $3 4\n"
"R $2 $3 1"
);
pex::RElement *e23b = rn.create_element (4.0, n2, n3);
EXPECT_EQ (e23 == e23b, true);
EXPECT_EQ (rn.to_string (),
"R $1 $2 2\n"
"R $1 $3 4\n"
"R $2 $3 0.2"
);
rn.remove_element (e23);
EXPECT_EQ (rn.to_string (),
"R $1 $2 2\n"
"R $1 $3 4"
);
rn.remove_node (n3);
EXPECT_EQ (rn.to_string (),
"R $1 $2 2"
);
rn.clear ();
EXPECT_EQ (rn.to_string (), "");
} }