Delving into heekscad object->WriteXML(root) hummed to the tune of grandma got run over by a reindeer

This is part of my virtual road trip to write test routine to find constraint bugs, to fix the bugs  that are hosing up my pop-up card project.
I’m working on function to extract constraint information in part  how this data is saved to xml.

I’m trying to write this function as I tear apart the function that saves to xml.  Initially, I thought that all I had to do was to iterate through the m_objects list and everything would spit out.
Well, I was correct insofar as I need to iterate through the list, but that doesn’t represent all the  objects.  It seems to me that what I’m looking at in that saveXML file is the tips of various icebergs represents by sketches.
So…to really see whats going on, I need to get my hammer drill out and part poking around the iceberg around the  WriteXML function.     This function is a virtual function which is declared in the HeekObj.   I pretty much understand how this virtual function stuff works, but I needed at little confirmation that what I thought and what is it are pretty much the same thing.     I found this which to me was conceptually very easy to understand (http://en.wikipedia.org/wiki/Virtual_function

Ok… It seems like I need to understand what’s going on with.
object->WriteXML(root)
So… where does this show up..
Checking my Doxy documentations.

WriteXML() : HeeksObj , Constraint , CoordinateSystem , CEdge , CFace , CGroup , HAngularDimension , HArc , HCircle , HDimension , HEllipse , HILine , HImage , HLine , HPoint , HSpline , HText , HXml , COrientationModifier , CPad , CPocket , CShape , CSketch , CStlSolid

Ok.. So what I think I need for my constraint tester function and what I hope I’m going to run into when I drill down into WriteXML() should hopefully be one in the same.
I’m thinking that I need some type of recursive thing that will iterate from the top of the tree down to the bottom.

Time to generate some more theories to test.
So a HeeksObj base class to me seems to be more of a kid than a parent:
I get this from the HeekObj list pointer called m_owners.

class HeeksObj{
std::list<HeeksObj*> m_owners;
std::list<HeeksObj*>::iterator m_owners_it;
public:
bool m_skip_for_undo;
unsigned int m_id;
unsigned int m_layer;
bool m_visible;
bool m_preserving_id;

HeeksObj(void);
HeeksObj(const HeeksObj& ho);
virtual ~HeeksObj();

I suspected m_owners is a list of the parents that this child belongs to.
Now I think mom and dad are pretty much represented by

class ObjList : public HeeksObj
{
protected:
std::list m_objects;
std::list::iterator LoopIt;
std::list::iterator> LoopItStack;
std::vector m_index_list; // for quick performance of GetAtIndex();
bool m_index_list_valid;

void recalculate_index_list();
void copy_objects(const ObjList& objlist);

public:

Now… I believe the grand matriarch who keeps tabs on the operation is represented HeekCadAPP

class HeeksCADapp : public wxApp, public ObjList
{
private:
std::set observers;
#ifdef USE_UNDO_ENGINE
UndoEngine *history;
#endif
std::map > m_transient_objects;

typedef std::map< int, std::list > IdsToObjects_t;
typedef int GroupId_t;
typedef std::map< GroupId_t, IdsToObjects_t > UsedIds_t;

UsedIds_t used_ids;

// std::map< int, std::map > used_ids; // map of group type ( usually same as object type ) to “map of ID to object”
std::map< int, int > next_id_map;
std::map< std::string, HeeksObj*(*)(TiXmlElement* pElem) > xml_read_fn_map;

void render_screen_text2(const wxChar* str);
void RenderDatumOrCurrentCoordSys(bool select);

Our little matriarch tries to keep a tight reign on things and communication with the outside world I think runs through here via wxApp. Although at the moment, I don’t understand how to frame the relationship with m_transient_objects. Hopefully it’s one of grandma’s family secrets that we don’t need to know.

Now, when you take a look at how constraints are stored in a heekscad xml file that don’t really fall within a traditional family tree. It’s almost as if some parents where being naughty and there where some step-children the by-product. You don’t know where to put them and it’s unclear how to handle them.

One other think, I believe that grandma got around as was married a few times.. The side of the family that I believe her kids that we’re going to be looking at are named “Sketches”

Now this is how I framed this representation in my head, whether it represents reality… I guess we’ll see.

Ok..
back to object->WriteXML(root)
I’m going to create a single line in heekscad and create a breakpoint on WriteXML(root) to see if I can figure out the family dynamic of how grandma talks to here family and deals with here unruly stepchildren (aka constraints).

So.. grandma’s(HeekscadAPP) memory is not too good. She wrote down the address of her kids on a list m_objects ( from her one husband namd the sketches). So if someone asks grandma provide a list of her family (via saveXML) she gets a little red and embarrassed and quietly starts going through her phone book calling her kids(the sketches) via the virtual function WriteXML(root) which appears here:

void CSketch::WriteXML(TiXmlNode *root)
{
if (GetNumChildren() > 0)
{
TiXmlElement * element = new TiXmlElement( “Sketch” );
root->LinkEndChild( element );
element->SetAttribute(“title”, m_title.utf8_str());
WriteBaseXML(element);
}
}

So.. She makes her call to here kids the sketches… Now what’s curious to me is that if the sketch as no kids the phone doesn’t even get picked up (if (GetNumChildren() > 0).
GetNumChildren is a member function of Class Objlist and basically returns the count of the stl list of HeekObj pointers. Essentially Grandma is calling her kids and the first thing the Sketch side of the family tries figure out if they have any kids before they answer. Because WriteXML is a virtual function which is declared in the HeeksObj base class , the answer you get WriteXML may very depending on who inherited from HeekObj. Grandma may have some grandchildren who are maybe a brillliant C++ programmer or a bum…. Because GetNumChildren is not a virtual function, should it get asked within WriteXML, it would get answered the same way.

So… I want to take a look at an XML file of a simple line and compare it to the code above.

<?xml version=”1.0″ encoding=”UTF-8″ ?>
<HeeksCAD_Document>
<Sketch title=“Sketch” id=”1″>
<Line col=”0″ id=”1″>
<Point col=”0″ x=”-18″ y=”3″ z=”0″ id=”1″ />
<Point col=”0″ x=”-2″ y=”14″ z=”0″ id=”2″ />
</Line>
</Sketch>
</HeeksCAD_Document>

I’m making a bunch of assumptions here. I guess I should spet into SetAttribute so we what’s going on with that.
(woe… just a side note. I just stepped throw the constructor of TiXmlElement… I think you could probably spend a week studying that… (At least that’s heavily documented).
Now what gets interesting is when we step into the call:

void ObjList::WriteBaseXML(TiXmlElement *element)
{
std::list<HeeksObj*>::iterator It;
for(It=m_objects.begin(); It!=m_objects.end() ;It++) (*It)->WriteXML(element);
HeeksObj::WriteBaseXML(element);
}

Now it appears that grandma’s kids shares some characterics with grandma’ma in that they have a phone but of their kids and need to make a call to figure out how many children they have, in a similar, but unique way.
Know what’s got me confused is this Objlist::WriteBaseXML and then the HeekSObj::WriteBaseXML(element) later on… I’m not quite sure what’s up with that.
So… I think in this instance WriteXML (with sketch as the parent is going to find one child in here phone book called “Line” (whose going to make the call and find she has two kids named Point))

I see WriteBaseXML being called by all these objects but I get the impression it’s not as polymorphic as WriteXML.  I little trip to my doxy documentation should give me that answer to that.

WriteBaseXML() : HeeksObj , ObjList

Ok.. So two variations to WriteBaseXML.. I get I should list out HeeksOBJ::WriteBaseXML(element) to see if there’s anything that makes sense here.

void HeeksObj::WriteBaseXML(TiXmlElement *element)
{
#ifdef HEEKSCAD
wxGetApp().ObjectWriteBaseXML(this, element);
#else
heeksCAD->ObjectWriteBaseXML(this, element);
#endif
}

I’m not sure I need to deal with the ObjectWriteBaseXML, but I guess we should take a look at it:
Doxy says…
ObjectWriteBaseXML() : CHeeksCADInterface , HeeksCADapp

void HeeksCADapp::ObjectWriteBaseXML(HeeksObj *object, TiXmlElement *element)
{
if(object->UsesID())element->SetAttribute(“id”, object->m_id);
if(!object->m_visible)element->SetAttribute(“vis”, 0);
}

Ohhh… I was wondering where the Id gets set, I guess it’s here.

So the I think the way to think about this now, is that WriteXML is a phone call from the mom to each of here kids to ask them about their kids.
During this call, the Kids go through there phone book, who in turns….. and so and so on.

I suspect that the general recursive pattern is that
WriteXML calls ObjList::WriteBaseXML(TiXmlElement *element) which in recursively calls WriteXML and when its done calls HeeksObj:WriteBaseXML which basically returns the first name (Aka id=) of the object type being called.
I still need to test this out to confirm that I’m looking at this correctly. But it sort of makes sense to me.
Hmm… Out of time and I haven’t drilled down to those naughty stepkids the constraints yet..  Oh well.

I need to do some stuff with the real family…. so later…

This entry was posted in Uncategorized. Bookmark the permalink.

2 Responses to Delving into heekscad object->WriteXML(root) hummed to the tune of grandma got run over by a reindeer

  1. Michael Haberler says:

    Would you mind describing the steps how you generated the doxygen docs for HeeksCAD? I’d really appreciate it
    -Michael

  2. admin says:

    It’s not much of a guide, but I outlined my steps here.
    http://www.metalshaperman.com/?p=478
    Reading over my notes, they are not particularly useful, but perhaps they can help. I’m on the verge of completing (? when is anything ever done) a routine to validate constraints which I hope to commit within the next couple of days.
    At this point, I’ll want to update my source and regenerate my doxy documentation. I’ll make it a point to to write down some more coherent instructions.
    From what I recall:
    I needed to run doxywizard from the command line (which at the time seemed ironic to me, since it was a gui program).
    There was a option to use an alternate program to generate the graphs as an option. (I tried it both ways and really liked the alternate option rather than the default). I also vaguely remember thinking that I should written that down. sorry 🙁
    There is also option to install a search function and basically run it from a server which I didn’t choose and decided to run locally off static HTML files

    Overall, the doxywizard was one of the most painless experiences I’ve had in my Linux adventure. It pretty much drove itself and really produced some remarkable results.
    I really don’t think you’ll have major issues using it. Let me know how it works out, perhaps we can collaborate and post some instructions on how to generate it on the heeks wiki or figure out how to post the actual doxy documentation.

    JT

Leave a Reply

Your email address will not be published. Required fields are marked *