Reading step file with Open Cascade - c++

I need to read simple step files (turning parts) with C++. Therefore I try to use Open Cascade. I already can open my step file and read the number of shapes in my file. Now I need to get the geometrical data (length, width, diameters..), but I dont know how it works, although I read all of the documentations.
Is there anyone who already worked with Open Cascade and can help me with my Problem? I would be very happy, thank alot !!
That's my Code since then
#include <iostream>
#include <STEPControl_Reader.hxx>
#include <string>
using namespace std;
int main() {
STEPControl_Reader reader;
IFSelect_ReturnStatus stat = reader.ReadFile("C:\\Users\\Kelevradesktop.Kelevra-desktop\\Desktop\\Studienarbeit\\steptest.step");
IFSelect_PrintCount mode = IFSelect_ListByItem;
reader.PrintCheckLoad(false, mode);
Standard_Integer NbRoots = reader.NbRootsForTransfer(); //Transfer whole file
Standard_Integer num = reader.TransferRoots();
Standard_Integer NbTrans = reader.TransferRoots();
TopoDS_Shape result = reader.OneShape();
TopoDS_Shape shape = reader.Shape();
cout << NbRoots << endl;
cout << NbTrans << endl;
cout << num << endl;
system("pause");
return 0;
}

Check the FreeCad source code. They use OpenCascade and can import step and iges. It should get you started. The function ImportStepParts(...) in https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Part/App/ImportStep.cpp is what you search for.

Use TopExpExplorer class to iterate through the objects (vertexes, edges, faces..) of a shape. An iterating example you can find in this tutorial.
Use GProp_GProps class to get properties of a shape. Example:
GProp_GProps propertiesSystemFace;
BRepGProp::VolumeProperties(shape, propertiesSystemFace);
double shapeVolume = propertiesSystemFace.Mass();
gp_Pnt centerOfMass = propertiesSystemFace.CentreOfMass();
Also you can convert TopoDS_Edge to curve object to get some other parameters according to the edge type:
BRepAdaptor_Curve adaptCrv = BRepAdaptor_Curve(edge);

Related

CGAL boolean operation on 3d mesh with color

what I'm trying to do is performing CGAL boolean operator (union operator) on 2 models that has RGB color for each vertex. but the result doesn't retain the color info.
Maybe you have an idea how to solve this issue.
Here are the models for doing boolean operation (coff format):
model1
model2
image of input models
Here is the code I'm using:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Polyhedron_items_with_id_3.h>
#include <CGAL/Polygon_mesh_processing/corefinement.h>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Polyhedron_3<K, CGAL::Polyhedron_items_with_id_3> Mesh;
namespace PMP = CGAL::Polygon_mesh_processing;
int main(int argc, char* argv[])
{
const char* filename1 = (argc > 1) ? argv[1] : "data/b1.off";
const char* filename2 = (argc > 2) ? argv[2] : "data/b2.off";
std::ifstream input(filename1);
Mesh mesh1, mesh2;
if (!input || !(input >> mesh1))
{
std::cerr << "First mesh is not a valid off file." << std::endl;
return 1;
}
input.close();
input.open(filename2);
if (!input || !(input >> mesh2))
{
std::cerr << "Second mesh is not a valid off file." << std::endl;
return 1;
}
Mesh out;
bool valid_union = PMP::corefine_and_compute_union(mesh1, mesh2, out);
if (valid_union)
{
std::cout << "Union was successfully computed\n";
std::ofstream output("union.off");
output << out;
return 0;
}
std::cout << "Union could not be computed\n";
return 1;
}
What I get at the end has correct mesh but doesn't retain the color info.
Is there any chance to fix the color info?
union model as result
It is not yet possible. There is one hidden parameter in corefine to preserve those attributes but the output builder for the Boolean operation is missing a visitor (that I hope to have time to add in CGAL 4.13).
There a few workaround but none of them will handle all the possible cases.
EDIT:
In CGAL 4.13 this will be possible by passing in the named parameter a visitor. This PR is the one adding the support and is already merged into the master branch. The following example shows how to do it.
I found that there is a command in cgal library to load "coff" format
which contains color RGB. But I don't know how to use it. My first
attempt is how to define data types.
As far as I know, only the Surface_mesh data structure is able to work with a COFF file. You can look at the code of the Surface_mesh_io_plugin in Polyhedron/demo/Polyhedron.
The COFF format is a standard that is quite well documented.

ofstream does not create file when running with CLion using CMake

