DrawSketchHandlerLineSet walk through

I’ve been trying to get the silly arc going without really understanding how the whole line thing draws out so I thought it be good for me to work it out.    The polyline code migrates back and forth through mousemoves, mouse down and mouse up events…  There’s are lot of weaving in and out, of varying states so it’s sort of hard to figure out what’s going on.    I got the code hacked up to start incorporating the arc, but only the line portion is fully functional at this point(The enums are slightly different. Once again this may only make sense to me…

I’m wondering if I be better off flowcharting this out, but…let  see if this works…
Ok.. So the DrawSketchHanlderLineSet Object gets create here:

void CmdSketcherCreatePolyline::activated(int iMsg)
{
ActivateHandler(getActiveGuiDocument(),new DrawSketchHandlerLineSet() );
}

So… This will fire off the constructor

DrawSketchHandlerLineSet()
: Mode(STATUS_LINE_SEEK_First),EditCurve(2),firstPoint(-1),previousCurve(-1),LineMode(LINE_MODE_Line){
keyArcValue=(int)SoKeyboardEvent::A;
}

STATUS_LINE_SEE_First, LineMode, KeyArcValue are my creations…..

So… what are these variables getting initialized: (Bold was prehacked)
std::vector<Base::Vector2D> EditCurve;
    Base::Vector2D lastPos;
    int firstPoint;
    int firstCurve;
    int previousCurve;
    std::vector<AutoConstraint> sugConstr1, sugConstr2, sugConstr3;

Base::Vector2D CenterPoint;
float rx, ry, startAngle, endAngle, arcAngle;

private:
int keyArcValue;
SelectLineMode LineMode;

 

So EditCurve is a freecad construct and everything else seems seems pretty straight forward except for the suggested constraints.

 

The Vector2D is defined within ../src/Base/Tools2D.h

 

namespace Base {

class Vector2D;
class BoundBox2D;
class Line2D;
class Polygon2D;

/**
* The vector class for 2D calculations.
*/
class BaseExport Vector2D
{
public:
float fX, fY;

inline Vector2D (void);
inline Vector2D (float x, float y);
inline Vector2D (double x, double y);
inline Vector2D (const Vector2D &rclVct);

// methods
inline float Length (void) const;

// operators
inline Vector2D& operator= (const Vector2D &rclVct);
inline float     operator* (const Vector2D &rclVct) const;
inline bool      operator== (const Vector2D &rclVct) const;
inline Vector2D  operator+ (const Vector2D &rclVct) const;
inline Vector2D  operator- (const Vector2D &rclVct) const;

inline void Set (float fPX, float fPY);
inline void Scale (float fS);
inline void Normalize (void);
float GetAngle (const Vector2D &rclVect) const;
void  ProjToLine (const Vector2D &rclPt, const Vector2D &rclLine);
};

Note to self… that GetAngle function look like it could come in handy for me…
Ok… So I guess I should look at the AutoConstraint to see what that’s made out of..

// A Simple data type to hold basic information for suggested constraints
struct AutoConstraint
{
Sketcher::ConstraintType Type;
int Index;
};

enum Type
{
VERTEX,
CURVE
};

Everything appears straight forward  except I don’t know how the Index in the AutoConstraint structure is used yet.

So at this point, when I’m in polyline  the cursor shows is replaced by a polyline graphic and a coordinate.  This polyline graphic is being done further  upstream to the function I’m looking at the moment. And the coordinates are being set by setPositionText(onSketchPos)
The bolded test in the next routine are the lines which fire on a mouseMove prior to a buttton being clicked

 

virtual void mouseMove(Base::Vector2D onSketchPos)
{

setPositionText(onSketchPos);

// This addresses the Arc being enabled or disabled during
switch (LineMode){
case LINE_MODE_Arc:
switch(Mode){
case STATUS_ARC_SEEK_First:
case STATUS_ARC_SEEK_Second:
case STATUS_ARC_Do:
case STATUS_ARC_Close:
// we are in Arc mode and we are in an arc state.
// All is well
break;
case STATUS_LINE_SEEK_Second:
Mode =STATUS_ARC_SEEK_Second;
break;
default:
Mode =STATUS_ARC_SEEK_First;//Put us in the default arc state mode
}
break;
case LINE_MODE_Line:
switch(Mode){
case STATUS_LINE_SEEK_First:
case STATUS_LINE_SEEK_Second:
case STATUS_LINE_Do:
case STATUS_LINE_Close:
break;
case STATUS_ARC_SEEK_Second:
Mode =STATUS_LINE_SEEK_Second;
break;
default:
Mode =STATUS_LINE_SEEK_First;

}
break;
}
switch(Mode){
case STATUS_LINE_SEEK_First:
case STATUS_ARC_SEEK_First:
    if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) {
                    renderSuggestConstraintsCursor(sugConstr1);
                    return;
}
break;
case STATUS_LINE_SEEK_Second:
EditCurve[1] = onSketchPos;
sketchgui->drawEdit(EditCurve);
if (seekAutoConstraint(sugConstr2, onSketchPos, onSketchPos – EditCurve[0])) {
renderSuggestConstraintsCursor(sugConstr2);
return;
}
break;
case STATUS_ARC_SEEK_Second:
float angle1 = atan2(onSketchPos.fY – CenterPoint.fY,
onSketchPos.fX – CenterPoint.fX) – startAngle;
float angle2 = angle1 + (angle1 < 0. ? 2 : -2) * M_PI ;
arcAngle = abs(angle1-arcAngle) < abs(angle2-arcAngle) ? angle1 : angle2;
for (int i=1; i <= 29; i++) {
float angle = i*arcAngle/29.0;
float dx = rx * cos(angle) – ry * sin(angle);
float dy = rx * sin(angle) + ry * cos(angle);
EditCurve[i] = Base::Vector2D(CenterPoint.fX + dx, CenterPoint.fY + dy);
}
sketchgui->drawEdit(EditCurve);
if (seekAutoConstraint(sugConstr3, onSketchPos, Base::Vector2D(0.f,0.f))) {
renderSuggestConstraintsCursor(sugConstr2);
return;
}
break;
}

applyCursor();
}

Ok so If I disable setPositionText(onSketchPos) I don’t get the coordinates….

If I re-enable setPositionText(onSketchPos) and disable applyCursor()  I’m not seeing any obvious change in behavior so I need to do some digging to see what applyCursor does.

Stepping into I find myself here:

 

void DrawSketchHandler::applyCursor(void)
{
applyCursor(actCursor);
}

Soo what’s actCursor

 

class SketcherGuiExport DrawSketchHandler
{
public:
DrawSketchHandler();
virtual ~DrawSketchHandler();

virtual void activated(ViewProviderSketch *sketchgui){};
virtual void mouseMove(Base::Vector2D onSketchPos)=0;
virtual bool pressButton(Base::Vector2D onSketchPos)=0;
virtual bool releaseButton(Base::Vector2D onSketchPos)=0;
virtual bool onSelectionChanged(const Gui::SelectionChanges& msg) { return false; };

virtual void quit(void);

friend class ViewProviderSketch;

// get the actual highest vertex index, the next use will be +1
int getHighestVertexIndex(void);
// get the actual highest edge index, the next use will be +1
int getHighestCurveIndex(void);

int seekAutoConstraint(std::vector<AutoConstraint> &suggestedConstraints,
const Base::Vector2D &Pos, const Base::Vector2D &Dir, Type selType = VERTEX);
void createAutoConstraints(const std::vector<AutoConstraint> &autoConstrs,
int geoId, Sketcher::PointPos pointPos=Sketcher::none);

void setPositionText(const Base::Vector2D &Pos);
void resetPositionText(void);
void renderSuggestConstraintsCursor(std::vector<AutoConstraint> &suggestedConstraints);
virtual void registerPressedKey(bool pressed, int key){};
protected:
// helpers
void setCursor( const QPixmap &p,int x,int y );
void unsetCursor(void);
void applyCursor(void);
void applyCursor(QCursor &newCursor);

ViewProviderSketch *sketchgui;
QCursor oldCursor;
QCursor actCursor;
};

So  applying the cursor goes.

void DrawSketchHandler::applyCursor(QCursor &newCursor)
{
Gui::MDIView* view = Gui::getMainWindow()->activeWindow();
if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) {
Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(view)->getViewer();
viewer->getWidget()->setCursor(newCursor);
}
}


