From da7528c5b9c2a980636a578b8906fdada2b26b72 Mon Sep 17 00:00:00 2001 From: mrlukeparry Date: Sun, 15 Jul 2012 13:23:59 +0200 Subject: [PATCH] Sketcher, 0000466: improve visualization of constraints --- src/Mod/Sketcher/App/Constraint.cpp | 12 +- src/Mod/Sketcher/App/Constraint.h | 1 + src/Mod/Sketcher/Gui/SoDatumLabel.cpp | 693 +++++++++++++++++--- src/Mod/Sketcher/Gui/SoDatumLabel.h | 24 +- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 326 +++------ 5 files changed, 697 insertions(+), 359 deletions(-) diff --git a/src/Mod/Sketcher/App/Constraint.cpp b/src/Mod/Sketcher/App/Constraint.cpp index 92fc804d0..b9d1c0405 100644 --- a/src/Mod/Sketcher/App/Constraint.cpp +++ b/src/Mod/Sketcher/App/Constraint.cpp @@ -51,7 +51,8 @@ Constraint::Constraint() SecondPos(none), Third(GeoUndef), ThirdPos(none), - LabelDistance(10.f) + LabelDistance(10.f), + LabelPosition(0.f) { } @@ -65,7 +66,8 @@ Constraint::Constraint(const Constraint& from) SecondPos(from.SecondPos), Third(from.Third), ThirdPos(from.ThirdPos), - LabelDistance(from.LabelDistance) + LabelDistance(from.LabelDistance), + LabelPosition(from.LabelPosition) { } @@ -100,7 +102,8 @@ void Constraint::Save (Writer &writer) const << "SecondPos=\"" << (int) SecondPos << "\" " << "Third=\"" << Third << "\" " << "ThirdPos=\"" << (int) ThirdPos << "\" " - << "LabelDistance=\"" << LabelDistance<< "\" />" + << "LabelDistance=\"" << LabelDistance << "\" " + << "LabelPosition=\"" << LabelPosition << "\" />" << std::endl; } @@ -123,4 +126,7 @@ void Constraint::Restore(XMLReader &reader) // Read the distance a constraint label has been moved if (reader.hasAttribute("LabelDistance")) LabelDistance = (float)reader.getAttributeAsFloat("LabelDistance"); + + if (reader.hasAttribute("LabelPosition")) + LabelPosition = (float)reader.getAttributeAsFloat("LabelPosition"); } diff --git a/src/Mod/Sketcher/App/Constraint.h b/src/Mod/Sketcher/App/Constraint.h index 3bfb5e28f..68d7ebcc4 100644 --- a/src/Mod/Sketcher/App/Constraint.h +++ b/src/Mod/Sketcher/App/Constraint.h @@ -83,6 +83,7 @@ public: int Third; PointPos ThirdPos; float LabelDistance; + float LabelPosition; }; } //namespace Sketcher diff --git a/src/Mod/Sketcher/Gui/SoDatumLabel.cpp b/src/Mod/Sketcher/Gui/SoDatumLabel.cpp index 2896a54b8..7b7cb544b 100644 --- a/src/Mod/Sketcher/Gui/SoDatumLabel.cpp +++ b/src/Mod/Sketcher/Gui/SoDatumLabel.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) 2011 * + * Copyright (c) 2011-2012 Luke Parry * * * * This file is part of the FreeCAD CAx development system. * * * @@ -45,6 +45,7 @@ # include #endif +#include #include #include #include @@ -73,11 +74,23 @@ SoDatumLabel::SoDatumLabel() SO_NODE_CONSTRUCTOR(SoDatumLabel); SO_NODE_ADD_FIELD(string, ("")); SO_NODE_ADD_FIELD(textColor, (SbVec3f(1.0f,1.0f,1.0f))); - SO_NODE_ADD_FIELD(name, ("Helvetica")); - SO_NODE_ADD_FIELD(size, (12)); + SO_NODE_ADD_FIELD(pnts, (SbVec3f(.0f,.0f,.0f))); - this->bbx = 0; - this->bby = 0; + SO_NODE_ADD_FIELD(name, ("Helvetica")); + SO_NODE_ADD_FIELD(size, (12.f)); + SO_NODE_ADD_FIELD(lineWidth, (2.f)); + + SO_NODE_ADD_FIELD(datumtype, (SoDatumLabel::DISTANCE)); + + SO_NODE_DEFINE_ENUM_VALUE(Type, DISTANCE); + SO_NODE_DEFINE_ENUM_VALUE(Type, DISTANCEX); + SO_NODE_DEFINE_ENUM_VALUE(Type, DISTANCEY); + SO_NODE_DEFINE_ENUM_VALUE(Type, ANGLE); + SO_NODE_DEFINE_ENUM_VALUE(Type, RADIUS); + SO_NODE_SET_SF_ENUM_TYPE(datumtype, Type); + + this->imgWidth = 0; + this->imgHeight = 0; } void SoDatumLabel::drawImage() @@ -123,103 +136,199 @@ void SoDatumLabel::drawImage() void SoDatumLabel::computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er) { - SbVec2s size; - int nc; - - const unsigned char * dataptr = this->image.getValue(size, nc); - if (dataptr == NULL) { - box.setBounds(SbVec3f(0,0,0), SbVec3f(0,0,0)); - center.setValue(0.0f,0.0f,0.0f); - return; - } - - float srcw = size[0]; - float srch = size[1]; - - float height, width; - - if(action->getTypeId() == SoGLRenderAction::getClassTypeId()) { - // Update using the GL state - SoState *state = action->getState(); - float srcw = size[0]; - float srch = size[1]; - - const SbViewVolume & vv = SoViewVolumeElement::get(state); - float scale = vv.getWorldToScreenScale(SbVec3f(0.f,0.f,0.f), 0.5f); - - float aspectRatio = (float) srcw / (float) srch; - float height = scale / (float) srch; - float width = aspectRatio * (float) height; - - // Update stored values - this->bbx = width; - this->bby = height; - } else { - // Update Primitives using stored dimensions - width = this->bbx; - height = this->bby; - } - - SbVec3f min (-width / 2, -height / 2, 0.f); - SbVec3f max (width / 2, height / 2, 0.f); - box.setBounds(min, max); - center.setValue(0.f,0.f,0.f); + // Set the bounding box using stored parameters + box.setBounds(this->bbox.getMin(),this->bbox.getMax() ); + SbVec3f bbcenter = this->bbox.getCenter(); + center.setValue(bbcenter[0], bbcenter[1], bbcenter[2]); } void SoDatumLabel::generatePrimitives(SoAction * action) { - // Get the size - SbVec2s size; - int nc; - const unsigned char * dataptr = this->image.getValue(size, nc); - if (dataptr == NULL) - return; - - float width, height; + // Initialisation check (needs something more sensible) prevents an infinite loop bug + if(this->imgHeight <= FLT_EPSILON || this->imgWidth <= FLT_EPSILON) + return; - if (action->getTypeId() == SoGLRenderAction::getClassTypeId()) { - // Update using the GL state - SoState *state = action->getState(); - float srcw = size[0]; - float srch = size[1]; + // Get the points stored + const SbVec3f *pnts = this->pnts.getValues(0); + SbVec3f p1 = pnts[0]; + SbVec3f p2 = pnts[1]; - const SbViewVolume & vv = SoViewVolumeElement::get(state); - float scale = vv.getWorldToScreenScale(SbVec3f(0.f,0.f,0.f), 0.5f); + float offsetX, offsetY; - float aspectRatio = (float) srcw / (float) srch; - float height = scale / (float) srch; - float width = aspectRatio * (float) height; + // Change the offset and bounding box parameters depending on Datum Type + if(this->datumtype.getValue() == DISTANCE || this->datumtype.getValue() == DISTANCEX || this->datumtype.getValue() == DISTANCEY ){ - // Update stored dimensions - this->bbx = width; - this->bby = height; - } else { - // Update Primitives using stored dimensions - width = this->bbx; - height = this->bby; + float length = this->param1.getValue(); + float length2 = this->param2.getValue(); + SbVec3f dir, norm; + if (this->datumtype.getValue() == DISTANCE) { + dir = (p2-p1); + } else if (this->datumtype.getValue() == DISTANCEX) { + dir = SbVec3f( (p2[0] - p1[0] >= FLT_EPSILON) ? 1 : -1, 0, 0); + } else if (this->datumtype.getValue() == DISTANCEY) { + dir = SbVec3f(0, (p2[1] - p1[1] >= FLT_EPSILON) ? 1 : -1, 0); + } + + dir.normalize(); + norm = SbVec3f (-dir[1],dir[0],0); + + float normproj12 = (p2-p1).dot(norm); + SbVec3f p1_ = p1 + normproj12 * norm; + + SbVec3f midpos = (p1_ + p2)/2; + // Get magnitude of angle between horizontal + float angle = atan2f(dir[1],dir[0]); + + SbVec3f img1 = SbVec3f(-this->imgWidth / 2, -this->imgHeight / 2, 0.f); + SbVec3f img2 = SbVec3f(-this->imgWidth / 2, this->imgHeight / 2, 0.f); + SbVec3f img3 = SbVec3f( this->imgWidth / 2, -this->imgHeight / 2, 0.f); + SbVec3f img4 = SbVec3f( this->imgWidth / 2, this->imgHeight / 2, 0.f); + + // Rotate through an angle + float s = sin(angle); + float c = cos(angle); + + img1 = SbVec3f((img1[0] * c) - (img1[1] * s), (img1[0] * s) + (img1[1] * c), 0.f); + img2 = SbVec3f((img2[0] * c) - (img2[1] * s), (img2[0] * s) + (img2[1] * c), 0.f); + img3 = SbVec3f((img3[0] * c) - (img3[1] * s), (img3[0] * s) + (img3[1] * c), 0.f); + img4 = SbVec3f((img4[0] * c) - (img4[1] * s), (img4[0] * s) + (img4[1] * c), 0.f); + + SbVec3f textOffset = midpos + norm * length + dir * length2; + + img1 += textOffset; + img2 += textOffset; + img3 += textOffset; + img4 += textOffset; + + // Primitive Shape is only for text as this should only be selectable + SoPrimitiveVertex pv; + + this->beginShape(action, QUADS); + + pv.setNormal( SbVec3f(0.f, 0.f, 1.f) ); + + // Set coordinates + pv.setPoint( img1 ); + shapeVertex(&pv); + + pv.setPoint( img2 ); + shapeVertex(&pv); + + pv.setPoint( img3 ); + shapeVertex(&pv); + + pv.setPoint( img4 ); + shapeVertex(&pv); + + this->endShape(); + + } else if (this->datumtype.getValue() == RADIUS) { + + SbVec3f dir = (p2-p1); + dir.normalize(); + SbVec3f norm (-dir[1],dir[0],0); + + float length = this->param1.getValue(); + SbVec3f pos = p2 + length*dir; + + float angle = atan2f(dir[1],dir[0]); + + SbVec3f img1 = SbVec3f(-this->imgWidth / 2, -this->imgHeight / 2, 0.f); + SbVec3f img2 = SbVec3f(-this->imgWidth / 2, this->imgHeight / 2, 0.f); + SbVec3f img3 = SbVec3f( this->imgWidth / 2, -this->imgHeight / 2, 0.f); + SbVec3f img4 = SbVec3f( this->imgWidth / 2, this->imgHeight / 2, 0.f); + + // Rotate through an angle + float s = sin(angle); + float c = cos(angle); + + img1 = SbVec3f((img1[0] * c) - (img1[1] * s), (img1[0] * s) + (img1[1] * c), 0.f); + img2 = SbVec3f((img2[0] * c) - (img2[1] * s), (img2[0] * s) + (img2[1] * c), 0.f); + img3 = SbVec3f((img3[0] * c) - (img3[1] * s), (img3[0] * s) + (img3[1] * c), 0.f); + img4 = SbVec3f((img4[0] * c) - (img4[1] * s), (img4[0] * s) + (img4[1] * c), 0.f); + + SbVec3f textOffset = pos; + + img1 += textOffset; + img2 += textOffset; + img3 += textOffset; + img4 += textOffset; + + // Primitive Shape is only for text as this should only be selectable + SoPrimitiveVertex pv; + + this->beginShape(action, QUADS); + + pv.setNormal( SbVec3f(0.f, 0.f, 1.f) ); + + // Set coordinates + pv.setPoint( img1 ); + shapeVertex(&pv); + + pv.setPoint( img2 ); + shapeVertex(&pv); + + pv.setPoint( img3 ); + shapeVertex(&pv); + + pv.setPoint( img4 ); + shapeVertex(&pv); + + this->endShape(); + } else if (this->datumtype.getValue() == ANGLE) { + + // Only the angle intersection point is needed + SbVec3f p0 = pnts[0]; + + // Load the Paramaters + float length = this->param1.getValue(); + float startangle = this->param2.getValue(); + float range = this->param3.getValue(); + float endangle = startangle + range; + + float r = 2*length; + + // Useful Information + // v0 - vector for text position + // p0 - vector for angle intersect + SbVec3f v0(cos(startangle+range/2),sin(startangle+range/2),0); + + SbVec3f textOffset = p0 + v0 * r; + + SbVec3f img1 = SbVec3f(-this->imgWidth / 2, -this->imgHeight / 2, 0.f); + SbVec3f img2 = SbVec3f(-this->imgWidth / 2, this->imgHeight / 2, 0.f); + SbVec3f img3 = SbVec3f( this->imgWidth / 2, -this->imgHeight / 2, 0.f); + SbVec3f img4 = SbVec3f( this->imgWidth / 2, this->imgHeight / 2, 0.f); + + img1 += textOffset; + img2 += textOffset; + img3 += textOffset; + img4 += textOffset; + + // Primitive Shape is only for text as this should only be selectable + SoPrimitiveVertex pv; + + this->beginShape(action, QUADS); + + pv.setNormal( SbVec3f(0.f, 0.f, 1.f) ); + + // Set coordinates + pv.setPoint( img1 ); + shapeVertex(&pv); + + pv.setPoint( img2 ); + shapeVertex(&pv); + + pv.setPoint( img3 ); + shapeVertex(&pv); + + pv.setPoint( img4 ); + shapeVertex(&pv); + + this->endShape(); } - SoPrimitiveVertex pv; - - beginShape(action, QUADS); - - pv.setNormal( SbVec3f(0.f, 0.f, 1.f) ); - - // Set coordinates - pv.setPoint( SbVec3f(-width / 2, height / 2, 0.f) ); - shapeVertex(&pv); - - pv.setPoint( SbVec3f(-width / 2, -height / 2, 0.f) ); - shapeVertex(&pv); - - pv.setPoint( SbVec3f(width / 2, -height / 2, 0.f) ); - shapeVertex(&pv); - - pv.setPoint( SbVec3f(width / 2, height / 2, 0.f) ); - shapeVertex(&pv); - - endShape(); } void SoDatumLabel::GLRender(SoGLRenderAction * action) @@ -239,13 +348,384 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action) int srcw = size[0]; int srch = size[1]; + // Create the quad to hold texture + const SbViewVolume & vv = SoViewVolumeElement::get(state); + float scale = vv.getWorldToScreenScale(SbVec3f(0.f,0.f,0.f), 0.4f); + + float aspectRatio = (float) srcw / (float) srch; + this->imgHeight = scale / (float) srch; + this->imgWidth = aspectRatio * (float) this->imgHeight; + + + // Get the points stored + const SbVec3f *pnts = this->pnts.getValues(0); + state->push(); + //Set General OpenGL Properties glPushAttrib(GL_ENABLE_BIT | GL_PIXEL_MODE_BIT | GL_COLOR_BUFFER_BIT); glDisable(GL_LIGHTING); - glEnable(GL_DEPTH_TEST); + + //Enable Anti-alias + if(action->isSmoothing()) + { + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + glHint(GL_LINE_SMOOTH_HINT,GL_NICEST); + } + // Position for Datum Text Label + float offsetX, offsetY, angle; + + SbVec3f textOffset; + if(this->datumtype.getValue() == DISTANCE || this->datumtype.getValue() == DISTANCEX || this->datumtype.getValue() == DISTANCEY ) + { + float length = this->param1.getValue(); + float length2 = this->param2.getValue(); + const SbVec3f *pnts = this->pnts.getValues(0); + + SbVec3f p1 = pnts[0]; + SbVec3f p2 = pnts[1]; + + SbVec3f dir, norm; + if (this->datumtype.getValue() == DISTANCE) { + dir = (p2-p1); + } else if (this->datumtype.getValue() == DISTANCEX) { + dir = SbVec3f( (p2[0] - p1[0] >= FLT_EPSILON) ? 1 : -1, 0, 0); + } else if (this->datumtype.getValue() == DISTANCEY) { + dir = SbVec3f(0, (p2[1] - p1[1] >= FLT_EPSILON) ? 1 : -1, 0); + } + + dir.normalize(); + norm = SbVec3f (-dir[1],dir[0],0); + + // when the datum line is not parallel to p1-p2 the projection of + // p1-p2 on norm is not zero, p2 is considered as reference and p1 + // is replaced by its projection p1_ + float normproj12 = (p2-p1).dot(norm); + SbVec3f p1_ = p1 + normproj12 * norm; + + SbVec3f midpos = (p1_ + p2)/2; + + float offset1 = (length + normproj12 < 0) ? -0.02 : 0.02; + float offset2 = (length < 0) ? -0.02 : 0.02; + + // Get magnitude of angle between horizontal + angle = atan2f(dir[1],dir[0]); + bool flip=false; + if (angle > M_PI_2+M_PI/12) { + angle -= M_PI; + flip = true; + } else if (angle <= -M_PI_2+M_PI/12) { + angle += M_PI; + flip = true; + } + + textOffset = midpos + norm * length + dir * length2; + + // Get the colour + const SbColor& t = textColor.getValue(); + + // Set GL Properties + glLineWidth(this->lineWidth.getValue()); + glColor3f(t[0], t[1], t[2]); + float margin = 0.01f; + margin *= scale; + + SbVec3f perp1 = p1_ + norm * (length + offset1 * scale); + SbVec3f perp2 = p2 + norm * (length + offset2 * scale); + + // Calculate the coordinates for the parallel datum lines + SbVec3f par1 = p1_ + norm * length; + SbVec3f par2 = midpos + norm * length + dir * (length2 - this->imgWidth / 2 - margin); + SbVec3f par3 = midpos + norm * length + dir * (length2 + this->imgWidth / 2 + margin); + SbVec3f par4 = p2 + norm * length; + + bool flipTriang = false; + + if ((par3-par1).dot(dir) > (par4 - par1).length()) { + // Increase Margin to improve visability + float tmpMargin = 0.08f * scale; + par3 = par4; + if((par2-par1).dot(dir) > (par4 - par1).length()) { + par3 = par2; + par2 = par1 - dir * tmpMargin; + flipTriang = true; + } + } else if ((par2-par1).dot(dir) < 0.f) { + float tmpMargin = 0.08f * scale; + par2 = par1; + if((par3-par1).dot(dir) < 0.f) { + par2 = par3; + par3 = par4 + dir * tmpMargin; + flipTriang = true; + } + } + // Perp Lines + glBegin(GL_LINES); + glVertex2f(p1[0], p1[1]); + glVertex2f(perp1[0], perp1[1]); + + glVertex2f(p2[0], p2[1]); + glVertex2f(perp2[0], perp2[1]); + + glVertex2f(par1[0], par1[1]); + glVertex2f(par2[0], par2[1]); + + glVertex2f(par3[0], par3[1]); + glVertex2f(par4[0], par4[1]); + glEnd(); + + SbVec3f ar1 = par1 + ((flipTriang) ? -1 : 1) * dir * 0.866 * 2 * margin; + SbVec3f ar2 = ar1 + norm * margin; + ar1 -= norm * margin; + + SbVec3f ar3 = par4 - ((flipTriang) ? -1 : 1) * dir * 0.866 * 2 * margin; + SbVec3f ar4 = ar3 + norm * margin ; + ar3 -= norm * margin; + + //Draw a pretty arrowhead (Equilateral) (Eventually could be improved to other shapes?) + glBegin(GL_TRIANGLES); + glVertex2f(par1[0], par1[1]); + glVertex2f(ar1[0], ar1[1]); + glVertex2f(ar2[0], ar2[1]); + + glVertex2f(par4[0], par4[1]); + glVertex2f(ar3[0], ar3[1]); + glVertex2f(ar4[0], ar4[1]); + glEnd(); + + // BOUNDING BOX CALCULATION - IMPORTANT + // Finds the mins and maxes + std::vector corners; + corners.push_back(p1); + corners.push_back(p2); + corners.push_back(perp1); + corners.push_back(perp2); + + float minX = p1[0], minY = p1[1], maxX = p1[0] , maxY = p1[1]; + for (std::vector::const_iterator it=corners.begin(); it != corners.end(); ++it) { + minX = ((*it)[0] < minX) ? (*it)[0] : minX; + minY = ((*it)[1] < minY) ? (*it)[1] : minY; + maxX = ((*it)[0] > maxX) ? (*it)[0] : maxX; + maxY = ((*it)[1] > maxY) ? (*it)[1] : maxY; + } + //Store the bounding box + this->bbox.setBounds(SbVec3f(minX, minY, 0.f), SbVec3f (maxX, maxY, 0.f)); + + } else if (this->datumtype.getValue() == RADIUS) { + // Get the Points + SbVec3f p1 = pnts[0]; + SbVec3f p2 = pnts[1]; + + SbVec3f dir = (p2-p1); + dir.normalize(); + SbVec3f norm (-dir[1],dir[0],0); + + float length = this->param1.getValue(); + SbVec3f pos = p2 + length*dir; + + // Get magnitude of angle between horizontal + angle = atan2f(dir[1],dir[0]); + bool flip=false; + if (angle > M_PI_2+M_PI/12) { + angle -= M_PI; + flip = true; + } else if (angle <= -M_PI_2+M_PI/12) { + angle += M_PI; + flip = true; + } + + textOffset = pos; + + // Get the colour + const SbColor& t = textColor.getValue(); + + // Set GL Properties + glLineWidth(this->lineWidth.getValue()); + glColor3f(t[0], t[1], t[2]); + + float margin = 0.01f; + margin *= scale; + + // Create the arrowhead + SbVec3f ar0 = p2; + SbVec3f ar1 = p2 - dir * 0.866 * 2 * margin; + SbVec3f ar2 = ar1 + norm * margin; + ar1 -= norm * margin; + + SbVec3f p3 = pos + dir * (this->imgWidth / 2 + margin); + if ((p3-p1).length() > (p2-p1).length()) + p2 = p3; + + // Calculate the points + SbVec3f pnt1 = pos - dir * (margin + this->imgWidth / 2); + SbVec3f pnt2 = pos + dir * (margin + this->imgWidth / 2); + + // Draw the Lines + glBegin(GL_LINES); + glVertex2f(p1[0], p1[1]); + glVertex2f(pnt1[0], pnt1[1]); + + glVertex2f(pnt2[0], pnt2[1]); + glVertex2f(p2[0], p2[1]); + glEnd(); + + glBegin(GL_TRIANGLES); + glVertex2f(ar0[0], ar0[1]); + glVertex2f(ar1[0], ar1[1]); + glVertex2f(ar2[0], ar2[1]); + glEnd(); + // BOUNDING BOX CALCULATION - IMPORTANT + // Finds the mins and maxes + std::vector corners; + corners.push_back(p1); + corners.push_back(p2); + corners.push_back(pnt1); + corners.push_back(pnt2); + + float minX = p1[0], minY = p1[1], maxX = p1[0] , maxY = p1[1]; + for (std::vector::const_iterator it=corners.begin(); it != corners.end(); ++it) { + minX = ((*it)[0] < minX) ? (*it)[0] : minX; + minY = ((*it)[1] < minY) ? (*it)[1] : minY; + maxX = ((*it)[0] > maxX) ? (*it)[0] : maxX; + maxY = ((*it)[1] > maxY) ? (*it)[1] : maxY; + } + //Store the bounding box + this->bbox.setBounds(SbVec3f(minX, minY, 0.f), SbVec3f (maxX, maxY, 0.f)); + } else if (this->datumtype.getValue() == ANGLE) { + // Only the angle intersection point is needed + SbVec3f p0 = pnts[0]; + + // Load the Paramaters + float length = this->param1.getValue(); + float startangle = this->param2.getValue(); + float range = this->param3.getValue(); + float endangle = startangle + range; + + + float r = 2*length; + + // Set the Text label angle to zero + angle = 0.f; + + // Useful Information + // v0 - vector for text position + // p0 - vector for angle intersect + SbVec3f v0(cos(startangle+range/2),sin(startangle+range/2),0); + + // leave some space for the text + if (range >= 0) + range = std::max(0.2f*range, range - this->imgWidth/(2*r)); + else + range = std::min(0.2f*range, range + this->imgWidth/(2*r)); + + int countSegments = std::max(6, abs(int(50.0 * range / (2 * M_PI)))); + double segment = range / (2*countSegments-2); + + textOffset = p0 + v0 * r; + + float margin = 0.01f; + margin *= scale; + + // Get the colour + const SbColor& t = textColor.getValue(); + + // Set GL Properties + glLineWidth(this->lineWidth.getValue()); + glColor3f(t[0], t[1], t[2]); + + // Draw + glBegin(GL_LINE_STRIP); + + int i=0; + + for (; i < countSegments; i++) { + double theta = startangle + segment*i; + SbVec3f v1 = p0+SbVec3f(r*cos(theta),r*sin(theta),0); + glVertex2f(v1[0],v1[1]); + } + glEnd(); + + glBegin(GL_LINE_STRIP); + i=0; + for (; i < countSegments; i++) { + double theta = endangle - segment*i; + SbVec3f v1 = p0+SbVec3f(r*cos(theta),r*sin(theta),0); + glVertex2f(v1[0],v1[1]); + } + glEnd(); + + // Direction vectors for start and end lines + SbVec3f v1(cos(startangle),sin(startangle),0); + SbVec3f v2(cos(endangle),sin(endangle),0); + + SbVec3f pnt1 = p0+(r-margin)*v1; + SbVec3f pnt2 = p0+(r+margin)*v1; + SbVec3f pnt3 = p0+(r-margin)*v2; + SbVec3f pnt4 = p0+(r+margin)*v2; + + glBegin(GL_LINES); + glVertex2f(pnt1[0],pnt1[1]); + glVertex2f(pnt2[0],pnt2[1]); + + glVertex2f(pnt3[0],pnt3[1]); + glVertex2f(pnt4[0],pnt4[1]); + glEnd(); + + // BOUNDING BOX CALCULATION - IMPORTANT + // Finds the mins and maxes + // We may need to include the text position too + + SbVec3f img1 = SbVec3f(-this->imgWidth / 2, -this->imgHeight / 2, 0.f); + SbVec3f img2 = SbVec3f(-this->imgWidth / 2, this->imgHeight / 2, 0.f); + SbVec3f img3 = SbVec3f( this->imgWidth / 2, -this->imgHeight / 2, 0.f); + SbVec3f img4 = SbVec3f( this->imgWidth / 2, this->imgHeight / 2, 0.f); + + img1 += textOffset; + img2 += textOffset; + img3 += textOffset; + img4 += textOffset; + + std::vector corners; + corners.push_back(pnt1); + corners.push_back(pnt2); + corners.push_back(pnt3); + corners.push_back(pnt4); + corners.push_back(img1); + corners.push_back(img2); + corners.push_back(img3); + corners.push_back(img4); + + float minX = pnt1[0], minY = pnt1[1], maxX = pnt1[0] , maxY = pnt1[1]; + for (std::vector::const_iterator it=corners.begin(); it != corners.end(); ++it) { + minX = ((*it)[0] < minX) ? (*it)[0] : minX; + minY = ((*it)[1] < minY) ? (*it)[1] : minY; + maxX = ((*it)[0] > maxX) ? (*it)[0] : maxX; + maxY = ((*it)[1] > maxY) ? (*it)[1] : maxY; + } + //Store the bounding box + this->bbox.setBounds(SbVec3f(minX, minY, 0.f), SbVec3f (maxX, maxY, 0.f)); + + } + + SbVec3f surfNorm(0.f, 0.f, 1.f) ; + //Get the camera z-direction + SbVec3f z = vv.zVector(); + const SbViewportRegion & vpr = SoViewportRegionElement::get(state); + + SoGetMatrixAction * getmatrixaction = new SoGetMatrixAction(vpr); + getmatrixaction->apply(this); + + SbMatrix transform = getmatrixaction->getMatrix(); + transform.multVecMatrix(surfNorm, surfNorm); + + bool flip = surfNorm.dot(z) > 0; + + glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); // Enable Textures - glEnable(GL_BLEND); + glEnable(GL_BLEND); + // Copy the text bitmap into memory and bind GLuint myTexture; // generate a texture @@ -259,27 +739,26 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action) glTexImage2D(GL_TEXTURE_2D, 0, nc, srcw, srch, 0, GL_RGBA, GL_UNSIGNED_BYTE,(const GLvoid*) dataptr); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - // Create the quad to hold texture - const SbViewVolume & vv = SoViewVolumeElement::get(state); - float scale = vv.getWorldToScreenScale(SbVec3f(0.f,0.f,0.f), 0.4f); - - float aspectRatio = (float) srcw / (float) srch; - float height = scale / (float) srch; - float width = aspectRatio * (float) height; - this->bbx = width; - this->bby = height; + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + // Apply a rotation and translation matrix + glTranslatef(textOffset[0],textOffset[1], textOffset[2]); + glRotatef((GLfloat) angle * 180 / M_PI, 0,0,1); glBegin(GL_QUADS); + glColor3f(1.f, 1.f, 1.f); - glTexCoord2f(0.f, 1.f); glVertex2f(-width/ 2, height / 2); - glTexCoord2f(0.f, 0.f); glVertex2f(-width / 2,-height / 2); - glTexCoord2f(1.f, 0.f); glVertex2f( width/ 2,-height / 2); - glTexCoord2f(1.f, 1.f); glVertex2f( width / 2, height / 2); + glTexCoord2f((flip) ? 0.f : 1.f, 1.f); glVertex2f( -this->imgWidth / 2, this->imgHeight / 2); + glTexCoord2f((flip) ? 0.f : 1.f, 0.f); glVertex2f( -this->imgWidth / 2, -this->imgHeight / 2); + glTexCoord2f((flip) ? 1.f : 0.f, 0.f); glVertex2f( this->imgWidth / 2, -this->imgHeight / 2); + glTexCoord2f((flip) ? 1.f : 0.f, 1.f); glVertex2f( this->imgWidth / 2, this->imgHeight / 2); + glEnd(); // Reset the Mode - + glPopMatrix(); glPopAttrib(); state->pop(); } diff --git a/src/Mod/Sketcher/Gui/SoDatumLabel.h b/src/Mod/Sketcher/Gui/SoDatumLabel.h index 0e4adb11a..0fa276198 100644 --- a/src/Mod/Sketcher/Gui/SoDatumLabel.h +++ b/src/Mod/Sketcher/Gui/SoDatumLabel.h @@ -1,5 +1,5 @@ /*************************************************************************** - * * + * Copyright (c) 2011-2012 Luke Parry * * * * This file is part of the FreeCAD CAx development system. * * * @@ -33,27 +33,40 @@ #include #include #include +#include #include #include namespace SketcherGui { - + class SketcherGuiExport SoDatumLabel : public SoShape { typedef SoShape inherited; SO_NODE_HEADER(SoDatumLabel); public: + enum Type + { + DISTANCE, + DISTANCEX, + DISTANCEY, + ANGLE, + RADIUS}; static void initClass(); SoDatumLabel(); SoMFString string; SoSFColor textColor; - SoSFEnum justification; + SoSFEnum datumtype; SoSFName name; SoSFInt32 size; + SoSFFloat param1; + SoSFFloat param2; + SoSFFloat param3; + SoMFVec3f pnts; SoSFImage image; + SoSFFloat lineWidth; protected: virtual ~SoDatumLabel() {}; @@ -63,8 +76,9 @@ protected: private: void drawImage(); - float bbx; - float bby; + SbBox3f bbox; + float imgWidth; + float imgHeight; }; } diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 727626a9b..ed7c5d43f 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -46,6 +46,7 @@ # include # include # include +# include # include # include # include @@ -395,7 +396,6 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe //Base::Console().Log("start dragging, point:%d\n",this->DragPoint); Mode = STATUS_SELECT_Constraint; done = true; - } if (done && length < dblClickRadius && tmp.getValue() < dci) { @@ -418,8 +418,7 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe default: return false; } - } - else { + } else { // Do things depending on the mode of the user interaction switch (Mode) { case STATUS_SELECT_Point: @@ -922,8 +921,9 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2D &toPo else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) { const Part::GeomCircle *circle = dynamic_cast(geo); double radius = circle->getRadius(); - double angle = M_PI/4; p1 = circle->getCenter(); + Base::Vector3d tmpDir = Base::Vector3d(toPos.fX, toPos.fY, 0) - p1; + double angle = atan2f(tmpDir.y, tmpDir.x); p2 = p1 + radius * Base::Vector3d(cos(angle),sin(angle),0.); } else return; @@ -940,11 +940,17 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2D &toPo else if (Constr->Type == DistanceY) dir = Base::Vector3d(0, (p2.y - p1.y >= FLT_EPSILON) ? 1 : -1, 0); - if (Constr->Type == Radius) + if (Constr->Type == Radius) { Constr->LabelDistance = vec.x * dir.x + vec.y * dir.y; - else { + Constr->LabelPosition = atan2f(dir.y, dir.x); + } else { Base::Vector3d norm(-dir.y,dir.x,0); Constr->LabelDistance = vec.x * norm.x + vec.y * norm.y; + if (Constr->Type == Distance || + Constr->Type == DistanceX || Constr->Type == DistanceY) { + vec = Base::Vector3d(toPos.fX, toPos.fY, 0) - (p2 + p1) / 2; + Constr->LabelPosition = vec.x * dir.x + vec.y * dir.y; + } } } else if (Constr->Type == Angle) { @@ -1018,11 +1024,11 @@ bool ViewProviderSketch::isConstraintAtPosition(const Base::Vector3d &constrPos, if (pp) { SoPath *path = pp->getPath(); int length = path->getLength(); - SoNode *tailFather = path->getNode(length-2); + SoNode *tailFather1 = path->getNode(length-2); SoNode *tailFather2 = path->getNode(length-3); // checking if a constraint is the same as the one selected - if (tailFather2 == constraint || tailFather == constraint) { + if (tailFather1 == constraint || tailFather2 == constraint) { return false; } else { return true; @@ -1414,33 +1420,42 @@ void ViewProviderSketch::updateColor(void) // colors of the constraints for (int i=0; i < edit->constrGroup->getNumChildren(); i++) { SoSeparator *s = dynamic_cast(edit->constrGroup->getChild(i)); - SoMaterial *m = dynamic_cast(s->getChild(0)); // Check Constraint Type ConstraintType type = getSketchObject()->Constraints.getValues()[i]->Type; bool hasDatumLabel = (type == Sketcher::Angle || - type == Sketcher::Radius || - type == Sketcher::Distance || type == Sketcher::DistanceX || type == Sketcher::DistanceY); + type == Sketcher::Radius || + type == Sketcher::Distance || + type == Sketcher::DistanceX || type == Sketcher::DistanceY); + + // Non DatumLabel Nodes will have a material excluding coincident + bool hasMaterial = false; + + SoMaterial *m; + if (!hasDatumLabel && type != Sketcher::Coincident) { + hasMaterial = true; + m = dynamic_cast(s->getChild(0)); + } if (edit->SelConstraintSet.find(i) != edit->SelConstraintSet.end()) { - m->diffuseColor = SelectColor; if (hasDatumLabel) { - SoDatumLabel *l = dynamic_cast(s->getChild(4)); + SoDatumLabel *l = dynamic_cast(s->getChild(0)); l->textColor = SelectColor; - } + } else if (hasMaterial) + m->diffuseColor = SelectColor; } else if (edit->PreselectConstraint == i) { - m->diffuseColor = PreselectColor; if (hasDatumLabel) { - SoDatumLabel *l = dynamic_cast(s->getChild(4)); + SoDatumLabel *l = dynamic_cast(s->getChild(0)); l->textColor = PreselectColor; - } + } else if (hasMaterial) + m->diffuseColor = PreselectColor; } else { - m->diffuseColor = ConstrDimColor; if (hasDatumLabel) { - SoDatumLabel *l = dynamic_cast(s->getChild(4)); + SoDatumLabel *l = dynamic_cast(s->getChild(0)); l->textColor = ConstrDimColor; - } + } else if (hasMaterial) + m->diffuseColor = ConstrDimColor; } } @@ -1729,7 +1744,6 @@ void ViewProviderSketch::draw(bool temp) edit->CurvIdToGeoId.push_back(GeoId); } else { - ; } } @@ -2071,28 +2085,7 @@ Restart: } else break; - SbVec3f p1(pnt1.x,pnt1.y,zConstr); - SbVec3f p2(pnt2.x,pnt2.y,zConstr); - - SbVec3f dir, norm; - if (Constr->Type == Distance) - dir = (p2-p1); - else if (Constr->Type == DistanceX) - dir = SbVec3f( (pnt2.x - pnt1.x >= FLT_EPSILON) ? 1 : -1, 0, 0); - else if (Constr->Type == DistanceY) - dir = SbVec3f(0, (pnt2.y - pnt1.y >= FLT_EPSILON) ? 1 : -1, 0); - dir.normalize(); - norm = SbVec3f (-dir[1],dir[0],0); - - // when the datum line is not parallel to p1-p2 the projection of - // p1-p2 on norm is not zero, p2 is considered as reference and p1 - // is replaced by its projection p1_ - float normproj12 = (p2-p1).dot(norm); - - SbVec3f p1_ = p1 + normproj12 * norm; - SbVec3f midpos = (p1_ + p2)/2; - - SoDatumLabel *asciiText = dynamic_cast(sep->getChild(4)); + SoDatumLabel *asciiText = dynamic_cast(sep->getChild(0)); if ((Constr->Type == DistanceX || Constr->Type == DistanceY) && Constr->FirstPos != Sketcher::none && Constr->Second == Constraint::GeoUndef) // display negative sign for absolute coordinates @@ -2100,68 +2093,25 @@ Restart: else // hide negative sign asciiText->string = SbString().sprintf("%.2f",std::abs(Constr->Value)); - // Get Bounding box dimensions for Datum text - Gui::View3DInventorViewer *viewer = static_cast(mdi)->getViewer(); + if (Constr->Type == Distance) + asciiText->datumtype = SoDatumLabel::DISTANCE; + else if (Constr->Type == DistanceX) + asciiText->datumtype = SoDatumLabel::DISTANCEX; + else if (Constr->Type == DistanceY) + asciiText->datumtype = SoDatumLabel::DISTANCEY; - // [FIX ME] Its an attempt to find the height of the text using the bounding box, but is in correct. - SoGetBoundingBoxAction bbAction(viewer->getViewportRegion()); - bbAction.apply(sep->getChild(4)); + // Assign the Datum Points + asciiText->pnts.setNum(2); + SbVec3f *verts = asciiText->pnts.startEditing(); - float bx,by,bz; - bbAction.getBoundingBox().getSize(bx,by,bz); - SbVec3f textBB(bx,by,bz); - // bbAction.setCenter(, true) - // This is the bounding box containing the width and height of text + verts[0] = SbVec3f (pnt1.x,pnt1.y,zConstr); + verts[1] = SbVec3f (pnt2.x,pnt2.y,zConstr); - SbVec3f textBBCenter = bbAction.getBoundingBox().getCenter(); + asciiText->pnts.finishEditing(); - float length = Constr->LabelDistance; - - // Get magnitude of angle between horizontal - double angle = atan2f(dir[1],dir[0]); - bool flip=false; - if (angle > M_PI_2+M_PI/12) { - angle -= M_PI; - flip = true; - } else if (angle <= -M_PI_2+M_PI/12) { - angle += M_PI; - flip = true; - } - - SbVec3f textpos = midpos + norm * (length + ( (flip ? 1:-1) * textBBCenter[1] / 4)); - - // set position and rotation of Datums Text - SoTransform *transform = dynamic_cast(sep->getChild(2)); - transform->rotation.setValue(SbVec3f(0, 0, 1), (float)angle); - transform->translation.setValue(textpos); - - // Get the datum nodes - SoSeparator *sepDatum = dynamic_cast(sep->getChild(1)); - SoCoordinate3 *datumCord = dynamic_cast(sepDatum->getChild(0)); - - // [Fixme] This should be made neater - compute the vertical datum line length - float offset1 = (length + normproj12 < 0) ? -0.5 : 0.5; - float offset2 = (length < 0) ? -0.5 : 0.5; - offset1 *= getScaleFactor(); - offset2 *= getScaleFactor(); - // Calculate coordinates for perpendicular datum lines - datumCord->point.set1Value(0,p1); - datumCord->point.set1Value(1,p1_ + norm * (length + offset1)); - datumCord->point.set1Value(2,p2); - datumCord->point.set1Value(3,p2 + norm * (length + offset2)); - - // Calculate the coordinates for the parallel datum lines - datumCord->point.set1Value(4,p1_ + norm * length); - datumCord->point.set1Value(5,midpos + norm * length - dir * (textBB[0]/1.7f) ); - datumCord->point.set1Value(6,midpos + norm * length + dir * (textBB[0]/1.7f) ); - datumCord->point.set1Value(7,p2 + norm * length); - - // Use the coordinates calculated earlier to the lineset - SoLineSet *datumLineSet = dynamic_cast(sepDatum->getChild(1)); - datumLineSet->numVertices.set1Value(0,2); - datumLineSet->numVertices.set1Value(1,2); - datumLineSet->numVertices.set1Value(2,2); - datumLineSet->numVertices.set1Value(3,2); + //Assign the Label Distance + asciiText->param1 = Constr->LabelDistance; + asciiText->param2 = Constr->LabelPosition; } break; case PointOnObject: @@ -2385,68 +2335,20 @@ Restart: } else break; - SoDatumLabel *asciiText = dynamic_cast(sep->getChild(4)); - asciiText->string = SbString().sprintf("%.2f",Base::toDegrees(std::abs(Constr->Value))); + SoDatumLabel *asciiText = dynamic_cast(sep->getChild(0)); + asciiText->string = SbString().sprintf("%.2f",Base::toDegrees(std::abs(Constr->Value))); + asciiText->datumtype = SoDatumLabel::ANGLE; + asciiText->param1 = Constr->LabelDistance; + asciiText->param2 = startangle; + asciiText->param3 = range; - // Get Bounding box dimensions for Datum text - Gui::View3DInventorViewer *viewer = static_cast(mdi)->getViewer(); + asciiText->pnts.setNum(2); + SbVec3f *verts = asciiText->pnts.startEditing(); - // [FIX ME] Its an attempt to find the height of the text using the bounding box, but is in correct. - SoGetBoundingBoxAction bbAction(viewer->getViewportRegion()); - bbAction.apply(sep->getChild(4)); + verts[0] = p0; - float bx,by,bz; - bbAction.getBoundingBox().getSize(bx,by,bz); - SbVec3f textBB(bx,by,bz); + asciiText->pnts.finishEditing(); - SbVec3f textBBCenter = bbAction.getBoundingBox().getCenter(); - - float length = Constr->LabelDistance; - float r = 2*length; - - SbVec3f v0(cos(startangle+range/2),sin(startangle+range/2),0); - SbVec3f textpos = p0 + v0 * r - SbVec3f(0,1,0) * textBBCenter[1]/4; - - // leave some space for the text - if (range >= 0) - range = std::max(0.2*range, range - textBB[0]/(2*r)); - else - range = std::min(0.2*range, range + textBB[0]/(2*r)); - - int countSegments = std::max(6, abs(int(50.0 * range / (2 * M_PI)))); - double segment = range / (2*countSegments-2); - - // set position and rotation of Datums Text - SoTransform *transform = dynamic_cast(sep->getChild(2)); - transform->translation.setValue(textpos); - - // Get the datum nodes - SoSeparator *sepDatum = dynamic_cast(sep->getChild(1)); - SoCoordinate3 *datumCord = dynamic_cast(sepDatum->getChild(0)); - - datumCord->point.setNum(2*countSegments+4); - int i=0; - int j=2*countSegments-1; - for (; i < countSegments; i++, j--) { - double angle = startangle + segment*i; - datumCord->point.set1Value(i,p0+SbVec3f(r*cos(angle),r*sin(angle),0)); - angle = endangle - segment*i; - datumCord->point.set1Value(j,p0+SbVec3f(r*cos(angle),r*sin(angle),0)); - } - SbVec3f v1(cos(startangle),sin(startangle),0); - SbVec3f v2(cos(endangle),sin(endangle),0); - float sf = getScaleFactor(); - datumCord->point.set1Value(2*countSegments ,p0+(r-0.5f * sf)*v1); - datumCord->point.set1Value(2*countSegments+1,p0+(r+0.5f * sf)*v1); - datumCord->point.set1Value(2*countSegments+2,p0+(r-0.5f * sf)*v2); - datumCord->point.set1Value(2*countSegments+3,p0+(r+0.5f * sf)*v2); - - // Use the coordinates calculated earlier to the lineset - SoLineSet *datumLineSet = dynamic_cast(sepDatum->getChild(1)); - datumLineSet->numVertices.set1Value(0,countSegments); - datumLineSet->numVertices.set1Value(1,countSegments); - datumLineSet->numVertices.set1Value(2,2); - datumLineSet->numVertices.set1Value(3,2); } break; case Radius: @@ -2469,7 +2371,7 @@ Restart: else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) { const Part::GeomCircle *circle = dynamic_cast(geo); double radius = circle->getRadius(); - double angle = M_PI/4; + double angle = (double) Constr->LabelPosition; pnt1 = circle->getCenter(); pnt2 = pnt1 + radius * Base::Vector3d(cos(angle),sin(angle),0.); } else @@ -2480,68 +2382,19 @@ Restart: SbVec3f p1(pnt1.x,pnt1.y,zConstr); SbVec3f p2(pnt2.x,pnt2.y,zConstr); - SbVec3f dir = (p2-p1); - dir.normalize(); - SbVec3f norm (-dir[1],dir[0],0); + SoDatumLabel *asciiText = dynamic_cast(sep->getChild(0)); + asciiText->string = SbString().sprintf("%.2f",Constr->Value); + asciiText->datumtype = SoDatumLabel::RADIUS; + asciiText->param1 = Constr->LabelDistance; + asciiText->param2 = Constr->LabelPosition; - float length = Constr->LabelDistance; - SbVec3f pos = p2 + length*dir; + asciiText->pnts.setNum(2); + SbVec3f *verts = asciiText->pnts.startEditing(); - SoDatumLabel *asciiText = dynamic_cast(sep->getChild(4)); - asciiText->string = SbString().sprintf("%.2f",Constr->Value); + verts[0] = p1; + verts[1] = p2; - // Get Bounding box dimensions for Datum text - Gui::MDIView *mdi = Gui::Application::Instance->activeDocument()->getActiveView(); - Gui::View3DInventorViewer *viewer = static_cast(mdi)->getViewer(); - - // [FIX ME] Its an attempt to find the height of the text using the bounding box, but is in correct. - SoGetBoundingBoxAction bbAction(viewer->getViewportRegion()); - bbAction.apply(sep->getChild(3)); - - float bx=0,by=0,bz=0; - SbBox3f bbox = bbAction.getBoundingBox(); - if (!bbox.isEmpty()) - bbox.getSize(bx,by,bz); - SbVec3f textBB(bx,by,bz); - - SbVec3f textBBCenter = bbAction.getBoundingBox().getCenter(); - - // Get magnitude of angle between horizontal - double angle = atan2f(dir[1],dir[0]); - bool flip=false; - if (angle > M_PI_2+M_PI/12) { - angle -= M_PI; - flip = true; - } else if (angle <= -M_PI_2+M_PI/12) { - angle += M_PI; - flip = true; - } - - SbVec3f textpos = pos + norm * ( (flip ? 1:-1) * textBBCenter[1] / 1.7f); - - // set position and rotation of Datums Text - SoTransform *transform = dynamic_cast(sep->getChild(2)); - transform->rotation.setValue(SbVec3f(0, 0, 1), (float)angle); - transform->translation.setValue(textpos); - - // Get the datum nodes - SoSeparator *sepDatum = dynamic_cast(sep->getChild(1)); - SoCoordinate3 *datumCord = dynamic_cast(sepDatum->getChild(0)); - - SbVec3f p3 = pos + dir * (6+textBB[0]/1.7f); - if ((p3-p1).length() > (p2-p1).length()) - p2 = p3; - - // Calculate the coordinates for the parallel datum lines - datumCord->point.set1Value(0,p1); - datumCord->point.set1Value(1,pos - dir * (1+textBB[0]/1.7f) ); - datumCord->point.set1Value(2,pos + dir * (1+textBB[0]/1.7f) ); - datumCord->point.set1Value(3,p2); - - // Use the coordinates calculated earlier to the lineset - SoLineSet *datumLineSet = dynamic_cast(sepDatum->getChild(1)); - datumLineSet->numVertices.set1Value(0,2); - datumLineSet->numVertices.set1Value(1,2); + asciiText->pnts.finishEditing(); } break; case Coincident: // nothing to do for coincident @@ -2575,10 +2428,10 @@ void ViewProviderSketch::rebuildConstraintsVisual(void) SoSeparator *sep = new SoSeparator(); // no caching for fluctuand data structures sep->renderCaching = SoSeparator::OFF; + // every constrained visual node gets its own material for preselection and selection SoMaterial *Material = new SoMaterial; Material->diffuseColor = ConstrDimColor; - sep->addChild(Material); // distinguish different constraint types to build up switch ((*it)->Type) { @@ -2588,35 +2441,22 @@ void ViewProviderSketch::rebuildConstraintsVisual(void) case Radius: case Angle: { - SoSeparator *sepDatum = new SoSeparator(); - sepDatum->addChild(new SoCoordinate3()); - SoLineSet *lineSet = new SoLineSet; - sepDatum->addChild(lineSet); - - sep->addChild(sepDatum); - - // Add the datum text - sep->addChild(new SoTransform()); - - // add font for the datum text - SoFont *font = new SoFont(); - font->size = 8.f; - font->name = "FreeSans:bold, Helvetica, Arial, FreeSans:bold"; - - sep->addChild(font); - SoDatumLabel *text = new SoDatumLabel(); - //text->justification = SoDatumLabel::CENTER; text->string = ""; text->textColor = ConstrDimColor; + SoAnnotation *anno = new SoAnnotation(); + anno->renderCaching = SoSeparator::OFF; + anno->addChild(text); sep->addChild(text); - + edit->constrGroup->addChild(anno); edit->vConstrType.push_back((*it)->Type); + continue; // jump to next constraint } break; case Horizontal: case Vertical: { + sep->addChild(Material); sep->addChild(new SoZoomTranslation()); // 1. sep->addChild(new SoImage()); // 2. constraint icon @@ -2632,6 +2472,7 @@ void ViewProviderSketch::rebuildConstraintsVisual(void) case Equal: { // Add new nodes to Constraint Seperator + sep->addChild(Material); sep->addChild(new SoZoomTranslation()); // 1. sep->addChild(new SoImage()); // 2. first constraint icon sep->addChild(new SoZoomTranslation()); // 3. @@ -2645,6 +2486,7 @@ void ViewProviderSketch::rebuildConstraintsVisual(void) case Tangent: { // Add new nodes to Constraint Seperator + sep->addChild(Material); sep->addChild(new SoZoomTranslation()); // 1. sep->addChild(new SoImage()); // 2. constraint icon @@ -2667,6 +2509,7 @@ void ViewProviderSketch::rebuildConstraintsVisual(void) sepArrows->addChild(new SoCoordinate3()); SoLineSet *lineSet = new SoLineSet; sepArrows->addChild(lineSet); + sep->addChild(Material); sep->addChild(sepArrows); // 1. // Add new nodes to Constraint Seperator @@ -2976,11 +2819,6 @@ void ViewProviderSketch::createEditInventorNodes(void) MtlBind->value = SoMaterialBinding::OVERALL ; edit->EditRoot->addChild(MtlBind); - // add font for the text shown constraints - font = new SoFont(); - font->size = 8.0; - edit->EditRoot->addChild(font); - // use small line width for the Constraints DrawStyle = new SoDrawStyle; DrawStyle->lineWidth = 1;