I have this code to create a file, when I run it with CLion it prints out to the console but does not create file, how can I fix this? thanks
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ofstream log_file;
log_file.open("sample23.txt");
if (log_file.is_open())
std::cout << "Open";
log_file << "stuff" << endl;
log_file.close();
return 0;
}
The file may be created into another directory (the working directory).
You can find that location (and change it if needed) as indicated here:
How do I change the working directory for my program
make sure to flush before closing because file is empty
try this out
ofstream f;
f.open( "sample.txt", ios::out );
f << flush;
f.close();
3 things here:
1.) In order to output to another file, you must make another variable like this:
ifstream someoutputfile;
someoutputfile.open("filename");
2.) you actually must make another variable to be "placeholder" of sorts that will automatically assign the first thing your file finds and assigns that to. This may depend on what datatype (int, double, string etc) your input file consists of. Instead of:
log_file << "stuff" << endl;
you can do something like this...
// if my input file is integers for instance..
int data = 0;
log_file >> data;
This can also work for if your file contains multiple data types.
ex:
// if I have two different data types...
string somebody;
int data = 0;
log_file >> data >> somebody;
3.) to output your file data to the screen, just follow a similar way as the example in #1.
someoutputfile << data << somebody << endl;
in addition, dont forget to close the data of BOTH your input and output files:
someoutputfile.close()
Hope that helps in some way :)

How to enter to and read from a console program?

For a program that I want to write, I have to enter commands to and read from a console program, and I have no idea how to.
For understanding, perhaps a solution to the following example would be helpful:
I want to write a program that squares all natural numbers up to 100 and saves the result to a text file. Assume that I don't know how to square numbers and therefore use the executable file square_x.exe with the following (unavailable) source code:
#include <iostream>
using namespace std;
int main(){
double in;
cout << "Input: ";
while(cin>>in){
cout << in << static_cast<char>(253)/*²*/ << " = " << in*in << endl
<< endl
<< "Input: ";
}
return 0;
}
How then must I add to the following code fragment? (Proposedly, where indicated by "Somehow"):
#include <fstream>
using namespace std;
ofstream file;
void writeToFile( const char* name, const char* content ){
file.open( name, ios::app );
file << content;
file.close();
}
int main(){
char buffer[30], buffer2[50];
//Somehow call square_x.exe
for( int i = 1 ; i <= 100 ; i++ ){
//Somehow send i to square_x.exe
//Somehow get a result from square_x.exe and safe it to buffer2
//Extract from the got string the result of the calculation
strtok(buffer2," "); strtok(0, " ");
strncpy(buffer2,strtok(0, " \n"),sizeof(buffer2)-1);
sprintf( buffer , "%d\n%s\n\n" , i , buffer2 );
writeToFile( "list.txt", buffer );
}
//Somehow close square_x.exe
return 0;
}
I asked a friend of mine if he could help me with that and he sent me this. But since I have no idea how I would have to change this code to fulfill my needs, he then sent me here.
I assume that want you really want is the way to pass input to an auxilliary program and get its output.
The referenced link explains how to do it using WinAPI functions. Unfortunately, there is no simpler solution on Windows, because of the lacking of a fork function(*).
Taking the link as reference you must replace in your source //Somehow call square_x.exe with pipes and child process creation (CreatePipeand CreateProcess API calls, child process here is square_x.exe). Then to send something to the child, you just use WriteFile on the write end of the input pipe, and to read from the child, you use ReadFile from the read end of the output pipe.
But you example will be a little harder, because you child adds the noisy string "Input: " that you will have to ignore.
Try to put this in your code, and come back here to ask another question (with the new code) if you are stuck.
(*) But you could find a library that deals with all that gory details for you, such as libexecstream proposed by #a486408.
You can try using libexecstream - it allows you to launch new processes and communicate with them using c++ iostreams without digging into OS-specific stuff.

C++, OpenCV : Assertion failed in Resize