Ok… I hope I don’t need to go down to the coin layer in this path… So I think I stop here..
I’m still curious to  see If I can figure out where actCursor is set before going back

 

void DrawSketchHandler::setCursor(const QPixmap &p,int x,int y)
{
Gui::MDIView* view = Gui::getMainWindow()->activeWindow();
if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) {
Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(view)->getViewer();

oldCursor = viewer->getWidget()->cursor();
        QCursor cursor(p, x, y);
        actCursor = cursor;

viewer->getWidget()->setCursor(cursor);
}
}

Ok… I have

to know, what fires void DrawSketchHandler::setCursor(const QPixmap &p,int x,int y)

So setCursor is called by

(DrawSketchHandlerLineSet)

 

virtual void activated(ViewProviderSketch *sketchgui)
{
setCursor(QPixmap(cursor_createlineset),7,7);
}

which is called by:

// handler management ***************************************************************
void ViewProviderSketch::activateHandler(DrawSketchHandler *newHandler)
{
assert(edit);
assert(edit->sketchHandler == 0);
edit->sketchHandler = newHandler;
Mode = STATUS_SKETCH_UseHandler;
edit->sketchHandler->sketchgui = this;
edit->sketchHandler->activated(this);
}

Ohhhh… I think a light bulb sort of just flickered in my head here…. So sketchHandler is basically the pointer to DrawSketchHandlerLineSet.  How that gets set, I hope to avoid at the moment but this is all starting to make sense….
Now let see if I can collapse and get back to my walk through….

So I’m at this line of code:

 

    if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) {
                    renderSuggestConstraintsCursor(sugConstr1);
                    return;
}
break;

Basically what it does is a  little dot to the cursor showing a point or line on the highlighted object based on whether we’re looking a  point, line or arc.
Points to note… the actual bolding of the selected object is happening further up stream… We’re just messing with the cursor here.

As interesting as it might be to drill into seekAutoConstraint, as well as the activated inside DrawSketchHandlerLineSet (which does some really cools stuff) I think I need to move unto the next part of the life cycle of the polyline….

