Base: refactoring of Builder3D/InventorBuilder

This commit is contained in:
wmayer
2022-11-27 20:06:00 +01:00
parent 5ed096226e
commit abd044fe33
2 changed files with 130 additions and 346 deletions

View File

@@ -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<typename T>
std::vector<T> InventorLoader::readData(const char* fieldName) const
{

View File

@@ -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; i<pMesh->CountPoints(); 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; i<pMesh->CountPoints(); 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