From 567e0434e62ee0f99b2c4ef3f85eda4c81973167 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sun, 27 Nov 2022 20:06:00 +0100 Subject: [PATCH] Base: refactoring of Builder3D/InventorBuilder --- src/Base/Builder3D.cpp | 335 ++++++++++------------------------------- src/Base/Builder3D.h | 141 +++++++---------- 2 files changed, 130 insertions(+), 346 deletions(-) diff --git a/src/Base/Builder3D.cpp b/src/Base/Builder3D.cpp index 869493c087..eb86430873 100644 --- a/src/Base/Builder3D.cpp +++ b/src/Base/Builder3D.cpp @@ -105,264 +105,6 @@ const char* PolygonOffset::styleAsString() const return "FILLED"; } -/** - * A constructor. - * A more elaborate description of the constructor. - */ -Builder3D::Builder3D() - : bStartEndOpen(false) -{ - result << "#Inventor V2.1 ascii \n\n"; - result << "Separator { "; -} - -/** - * A destructor. - * A more elaborate description of the destructor. - */ -Builder3D::~Builder3D() = default; - - -//************************************************************************** -// points handling - -/** - * Starts the definition of point set with the given point size and color. - * If possible don't make too many startPoints() and endPoints() calls. - * Try to put all points in one set. - * @see endPoints() - * @param pointSize the point size in pixel that are displayed. - * @param ColorRGB point color. - */ -void Builder3D::startPoints(short pointSize, const ColorRGB& color) -{ - bStartEndOpen = true; - result << "Separator { "; - result << "Material { "; - result << "diffuseColor " << color.red() << " "<< color.green() << " " << color.blue(); - result << "} "; - result << "MaterialBinding { value PER_PART } "; - result << "DrawStyle { pointSize " << pointSize << "} "; - result << "Coordinate3 { "; - result << "point [ "; -} - -/// add a point to a point set -void Builder3D::addPoint(const Vector3f &point) -{ - result << point.x << " " << point.y << " " << point.z << ","; -} -/** - * Ends the point set operations and write the resulting inventor string. - * @see startPoints() - */ -void Builder3D::endPoints() -{ - result << "] "; - result << "} "; - result << "PointSet { } "; - result << "} "; - bStartEndOpen = false; -} - -void Builder3D::addSinglePoint(const Base::Vector3f &point, DrawStyle drawStyle, const ColorRGB& color) -{ - // addSinglePoint() not between startXXX() and endXXX() allowed - assert(!bStartEndOpen); - - result << "Separator { "; - result << "Material { "; - result << "diffuseColor " << color.red() << " "<< color.green() << " "<< color.blue(); - result << "} "; - result << "MaterialBinding { value PER_PART } "; - result << "DrawStyle { pointSize " << drawStyle.pointSize << "} "; - result << "Coordinate3 { "; - result << "point [ "; - result << point.x << " " << point.y << " " << point.z << ","; - result << "] "; - result << "} "; - result << "PointSet { } "; - result << "} "; -} - -//************************************************************************** -// text handling - - -/** - * Add a Text with a given position to the 3D set. The origin is the - * lower leftmost corner. - * @param point origin of the text - * @param text the text to display. - * @param color text color. - */ -void Builder3D::addText(const Base::Vector3f& point, const char * text, const Base::ColorRGB& color) -{ - // addSinglePoint() not between startXXX() and endXXX() allowed - assert(!bStartEndOpen); - - result << "Separator { " - << "Material { diffuseColor " << color.red() << " "<< color.green() << " "<< color.blue() << "} " - << "Transform { translation " << point.x << " "<< point.y << " "<< point.z << "} " - << "Text2 { string \" " << text << "\" " << "} " - << "} "; -} - -void Builder3D::clear () -{ - // under gcc stringstream::str() returns a copy not a reference -#if defined(_MSC_VER) - result.str().clear(); -#endif - result.clear(); -} - -//************************************************************************** -// line/arrow handling - -void Builder3D::addSingleLine(const Base::Line3f& line, DrawStyle drawStyle, const ColorRGB& color) -{ - std::string pattern = drawStyle.patternAsString(); - - result << "Separator { " - << "Material { diffuseColor " << color.red() << " "<< color.green() << " "<< color.blue() << "} " - << "DrawStyle { lineWidth " << drawStyle.lineWidth << " linePattern " << pattern << " } " - << "Coordinate3 { " - << "point [ " - << line.p1.x << " " << line.p1.y << " " << line.p1.z << "," - << line.p2.x << " " << line.p2.y << " " << line.p2.z - << "] " - << "} " - << "LineSet { } " - << "} "; -} - -void Builder3D::addSingleArrow(const Base::Line3f& line, DrawStyle drawStyle, const ColorRGB& color) -{ - float length = line.Length(); - float coneLength = length / 10.0F; - float coneRadius = coneLength / 2.0F; - float sf1 = length - coneLength; - float sf2 = length - coneLength/2.0F; - - Vector3f dir = line.GetDirection(); - dir.Normalize(); - dir.Scale(sf1, sf1, sf1); - Vector3f pt2s = line.p1 + dir; - dir.Normalize(); - dir.Scale(sf2, sf2, sf2); - Vector3f cpt = line.p1 + dir; - - Vector3f rot = Vector3f(0.0f, 1.0f, 0.0f) % dir; - rot.Normalize(); - float a = Vector3f(0.0f, 1.0f, 0.0f).GetAngle(dir); - - result << "Separator { " - << "Material { diffuseColor " << color.red() << " "<< color.green() << " "<< color.blue() << "} " - << "DrawStyle { lineWidth " << drawStyle.lineWidth << "} " - << "Coordinate3 { " - << "point [ " - << line.p1.x << " " << line.p1.y << " " << line.p1.z << "," - << pt2s.x << " " << pt2s.y << " " << pt2s.z - << "] " - << "} " - << "LineSet { } " - << "Transform { " - << "translation " << cpt.x << " " << cpt.y << " " << cpt.z << " " - << "rotation " << rot.x << " " << rot.y << " " << rot.z << " " << a - << "} " - << "Cone { bottomRadius " << coneRadius << " height " << coneLength << "} " - << "} "; - -} - -//************************************************************************** -// triangle handling - -void Builder3D::addSingleTriangle(const Triangle& triangle, DrawStyle drawStyle, const ColorRGB& color) -{ - std::string fs = ""; - if (drawStyle.style == DrawStyle::Style::Filled) { - fs = "IndexedFaceSet { coordIndex[ 0, 1, 2, -1 ] } "; - } - - result << "Separator { " - << "Material { diffuseColor " << color.red() << " "<< color.green() << " "<< color.blue() << "} " - << "DrawStyle { lineWidth " << drawStyle.lineWidth << "} " - << "Coordinate3 { " - << "point [ " - << triangle.getPoint1().x << " " << triangle.getPoint1().y << " " << triangle.getPoint1().z << "," - << triangle.getPoint2().x << " " << triangle.getPoint2().y << " " << triangle.getPoint2().z << "," - << triangle.getPoint3().x << " " << triangle.getPoint3().y << " " << triangle.getPoint3().z << "," - << "] " - << "} " - << "LineSet { } " - << fs - << "} "; -} - -void Builder3D::addTransformation(const Base::Matrix4D& transform) -{ - Base::Placement placement; - placement.fromMatrix(transform); - addTransformation(placement); -} - -void Builder3D::addTransformation(const Base::Placement& transform) -{ - Base::Vector3d translation = transform.getPosition(); - Base::Vector3d rotationaxis; - double angle{}; - transform.getRotation().getValue(rotationaxis, angle); - result << "Transform {"; - result << " translation " << translation.x << " " << translation.y << " " << translation.z; - result << " rotation " << rotationaxis.x << " " << rotationaxis.y << " " << rotationaxis.z << " " << angle; - result << "}"; -} - -//************************************************************************** -// output handling - -/** - * Save the resulting inventor 3D representation to the Console().Log() facility. - * In DEBUG mode the Gui (if running) will trigger on that and show the representation in - * the active Viewer/Document. It shows only one representation on time. If you need to - * show more then one representation use saveToFile() instead. - * @see saveToFile() - */ -void Builder3D::saveToLog() -{ - result << "} "; - // Note: The string can become very long, so that ConsoleSingelton::Log() will internally - // truncate the string which causes Inventor to fail to interpret the truncated string. - // So, we send the string directly to the observer that handles the Inventor stuff. - //Console().Log("Vdbg: %s \n",result.str().c_str()); - ILogger* obs = Base::Console().Get("StatusBar"); - if (obs){ - obs->SendLog(result.str().c_str(), Base::LogStyle::Log); - } -} - -/** - * Save the resulting inventor 3D representation to a file. Ending should be *.iv. - * That enables you to show the result in a Inventor Viewer or in FreeCAD by: - * /code - * Gui.document().addAnnotation("Debug","MyFile.iv") - * /endcode - * @see saveToFile() - */ -void Builder3D::saveToFile(const char* FileName) -{ - result << "} "; - Base::FileInfo fi(FileName); - Base::ofstream file(fi); - if (!file) - throw FileException("Builder3D::saveToFile(): Can not open file..."); - - file << "#Inventor V2.1 ascii \n"; - file << result.str(); -} - // ----------------------------------------------------------------------------- InventorBuilder::InventorBuilder(std::ostream& output) @@ -539,6 +281,23 @@ void InventorBuilder::addPointSet() result << Base::blanks(indent) << "PointSet { } \n"; } +void InventorBuilder::addSinglePoint(const Base::Vector3f &point, DrawStyle drawStyle, const ColorRGB& color) +{ + result << Base::blanks(indent) << "Separator { "; + result << Base::blanks(indent) << " Material { "; + result << Base::blanks(indent) << " diffuseColor " << color.red() << " "<< color.green() << " "<< color.blue(); + result << Base::blanks(indent) << " }"; + result << Base::blanks(indent) << " MaterialBinding { value PER_PART } "; + result << Base::blanks(indent) << " DrawStyle { pointSize " << drawStyle.pointSize << "} "; + result << Base::blanks(indent) << " Coordinate3 { "; + result << Base::blanks(indent) << " point [ "; + result << point.x << " " << point.y << " " << point.z << ","; + result << Base::blanks(indent) << " ] "; + result << Base::blanks(indent) << " }"; + result << Base::blanks(indent) << " PointSet { } "; + result << Base::blanks(indent) <<"}"; +} + /** * Adds a SoLineSet node after creating a SoCordinate3 node with * beginPoints() and endPoints(). @@ -923,6 +682,66 @@ void InventorBuilder::addTransformation(const Base::Placement& transform) // ----------------------------------------------------------------------------- +/** + * A constructor. + * A more elaborate description of the constructor. + */ +Builder3D::Builder3D() + : InventorBuilder(result) +{ +} + +/** + * A destructor. + * A more elaborate description of the destructor. + */ +Builder3D::~Builder3D() = default; + +void Builder3D::clear () +{ + // under gcc stringstream::str() returns a copy not a reference +#if defined(_MSC_VER) + result.str().clear(); +#endif + result.clear(); +} + +/** + * Save the resulting inventor 3D representation to the Console().Log() facility. + * In DEBUG mode the Gui (if running) will trigger on that and show the representation in + * the active Viewer/Document. It shows only one representation on time. If you need to + * show more then one representation use saveToFile() instead. + * @see saveToFile() + */ +void Builder3D::saveToLog() +{ + ILogger* obs = Base::Console().Get("StatusBar"); + if (obs){ + obs->SendLog(result.str().c_str(), Base::LogStyle::Log); + } +} + +/** + * Save the resulting inventor 3D representation to a file. Ending should be *.iv. + * That enables you to show the result in a Inventor Viewer or in FreeCAD by: + * /code + * Gui.document().addAnnotation("Debug","MyFile.iv") + * /endcode + * @see saveToFile() + */ +void Builder3D::saveToFile(const char* FileName) +{ + Base::FileInfo fi(FileName); + Base::ofstream file(fi); + if (!file) { + throw FileException("Cannot open file"); + } + + file << result.str(); +} + +// ----------------------------------------------------------------------------- + template std::vector InventorLoader::readData(const char* fieldName) const { diff --git a/src/Base/Builder3D.h b/src/Base/Builder3D.h index f642d0f480..bc227ac200 100644 --- a/src/Base/Builder3D.h +++ b/src/Base/Builder3D.h @@ -128,94 +128,6 @@ private: Base::Vector3f pt3; }; -/** A Builder class for 3D representations on App level - * On the application level nothing is known of the visual representation of data. - * Nevertheless it's often needed to see some 3D information, e.g. points, directions, - * when you program or debug an algorithm. Builder3D was made for this specific purpose. - * This class allows you to easily build up a 3D representation of some mathematical and - * algorithm internals. You can save this representation to a file and view it in an - * Inventor viewer, or send it to the log. In the case of using the log and a debug - * FreeCAD the representation will be loaded into the active viewer. - * \par - * The workflow goes as follows: Create the a Builder3D object and call the methods - * to insert the graphical elements. After that call either saveToLog() or saveToFile(). - * \par - * Usage: - * \code - Base::Builder3D log3D; - for ( unsigned long i=0; iCountPoints(); i++ ) - { - log3D.addSinglePoint(pMesh->GetPoint(i)); - log3D.addText(pMesh->GetPoint(i),"Point"); - ... - } - log3D.saveToLog(); - * \endcode - * \see Base::ConsoleSingleton - */ -class BaseExport Builder3D -{ -public: - Builder3D(); - virtual ~Builder3D(); - - /** @name point set handling */ - //@{ - /// starts a point set - void startPoints(short pointSize=2, const ColorRGB& color = ColorRGB{1.0F, 0.0F, 0.0F}); - /// add a point to a point set - void addPoint(const Vector3f& point); - /// ends the points set operation - void endPoints(); - /// add a single point (without startPoints() & endPoints() ) - void addSinglePoint(const Base::Vector3f& point, DrawStyle drawStyle, const ColorRGB& color = ColorRGB{1.0F, 1.0F, 1.0F}); - //@} - - /** @name line/direction handling */ - //@{ - /// add a line - void addSingleLine(const Base::Line3f& line, DrawStyle drawStyle, const ColorRGB& color = ColorRGB{1.0F, 1.0F, 1.0F}); - /// add an arrow. - void addSingleArrow(const Base::Line3f& line, DrawStyle drawStyle, const ColorRGB& color = ColorRGB{1.0F, 1.0F, 1.0F}); - //@} - - /** @name triangle handling */ - //@{ - /// add a triangle - void addSingleTriangle(const Triangle& triangle, DrawStyle drawStyle, const ColorRGB& color = ColorRGB{1.0F, 1.0F, 1.0F}); - //@} - - /** @name Transformation */ - //@{ - /// adds a transformation - void addTransformation(const Base::Matrix4D&); - void addTransformation(const Base::Placement&); - //@} - - /** @name text handling */ - //@{ - /// add a text - void addText(const Base::Vector3f& point, const char * text, const ColorRGB& color = ColorRGB{1.0F, 1.0F, 1.0F}); - //@} - - /// clear the string buffer - void clear(); - - /** @name write the result */ - //@{ - /// sends the result to the log and gui - void saveToLog(); - /// save the result to a file (*.iv) - void saveToFile(const char* FileName); - //@} - -private: - /// the result string - std::stringstream result; - - bool bStartEndOpen; -}; - /** * This class does basically the same as Builder3D except that it writes the data * directly into a given stream without buffering the output data in a string stream. @@ -322,6 +234,8 @@ public: void endPoints(); /// add an SoPointSet node void addPointSet(); + /// add a single point (without startPoints() & endPoints() ) + void addSinglePoint(const Base::Vector3f& point, DrawStyle drawStyle, const ColorRGB& color = ColorRGB{1.0F, 1.0F, 1.0F}); //@} /** @name Normal handling */ @@ -393,6 +307,57 @@ private: int indent; }; +/** A Builder class for 3D representations on App level + * On the application level nothing is known of the visual representation of data. + * Nevertheless it's often needed to see some 3D information, e.g. points, directions, + * when you program or debug an algorithm. Builder3D was made for this specific purpose. + * This class allows you to easily build up a 3D representation of some mathematical and + * algorithm internals. You can save this representation to a file and view it in an + * Inventor viewer, or send it to the log. In the case of using the log and a debug + * FreeCAD the representation will be loaded into the active viewer. + * \par + * The workflow goes as follows: Create the a Builder3D object and call the methods + * to insert the graphical elements. After that call either saveToLog() or saveToFile(). + * \par + * Usage: + * \code + Base::Builder3D log3D; + for ( unsigned long i=0; iCountPoints(); i++ ) + { + log3D.addSinglePoint(pMesh->GetPoint(i)); + log3D.addText(pMesh->GetPoint(i),"Point"); + ... + } + log3D.saveToLog(); + * \endcode + * \see Base::ConsoleSingleton + */ +class BaseExport Builder3D : public InventorBuilder +{ +public: + Builder3D(); + virtual ~Builder3D(); + + /** @name point set handling */ + //@{ + //@} + + /// clear the string buffer + void clear(); + + /** @name write the result */ + //@{ + /// sends the result to the log and gui + void saveToLog(); + /// save the result to a file (*.iv) + void saveToFile(const char* FileName); + //@} + +private: + /// the result string + std::stringstream result; +}; + /** * Loads an OpenInventor file. * @author Werner Mayer