Well, I submitted what I consider actually coding contribution to Heekscad
http://code.google.com/p/heekscad/source/detail?r=1332
It’s not really a address the root cause of why these constraint errors are happening, but at least it catches some of them on a file load and blocks them so they don’t create segmentation faults.
I’m thinking that eventual this could be used on file save as well as file load. I was playing around with my pop-up card project and it seemed to be filtering the contraint bugs pretty well… If I ran into a critter, I might loose a constraint, but a least the program wouldn’t crash.
Than I start getting some segmentation faults, which I think are being caused by duplicate constraints. Man is this irritating….
So…. I think the next thing to investigate is if there is a checkForDuplicateContraint function within Heekscad and if not, write one.
After that, I suppose we need to comeup with a routine to validate the constraints within memory and if someone goofy shows up, pop up a message box. I think that might be useful to zero in on what ever is creating these problems and hopefully fix it.
So..
First step I think is poking around src/ConstraintObject.h
// ConstrainedObject.h
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.
#pragma once
class Constraint;
#include “../interface/HeeksObj.h”
#include “Constraint.h”
class HPoint;
class ConstrainedObject: public ObjList{
public:
std::list constraints;ConstrainedObject();
~ConstrainedObject(void);const ConstrainedObject& operator=(const ConstrainedObject &b);
virtual void LoadToDoubles();
virtual void LoadFromDoubles();void SetAbsoluteAngleConstraint(EnumAbsoluteAngle angle);
bool SetPerpendicularConstraint(ConstrainedObject* obj);
bool SetParallelConstraint(ConstrainedObject* obj);
bool SetEqualLengthConstraint(ConstrainedObject* obj);
bool SetColinearConstraint(ConstrainedObject* obj);
bool SetConcentricConstraint(ConstrainedObject* obj);
bool SetEqualRadiusConstraint(ConstrainedObject* obj);
void glCommands(HeeksColor color, gp_Ax1 mid_point);
bool RemoveExisting(HeeksObj* obj, EnumConstraintType type);
Constraint* GetExisting(EnumConstraintType type);
bool HasConstraints();
void ReloadPointers();
void SetCoincidentPoint(ConstrainedObject* obj, bool remove);
bool HasPointConstraint(ConstrainedObject* obj);
void SetLineLengthConstraint(double length);
void SetLineVerticalLengthConstraint(double length);
void SetLineHorizontalLengthConstraint(double length);
void SetRadiusConstraint(double radius);
void SetLineLength(double length);
void SetLineVerticalLength(double length);
void SetLineHorizontalLength(double length);
void SetRadius(double radius);
void SetTangentConstraint(ConstrainedObject* obj);
void SetPointOnLineConstraint(HPoint* obj);
void SetPointOnLineMidpointConstraint(HPoint* obj);
void SetPointOnArcConstraint(HPoint* obj);
void SetPointOnArcMidpointConstraint(HPoint* obj);
void SetPointOnCircleConstraint(HPoint* obj);
void SetPointFixedConstraint();
};
Hmm… This looks real promising here:
I think poking around the implementation of these functions could give me an idea of what I need to do.
bool RemoveExisting(HeeksObj* obj, EnumConstraintType type);
Constraint* GetExisting(EnumConstraintType type);
bool HasConstraints();
So… I was looking at these implementations:
bool ConstrainedObject::HasConstraints()
{
return !constraints.empty();
}
bool ConstrainedObject::HasPointConstraint(ConstrainedObject* obj)
{
std::list::iterator it;
for(it = constraints.begin(); it!=constraints.end(); ++it)
{
Constraint* c = *it;
if(c->m_type == CoincidantPointConstraint)
{
if(c->m_obj1 == this && c->m_obj2 == obj)
return true;
if(c->m_obj2 == this && c->m_obj1 == obj)
return true;
}
}
return false;
So… I think I could hack up HasPointConstraint to see if I can turn it into something that has a duplicate constraint… I need to think about this some more.
What I don’t understand at the moment… Is how “constrains” falls into this… Lets see:
class constraint
{
public:
constraint(){parameter = 0;}
constraintType type;
point point1;
point point2;
line line1;
line line2;
line SymLine;
circle circle1;
circle circle2;
ellipse ellipse1;
ellipse ellipse2;
arc arc1;
arc arc2;
double *parameter; //radius, length, angle etc…
};
Ok.. I wasn’t expecting this. So… We have a vector which defines arcs and line… and when you go into the definition of those things… Point for example there is a pointer..
class point
{
public:
point(){x = 0; y = 0;}
double * x;
double * y;
};
So x, y are pointers… So does that me they are pointers to the heeksobj?? Don’t know yet…. There be a lot of weird stuff going on here….
What the… there is a “class Constraint” and a
”
c
lass constraint”
Oh… that’s not confusing..
class Constraint : public HeeksObj{
public:
ConstrainedObject* m_obj1;
ConstrainedObject* m_obj2;EnumConstraintType m_type;
EnumAbsoluteAngle m_angle;double m_length;
Constraint();
Constraint(const Constraint* obj);
Constraint(EnumConstraintType,EnumAbsoluteAngle,ConstrainedObject* obj);
Constraint(EnumConstraintType,double length,ConstrainedObject* obj);
Constraint(EnumConstraintType,ConstrainedObject* obj);
Constraint(EnumConstraintType,ConstrainedObject* obj1, ConstrainedObject* obj2);
Constraint(EnumConstraintType,EnumAbsoluteAngle,double length,ConstrainedObject* obj1, ConstrainedObject* obj2);~Constraint(void);
void ReloadPointers();
bool IsTransient(){return true;}
HeeksObj *MakeACopy(void)const;
int GetType()const{return ConstraintType;}
const wxChar* GetTypeString(void)const{return _(“Constraint”);}
void Disconnect(std::list parents);
void WriteXML(TiXmlNode *root);
static HeeksObj* ReadFromXMLElement(TiXmlElement* pElem);
static void BeginSave();
static void EndSave(TiXmlNode *root);
bool IsDifferent(HeeksObj* other);bool operator==(const Constraint &other) const {
return m_type == other.m_type && m_angle==other.m_angle && m_obj1 == other.m_obj1 && m_obj2 == other.m_obj2 && m_length == other.m_length;
}const Constraint& operator=(const Constraint &b);
void glCommands(HeeksColor color, gp_Ax1 mid_point);
void render_text(const wxChar* str);};
So… The big “C”onstraint is a HeeksObj and the little “c”onstraint is a object is in a vector.
I suppose that makes sense… I’m thinking that the pointer in the constraint is probably looking at that location in the heeksobj. Maybe? The thing that does make sense is how would this setup work with multiple sketches…
Hmm.
Time for a quick test.
Ok… Id’s are unique to lines and points but it looks like they done renumber in sketches.. In other works sketch 1 has lines 1-5 and sketch 2 lines 6-7… etch…
So… I did a little experiment here… I set a break point on the Constraint constructor that would fire for a horizontal line and fired up the code::blocks debugger and stepped into until I got here.
#0 ( ObjList::Add(this=0x87bbdd0, object=0x885c1e0, prev_object=0x0) (/home/jonas/HeeksCAD/interface/ObjList.cpp:224)
#1 0x80b6b40 Constraint(this=0x885c1e0, type=AbsoluteAngleConstraint, angle=AbsoluteAngleHorizontal, obj=0x87bbdd0) (/home/jonas/HeeksCAD/src/Constraint.cpp:61)
#2 0x80b56ac ConstrainedObject::SetAbsoluteAngleConstraint(this=0x87bbdd0, angle=AbsoluteAngleHorizontal) (/home/jonas/HeeksCAD/src/ConstrainedObject.cpp:149)
#3 0x812d279 SetLineHorizontal::Run(this=0x83838c4) (/home/jonas/HeeksCAD/src/HLine.cpp:42)
#4 0x8144fa2 HeeksCADapp::on_menu_event(this=0x84af4d8, event=…) (/home/jonas/HeeksCAD/src/HeeksCAD.cpp:1982)
#5 0x810a8d4 CGraphicsCanvas::OnMenuEvent(this=0x85e0488, event=…) (/home/jonas/HeeksCAD/src/GraphicsCanvas.cpp:396)
#6 0xb77bfa9f wxAppConsole::HandleEvent(wxEvtHandler*, void (wxEvtHandler::*)(wxEvent&) (/usr/lib/libwx_baseu-2.8.so.0:??)
#7 0xb785e209 wxEvtHandler::ProcessEventIfMatches(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () (/usr/lib/libwx_baseu-2.8.so.0:??)
#8 0xb785f2d4 wxEventHashTable::HandleEvent(wxEvent&, wxEvtHandler*) () (/usr/lib/libwx_baseu-2.8.so.0:??)
#9 0xb785f3d3 wxEvtHandler::ProcessEvent(wxEvent&) () (/usr/lib/libwx_baseu-2.8.so.0:??)
#10 0xb7b281dd wxMenuBase::SendEvent(int, int) () (/usr/lib/libwx_gtk2u_core-2.8.so.0:??)
#11 0xb7aabdf0 ??() (/usr/lib/libwx_gtk2u_core-2.8.so.0:??)
#12 0xb3446dcc g_cclosure_marshal_VOID__VOID() (/usr/lib/libgobject-2.0.so.0:??)
#13 0xb3439252 g_closure_invoke() (/usr/lib/libgobject-2.0.so.0:??)
#14 0xb344d99d ??() (/usr/lib/libgobject-2.0.so.0:??)
#15 0xb344edb4 g_signal_emit_valist() (/usr/lib/libgobject-2.0.so.0:??)
#16 0xb344f256 g_signal_emit() (/usr/lib/libgobject-2.0.so.0:??)
#17 0xb39563e5 gtk_widget_activate() (/usr/lib/libgtk-x11-2.0.so.0:??)
#18 0xb38349a0 gtk_menu_shell_activate_item() (/usr/lib/libgtk-x11-2.0.so.0:??)
#19 0xb383631f ??() (/usr/lib/libgtk-x11-2.0.so.0:??)
#20 0xb382bc64 ??() (/usr/lib/libgtk-x11-2.0.so.0:??)
#21 0xb3825424 ??() (/usr/lib/libgtk-x11-2.0.so.0:??)
#22 0xb34378b9 ??() (/usr/lib/libgobject-2.0.so.0:??)
#23 0xb3439252 g_closure_invoke() (/usr/lib/libgobject-2.0.so.0:??)
#24 0xb344d5e6 ??() (/usr/lib/libgobject-2.0.so.0:??)
#25 0xb344ec33 g_signal_emit_valist() (/usr/lib/libgobject-2.0.so.0:??)
#26 0xb344f256 g_signal_emit() (/usr/lib/libgobject-2.0.so.0:??)
#27 0xb3952636 ??() (/usr/lib/libgtk-x11-2.0.so.0:??)
#28 0xb381da5d gtk_propagate_event() (/usr/lib/libgtk-x11-2.0.so.0:??)
#29 0xb381ee07 gtk_main_do_event() (/usr/lib/libgtk-x11-2.0.so.0:??)
Ok… I got to say this code blocks debugger is way cool.
This is cool:
void ConstrainedObject::SetAbsoluteAngleConstraint(EnumAbsoluteAngle angle)
{
Constraint* c = GetExisting(AbsoluteAngleConstraint);
if(c)
{
if(c->m_angle == angle)
{
constraints.remove(c);
delete c;
}
else
c->m_angle = angle;}
else
constraints.push_back(new Constraint(AbsoluteAngleConstraint,angle,this));
}
Ok… and this…
bool ObjList::Add(HeeksObj* object, HeeksObj* prev_object)
{
if (object==NULL) return false;
if (!CanAdd(object)) return false;
if (m_objects.size()==0 || prev_object==NULL)
{
m_objects.push_back(object);
LoopIt = m_objects.end();
LoopIt–;
}
else
{
for(LoopIt = m_objects.begin(); LoopIt != m_objects.end(); LoopIt++) { if (*LoopIt==prev_object) break; }
m_objects.insert(LoopIt, object);
}
m_index_list_valid = false;
HeeksObj::Add(object, prev_object);#ifdef HEEKSCAD
if((!wxGetApp().m_in_OpenFile || wxGetApp().m_file_open_or_import_type != FileOpenTypeHeeks) && object->UsesID() && (object->m_id == 0 || (wxGetApp().m_file_open_or_import_type == FileImportTypeHeeks && wxGetApp().m_in_OpenFile)))
{
object->SetID(wxGetApp().GetNextID(object->GetIDGroupType()));
}
#else
if(!heeksCAD->InOpenFile() && object->UsesID() && object->m_id == 0)
{
object->SetID(heeksCAD->GetNextID(object->GetIDGroupType()));
}
#endifreturn true;
}
So this is scary.. this sort almost makes sense whats going on. I need to look at whats going on with bool ObjList::Add(HeeksObj* object, HeeksObj* prev_object) a little more in detail.
Something for a another day.