Groups of nodes with the same attributes in GraphViz file - grouping

In the dot language of GraphViz I want to describe a 2-mode network. So I have nodes of two different types. One group for example could contains people how read and the other group could contain the books being read by the people.
I want to give the nodes in these two groups different looks (shape, color, etc). How can I specify the attributes for a group of nodes in one statement. The aim is to be able to change the look for each group of nodes in one place, not in all individual node descriptions.
This could be done with something like attribute inheritance, but I don't know whether the dot language has this concept.

In principal there are three possibilities
set default attributes before creating a node
globally - valid for all following node creations
locally in a subgraph - valid for node creations within subgraph only
create nodes with explicit attributes
assign attributes to a group of nodes after creation.
Options 1 and 2 allow only one group per node as creation is a single event. Option 3 allows different grouping for each assignment.
set default attributes globally before creating a node
digraph {
x // node with current defaults
// set default
node [shape=box color=red]
// create with default values
a1, a2
// set default
node [shape=circle color=blue]
// create with default values
b1, b2
y // node with current defaults
x->{a1 a2}
a1->{b1 b2}
a2->{b1 b2}
{b1,b2}->y
}
set default attributes locally before creating a node
digraph {
x // node with current defaults
{
// set default
node [shape=box color=red]
// create with default values
a1, a2
}
{
// set default
node [shape=circle color=blue]
// create with default values
b1, b2
}
y // node with current defaults
x->{a1 a2}
a1->{b1 b2}
a2->{b1 b2}
{b1,b2}->y
}
create nodes with explicit attributes
digraph {
x // node with current defaults
// create with explicit attributes
a1, a2 [shape=box color=red]
// create with explicit attributes
b1, b2 [shape=circle color=blue]
y // node with current defaults
x->{a1 a2}
a1->{b1 b2}
a2->{b1 b2}
{b1,b2}->y
}
assign attributes to a group of nodes after creation
digraph {
x // node with current defaults
// create with default values
a1, a2, b1, b2
// assign shape
a1, a2 [shape=box]
b1, b2 [shape=circle]
// assign color
a1, b2 [color=red]
b1, a2 [color=blue]
y // node with current defaults
x->{a1 a2}
a1->{b1 b2}
a2->{b1 b2}
{b1,b2}->y
}

This can be done for all nodes in a graph with the node keyword, or for all edges in graph with the edge keyword. This can also be done on a node-by-node or edge-by-edge basis.
Example for a whole graph or subgraph:
digraph
{
subgraph readers
{
node[shape=box; color=red;]
r1; r2; r3;
}
subgraph books
{
node[shape=circle; color=blue;]
b1; b2; b3;
}
r1->{b1 b2}
r2->{b2 b3}
r3->{b1 b2 b3}
}
This would give you the graph:
Example of per node attributes:
digraph
{
n1[shape=triangle];
n2[shape=star];
n3[shape=square];
n1->n2->n3
}
Would give the graph:

Related

How to get the parent node of the current node while iterating over YAML::Node?

I am building a tree structure while iterating over a YAML::Node. So far, i am able to build the tree when the hierarchy goes downwards. But if there is change in heirarchy i am not able to get the parent node.
batman:
type: super hero
entity: ""
natural: yes
attributes:
powers:
whip:
x: ""
y: ""
batmobile:
x: ""
y: ""
Based on the above structure, how do i get the parent node of batmobile?
Assuming, i am iterating like this:
for (YAML::const_iterator it = node.begin(); it != node.end(); ++it)
{
std::cout << it->first.as<std::string>() << std::endl; // prints batmobile
// how to get the parent node of batmobile?
}
You can't because in general, a YAML node does not have a single parent.
The content of a YAML file constitutes a directed graph, not a tree. For example, this YAML:
- &a 123
- foo: *a
Defines a sequence of two items, the scalar node 123 and a mapping node containing a single key-value pair. That pair has the scalar foo as key and the scalar node 123 as value (the alias gets resolved by the parser). This means that the scalar node 123 is referenced from two places and thus does not have a single parent.
Another problem would be that within a pair foo: bar, asking for the parent node of bar would yield the mapping containing the pair, because the pair itself is not a node. But you probably also want to know the corresponding key.
The takeaway is that when descending into a YAML graph, you need to store the path you take somewhere if you want to backtrack.