The next thing I need to follow is when the mousedown is pressed.

————————————————————————-

 

virtual bool pressButton(Base::Vector2D onSketchPos){

switch (Mode){

case STATUS_LINE_SEEK_First:
// remember our first point
firstPoint = getHighestVertexIndex() + 1;
firstCurve = getHighestCurveIndex() + 1;
EditCurve[0] = onSketchPos;
Mode = STATUS_LINE_SEEK_Second;
break;

Alrighty… This is less studied for me, so I need really dissect what’s going on here:
so firstPoint and firstCurve are int’s which are….????? fairly obvious what I need to step into here:

/** Handler to create new sketch geometry
* This class has to be reimplemented to create geometry in the
* sketcher while its in editing.
*/
class SketcherGuiExport DrawSketchHandler
{
public:
DrawSketchHandler();
virtual ~DrawSketchHandler();

virtual void activated(ViewProviderSketch *sketchgui){};
virtual void mouseMove(Base::Vector2D onSketchPos)=0;
virtual bool pressButton(Base::Vector2D onSketchPos)=0;
virtual bool releaseButton(Base::Vector2D onSketchPos)=0;
virtual bool onSelectionChanged(const Gui::SelectionChanges& msg) { return false; };

virtual void quit(void);

friend class ViewProviderSketch;

    // get the actual highest vertex index, the next use will be +1
    int getHighestVertexIndex(void);
    // get the actual highest edge index, the next use will be +1
    int getHighestCurveIndex(void);

int seekAutoConstraint(std::vector<AutoConstraint> &suggestedConstraints,
const Base::Vector2D &Pos, const Base::Vector2D &Dir, Type selType = VERTEX);
void createAutoConstraints(const std::vector<AutoConstraint> &autoConstrs,
int geoId, Sketcher::PointPos pointPos=Sketcher::none);

void setPositionText(const Base::Vector2D &Pos);
void resetPositionText(void);
void renderSuggestConstraintsCursor(std::vector<AutoConstraint> &suggestedConstraints);
virtual void registerPressedKey(bool pressed, int key){};
protected:
// helpers
void setCursor( const QPixmap &p,int x,int y );
void unsetCursor(void);
void applyCursor(void);
void applyCursor(QCursor &newCursor);

ViewProviderSketch *sketchgui;
QCursor oldCursor;
QCursor actCursor;
};

} // namespace SketcherGui

A few things I find noteworthy here are that getHighestVertexIndex and getHighestCurveIndex is that these are not virtual functions so all the business is being handled by the DrawSketchHandler base class… So probably a bunch of coin stuff?  (Hopefully, I can stay on the outer layers to get what I need  done…)

 

int DrawSketchHandler::getHighestVertexIndex(void)
{
return sketchgui->getSketchObject()->getHighestVertexIndex();
}

int DrawSketchHandler::getHighestCurveIndex(void)
{
return sketchgui->getSketchObject()->getHighestCurveIndex();
}

Oh boy…. so  what the heck is sketchgui….

class SketcherGuiExport DrawSketchHandler
{
public:
DrawSketchHandler();
virtual ~DrawSketchHandler();

virtual void activated(ViewProviderSketch *sketchgui){};
virtual void mouseMove(Base::Vector2D onSketchPos)=0;
virtual bool pressButton(Base::Vector2D onSketchPos)=0;
virtual bool releaseButton(Base::Vector2D onSketchPos)=0;
virtual bool onSelectionChanged(const Gui::SelectionChanges& msg) { return false; };

virtual void quit(void);

friend class ViewProviderSketch;

// get the actual highest vertex index, the next use will be +1
int getHighestVertexIndex(void);
// get the actual highest edge index, the next use will be +1
int getHighestCurveIndex(void);

int seekAutoConstraint(std::vector<AutoConstraint> &suggestedConstraints,
const Base::Vector2D &Pos, const Base::Vector2D &Dir, Type selType = VERTEX);
void createAutoConstraints(const std::vector<AutoConstraint> &autoConstrs,
int geoId, Sketcher::PointPos pointPos=Sketcher::none);

void setPositionText(const Base::Vector2D &Pos);
void resetPositionText(void);
void renderSuggestConstraintsCursor(std::vector<AutoConstraint> &suggestedConstraints);
virtual void registerPressedKey(bool pressed, int key){};
protected:
// helpers
void setCursor( const QPixmap &p,int x,int y );
void unsetCursor(void);
void applyCursor(void);
void applyCursor(QCursor &newCursor);

ViewProviderSketch *sketchgui;
QCursor oldCursor;
QCursor actCursor;
};

Ahhh ViewProviderSketch,  I’ve dealt with you before, keypresses and mouse clicks get fed into DrawSketchHandlerLineSet through you..
So… how does the pointer to sketchgui get set…

Well,
Not through the constructor:

DrawSketchHandler::DrawSketchHandler()
: sketchgui(0)
{

}

Hmm.. I think the pointer to sketchgui gets set here:

// handler management ***************************************************************
void ViewProviderSketch::activateHandler(DrawSketchHandler *newHandler)
{
assert(edit);
assert(edit->sketchHandler == 0);
edit->sketchHandler = newHandler;
Mode = STATUS_SKETCH_UseHandler;
edit->sketchHandler->sketchgui = this;
edit->sketchHandler->activated(this);
}

And it looks like  ViewProvider sketch sets things in motion.
Ok… One more thing to look at… What is all defined in ViewProviderSketch.
I’m still trying to trace sketchgui->getSketchObject()->getHighestVertexIndex();

 

class SketcherGuiExport ViewProviderSketch : public PartGui::ViewProvider2DObject, public Gui::SelectionObserver
{
PROPERTY_HEADER(PartGui::ViewProviderSketch);

public:
/// constructor
ViewProviderSketch();
/// destructor
virtual ~ViewProviderSketch();

App::PropertyBool Autoconstraints;

/// draw constraint icon given the constraint id
void drawConstraintIcons();
/// draw the sketch in the inventor nodes
void draw(bool temp=false);
/// draw the edit curve
void drawEdit(const std::vector<Base::Vector2D> &EditCurve);

/// Is the view provider selectable
bool isSelectable(void) const;
/// Observer message from the Selection
virtual void onSelectionChanged(const Gui::SelectionChanges& msg);

/** @name handler control */
//@{
/// sets an DrawSketchHandler in control
void activateHandler(DrawSketchHandler *newHandler);
/// removes the active handler
void purgeHandler(void);
//@}

/** @name modus handling */
//@{
/// mode table
enum SketchMode{
STATUS_NONE,              /**< enum value View provider is in neutral. */
STATUS_SELECT_Point,      /**< enum value a point was selected. */
STATUS_SELECT_Edge,       /**< enum value a edge was selected. */
STATUS_SELECT_Constraint, /**< enum value a constraint was selected. */
STATUS_SELECT_Cross,      /**< enum value the base coordinate system was selected. */
STATUS_SKETCH_DragPoint,  /**< enum value while dragging a point. */
STATUS_SKETCH_DragCurve,  /**< enum value while dragging a curve. */
STATUS_SKETCH_DragConstraint,  /**< enum value while dragging a compatible constraint. */
STATUS_SKETCH_UseHandler  /**< enum value a DrawSketchHandler is in control. */
};
/// is called by GuiCommands to set the drawing mode
void setSketchMode(SketchMode mode) {Mode = mode;}
/// get the sketch mode
SketchMode getSketchMode(void) const {return Mode;}
//@}

/** @name helper functions */
//@{
/// give the coordinates of a line on the sketch plane in sketcher (2D) coordinates
void getCoordsOnSketchPlane(double &u, double &v,const SbVec3f &point, const SbVec3f &normal);
/// helper to detect preselection
//bool handlePreselection(const SoPickedPoint *pp);
/// helper to detect preselection
bool detectPreselection(const SoPickedPoint *Point, int &PtIndex,int &CurvIndex, int &ConstrIndex, int &CrossIndex);
/// helper change the color of the sketch according to selection and solver status
void updateColor(void);
/// get the pointer to the sketch document object
Sketcher::SketchObject *getSketchObject(void) const;

/// snap points x,y (mouse coordinates) onto grid if enabled
void snapToGrid(double &x, double &y);

/// moves a selected constraint
void moveConstraint(int constNum, const Base::Vector2D &toPos);
/// checks if there is a constraint object at position vector
bool isConstraintAtPosition(const Base::Vector3d &constrPos, const SoNode *constraint);
/// finds a free position for placing a constraint icon
Base::Vector3d seekConstraintPosition(const Base::Vector3d &suggestedPos,
const Base::Vector3d &dir, float step,
const SoNode *constraint);

float getScaleFactor();
int getPreselectPoint(void) const;
int getPreselectCurve(void) const;
int getPreselectConstraint(void) const;
//@}

/** @name base class implementer */
//@{
virtual void attach(App::DocumentObject *);
virtual void updateData(const App::Property *);

virtual void setupContextMenu(QMenu *menu, QObject *receiver, const char *member);
/// is called when the Provider is in edit and a deletion request occurs
virtual bool onDelete(const std::vector<std::string> &);
/// is called by the tree if the user double click on the object
virtual bool doubleClicked(void);
/// is called when the Provider is in edit and the mouse is moved
virtual bool mouseMove(const SbVec3f &pNear, const SbVec3f &pFar, const SoPickedPoint *pp);
/// is called when the Provider is in edit and a key event ocours. Only ESC ends edit.
virtual bool keyPressed(bool pressed, int key);
/// is called when the Provider is in edit and the mouse is clicked
virtual bool mouseButtonPressed(int Button, bool pressed, const SbVec3f &point,
const SbVec3f &normal, const SoPickedPoint *pp);
//@}

friend class DrawSketchHandler;

/// signals if the constraints list has changed
boost::signal<void ()> signalConstraintsChanged;
/// signals if the sketch has been set up
boost::signal<void (int type, int dofs, std::string &msg)> signalSetUp;
/// signals if the sketch has been solved
boost::signal<void (int type, float time)> signalSolved;

protected:
virtual bool setEdit(int ModNum);
virtual void unsetEdit(int ModNum);
virtual void setEditViewer(Gui::View3DInventorViewer*, int ModNum);
virtual void unsetEditViewer(Gui::View3DInventorViewer*);
/// helper to detect whether the picked point lies on the sketch
bool isPointOnSketch(const SoPickedPoint *pp) const;
/// get called by the container whenever a property has been changed
virtual void onChanged(const App::Property *prop);

/// get called if a subelement is double clicked while editing
void editDoubleClicked(void);

/// set up the edition data structure EditData
void createEditInventorNodes(void);
/// pointer to the edit data structure if the ViewProvider is in edit.
EditData *edit;
/// build up the visual of the constraints
void rebuildConstraintsVisual(void);

void setPositionText(const Base::Vector2D &Pos);
void resetPositionText(void);

// handle preselection and selection of points
void setPreselectPoint(int PreselectPoint);
void resetPreselectPoint(void);
void addSelectPoint(int SelectPoint);
void removeSelectPoint(int SelectPoint);
void clearSelectPoints(void);

// modes while sketching
SketchMode Mode;

// colors
static SbColor VertexColor;
static SbColor CurveColor;
static SbColor CurveDraftColor;
static SbColor CurveExternalColor;
static SbColor CrossColorV;
static SbColor CrossColorH;
static SbColor FullyConstrainedColor;
static SbColor ConstrDimColor;
static SbColor ConstrIcoColor;
static SbColor PreselectColor;
static SbColor SelectColor;

static SbTime prvClickTime;
static SbVec3f prvClickPoint;

float zCross;
float zLines;
float zPoints;
float zConstr;
float zHighlight;
float zText;
float zEdit;

// reference coordinates for relative operations
double xInit,yInit;
bool relative;
};

Oh darn… the C++ train has just come to a halt…
Sketcher::SketchObject *getSketchObject(void) const;   has got me a bit confused..  It appears to be a function which a point to sketch object.   If that’s the case there should an implementation of it in the ViewProviderSketch.cpp. (and there is..)

 

Sketcher::SketchObject *ViewProviderSketch::getSketchObject(void) const
{
return dynamic_cast<Sketcher::SketchObject *>(pcObject);
}

So I use this line make sense than sketchgui->getSketchObject()->getHighestVertexIndex()

And now a new player has just arrived on the seen pcObject politcally correct?
When I hover my cursor in the QT id it tells me this is off type App:DocumentObject

I’m some what confused by the pcObject when I do a search for this, it show’s up in a bunch of spots.  At first glance it seems like this variable name is redeclared a whole bunch of times… but think this variable should be defined either in ViewProviderSketch or one of its inherited classes.
class SketcherGuiExport ViewProviderSketch : public PartGui::ViewProvider2DObject, public Gui::SelectionObserver

Not in ViewProviderSketch

class PartGuiExport ViewProvider2DObject: public PartGui::ViewProviderPart

Not in ViewProvider2Object

class PartGuiExport ViewProviderPart : public ViewProviderPartExt

Not in ViewProviderPartExt

class PartGuiExport ViewProviderPartExt : public Gui::ViewProviderGeometryObject

ViewProviderGeometryObject has a reference to it but it’s not declared

class GuiExport ViewProviderGeometryObject : public ViewProviderDocumentObject

Bingo..

class GuiExport ViewProviderDocumentObject : public ViewProvider
{
PROPERTY_HEADER(Gui::ViewProviderDocumentObject);

public:
/// constructor.
ViewProviderDocumentObject();

/// destructor.
virtual ~ViewProviderDocumentObject();

// Display properties
App::PropertyEnumeration DisplayMode;
App::PropertyBool Visibility;

virtual void attach(App::DocumentObject *pcObject);
/// Get the default display mode
virtual const char* getDefaultDisplayMode() const;
/// Return a list of all possible modes
virtual std::vector<std::string> getDisplayModes(void) const;
/// Set the active mode, i.e. the first item of the ‘Display’ property.
void setActiveMode();
/// Hide the object in the view
virtual void hide(void);
/// Show the object in the view
virtual void show(void);

/// Get a list of TaskBoxes associated with this object
virtual void getTaskViewContent(std::vector<Gui::TaskView::TaskContent*>&) const;

/// Run a redraw
void updateView();
/// Gets called if some of the property hade bin changed
virtual void updateData(const App::Property*){};
/// Get the object of this ViewProvider object
App::DocumentObject *getObject(void) const {return pcObject;}
/// Get the python wrapper for that ViewProvider
PyObject* getPyObject();

/** @name Restoring view provider from document load */
//@{
virtual void startRestoring();
virtual void finishRestoring();
//@}

protected:
/// Get the active mdi view of a view provider
Gui::MDIView* getActiveView() const;
/// Gets called by the container whenever a property has been changed
virtual void onChanged(const App::Property* prop);
/** Searches in all view providers that are attached to an object that
* is part of the same document as the object this view provider is
* attached to for an front root of \a type.
* Before calling this function this view provider has to be attached
* to an object. The method returns after the first front root node
* matches. If no front root node matches, 0 is returned.
*/
SoNode* findFrontRootOfType(const SoType& type) const;

protected:
App::DocumentObject *pcObject;

private:
std::vector<const char*> aDisplayEnumsArray;
std::vector<std::string> aDisplayModesArray;
};

} // namespace Gui