As a C++ beginner, I am currently facing a problem I somehow can't solve, even if the code is pretty simple.
I've been searching for answers all over the Internet, but none was applicable for my problem.
I am currently coding basic SVMs with C++, under VS2013, using OpenCV 2.4.8.
I was able to work on images of same size, specifying fixed height, width at the beginning of my code.
Now, I'm trying to : open images of different sizes, resize them to a certain lower size, and apply the previous code to the now-resized dataset. Simple as that.
Here's the beginning of my code :
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/ml/ml.hpp>
#include <iostream>
#include <math.h>
#include <fstream>
#include <string>
#include <sstream>
#include <windows.h>
using namespace cv;
using namespace std;
int main(){
Input parameters are :
int Nb_Data_Class_1 = 10;
int Nb_Data_Class_0 = 5;
int Height_Zone = 200;
int Width_Zone = 200;
so I will resize all my files to 200x200 format.
string Path = "C:\\Users\\....";
string Format = ".jpg";
int Nb_Files = Nb_Data_Class_1 + Nb_Data_Class_0;
Mat TrainingMat(Nb_Files, Zone_Image, CV_32FC1);
Mat TrainingLabels(Nb_Files, 1, CV_32FC1);
For every file of the class labelled {1} - they are all named Tree01, Tree02, etc. - I open, and resize.
for (int i = 0; i < Nb_Data_Class_1; ++i)
{
stringstream ss;
ss << Path << "\\Tree0" << i + 1 << Format;
Mat Image = cv::imread(ss.str(), 0);
resize(Image, Image, Size(Width_Zone, Height_Zone));}
Things worked perfectly without the last line. I had a Mat array, filled with 0-t0-255 numbers. Now, I get the following error :
OpenCV Error: Assertion failed <ssize.area<> >0> in cv::resize,
file C:\builds\2-4-PackSlave-win32-vc12-shared\opencv\modules\imgproc\serc\imgwarp.cpp, line 1824
What could be the problem ?
I thought that maybe OpenCV wasn't properly opening the files ; but, in that case, how everything could have been previously working ?
Still wondering.
Any help would be much appreciated ! Thanks in advance.
The only reason for resize to crush is absence of Image. Even if you checked that some of the images were read properly it doesn't mean that all of them were - some of them may be missing. Reading files from disk is a very common point of failure for programs because you never can be sure if the read was successfully or not. As a result every time you read an image you really really should verify that it is not empty:
if (Image.cols == 0) {
cout << "Error reading file " << ss << endl;
return -1;
}
Not going to solve the problem in this case, but this assertion can also be caused by trying to resize a Mat with a signed type like CV_8SC3. For example:
Mat wrong = Mat::zeros(4, 4, CV_8SC3); // <- Notice 'S'
Mat right = Mat::zeros(4, 4, CV_8UC3); // <- Notice 'U'
imshow("OK", right);
imshow("ASSERTS", wrong);
Note that checking wrong.cols != 0 will not prevent this from crashing.
Your line:
ss << Path << "\Tree0" << i + 1 << Format;
will produce (where i=0):
"C:\Users\....\Tree01.jpg".
Solution
Change "string Path = "C:\Users\....";" line to:
string Path = "C:\Users";
and
change "ss << Path << "\Tree0" << i + 1 << Format;" line to:
ss << Path << "Tree0" << i + 1 << Format;

Save/Load workspace in C++ application

I'm working on adding a new feature to an existing program. It's basically a save/load workspace feature, where a user can save the positions of their windows, and then load said positions whenever they want to by selecting a menu item. In order to implement this, I have created code which extracts the screen coordinates of the window and writes them to a file (below) :
void CMainFrame::SaveWorkspace()
{
RECT ctrlsize;
m_pDialog->GetWindowRect((LPRECT)&ctrlsize); //obtains location for window
ofstream Workspace("saveone", ios::out);
Workspace << ctrlsize.left << "," << ctrlsize.top << "," << ctrlsize.right << "," << ctrlsize.bottom;
}
And this (is supposed to) loads the workspace:
void CMainFrame::LoadWorkspace()
{
//Read in the data from the file
int data[3][4];
int r=0;
int a=0;
int b=0;
ifstream infile;
infile.open("saveone");
for(a = 0; a< 3; a++)
{
for(b = 0;b<4;b++)
{
infile >> data[a][b];
cout << data[a][b];
}
}
infile.close();
//Now, assign the extracted values
RECT ctrlset;
ctrlset.top = data[0][1];
ctrlset.left = data[0][0];
ctrlset.right = data[2][0];
ctrlset.bottom = data[0][3];
// Finally, reassign the window positions
m_pDialog->SetWindowPos(NULL, ctrlset.left, ctrlset.top, (ctrlset.right - ctrlset.left), (ctrlset.bottom - ctrlset.top), SWP_SHOWWINDOW);
}
Problems:
1) the SaveWorkspace function works sporadically; more often than not, it doesn't create a file.
2) the LoadWorkspace function doesn't work. Specifically, only the data[0][0] coordinate gets saved to the array (the first value in the file).
This seems like a fairly easy thing to do, I'm a bit embarrassed that it's giving me so much trouble...
EDIT: I've fixed problem #1. Now I just need to figure out why my array isn't working.
You have at least two problems in the reading.
Your array definition is wrong. It is :
data[2][3];
This has only 6 values.
However, in the loop you are reading 12 values out.
You have the "," values in the file. You are not getting rid of them.
Maybe as an easy solution, you could add a new line after each entry when you write them.
Or you could enter the details of a single rectangle on one line, then read the full line and parse for the individual components yourself.