How do physics engine check if two objects belong to compatible categories for collisions?

To be clear, this question is not about geometry or about the actual physics of collision detection, but determining if two object belong to compatible categories for colliding (nothing to do with the actual physics part).
Take a look at this image:
Many physics engines (Box2d etc) follow such a system, where they allow you to define which category (Cat.) that an object belongs to, and the Mask - the categories of objects that it can collide with, and based on this determine if a collision should take place. I'm trying to implement the same, as I have an analogous problem, and need only this (no physics).
For example, an object (Object1) may belong to multiple categories - 0,1,2,3 and collide with categories (Mask), 5,8,9. Another Object (Object2), can belong to category (5), and collide only with Category (3). In this case a collision between Object1 and Object2 can take place.
Additional example, an object (Object1) may belong to multiple categories - 0,1,2,3 and collide with categories (Mask), 5,8,9. Another Object (Object2), can belong to category (5), and collide only with Category (4). In this case a collision between Object1 and Object2 will not take place, because although Object1 is interested in colliding with objects in category 5, Object2 is not interested in colliding with any of Object1's categories.
The collisions will take place only if A collides with B, and B collides with A.
I am trying to implement something which does the same, and am trying to figure out the data structure and algorithm to use, to efficiently check if two objects should "collide", according to the above logic. By efficiently, I mean use minimal memory and cpu required, so that I can do this check every clock tick - I am not trying to optimize specifically for memory or cpu, but simply find a solution that doesn't use more than it requires of each!
Here is the algorithm and data structures I've considered so far:
std::unordered_map<int,std::unordered_set<GameObject*>> categoryToObject
std::unordered_map<int,std::unordered_set<GameObject*>> maskToObject
std::unordered_map<GameObject*,std::unordered_set<GameObject*> objectsItCollidesWith
Algorithm:
Each time a new GameObject is created, for every category and mask it belongs to, it is added to the appropriate vector in each map. That means an object with Cat{1,3,7} & Mask{2,7} would be added to three vectors in the Cat map and two vectors in the mask map.
Just before adding to each map, for a new object, iterate through the categories of the new object, and use each category as a key in maskToObject, to see which gameObjects are interested in colliding with it. For each of these objects, check their category, and see if any of their categories fall into the mask that this object collides with. If that is the case, then add this object to a set of objects that this object collides with, and vice versa for the other object.
This way, as long as the categories / masks don't change, we just need to refer to the objectItCollidesWith map.
Is there a more efficient way than this ? Since the initial calculation needs to be done only once, and doesn't need to be done again unless the category / mask changes and I thought this was good.
Heres the solution I came up with.
Included only the part of my CollisionDetector class that is used for computing if two objects are in compatible categories for collision. Unlike the bitwise example, which I assume was used to quickly check all objects against each other, I think mine will be faster, since I check only against compatible categories and masks, rather than all objects.
The actual physics part - space subdivision, or checking for overlaps of objects is not relevant to this question, so not included.
typedef enum{
COLLISION_CATEGORY_NO_CAT = 0, //Used only for looping.
COLLISION_CATEGORY_PLAYER,
COLLISION_CATEGORY_GROUND,
COLLISION_CATEGORY_END_CAT, //Used only for looping.
}COLLISION_CATEGORIES;
class CollisionDetector{
private:
std::unordered_map<int,std::unordered_set<GameObject*>> categoryToObject; //Each gameObject belongs to the category key
std::unordered_map<int,std::unordered_set<GameObject*>> maskToObject; //Each gameObject contains the key as a mask
public:
CollisionDetector(){
for (int i = COLLISION_CATEGORY_NO_CAT + 1; i<COLLISION_CATEGORY_END_CAT; i++ ){
std::unordered_set<GameObject*> o;
categoryToObject[i] = o;
maskToObject[i] = o;
}
}
void addObject(GameObject* o){
auto objectCategories = o->getCategories();
auto objectMasks = o->getMasks();
//Check if A collides with B, and B collides with A. If so, make both objects keep note of each other.
for(auto& mask : objectMasks){
if(categoryToObject.find(mask)!=categoryToObject.end()){
//Get the objects whose category matches the mask.
auto& setOfObjectsWithCategoryMatchingMaskOfO = categoryToObject[mask];
for(auto otherObject : setOfObjectsWithCategoryMatchingMaskOfO){
//Check if this objects category is in the other objects mask
auto otherObjectsMasks = otherObject->getMasks();
for(auto& thisObjectsCategory : objectCategories){
if(otherObjectsMasks.find(thisObjectsCategory) != otherObjectsMasks.end()){
//Set both objects to collide with each other
o->addGameObjectICollideWith(otherObject);
otherObject->addGameObjectICollideWith(o);
//If even one of this objects category, is in the other objects mask, then we have fullfilled the condition that this objects category is in the other objects mask, and the other objects category is in this objects mask.
break;
}
}
}
}
}
//Add this object to each of the sets of objects with these categories, so other objects can do the first part of this function.
for(auto cat : objectCategories){
auto& s = categoryToObject[cat];
s.insert(o);
}
//Add this object to each of the sets of objects with these masks, so other objects can do the first part of this function.
for(auto mask : objectMasks){
auto& s = maskToObject[mask];
s.insert(o);
}
}
void removeObject(GameObject* o){
auto c = o->getCategories();
for(auto cat : c){
auto& s = categoryToObject[cat];
s.erase(o);
}
auto m = o->getMasks();
for(auto mask : m){
auto& s = maskToObject[mask];
s.erase(o);
}
o->removeMyselfFromObjectsICollideWith();
}
};
GameObject Class:
class GameObject{
private:
std::unordered_set<GameObject*> _gameObjectsICollideWith;
std::unordered_set<int> _categoriesIBelongTo;
std::unordered_set<int> _masksICollideWith;
public:
Sprite* sprite = nullptr;
//TODO: Do Zorder
GameObject(Node* parent, const Vec2& initialPosition,std::string frameName){
sprite = Sprite::createWithSpriteFrameName(frameName);
parent->addChild(sprite);
sprite->setPosition(initialPosition);
}
~GameObject(){
for(auto otherObject : _gameObjectsICollideWith){
otherObject->removeGameObjectICollideWith(this);
}
if(sprite!=nullptr){
if(sprite->getParent()){
sprite->removeFromParent();
}
}
}
std::unordered_set<int> getCategories(){
return _categoriesIBelongTo;
}
std::unordered_set<int> getMasks(){
return _masksICollideWith;
}
void setCategories(const std::unordered_set<int>& categories){
_categoriesIBelongTo = categories;
}
void setMasks(const std::unordered_set<int>& masks){
_masksICollideWith = masks;
}
void addGameObjectICollideWith(GameObject* o){
_gameObjectsICollideWith.insert(o);
}
void removeGameObjectICollideWith(GameObject* o){
_gameObjectsICollideWith.erase(o);
}
void removeMyselfFromObjectsICollideWith(){
for(auto other : _gameObjectsICollideWith){
other->removeGameObjectICollideWith(this);
}
_gameObjectsICollideWith.clear();
}
};