Eeeeeh..  Ok… looking back at my notes, I’m trying to understand what’s going on with

int DrawSketchHandler::getHighestVertexIndex(void)
{
return sketchgui->getSketchObject()->getHighestVertexIndex();
}

int DrawSketchHandler::getHighestCurveIndex(void)
{
return sketchgui->getSketchObject()->getHighestCurveIndex();
}

 

Ok…

namespace Sketcher
{

class SketcherExport SketchObject : public Part::Part2DObject
{
PROPERTY_HEADER(Sketcher::SketchObject);

public:
SketchObject();
~SketchObject();

/// Property
Part    ::PropertyGeometryList   Geometry;
Sketcher::PropertyConstraintList Constraints;
App     ::PropertyLinkSubList    ExternalGeometry;
/** @name methods overide Feature */
//@{
/// recalculate the Feature
App::DocumentObjectExecReturn *execute(void);

/// returns the type name of the ViewProvider
const char* getViewProviderName(void) const {
return “SketcherGui::ViewProviderSketch”;
}
//@}

/// add unspecified geometry
int addGeometry(const Part::Geometry *geo);
/// add unspecified geometry
int addGeometry(const std::vector<Part::Geometry *> &geoList);
/// delete geometry
int delGeometry(int GeoId);
/// add all constraints in the list
int addConstraints(const std::vector<Constraint *> &ConstraintList);
/// add constraint
int addConstraint(const Constraint *constraint);
/// delete constraint
int delConstraint(int ConstrId);
int delConstraintOnPoint(int GeoId, PointPos PosId, bool onlyCoincident=true);
int delConstraintOnPoint(int VertexId, bool onlyCoincident=true);
/// transfers all contraints of a point to a new point
int transferConstraints(int fromGeoId, PointPos fromPosId, int toGeoId, PointPos toPosId);
/// add an external geometry reference
int addExternal(App::DocumentObject *Obj, const char* SubName);
/** delete external
*  ExtGeoId >= 0 with 0 corresponding to the first user defined
*  external geometry
*/
int delExternal(int ExtGeoId);

/** returns a pointer to a given Geometry index, possible indexes are:
*  id>=0 for user defined geometries,
*  id==-1 for the horizontal sketch axis,
*  id==-2 for the vertical sketch axis
*  id<=-3 for user defined projected external geometries,
*/
const Part::Geometry* getGeometry(int GeoId) const;
/// returns a list of all internal geometries
const std::vector<Part::Geometry *> &getInternalGeometry(void) const { return Geometry.getValues(); }
/// returns a list of projected external geometries
const std::vector<Part::Geometry *> &getExternalGeometry(void) const { return ExternalGeo; }
/// rebuilds external geometry (projection onto the sketch plane)
void rebuildExternalGeometry(void);
/// returns the number of external Geometry entities
int getExternalGeometryCount(void) const { return ExternalGeo.size(); }

/// retrieves a vector containing both normal and external Geometry (including the sketch axes)
std::vector<Part::Geometry*> getCompleteGeometry(void) const;

/// returns non zero if the sketch contains conflicting constraints
int hasConflicts(void) const;

/// set the datum of a Distance or Angle constraint and solve
int setDatum(int ConstrId, double Datum);
/// move this point to a new location and solve
int movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative=false);
/// retrieves the coordinates of a point
Base::Vector3d getPoint(int GeoId, PointPos PosId) const;

/// toggle geometry to draft line
int toggleConstruction(int GeoId);

/// create a fillet
int fillet(int geoId, PointPos pos, double radius, bool trim=true);
int fillet(int geoId1, int geoId2,
const Base::Vector3d& refPnt1, const Base::Vector3d& refPnt2,
double radius, bool trim=true);

/// trim a curve
int trim(int geoId, const Base::Vector3d& point);

/// retrieves for a Vertex number the corresponding GeoId and PosId
void getGeoVertexIndex(int VertexId, int &GeoId, PointPos &PosId);
    int getHighestVertexIndex(void) const { return VertexId2GeoId.size() – 1; }
    int getHighestCurveIndex(void) const { return Geometry.getSize() – 1; }
void rebuildVertexIndex(void);

/// retrieves for a Vertex number a list with all coincident points
void getCoincidentPoints(int GeoId, PointPos PosId, std::vector<int> &GeoIdList,
std::vector<PointPos> &PosIdList);
void getCoincidentPoints(int VertexId, std::vector<int> &GeoIdList, std::vector<PointPos> &PosIdList);

/// generates a warning message about constraint conflicts and appends it to the given message
static void appendConflictMsg(const std::vector<int> &conflicting, std::string &msg);

// from base class
virtual PyObject *getPyObject(void);
virtual unsigned int getMemSize(void) const;
virtual void Save(Base::Writer &/*writer*/) const;
virtual void Restore(Base::XMLReader &/*reader*/);

/// returns the number of construction lines (to be used as axes)
virtual int getAxisCount(void) const;
/// retrieves an axis iterating through the construction lines of the sketch (indices start at 0)
virtual Base::Axis getAxis(int axId) const;

protected:
/// get called by the container when a property has changed
virtual void onChanged(const App::Property* /*prop*/);
virtual void onDocumentRestored();
virtual void onFinishDuplicating();

private:
std::vector<Part::Geometry *> ExternalGeo;

std::vector<int> VertexId2GeoId;
std::vector<PointPos> VertexId2PosId;
};

