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
{
// -----------------------------------------------------------------------------
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 ()
{
// .. nothing yet ..
@ -36,10 +80,23 @@ RNetwork::~RNetwork ()
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
RNetwork::clear ()
{
m_elements.clear (); // must come before m_nodes
m_elements.clear (); // must happen before m_nodes
m_nodes.clear ();
m_elements_by_nodes.clear ();
m_nodes_by_type.clear ();
@ -51,7 +108,7 @@ std::map<std::pair<RNode::node_type, unsigned int>, RNode *> m_nodes;
RNode *
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));
if (i != m_nodes_by_type.end ()) {
@ -60,7 +117,7 @@ RNetwork::create_node (RNode::node_type type, unsigned int port_index)
} 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_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 {
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);
return new_node;
@ -87,13 +144,15 @@ RNetwork::create_element (double conductivity, RNode *a, RNode *b)
} else {
RElement *element = new RElement (conductivity, a, b);
a->elements.push_back (element);
element->m_ia = --a->elements.end ();
b->elements.push_back (element);
element->m_ia = --b->elements.end ();
RElement *element = new RElement (this, conductivity, a, b);
m_elements.push_back (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;
}
@ -102,9 +161,9 @@ RNetwork::create_element (double conductivity, RNode *a, RNode *b)
void
RNetwork::remove_node (RNode *node)
{
tl_assert (node->type == RNode::INTERNAL);
while (! node->elements.empty ()) {
remove_element (const_cast<RElement *> (node->elements.front ()));
tl_assert (node->type == RNode::Internal);
while (! node->m_elements.empty ()) {
delete const_cast<RElement *> (node->m_elements.front ());
}
delete node;
}
@ -112,19 +171,20 @@ RNetwork::remove_node (RNode *node)
void
RNetwork::remove_element (RElement *element)
{
RNode *a = const_cast<RNode *> (element->a);
RNode *b = const_cast<RNode *> (element->b);
RNode *a = const_cast<RNode *> (element->a ());
RNode *b = const_cast<RNode *> (element->b ());
delete element;
if (a && a->type == RNode::INTERNAL && a->elements.empty ()) {
if (a && a->type == RNode::Internal && a->m_elements.empty ()) {
delete a;
}
if (b && b->type == RNode::INTERNAL && b->elements.empty ()) {
if (b && b->type == RNode::Internal && b->m_elements.empty ()) {
delete b;
}
}
// -----------------------------------------------------------------------------
RExtractor::RExtractor ()
{

View File

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

View File

@ -24,8 +24,53 @@
#include "pexRExtractor.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 (), "");
}