How to trigger an update of several C++ classes when a shared member of all the classes is updated

Lets say we have a scenario as follows (what I have tried up to now in some very striped down version):
class A{
std::vector<int> ma;
};
class B{
A param;
// members that depend on "param"
int mb1;
// members that DO NOT depend on "param"
int mb2;
B(const A &p, const int &x) param(p), mb2(x) {
make_mb1();
};
void make_mb1(){
mb2 = std::accumulate(param.begin(), param.end(), 0);
};
};
int main{
A a({1,2,3});
B b1(a,1), b2(a,2), b3(a,3);
return 0;
}
When the contents of a are updated I would like all instances of B class that have a to updated them selves accordingly, so I want a behavior something like this:
int main{
A a({1,2,3});
B b1(a,...), b2(a,...), b3(a,...);
// first case
a = std::vector({4,5,6});
// b1, b2, b3 trigger an updated of members that depend on param
// second case
b1.param = std::vector({7,8,9});
// b1, b2, b3 trigger an updated of members that depend on param
return 0;
}
How can I do this so that all I need to do as a user is to simply updated the contents of a through its instance (first case above) or through any member instances (second case above) and then b1,b2,b3 trigger an internal update (perhaps using make_mb1) of members automatically without needing further code in main? If this is a concept with a name I am more than happy to just get the name and I will research it (I have tried to figure this out but can't seam to find how this would be called so I am having a hard time figuring out what to look up).

Method is being called on class with uninitialized attributes despite constructors

Premise: suppose I have a rectangular subset of 2D space and a collection of points, all with different x-values, in this subset. In the interest of the optimization of an algorithm as yet unwritten, I want to split my box into cells according to the following process: I halve my rectangle into 2 equal parts along the x-axis. Then I repeatedly halve each sub-rectangle until every cell contains either 1 point or none at all.
In this illustration the vertical lines represent the “halving process” and the lines are ordered by darkness (darker is newer).
First I’ll define two basic classes:
class Point{
private:
double x;
double y;
public:
// [...]
// the relevant constructor and getter
// overloaded operators +, -, * for vector calculations
};
class Box{
private:
Point bottom_left_point;
double width;
double height;
public:
Box(Point my_point, double my_x, double my_y) : // constructor
bottom_left_point(my_point), width(my_x), height(my_y){}
bool contains(const Point& p); // returns true iff the box contains p in the geometric sense
Box halve(bool b) const; // takes a boolean as input and returns the left half-rectangle for false, and the right half-rectangle for true
};
Now to implement the “halving algorithm” I’ll need a binary tree-like structure. Each node will represent a sub-cell of the rectangle (with the root node representing the total rectangle). A node may have two children, in which case the children represent its left and right halves. A node may also have a pointer to a particle which exists in the cell. The ultimate idea will be to start with an empty tree and insert the points in, one by one using a method insert(Point* to_be_inserted).
So I’ll define the following recursive class, whose private attributes are rather self-explanatory:
class Node;
class Node{
private:
enum node_type{ INT, EXT, EMPTY };
node_type type;
// type == INT means that it is an interior node, i.e. has children
// type == EXT means that it is an exterior node, i.e. has no children but contains a point
// type == EMPTY means that it has no children and no point
std::array<Node*,2> children;
Box domain; // the geometric region which is being represented
Point* tenant; // address of the particle that exists in this cell (if one such exists)
public:
Node(Box my_domain) :
type(EMPTY), children({nullptr}), domain(my_domain){}
//
// to be continued...
The first order of business is to define a subdivide() method which endows my node with two children:
void Node::subdivide(void){
type = INT;
children[0] = new Node(domain.halve(false));
children[1] = new Node(domain.halve(true));
}
Now everything is in place to write the crux of this whole affair, the insert method. Since it will be written recursively, the easiest solution is to have a boolean return type which tells us if the insertion was a success or failure. With this in mind, here’s the code:
bool Node::insert(Point* to_be_inserted){
if(not domain.contains(*to_be_inserted)) return false;
switch(type){
case INT:{
for(Node* child : children) if(child->insert(to_be_inserted)) return true;
return false;
}
case EXT:{
subdivide();
for(Node* child : children) if(child->insert(to_be_inserted)) break;
tenant = nullptr;
for(Node* child : children) if(child->insert(to_be_inserted)) return true;
break;
}
case EMPTY:{
type = EXT;
tenant = to_be_inserted;
return true;
}
}
throw 1; // this line should not, in, theory ever be reached
}
(Note that, for the sake of abstraction and generality, I have used for loops on the array children when I could have simply written out the two cases.)
Explanation:
First we check if to_be_inserted is in the geometric region represented by this. If not, return false.
If this is an internal node, we pass the point on to the each child until it is successfully inserted.
If this is an external node, that means that we have to split the node in two in order to be able to properly isolate to_be_inserted from the point that currently lives in the node.
First we call multiply().
Then we attempt to insert the current tenant into one of the children (please excuse how obscene this sounds, I assure you that it’s unintentional).
Once that is done, we do the same with to_be_inserted and return the result. (Note that a priori the insertion would be a success at this point because of the preliminary call to box::contains.
Finally, if this is an EMPTY node, we simply have to assign tenant to *to_be_inserted and change type to EXT and we’re done.
Ok, so let's try it out with a simple main:
int main(void){
Box my_box(ORIGIN, 1.0, 1.0); // rectangle of vertices (0,0),(0,1),(1,0),(1,1)
Node tree(box); // initializes an empty tree representing the region of my_box
Point p(0.1, 0.1);
Point q(0.6, 0.7);
tree.insert(&p);
tree.insert(&q);
return 0;
}
This compiles, but upon running the exception at the bottom of insert is thrown after a few calls. How is this possible, given that at no point a Node is constructed without a type value?
Edit: I have noticed, as well as this one, several possible errors which may also occur with small changes in the code:
An inexplicable call to nullptr->insert(something)
A call to insert by the address 0x0000000000000018 which doesn't point to an initialized Node.
The entirety of the code, including a makefile with the relevant debugging flags, can be found at https://github.com/raphael-vock/phantom-call.

Duplicating an edge in ogdf::GraphCopy

I'm using OGDF version 2012.07.
I have a GraphCopy which represents a copy of a Graph instance. It holds references to the original nodes and edges when operating on the graph copy. In the documentation of GraphCopy, it says:
Copies of graphs supporting edge splitting.
The class GraphCopy represents a copy of a graph and maintains a mapping between the nodes and edges of the original graph to the copy and vice versa.
[...]
There is a method ogdf::GraphCopy::newEdge(edge eOrig) which is documented as follows:
Creates a new edge (v,w) with original edge eOrig.
The method is implemented as follows:
edge GraphCopy::newEdge(edge eOrig)
{
OGDF_ASSERT(eOrig != 0 && eOrig->graphOf() == m_pGraph);
OGDF_ASSERT(m_eCopy[eOrig].empty()); // no support for edge splitting!
edge e = Graph::newEdge(m_vCopy[eOrig->source()], m_vCopy[eOrig->target()]);
m_eCopy[m_eOrig[e] = eOrig].pushBack(e);
return e;
}
In the second assertion, the number of associated edge copies of the edge eOrig in the original graph has to be zero, which is only possible when the edge copy has been deleted, since initially (when the GraphCopy was initialized with an original graph) all edges in the graph copy are associated with the corresponding original edge in the original graph; thus, m_eCopy[eOrig].empty() is false for all edges.
How am I supposed to duplicate an edge in the graph copy while not changing the original graph?
I can not follow your explanations about the implementation. When I browse the source code GraphCopy.h on the OGDF website (which says its for 2012.07.), I see totally different classes. There is one class GraphCopy (which is an interface for derrived GraphCopy classes supporting edge splitting) and another class GraphCopySimple which doesn't support edge spliting.
So my advice is to check if you really have the right version.
The method newEdge(edge eOrig) in GraphCopySimple looks like it does what you want:
edge newEdge(edge eOrig) {
OGDF_ASSERT(eOrig != 0 && eOrig->graphOf() == m_pGraph);
edge e = Graph::newEdge(m_vCopy[eOrig->source()], m_vCopy[eOrig->target()]);
m_eCopy[m_eOrig[e] = eOrig] = e;
return e;
}
But there is one issue remaining. GraphCopySimple has no implementation for the constructors, so I guess it meant as abstract base class, so you need to derive your own GraphCopy-class and implement the missing functions.