typedef App::FeaturePythonT<SketchObject> SketchObjectPython;

} //namespace Sketcher

——-

So I narrowing in on this stuff in on this so the sketch object has a PropertyGeometryList object defined within it.

class PartExport PropertyGeometryList: public App::PropertyLists
{
TYPESYSTEM_HEADER();

public:
/**
* A constructor.
* A more elaborate description of the constructor.
*/
PropertyGeometryList();

/**
* A destructor.
* A more elaborate description of the destructor.
*/
virtual ~PropertyGeometryList();

virtual void setSize(int newSize);
virtual int getSize(void) const;

/** Sets the property
*/
void setValue(const Geometry*);
void setValues(const std::vector<Geometry*>&);

/// index operator
const Geometry *operator[] (const int idx) const {
return _lValueList[idx];
}

const std::vector<Geometry*> &getValues(void) const {
return _lValueList;
}

virtual PyObject *getPyObject(void);
virtual void setPyObject(PyObject *);

virtual void Save(Base::Writer &writer) const;
virtual void Restore(Base::XMLReader &reader);

virtual Property *Copy(void) const;
virtual void Paste(const App::Property &from);

virtual unsigned int getMemSize(void) const;

private:
std::vector<Geometry*> _lValueList;
};

} // namespace Part

 

This just keeps going and going..

/** Base class of all property lists.
* The PropertyLists class is the base class for properties which can contain
* multiple values, not only a single value.
* All property types which may contain more than one value inherits this class.
*/
class AppExport PropertyLists : public Property
{
TYPESYSTEM_HEADER();

public:
virtual void setSize(int newSize)=0;
virtual int getSize(void) const =0;
};

} // namespace App

—–

And what sees what Property has in it..

namespace App
{

class PropertyContainer;

/** Base class of all properties
* This is the father of all properties. Properties are objects which are used
* in the document tree to parametrize e.g. features and their graphical output.
* They are also used to gain access from the scripting facility.
* /par
* This abstract base class defines all methods shared by all
* possible properties. It is also possible to define user properties
* and use them in the framework…
*/
class AppExport Property : public Base::Persistence
{
TYPESYSTEM_HEADER();

public:
Property();
virtual ~Property();

/** This method is used to get the size of objects
* It is not meant to have the exact size, it is more or less an estimation
* which runs fast! Is it two bytes or a GB?
* This method is defined in Base::Persistence
* @see Base::Persistence
*/
virtual unsigned int getMemSize (void) const {
// you have to implement this method in all property classes!
return Base::Persistence::getMemSize() + sizeof(father) + sizeof(StatusBits);
}

/// get the name of this property in the belonging container
const char* getName(void) const;

/// Get the class name of the associated property editor item
virtual const char* getEditorName(void) const { return “”; }

/// Get the type of the property in the container
short getType(void) const;

/// Get the group of this property
const char* getGroup(void) const;

/// Get the documentation of this property
const char* getDocumentation(void) const;

/// Is called by the framework to set the father (container)
void setContainer(PropertyContainer *Father);

/// Get a pointer to the PropertyContainer derived class the property belongs to
PropertyContainer *getContainer(void) const {return father;}
/// Set the property touched
void touch();
/// Test if this property is touched
bool isTouched(void) const {return StatusBits.test(0);}
/// Reset this property touched
void purgeTouched(void){StatusBits.reset(0);}

/// Returns a new copy of the property (mainly for Undo/Redo and transactions)
virtual Property *Copy(void) const = 0;
/// Paste the value from the property (mainly for Undo/Redo and transactions)
virtual void Paste(const Property &from) = 0;
/// Encodes an attribute upon saving.
std::string encodeAttribute(const std::string&) const;

friend class PropertyContainer;

/** Status bits of the property
* The first 8 bits are used for the base system the rest can be used in
* descendent classes to to mark special stati on the objects.
* The bits and their meaning are listed below:
* 0 – object is marked as ‘touched’
* 1 – object is marked as ‘immutable’
* 2 – object is marked as ‘read-ony’ (for property editor)
* 3 – object is marked as ‘hidden’ (for property editor)
*/
std::bitset<32> StatusBits;

protected:
/// Gets called by all setValue() methods after the value has changed
void hasSetValue(void);
/// Gets called by all setValue() methods before the value has changed
void aboutToSetValue(void);

private:
// forbidden
Property(const Property&);
Property& operator = (const Property&);

private:
PropertyContainer *father;
};

/** Base class of all property lists.
* The PropertyLists class is the base class for properties which can contain
* multiple values, not only a single value.
* All property types which may contain more than one value inherits this class.
*/
class AppExport PropertyLists : public Property
{
TYPESYSTEM_HEADER();

public:
virtual void setSize(int newSize)=0;
virtual int getSize(void) const =0;
};

} // namespace App

———

So… I went digging down so far, I kind of lost track of what I was trying to accomplish..   So I just went from mousemove and now we just pressed the button…

virtual bool pressButton(Base::Vector2D onSketchPos){

switch (Mode){

case STATUS_LINE_SEEK_First:
// remember our first point
firstPoint = getHighestVertexIndex() + 1;
firstCurve = getHighestCurveIndex() + 1;
EditCurve[0] = onSketchPos;
Mode = STATUS_LINE_SEEK_Second;
break;

…………………….
At this point, everything going on appears self-evident to me… I don’t understand the cuts of getHighestVertexIndex() and getHighestCurveIndex()  but perhaps I don’t need to at this point,
So the next step in the polyline life cycle should be:

(At this point, I haven’t hacked up any of this code yet, so its original… At this point, we’ve defined what the first point and first curve id will be and we’ve let go of the mouse button. Looking at the code (I haven’t stepped yet to verify, looks like release button only does something if (Mode==STATUS_LINE_Do || Mode==STATUS_LINE_Close), so we’re back to the mousemove

 

virtual bool releaseButton(Base::Vector2D onSketchPos)
{
//???? NEED TO FIGURE OUT to return
// getPolylineElementMode() returned here..

if (Mode==STATUS_LINE_Do || Mode==STATUS_LINE_Close) {
// open the transaction
Gui::Command::openCommand(“add sketch wire”);
// issue the geometry
Gui::Command::doCommand(Gui::Command::Doc,”App.ActiveDocument.%s.addGeometry(Part.Line(App.Vector(%f,%f,0),App.Vector(%f,%f,0)))”,
sketchgui->getObject()->getNameInDocument(),
EditCurve[0].fX,EditCurve[0].fY,EditCurve[1].fX,EditCurve[1].fY);

// issue the constraint
if (previousCurve != -1) {
Gui::Command::doCommand(Gui::Command::Doc,”App.ActiveDocument.%s.addConstraint(Sketcher.Constraint(‘Coincident’,%i,2,%i,1)) ”
,sketchgui->getObject()->getNameInDocument()
,previousCurve-1,previousCurve
);
}

if (Mode==STATUS_LINE_Close) {
// close the loop by constrain to the first curve point
Gui::Command::doCommand(Gui::Command::Doc,”App.ActiveDocument.%s.addConstraint(Sketcher.Constraint(‘Coincident’,%i,2,%i,1)) ”
,sketchgui->getObject()->getNameInDocument()
,previousCurve,firstCurve
);

Gui::Command::commitCommand();
Gui::Command::updateActive();

if (sugConstr2.size() > 0) {
// exclude any coincidence constraints
std::vector<AutoConstraint> sugConstr;
for (int i=0; i < sugConstr2.size(); i++) {
if (sugConstr2[i].Type != Sketcher::Coincident)
sugConstr.push_back(sugConstr2[i]);
}
createAutoConstraints(sugConstr, getHighestCurveIndex(), Sketcher::end);
sugConstr2.clear();
}

unsetCursor();
EditCurve.clear();
resetPositionText();
sketchgui->drawEdit(EditCurve);
sketchgui->purgeHandler(); // no code after this line, Handler get deleted in ViewProvider
}
else {
Gui::Command::commitCommand();
Gui::Command::updateActive();

// Add auto constraints
if (sugConstr1.size() > 0) {
createAutoConstraints(sugConstr1, getHighestCurveIndex(), Sketcher::start);
sugConstr1.clear();
}

if (sugConstr2.size() > 0) {
createAutoConstraints(sugConstr2, getHighestCurveIndex(), Sketcher::end);
sugConstr2.clear();
}

//remember the vertex for the next rounds constraint…
previousCurve = getHighestCurveIndex() + 1;

// setup for the next line segment
// Use updated endPoint as autoconstraints can modify the position
const Part::Geometry *geom = sketchgui->getSketchObject()->getGeometry(getHighestCurveIndex());
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
const Part::GeomLineSegment *lineSeg = dynamic_cast<const Part::GeomLineSegment *>(geom);
EditCurve[0] = Base::Vector2D(lineSeg->getEndPoint().x, lineSeg->getEndPoint().y);
}
else
EditCurve[0] = onSketchPos;

sketchgui->drawEdit(EditCurve);
applyCursor();

Mode = STATUS_LINE_SEEK_Second;
}
}
return true;
}

 

—————–

We’re back to the mousemove where Mode = STATUS_LINE_SEEK_Second

 

virtual void mouseMove(Base::Vector2D onSketchPos)
{

setPositionText(onSketchPos);

………………..
switch(Mode){
case STATUS_LINE_SEEK_First:
case STATUS_ARC_SEEK_First:
if (seekAutoConstraint(sugConstr1, onSketchPos, Base::Vector2D(0.f,0.f))) {
renderSuggestConstraintsCursor(sugConstr1);
return;
}
break;
case STATUS_LINE_SEEK_Second:
    EditCurve[1] = onSketchPos;
                sketchgui->drawEdit(EditCurve);
                if (seekAutoConstraint(sugConstr2, onSketchPos, onSketchPos – EditCurve[0])) {
                    renderSuggestConstraintsCursor(sugConstr2);
                    return;
                }
                break;

 

—–

At this point, everything seems to to be making sense to me up to this point, and I want to start working on drawing the arc in the mouse move up to the second click……  This blog post has gotten way to log for my tastes…

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

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