├── .travis.yml ├── CMakeLists.txt ├── Chapter0_Test ├── CMakeLists.txt └── chapter0.cpp ├── Chapter1_Basics ├── CMakeLists.txt ├── inc │ ├── AreaCalculations.hpp │ ├── BSplineBasisComputations.hpp │ ├── LeastSquaresFitting.hpp │ ├── LinePlaneIntersection.hpp │ ├── PointOnCurveDistributor.hpp │ ├── PointWriter.hpp │ └── WriteCoordinatesToFile.hpp ├── python │ ├── plotPoints.py │ └── plotVectors.py ├── runners │ ├── chapter1_1.cpp │ ├── chapter1_2.cpp │ ├── chapter1_2_exercise.cpp │ ├── chapter1_3.cpp │ ├── chapter1_4.cpp │ ├── chapter1_5.cpp │ └── chapter1_6.cpp ├── src │ ├── AreaCalculations.cpp │ ├── BSplineBasisComputations.cpp │ ├── LeastSquaresFitting.cpp │ ├── LinePlaneIntersection.cpp │ └── WriteCoordinatesToFile.cpp └── tests │ ├── BSplineBasisComputations_test.cpp │ ├── PointOnCurveDistributor_test.cpp │ └── main_test.cpp ├── Chapter2_Geom ├── CMakeLists.txt ├── inc │ ├── GeometryWriter.hpp │ └── TangentMagnitude.hpp ├── runners │ └── Chapter2_1.cpp ├── src │ ├── GeometryWriter.cpp │ └── TangentMagnitude.cpp └── tests │ └── main_test.cpp ├── OtherExamples ├── CMakeLists.txt ├── inc │ ├── CreateCurvedPlateWithHole.hpp │ └── StlPointsExtractor.hpp ├── runners │ ├── convertStepToStl.cpp │ ├── extractStlManifoldBoundaries.cpp │ ├── extractStlPoints.cpp │ └── moveAndRotateAssem.cpp ├── src │ ├── CreateCurvedPlateWithHole.cpp │ └── StlPointsExtractor.cpp └── tests │ ├── StlPointsExtractor_test.cpp │ └── main_test.cpp ├── README.md ├── Utilities └── inc │ ├── catch.hpp │ └── constants.hpp └── cmake ├── CreateExecutable.cmake └── CreateLibrary.cmake /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | language: cpp 4 | 5 | before_install: 6 | - sudo apt-get update -qq 7 | - sudo apt-get install -y liboce-* 8 | 9 | compiler: 10 | - gcc 11 | 12 | before_script: 13 | - mkdir build 14 | - cd build 15 | - cmake .. 16 | 17 | script: make && make test 18 | 19 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT(occtutorials) 4 | 5 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") 6 | 7 | INCLUDE(cmake/CreateExecutable.cmake) 8 | INCLUDE(cmake/CreateLibrary.cmake) 9 | 10 | #Find opencascade libraries 11 | 12 | FIND_PACKAGE(OCE REQUIRED) 13 | INCLUDE_DIRECTORIES(${OCE_INCLUDE_DIRS}) 14 | INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) 15 | 16 | ENABLE_TESTING() 17 | 18 | ADD_SUBDIRECTORY(Chapter0_Test) 19 | ADD_SUBDIRECTORY(Chapter1_Basics) 20 | ADD_SUBDIRECTORY(Chapter2_Geom) 21 | ADD_SUBDIRECTORY(OtherExamples) 22 | -------------------------------------------------------------------------------- /Chapter0_Test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT(chapter0) 4 | 5 | CreateExecutable(chapter0.cpp TKernel TKMath TKPrim TKBO TKSTEP) 6 | -------------------------------------------------------------------------------- /Chapter0_Test/chapter0.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "BRepPrimAPI_MakeCylinder.hxx" 4 | #include "BRepPrimAPI_MakeBox.hxx" 5 | #include "BRepAlgoAPI_Cut.hxx" 6 | #include "BRepGProp.hxx" 7 | #include "STEPControl_Writer.hxx" 8 | #include "GProp_GProps.hxx" 9 | 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | std::cout << "------- OpenCASCADE Tutorial by Laszlo Kudela -------" << std::endl; 14 | std::cout << "------- Chapter 0: Demonstrative example -------" << std::endl; 15 | 16 | //Create a simple box with a size 100x100x50, centered around the origin 17 | gp_Pnt lowerLeftCornerOfBox(-50.0,-50.0,0.0); 18 | BRepPrimAPI_MakeBox boxMaker(lowerLeftCornerOfBox,100,100,50); 19 | TopoDS_Shape box = boxMaker.Shape(); 20 | 21 | //Create a cylinder with a radius 25.0 and height 50.0, centered at the origin 22 | BRepPrimAPI_MakeCylinder cylinderMaker(25.0,50.0); 23 | TopoDS_Shape cylinder = cylinderMaker.Shape(); 24 | 25 | //Cut the cylinder out from the box 26 | BRepAlgoAPI_Cut cutMaker(box,cylinder); 27 | TopoDS_Shape boxWithHole = cutMaker.Shape(); 28 | 29 | //Write the resulting shape to a file 30 | STEPControl_Writer writer; 31 | writer.Transfer(boxWithHole,STEPControl_AsIs); 32 | writer.Write("boxWithHole.stp"); 33 | 34 | std::cout << "Created box with hole, file is written to boxWithHole.stp" << std::endl; 35 | 36 | //We compute some volumetric properties of the resulting shape 37 | GProp_GProps volumeProperties; 38 | BRepGProp::VolumeProperties(boxWithHole,volumeProperties); 39 | 40 | //Compute the volume of the model 41 | std::cout << std::setprecision(14) << "Volume of the model is: " << volumeProperties.Mass() << std::endl; 42 | 43 | //Compute the center of mass 44 | std::cout << "Center of mass is: " << volumeProperties.CentreOfMass().X() << " " << volumeProperties.CentreOfMass().Y() << " " << volumeProperties.CentreOfMass().Z() << std::endl; 45 | 46 | //Compute the matrix of inertia 47 | gp_Mat inertiaMatrix = volumeProperties.MatrixOfInertia(); 48 | std::cout << "Matrix of inertia: " << std::endl; 49 | for (int i = 1; i <= 3; ++i) { 50 | for (int j = 1; j <= 3; ++j) { 51 | std::cout << inertiaMatrix(i,j) << "\t"; 52 | } 53 | std::cout << std::endl; 54 | } 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /Chapter1_Basics/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT(chapter1) 4 | 5 | CreateLibrary() 6 | 7 | FILE(GLOB RUNNERSOURCES "${CMAKE_CURRENT_SOURCE_DIR}/runners/*.cpp") 8 | 9 | FOREACH(RUNNERSOURCE ${RUNNERSOURCES}) 10 | 11 | CreateExecutable(${RUNNERSOURCE} chapter1 TKernel TKMath) 12 | 13 | ENDFOREACH(RUNNERSOURCE) 14 | 15 | ADD_CUSTOM_COMMAND(TARGET chapter1_2 16 | POST_BUILD 17 | COMMAND ${CMAKE_COMMAND} -E copy_directory 18 | "${CMAKE_CURRENT_SOURCE_DIR}/python" 19 | "${CMAKE_BINARY_DIR}/bin") 20 | 21 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/testrunners") 22 | FILE(GLOB TESTSOURCES "${CMAKE_CURRENT_SOURCE_DIR}/tests/*.cpp") 23 | ADD_EXECUTABLE(chapter1_test ${TESTSOURCES}) 24 | TARGET_LINK_LIBRARIES(chapter1_test chapter1 TKernel TKMath) 25 | ADD_TEST(chapter1_tests "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/chapter1_test") 26 | -------------------------------------------------------------------------------- /Chapter1_Basics/inc/AreaCalculations.hpp: -------------------------------------------------------------------------------- 1 | #ifndef AREACALCULATIONS_HPP 2 | #define AREACALCULATIONS_HPP 3 | //OpenCASCADE tutorials 4 | //Laszlo Kudela 5 | //November 2015 6 | 7 | #include "TColgp_HArray1OfPnt.hxx" 8 | 9 | namespace AreaCalculations 10 | { 11 | double calculateTriangleArea(const Handle_TColgp_HArray1OfPnt triangleCorners); 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /Chapter1_Basics/inc/BSplineBasisComputations.hpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorial by Laszlo Kudela 2 | //December 2015 3 | #ifndef _BSPLINEBASIS_COMPUTATIONS_HPP 4 | #define _BSPLINEBASIS_COMPUTATIONS_HPP 5 | 6 | #include "math_Matrix.hxx" 7 | #include "Standard_Real.hxx" 8 | #include "Standard_Integer.hxx" 9 | #include "Handle_TColStd_HArray1OfReal.hxx" 10 | 11 | 12 | 13 | class BSplineBasisComputations 14 | { 15 | public: 16 | BSplineBasisComputations (); 17 | virtual ~BSplineBasisComputations (); 18 | 19 | static void calculateBasisFunctions(Handle_TColStd_HArray1OfReal knots, Standard_Integer degree, Standard_Real parameter, math_Matrix& basisFunctions); 20 | static double evaluateBasisFunction(Handle_TColStd_HArray1OfReal knots, Standard_Integer degree, Standard_Real parameter, Standard_Integer basisFunctionIndex); 21 | 22 | private: 23 | 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /Chapter1_Basics/inc/LeastSquaresFitting.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LEASTSQUARESFITTING_HPP 2 | #define LEASTSQUARESFITTING_HPP 3 | //OpenCASCADE tutorials by Laszlo Kudela 4 | //2015 November 5 | //Chapter 1.3 Least squares fitting 6 | 7 | class Handle_TColgp_HArray1OfPnt; 8 | 9 | #include "gp_Circ.hxx" 10 | 11 | class LeastSquaresFitting 12 | { 13 | public: 14 | LeastSquaresFitting (); 15 | virtual ~LeastSquaresFitting (); 16 | 17 | static gp_Circ fitLeastSquaresCircleToPoints(const Handle_TColgp_HArray1OfPnt& points); 18 | 19 | private: 20 | struct InitialGuessForLeastSquaresFitting 21 | { 22 | InitialGuessForLeastSquaresFitting(gp_Pnt center, double radius) 23 | { 24 | myCenterPoint = center; 25 | myRadius = radius; 26 | } 27 | gp_Pnt myCenterPoint; 28 | double myRadius; 29 | }; 30 | 31 | static InitialGuessForLeastSquaresFitting findInitialGuess(const Handle_TColgp_HArray1OfPnt& points); 32 | 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /Chapter1_Basics/inc/LinePlaneIntersection.hpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE Tutorials 2 | //Laszlo Kudela 3 | //Nov 19, 2015 4 | 5 | #ifndef CHAPTER1_BASICS_INC_LINEPLANEINTERSECTION_HPP_ 6 | #define CHAPTER1_BASICS_INC_LINEPLANEINTERSECTION_HPP_ 7 | 8 | #include "gp_Pnt.hxx" 9 | #include "gp_Lin.hxx" 10 | #include "gp_Pln.hxx" 11 | 12 | class LinePlaneIntersection { 13 | public: 14 | LinePlaneIntersection(); 15 | virtual ~LinePlaneIntersection(); 16 | 17 | struct LinePlaneIntersectionSolution 18 | { 19 | enum SolutionState{ 20 | OneSolution, 21 | NoSolution, 22 | InfiniteSolutions 23 | }; 24 | gp_Pnt intersectionPoint; 25 | SolutionState state; 26 | }; 27 | 28 | static LinePlaneIntersectionSolution intersectLineWithPlane(const gp_Lin& line, const gp_Pln& plane); 29 | }; 30 | 31 | #endif /* CHAPTER1_BASICS_INC_LINEPLANEINTERSECTION_HPP_ */ 32 | -------------------------------------------------------------------------------- /Chapter1_Basics/inc/PointOnCurveDistributor.hpp: -------------------------------------------------------------------------------- 1 | #ifndef POINTONCURVEDISTRIBUTOR_HPP 2 | #define POINTONCURVEDISTRIBUTOR_HPP 3 | //OpenCASCADE tutorials 4 | //Laszlo Kudela 5 | //November 2015 6 | 7 | #include "Standard_Integer.hxx" 8 | #include "TColgp_Array1OfPnt.hxx" 9 | #include "ElCLib.hxx" 10 | 11 | namespace PointOnCurveDistribution 12 | { 13 | template 14 | void distributePointsOnCurve(const CurveType& curve, TColgp_Array1OfPnt& pointArray, double lowerLimit, double upperLimit, Standard_Integer resolution) 15 | { 16 | double deltaU = (upperLimit - lowerLimit) / (resolution - 1); 17 | for(Standard_Integer i = 0;i 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | 19 | //Create two point classes, with (x,y,z) coordinates 20 | gp_Pnt pnt1(0.0,0.0,0.0); 21 | gp_Pnt pnt2(1.0,1.0,1.0); 22 | 23 | //Display their coordinates 24 | std::cout << "pnt1: " << pnt1.X() << " " << pnt1.Y() << " " << pnt1.Z() << std::endl; 25 | std::cout << "pnt2: " << pnt2.X() << " " << pnt2.Y() << " " << pnt2.Z() << std::endl; 26 | std::cout << "Distance between pnt1 and pnt2: " << pnt1.Distance(pnt2) << std::endl; 27 | 28 | //Rotate pnt1 around the point2, by 90 degrees 29 | gp_Trsf rotation; 30 | gp_Ax1 rotationAxis(gp_Pnt(1.0,1.0,0.0),gp_Dir(0.0,0.0,1.0)); 31 | rotation.SetRotation(rotationAxis,3.1415926/2.0); 32 | pnt1.Transform(rotation); 33 | std::cout << "pnt1 after rotation: " << pnt1.X() << " " << pnt1.Y() << " " << pnt1.Z() << std::endl; 34 | 35 | //Create a new point by mirroring pnt1 about the y axis 36 | gp_Ax1 axisOfSymmetry(gp_Pnt(0.0,0.0,0.0),gp_Dir(0.0,1.0,0.0)); 37 | gp_Pnt pnt3 = pnt1.Mirrored(axisOfSymmetry); 38 | std::cout << "pnt3 after mirroring: " << pnt3.X() << " " << pnt3.Y() << " " << pnt3.Z() << std::endl; 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /Chapter1_Basics/runners/chapter1_2.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorials by Laszlo Kudela 2 | //2015 November 3 | //Chapter 1.2 Basics 4 | //This example creates a circles, evaluates a set of points 5 | //on the circumference of the circle, and writes the points out in a file. 6 | //There is a python script provided in the bin folder to display the resulting points. 7 | //You can run it by typing in the bin folder: 8 | //python plotPoints.py chapter1_2_circlePoints.txt 9 | //It creates a point.png file that displays the points you have created in this example. 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "Utilities/inc/constants.hpp" 21 | 22 | int main(int argc, char *argv[]) 23 | { 24 | //We create a circle centered at (2.5,2.5) with a radius of 2.5 25 | //A circle needs to know 26 | //its center (2.5,2.5) 27 | //its orientation (lies on the xy plane, i.e. its normal is the z axis) 28 | //its radius (2.5) 29 | 30 | gp_Pnt centerPoint(2.5,2.5,0); 31 | gp_Dir normalDirection(0.0,0.0,1.0); 32 | gp_Dir xDirection(1.0,0.0,0.0); 33 | gp_Ax2 axis(centerPoint,normalDirection,xDirection); 34 | 35 | //Creating the circle 36 | gp_Circ circle(axis,2.5); 37 | 38 | //Some convenience functions provided by the circle class 39 | std::cout << "Circle area is: " << circle.Area() << std::endl; 40 | std::cout << "Circle circumference is: " << circle.Length() << std::endl; 41 | 42 | //Create a scaled copy of the circle 43 | gp_Circ circle2 = circle.Scaled(gp_Pnt(2.5,2.5,0.0),2.0); 44 | std::cout << "Scaled circle area is: " << circle2.Area() << std::endl; 45 | std::cout << "Scaled circle circumference is: " << circle2.Length() << std::endl; 46 | 47 | //Evaluating geometric entities happens through the ElClib package 48 | //ElClib = Elementary Curve operations 49 | //We now evaluate 15 points on the circle and write the resulting coordinates into a file 50 | 51 | //Divide the interval into 100 points 52 | Standard_Integer numberOfSamplePoints = 20; 53 | double deltaU = 2*PI/(numberOfSamplePoints - 1); 54 | 55 | std::ofstream file; 56 | file.open("chapter1_2_circlePoints.txt"); 57 | 58 | for(Standard_Integer i = 0; i 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | //Create a circle like before 21 | gp_Pnt centerPoint(2.5,2.5,0); 22 | gp_Dir normalDirection(0.0,0.0,1.0); 23 | gp_Dir xDirection(1.0,0.0,0.0); 24 | gp_Ax2 axis(centerPoint,normalDirection,xDirection); 25 | 26 | //Creating the circle 27 | gp_Circ circle(axis,2.5); 28 | 29 | Standard_Integer resolution = 20; 30 | 31 | //Here, an array of gp_Pnt is allocated, with 500 elements 32 | //Note that the indexing runs from 1 to 500, instead of the 33 | //standard convention of 0-499 34 | TColgp_Array1OfPnt pointsOnCircle(1,resolution); 35 | 36 | //Distribute the points and write them out to a file 37 | PointOnCurveDistribution::distributePointsOnCurve(circle,pointsOnCircle,0.0,2.0*PI,resolution); 38 | WriteCoordinatesToFile::writeCoordinatesToFile("chapter3points.txt",pointsOnCircle); 39 | 40 | //Sum the area of the small triangles, to get an approximate area 41 | //The for loop builds triangles with two corners on the circumference 42 | //and the center of the circle as third point 43 | double totalArea = 0.0; 44 | for(Standard_Integer i=1;i<=resolution;i++) 45 | { 46 | gp_Pnt firstPntOfTriangle = pointsOnCircle.Value(i); 47 | gp_Pnt secondPntOfTriangle; 48 | if(i != resolution) 49 | { 50 | secondPntOfTriangle = pointsOnCircle.Value(i+1); 51 | } 52 | else 53 | { 54 | //If we are at the end of the array, take the first point 55 | //because of periodicity 56 | secondPntOfTriangle = pointsOnCircle.Value(1); 57 | } 58 | gp_Pnt thirdPntOfTriangle = centerPoint; 59 | //A Handle (like a smart pointer) is built to an array of points 60 | Handle_TColgp_HArray1OfPnt trianglePointsArray = new TColgp_HArray1OfPnt(1,3); 61 | trianglePointsArray->ChangeValue(1) = firstPntOfTriangle; 62 | trianglePointsArray->ChangeValue(2) = secondPntOfTriangle; 63 | trianglePointsArray->ChangeValue(3) = thirdPntOfTriangle; 64 | totalArea += AreaCalculations::calculateTriangleArea(trianglePointsArray); 65 | 66 | } 67 | std::cout << "Polygonized area: " << totalArea << std::endl; 68 | std::cout << "Reference area: " << circle.Area() << std::endl; 69 | std::cout << "Error " << fabs(totalArea-circle.Area())/circle.Area() << std::endl; 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /Chapter1_Basics/runners/chapter1_4.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorial by Laszlo Kudela 2 | //November 2015 3 | //This example demonstrates the usage of OpenCASCADE's built in 4 | //optimization algorithms. In this example, we fit a circle onto a 5 | //scattered set of points, using math_BFGS. Check out LeastSquaresFitting.hpp 6 | //for more details. 7 | #include "Chapter1_Basics/inc/PointOnCurveDistributor.hpp" 8 | #include "Chapter1_Basics/inc/WriteCoordinatesToFile.hpp" 9 | #include "Chapter1_Basics/inc/LeastSquaresFitting.hpp" 10 | #include "Utilities/inc/constants.hpp" 11 | 12 | #include "TColgp_HArray1OfPnt.hxx" 13 | 14 | #include 15 | #include 16 | 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | //Create a circle like before 21 | gp_Pnt centerPoint(2.5,2.5,0); 22 | gp_Dir normalDirection(0.0,0.0,1.0); 23 | gp_Dir xDirection(1.0,0.0,0.0); 24 | gp_Ax2 axis(centerPoint,normalDirection,xDirection); 25 | 26 | //Creating the circle 27 | gp_Circ circle(axis,2.5); 28 | 29 | Standard_Integer resolution = 20; 30 | 31 | //Here, an array of gp_Pnt is allocated, with 500 elements 32 | //Note that the indexing runs from 1 to 500, instead of the 33 | //standard convention of 0-499 34 | TColgp_Array1OfPnt pointsOnCircle(1,resolution); 35 | 36 | //Seed random generator 37 | std::srand(static_cast(time(0))); 38 | 39 | //Distribute the points and write them out to a file 40 | PointOnCurveDistribution::distributePointsOnCurve(circle,pointsOnCircle,0.0,2.0*PI,resolution); 41 | Handle_TColgp_HArray1OfPnt pointsForLeastSquaresFit = new TColgp_HArray1OfPnt(1,resolution); 42 | for (Standard_Integer i = 1; i <= pointsForLeastSquaresFit->Upper(); ++i) 43 | { 44 | double randomXShift = static_cast(rand())/(static_cast(RAND_MAX/0.5))-0.25; 45 | double randomYShift = static_cast(rand())/(static_cast(RAND_MAX/0.5))-0.25; 46 | pointsForLeastSquaresFit->ChangeValue(i) = pointsOnCircle.Value(i); 47 | pointsForLeastSquaresFit->ChangeValue(i).SetX(pointsForLeastSquaresFit->ChangeValue(i).X()+randomXShift); 48 | pointsForLeastSquaresFit->ChangeValue(i).SetY(pointsForLeastSquaresFit->ChangeValue(i).Y()+randomYShift); 49 | 50 | } 51 | WriteCoordinatesToFile::writeCoordinatesToFile("chapter4.txt",pointsForLeastSquaresFit->Array1()); 52 | 53 | gp_Circ fittedCircle = LeastSquaresFitting::fitLeastSquaresCircleToPoints(pointsForLeastSquaresFit); 54 | 55 | PointOnCurveDistribution::distributePointsOnCurve(fittedCircle,pointsOnCircle,0.0,2.0*PI,resolution); 56 | WriteCoordinatesToFile::writeCoordinatesToFile("chapter4_fittedpoints.txt",pointsOnCircle); 57 | 58 | 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /Chapter1_Basics/runners/chapter1_5.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE Tutorials 2 | //Laszlo Kudela 3 | //Nov 19, 2015 4 | //This example demonstrates how to use OpenCASCADE's built in 5 | //features for solving equations. To this end, the intersection point between a 6 | //line and a plane is created. The algorithm deals with special cases, such as when the line lies 7 | //exactly on the plane, or the line and plane are parallel with no intersections. 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "Chapter1_Basics/inc/LinePlaneIntersection.hpp" 17 | 18 | #include 19 | 20 | void treatIntersectionSolution( 21 | LinePlaneIntersection::LinePlaneIntersectionSolution solution) { 22 | switch (solution.state) { 23 | case LinePlaneIntersection::LinePlaneIntersectionSolution::InfiniteSolutions: 24 | std::cout << "The line lies on the plane" << std::endl; 25 | break; 26 | case LinePlaneIntersection::LinePlaneIntersectionSolution::NoSolution: 27 | std::cout << "No intersection point found" << std::endl; 28 | break; 29 | case LinePlaneIntersection::LinePlaneIntersectionSolution::OneSolution: 30 | std::cout << "Intersection point is " << solution.intersectionPoint.X() 31 | << " " << solution.intersectionPoint.Y() << " " 32 | << solution.intersectionPoint.Z() << std::endl; 33 | } 34 | } 35 | 36 | int main(int argc, char **argv) { 37 | //Create a plane 38 | gp_Dir normalOfPlane(1.0, 0.0, 1.0); 39 | gp_Dir xDirectionOfPlane(1.0, 0.0, -1.0); 40 | gp_Pnt pointOnPlane(1.0, 0.0, 0.0); 41 | gp_Ax3 coordinateSystemOfPlane(pointOnPlane, normalOfPlane, 42 | xDirectionOfPlane); 43 | gp_Pln plane(coordinateSystemOfPlane); 44 | 45 | //Create a line 46 | gp_Lin line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 1.0)); 47 | LinePlaneIntersection::LinePlaneIntersectionSolution intersectionPoint = LinePlaneIntersection::intersectLineWithPlane( 48 | line, plane); 49 | treatIntersectionSolution(intersectionPoint); 50 | 51 | //Create a second line that lies on the plane 52 | gp_Lin line2(gp_Pnt(1.0, 0.0, 0.0), gp_Dir(1.0, 0.0, -1.0)); 53 | intersectionPoint = LinePlaneIntersection::intersectLineWithPlane(line2, 54 | plane); 55 | treatIntersectionSolution(intersectionPoint); 56 | 57 | //Create a line which is parallel to the plane 58 | gp_Lin line3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, -1.0)); 59 | intersectionPoint = LinePlaneIntersection::intersectLineWithPlane(line3, 60 | plane); 61 | treatIntersectionSolution(intersectionPoint); 62 | 63 | return 0; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /Chapter1_Basics/runners/chapter1_6.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorial by Laszlo Kudela 2 | //November 2015 3 | 4 | #include "BSplCLib.hxx" 5 | 6 | #include "TColgp_Array1OfPnt.hxx" 7 | #include "TColStd_Array1OfReal.hxx" 8 | #include "TColStd_Array1OfInteger.hxx" 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | //This example will demonstrate how to use BSplClib to perform elementary 13 | //computations on B-Spline curves. As we know from the theory of B-Splines, 14 | //they are defined by a polynomial degree, a set of controls points (denoted as poles in OpenCASCADE) 15 | //and a knot vector. We will create a 2nd order B-Spline with three poles. 16 | //This means that the number of knots required is 17 | // 18 | //m = n+p+1 19 | //m = 3+2+1 = 6 -> we need 6 knots to define the spline 20 | // 21 | //If the curve has to cross the first and the last control points 22 | //the multiplicity of the knots have to be p+1 = 3. 23 | //Thus, we have two knots, one at the beginning of the parameter space, 24 | //the other on at the end. Both of them has a multiplicity 3. 25 | //We begin by defining the knot vector, an array with two elements 26 | TColStd_Array1OfReal knots(1,2); 27 | knots.ChangeValue(1) = 0.0; 28 | knots.ChangeValue(2) = 1.0; 29 | 30 | //We then define the multiplicity of the knots, both of them is 3 31 | TColStd_Array1OfInteger multiplicites(1,2); 32 | multiplicites.SetValue(1,3); 33 | multiplicites.SetValue(2,3); 34 | 35 | //Now, we need a set of control points. OpenCASCADE denotes them as poles. 36 | TColgp_Array1OfPnt controlPoints(1,3); 37 | controlPoints.SetValue(1,gp_Pnt(1.0,0.0,0.0)); 38 | controlPoints.SetValue(2,gp_Pnt(1.0,1.0,0.0)); 39 | controlPoints.SetValue(3,gp_Pnt(0.0,1.0,0.0)); 40 | 41 | //We also have to assign a "weight" to each control point, in case 42 | //the curve is a NURBS. Here, we have a simple B-Spline, so no need 43 | //for special weights. 44 | TColStd_Array1OfReal weights(1,3); 45 | weights.SetValue(1,1.0); 46 | weights.SetValue(2,1.0); 47 | weights.SetValue(3,1.0); 48 | 49 | //The result of the evaluation will be stored in evalPoint 50 | gp_Pnt evalPoint; 51 | 52 | //Let's evaluate the first point on the curve 53 | BSplCLib::D0(0.0,0,2,Standard_False,controlPoints,weights,knots,multiplicites,evalPoint); 54 | std::cout << evalPoint.X() << " " << evalPoint.Y() << " " << evalPoint.Z() << std::endl; 55 | 56 | BSplCLib::D0(0.5,0,2,Standard_False,controlPoints,weights,knots,multiplicites,evalPoint); 57 | std::cout << evalPoint.X() << " " << evalPoint.Y() << " " << evalPoint.Z() << std::endl; 58 | 59 | BSplCLib::D0(1.0,0,2,Standard_False,controlPoints,weights,knots,multiplicites,evalPoint); 60 | std::cout << evalPoint.X() << " " << evalPoint.Y() << " " << evalPoint.Z() << std::endl; 61 | 62 | //To evaluate the tangent, we can call the D1 function (first derivative) 63 | //The derivative should be (0,2,0) at parameter u=0, and (-2,0,0) at u=1 64 | gp_Vec tangentVector; 65 | BSplCLib::D1(0.0,0,2,Standard_False,controlPoints,weights,knots,multiplicites,evalPoint,tangentVector); 66 | std::cout << "Tangent at u=0 " << tangentVector.X() << " " << tangentVector.Y() << " " << tangentVector.Z() << std::endl; 67 | 68 | BSplCLib::D1(1.0,0,2,Standard_False,controlPoints,weights,knots,multiplicites,evalPoint,tangentVector); 69 | std::cout << "Tangent at u=1 " << tangentVector.X() << " " << tangentVector.Y() << " " << tangentVector.Z() << std::endl; 70 | 71 | //Let's evaluate 10 points on the curve with their tangents, and save them into a file 72 | //You can display this file using the python script included in the tutorials, as follows: 73 | 74 | //python plotVectors.yp bSpline.txt 75 | //This will create a "vectors.png" file that you can open with any image viewer 76 | 77 | std::ofstream file; 78 | file.open("bSpline.txt"); 79 | double deltaU = 1.0 / 10.0; 80 | for (int i = 0; i <= 10; ++i) { 81 | BSplCLib::D1(i*deltaU,0,2,Standard_False,controlPoints,weights,knots,multiplicites,evalPoint,tangentVector); 82 | file << evalPoint.X() << " " <Value(1).X(); 18 | matrixForAreaCalculation(0,1) = triangleCorners->Value(1).Y(); 19 | matrixForAreaCalculation(0,2) = 1.0; 20 | matrixForAreaCalculation(1,0) = triangleCorners->Value(2).X(); 21 | matrixForAreaCalculation(1,1) = triangleCorners->Value(2).Y(); 22 | matrixForAreaCalculation(1,2) = 1.0; 23 | matrixForAreaCalculation(2,0) = triangleCorners->Value(3).X(); 24 | matrixForAreaCalculation(2,1) = triangleCorners->Value(3).Y(); 25 | matrixForAreaCalculation(2,2) = 1.0; 26 | 27 | double area = 0.5 * matrixForAreaCalculation.Determinant(); 28 | return area; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter1_Basics/src/BSplineBasisComputations.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorial by Laszlo Kudela 2 | //December 2015 3 | 4 | #include "../inc/BSplineBasisComputations.hpp" 5 | 6 | #include "TColStd_HArray1OfReal.hxx" 7 | #include "BSplCLib.hxx" 8 | 9 | BSplineBasisComputations::BSplineBasisComputations() 10 | { 11 | 12 | } 13 | BSplineBasisComputations::~BSplineBasisComputations() 14 | { 15 | 16 | } 17 | 18 | void BSplineBasisComputations::calculateBasisFunctions(Handle_TColStd_HArray1OfReal knots, Standard_Integer degree, 19 | Standard_Real parameter, math_Matrix& basisFunctions) 20 | { 21 | Standard_Integer numberOfNonVanishingFunctions = degree + 1; 22 | Standard_Integer firstNonZeroBSplineIndex; 23 | 24 | math_Matrix condensedBasisFunctions(1,1,1,numberOfNonVanishingFunctions); 25 | 26 | BSplCLib::EvalBsplineBasis(1,0,degree+1,knots->Array1(),parameter,firstNonZeroBSplineIndex,condensedBasisFunctions); 27 | 28 | for(Standard_Integer i = 0;iLength() - 1 - degree; 39 | math_Matrix basisFunctions(1,1,1,totalNumberOfBasisFunctions); 40 | 41 | BSplineBasisComputations::calculateBasisFunctions(knots,degree,parameter,basisFunctions); 42 | 43 | return basisFunctions(1,basisFunctionIndex + 1); 44 | } 45 | -------------------------------------------------------------------------------- /Chapter1_Basics/src/LeastSquaresFitting.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorials by Laszlo Kudela 2 | //2015 November 3 | //Chapter 1.4 Least squares fitting 4 | #include "../inc/LeastSquaresFitting.hpp" 5 | 6 | #include "TColgp_HArray1OfPnt.hxx" 7 | #include "math_MultipleVarFunctionWithGradient.hxx" 8 | #include "math_Vector.hxx" 9 | #include "math_BFGS.hxx" 10 | 11 | #include 12 | #include 13 | 14 | class CircleFitCostFunction : public math_MultipleVarFunctionWithGradient 15 | { 16 | public: 17 | CircleFitCostFunction(Handle_TColgp_HArray1OfPnt pointsToFitOnto); 18 | virtual ~CircleFitCostFunction(); 19 | 20 | Standard_Integer NbVariables() const; 21 | Standard_Boolean Value(const math_Vector& X, Standard_Real& F); 22 | Standard_Boolean Gradient(const math_Vector& X, math_Vector& G); 23 | Standard_Boolean Values(const math_Vector& X, Standard_Real& F, math_Vector& G); 24 | 25 | 26 | 27 | private: 28 | Handle_TColgp_HArray1OfPnt myPointsToFitOnto; 29 | 30 | }; 31 | 32 | CircleFitCostFunction::CircleFitCostFunction(Handle_TColgp_HArray1OfPnt pointsToFitOnto) : myPointsToFitOnto(pointsToFitOnto) 33 | { 34 | } 35 | 36 | CircleFitCostFunction::~CircleFitCostFunction() 37 | { 38 | } 39 | 40 | Standard_Integer CircleFitCostFunction::NbVariables() const 41 | { 42 | return 3; 43 | } 44 | Standard_Boolean CircleFitCostFunction::Value(const math_Vector& X, Standard_Real& F) 45 | { 46 | double sum = 0.0; 47 | for(Standard_Integer i = myPointsToFitOnto->Lower();i<=myPointsToFitOnto->Upper();i++) 48 | { 49 | double pxMinusCx = myPointsToFitOnto->Value(i).X()-X(1); 50 | double pyMinusCy = myPointsToFitOnto->Value(i).Y()-X(2); 51 | sum += (pxMinusCx*pxMinusCx+pyMinusCy*pyMinusCy-X(3)*X(3))*(pxMinusCx*pxMinusCx+pyMinusCy*pyMinusCy-X(3)*X(3)); 52 | } 53 | 54 | F = sum; 55 | 56 | return Standard_True; 57 | } 58 | Standard_Boolean CircleFitCostFunction::Gradient(const math_Vector& X, math_Vector& G) 59 | { 60 | double g0 = 0.0; 61 | double g1 = 0.0; 62 | double g2 = 0.0; 63 | 64 | for(Standard_Integer i = myPointsToFitOnto->Lower();i<=myPointsToFitOnto->Upper();i++) 65 | { 66 | double pxMinusCx = myPointsToFitOnto->Value(i).X()-X(1); 67 | double pyMinusCy = myPointsToFitOnto->Value(i).Y()-X(2); 68 | double distance = pxMinusCx*pxMinusCx+pyMinusCy*pyMinusCy-X(3)*X(3); 69 | g0 += pxMinusCx*distance; 70 | g1 += pyMinusCy*distance; 71 | g2 += distance; 72 | } 73 | 74 | G(1) = -4.0*g0; 75 | G(2) = -4.0*g1; 76 | G(3) = -4.0*X(3)*g2; 77 | 78 | return Standard_True; 79 | 80 | } 81 | Standard_Boolean CircleFitCostFunction::Values(const math_Vector& X, Standard_Real& F, math_Vector& G) 82 | { 83 | this->Value(X,F); 84 | this->Gradient(X,G); 85 | return Standard_True; 86 | } 87 | 88 | LeastSquaresFitting::LeastSquaresFitting () 89 | { 90 | } 91 | LeastSquaresFitting::~LeastSquaresFitting () 92 | { 93 | } 94 | 95 | gp_Circ LeastSquaresFitting::fitLeastSquaresCircleToPoints(const Handle_TColgp_HArray1OfPnt& points) 96 | { 97 | //Get initial guess for least squares fit 98 | InitialGuessForLeastSquaresFitting initialGuess = findInitialGuess(points); 99 | 100 | math_Vector startingPointForBFGS(1,3); 101 | startingPointForBFGS(1) = initialGuess.myCenterPoint.X(); 102 | startingPointForBFGS(2) = initialGuess.myCenterPoint.Y(); 103 | startingPointForBFGS(3) = initialGuess.myRadius; 104 | 105 | CircleFitCostFunction costFunction(points); 106 | 107 | math_BFGS minimizer(costFunction,startingPointForBFGS); 108 | 109 | math_Vector minimum(1,3); 110 | 111 | if (minimizer.IsDone()) 112 | { 113 | std::cout << "Minimizer is done, result is:" << std::endl; 114 | minimizer.Location(minimum); 115 | std::cout << minimum(1) << " " << minimum(2) << " " << minimum(3) << std::endl; 116 | 117 | } else 118 | { 119 | std::cout << "Error: minimizer failed!" << std::endl; 120 | } 121 | 122 | gp_Ax2 axis = gp::XOY(); 123 | axis.SetLocation(gp_Pnt(minimum(1),minimum(2),0.0)); 124 | gp_Circ result(axis,minimum(3)); 125 | 126 | return result; 127 | 128 | } 129 | 130 | LeastSquaresFitting::InitialGuessForLeastSquaresFitting LeastSquaresFitting::findInitialGuess(const Handle_TColgp_HArray1OfPnt& points) 131 | { 132 | //Compute center of gravity for point set 133 | double cx=0.0; 134 | double cy=0.0; 135 | 136 | for(Standard_Integer i=points->Lower();i<=points->Upper();i++) 137 | { 138 | cx += points->Value(i).X(); 139 | cy += points->Value(i).Y(); 140 | } 141 | 142 | cx /= points->Length(); 143 | cy /= points->Length(); 144 | 145 | gp_Pnt centerPoint(cx,cy,0.0); 146 | 147 | //Compute average radius 148 | double averageRadius = 0.0; 149 | for(Standard_Integer i=points->Lower();i<=points->Upper();i++) 150 | { 151 | averageRadius += centerPoint.Distance(points->Value(i)); 152 | } 153 | averageRadius /= points->Length(); 154 | 155 | return InitialGuessForLeastSquaresFitting(centerPoint,averageRadius); 156 | } 157 | -------------------------------------------------------------------------------- /Chapter1_Basics/src/LinePlaneIntersection.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE Tutorials 2 | //Laszlo Kudela 3 | //Nov 19, 2015 4 | 5 | #include 6 | 7 | #include "math_FunctionWithDerivative.hxx" 8 | #include "math_FunctionRoot.hxx" 9 | #include "math_DirectPolynomialRoots.hxx" 10 | #include "ElCLib.hxx" 11 | 12 | LinePlaneIntersection::LinePlaneIntersection() { 13 | // TODO Auto-generated constructor stub 14 | 15 | } 16 | 17 | LinePlaneIntersection::~LinePlaneIntersection() { 18 | // TODO Auto-generated destructor stub 19 | } 20 | 21 | LinePlaneIntersection::LinePlaneIntersectionSolution LinePlaneIntersection::intersectLineWithPlane(const gp_Lin& line, 22 | const gp_Pln& plane) { 23 | 24 | Standard_Real A,B,C,D; 25 | plane.Coefficients(A,B,C,D); 26 | 27 | gp_Pnt lineBasePoint = line.Location(); 28 | gp_Dir lineDirection = line.Direction(); 29 | 30 | Standard_Real X = A*lineDirection.X()+B*lineDirection.Y()+C*lineDirection.Z(); 31 | Standard_Real Y = A*lineBasePoint.X()+lineBasePoint.Y()+lineBasePoint.Z()+D; 32 | 33 | math_DirectPolynomialRoots rootFinder(X,Y); 34 | rootFinder.Dump(std::cout); 35 | 36 | LinePlaneIntersectionSolution result; 37 | 38 | if(rootFinder.InfiniteRoots()) 39 | { 40 | result.state = LinePlaneIntersectionSolution::InfiniteSolutions; 41 | } 42 | else if(rootFinder.NbSolutions() == 0) 43 | { 44 | result.state = LinePlaneIntersectionSolution::NoSolution; 45 | } 46 | else 47 | { 48 | result.state = LinePlaneIntersectionSolution::OneSolution; 49 | result.intersectionPoint = ElCLib::Value(rootFinder.Value(1),line); 50 | } 51 | 52 | return result; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /Chapter1_Basics/src/WriteCoordinatesToFile.cpp: -------------------------------------------------------------------------------- 1 | #include "Chapter1_Basics/inc/WriteCoordinatesToFile.hpp" 2 | 3 | #include 4 | #include 5 | 6 | namespace WriteCoordinatesToFile 7 | { 8 | void writeCoordinatesToFile(std::string fileName,const TColgp_Array1OfPnt& points) 9 | { 10 | std::ofstream file; 11 | file.open(fileName.c_str()); 12 | for(Standard_Integer i = points.Lower();i <= points.Upper();i++) 13 | { 14 | file << points.Value(i).X() << " " << points.Value(i).Y() << " " << points.Value(i).Z() << std::endl; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter1_Basics/tests/BSplineBasisComputations_test.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorial by Laszlo Kudela 2 | //December 2015 3 | 4 | #include "TColStd_HArray1OfReal.hxx" 5 | #include 6 | 7 | #include "Utilities/inc/catch.hpp" 8 | #include "Utilities/inc/constants.hpp" 9 | 10 | #include "../inc/BSplineBasisComputations.hpp" 11 | #include "../inc/WriteCoordinatesToFile.hpp" 12 | 13 | TEST_CASE("BezierBasis","[Chapter 1]") 14 | { 15 | Handle_TColStd_HArray1OfReal knots = new TColStd_HArray1OfReal(1,6); 16 | knots->SetValue(1,0.0); 17 | knots->SetValue(2,0.0); 18 | knots->SetValue(3,0.0); 19 | 20 | knots->SetValue(4,1.0); 21 | knots->SetValue(5,1.0); 22 | knots->SetValue(6,1.0); 23 | 24 | SECTION("Evaluate zeroth basis") 25 | { 26 | double value = BSplineBasisComputations::evaluateBasisFunction(knots,2,0.0,0); 27 | CHECK(value == Approx(1.0).epsilon(1E-12)); 28 | 29 | value = BSplineBasisComputations::evaluateBasisFunction(knots,2,0.5,0); 30 | CHECK(value == Approx(0.25).epsilon(1E-12)); 31 | 32 | value = BSplineBasisComputations::evaluateBasisFunction(knots,2,1.0,0); 33 | CHECK(value == Approx(0.0).epsilon(1E-12)); 34 | } 35 | 36 | SECTION("Evaluate first basis") 37 | { 38 | double value = BSplineBasisComputations::evaluateBasisFunction(knots,2,0.0,1); 39 | CHECK(value == Approx(0.0).epsilon(1E-12)); 40 | 41 | value = BSplineBasisComputations::evaluateBasisFunction(knots,2,0.5,1); 42 | CHECK(value == Approx(0.5).epsilon(1E-12)); 43 | 44 | value = BSplineBasisComputations::evaluateBasisFunction(knots,2,1.0,1); 45 | CHECK(value == Approx(0.0).epsilon(1E-12)); 46 | } 47 | 48 | SECTION("Evaluate second basis") 49 | { 50 | double value = BSplineBasisComputations::evaluateBasisFunction(knots,2,0.0,2); 51 | CHECK(value == Approx(0.0).epsilon(1E-12)); 52 | 53 | value = BSplineBasisComputations::evaluateBasisFunction(knots,2,0.5,2); 54 | CHECK(value == Approx(0.25).epsilon(1E-12)); 55 | 56 | value = BSplineBasisComputations::evaluateBasisFunction(knots,2,1.0,2); 57 | CHECK(value == Approx(1.0).epsilon(1E-12)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Chapter1_Basics/tests/PointOnCurveDistributor_test.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorial by Laszlo Kudela 2 | //November 2015 3 | 4 | #include "Utilities/inc/catch.hpp" 5 | #include "Utilities/inc/constants.hpp" 6 | 7 | #include "../inc/PointOnCurveDistributor.hpp" 8 | 9 | #include "gp_Pnt.hxx" 10 | #include "gp_Circ.hxx" 11 | 12 | TEST_CASE("Get points on circle","[chapter1]") 13 | { 14 | gp_Circ circle(gp::XOY(),1.0); 15 | TColgp_Array1OfPnt points(1,5); 16 | PointOnCurveDistribution::distributePointsOnCurve(circle,points,0.0,2.0*PI,5); 17 | 18 | 19 | REQUIRE(points.Value(1).X() == Approx(1.0).epsilon(1E-12)); 20 | REQUIRE(points.Value(1).Y() == Approx(0.0).epsilon(1E-12)); 21 | REQUIRE(points.Value(1).Z() == Approx(0.0).epsilon(1E-12)); 22 | 23 | REQUIRE(points.Value(2).X() == Approx(0.0).epsilon(1E-12)); 24 | REQUIRE(points.Value(2).Y() == Approx(1.0).epsilon(1E-12)); 25 | REQUIRE(points.Value(2).Z() == Approx(0.0).epsilon(1E-12)); 26 | 27 | REQUIRE(points.Value(3).X() == Approx(-1.0).epsilon(1E-12)); 28 | REQUIRE(points.Value(3).Y() == Approx(0.0).epsilon(1E-12)); 29 | REQUIRE(points.Value(3).Z() == Approx(0.0).epsilon(1E-12)); 30 | 31 | REQUIRE(points.Value(4).X() == Approx(0.0).epsilon(1E-12)); 32 | REQUIRE(points.Value(4).Y() == Approx(-1.0).epsilon(1E-12)); 33 | REQUIRE(points.Value(4).Z() == Approx(0.0).epsilon(1E-12)); 34 | } 35 | 36 | -------------------------------------------------------------------------------- /Chapter1_Basics/tests/main_test.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "Utilities/inc/catch.hpp" 3 | -------------------------------------------------------------------------------- /Chapter2_Geom/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT(chapter2) 4 | 5 | CreateLibrary() 6 | 7 | FILE(GLOB RUNNERSOURCES "${CMAKE_CURRENT_SOURCE_DIR}/runners/*.cpp") 8 | 9 | FOREACH(RUNNERSOURCE ${RUNNERSOURCES}) 10 | 11 | CreateExecutable(${RUNNERSOURCE} chapter2 TKernel TKMath TKSTL TKBO TKPrim TKSTEP) 12 | 13 | ENDFOREACH(RUNNERSOURCE) 14 | 15 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/testrunners") 16 | FILE(GLOB TESTSOURCES "${CMAKE_CURRENT_SOURCE_DIR}/tests/*.cpp") 17 | ADD_EXECUTABLE(chapter2_test ${TESTSOURCES}) 18 | TARGET_LINK_LIBRARIES(chapter2_test chapter2 TKernel TKMath) 19 | ADD_TEST(chapter2_tests "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/chapter2_test") 20 | -------------------------------------------------------------------------------- /Chapter2_Geom/inc/GeometryWriter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _GEOMETRYWRITER_HPP_ 2 | #define _GEOMETRYWRITER_HPP_ 3 | //OpenCASCADE tutorial by Laszlo Kudela 4 | //January 2016 5 | 6 | #include 7 | #include "Handle_Geom_Curve.hxx" 8 | #include "Handle_Geom_Surface.hxx" 9 | 10 | class GeometryWriter 11 | { 12 | public: 13 | GeometryWriter (); 14 | virtual ~GeometryWriter (); 15 | 16 | static void writeGeomEntityToStepFile(Handle_Geom_Curve curve, std::string fileName); 17 | static void writeGeomEntityToStepFile(Handle_Geom_Surface curve, std::string fileName); 18 | 19 | private: 20 | }; 21 | #endif 22 | -------------------------------------------------------------------------------- /Chapter2_Geom/inc/TangentMagnitude.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _TANGENTMAGNITUDE_HPP_ 2 | #define _TANGENTMAGNITUDE_HPP_ 3 | //OpenCASCADE tutorial by Laszlo Kudela 4 | //January 2016 5 | 6 | #include "math_Function.hxx" 7 | #include "Geom_Curve.hxx" 8 | 9 | class TangentMagnitude : public math_Function 10 | { 11 | public: 12 | TangentMagnitude (Handle_Geom_Curve curve); 13 | virtual ~TangentMagnitude (); 14 | Standard_Boolean Value(Standard_Real X, Standard_Real& F); 15 | 16 | const Handle_Geom_Curve getCurve() const; 17 | void setCurve(Handle_Geom_Curve curve); 18 | 19 | 20 | private: 21 | Handle_Geom_Curve myCurve; 22 | }; 23 | #endif 24 | -------------------------------------------------------------------------------- /Chapter2_Geom/runners/Chapter2_1.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorial by Laszlo Kudela 2 | //January 2016 3 | 4 | //This example demonstrates how to create geometric entities like curves and surfaces from the Geom package 5 | //and apply some transformations on them 6 | //Finally, we compute the length of the curve using the numerical integration provided by OpenCASCADE 7 | 8 | #include "Chapter2_Geom/inc/GeometryWriter.hpp" 9 | #include "Chapter2_Geom/inc/TangentMagnitude.hpp" 10 | #include "Utilities/inc/constants.hpp" 11 | 12 | #include "TColgp_Array1OfPnt.hxx" 13 | #include "Geom_BezierCurve.hxx" 14 | #include "math_GaussSingleIntegration.hxx" 15 | 16 | int main(void) 17 | { 18 | 19 | //Here, a simple Bezier curve is created. It is defined by 4 points in 20 | //the 3D space, therefore its order will be 3 21 | 22 | //A Bezier curve needs a set of control points in its constructor, 23 | //that we store in a 1D Array of points 24 | TColgp_Array1OfPnt controlPoints(1,4); 25 | 26 | controlPoints.SetValue(1,gp_Pnt(0.0,0.0,0.0)); 27 | controlPoints.SetValue(2,gp_Pnt(1.0,0.0,1.0/3.0)); 28 | controlPoints.SetValue(3,gp_Pnt(1.0,1.0,2.0/3.0)); 29 | controlPoints.SetValue(4,gp_Pnt(1.0,1.0,1.0)); 30 | 31 | Handle_Geom_Curve bezierCurve = new Geom_BezierCurve(controlPoints); 32 | 33 | GeometryWriter::writeGeomEntityToStepFile(bezierCurve,"bezierInitial.stp"); 34 | 35 | //Because a Bezier curve inherits from Geom_Geometry, all sorts of geometric transformations can be applied on it 36 | //Let us rotate the curve around the z axis by 180 degrees 37 | //Because "Rotate" is a function of the superclass, the function returns a 38 | //Geom_Geometry object 39 | Handle_Geom_Geometry rotated = bezierCurve->Rotated(gp::OZ(),PI); 40 | 41 | //If we want to convert it to a curve, we can use the built-in DownCast function of the Handle 42 | Handle_Geom_Curve rotatedCurve = Handle_Geom_Curve::DownCast(rotated); 43 | GeometryWriter::writeGeomEntityToStepFile(rotatedCurve,"rotatedBezier.stp"); 44 | 45 | //We can also scale the curve, applying a scaling 46 | Handle_Geom_Curve scaledCurve = Handle_Geom_Curve::DownCast(bezierCurve->Scaled(gp::Origin(),2.0)); 47 | 48 | //What are the parametric bounds of the created curve? 49 | Standard_Real firstParameter = bezierCurve->FirstParameter(); 50 | Standard_Real lastParameter = bezierCurve->LastParameter(); 51 | 52 | std::cout << "The parametric bounds of the created curve are: " << firstParameter << " " << lastParameter << std::endl; 53 | 54 | //To evaluate the curve at a given parameter, we can call the function "Value" 55 | gp_Pnt pointOnCurve = bezierCurve->Value(0.0); 56 | std::cout << "Point at u = 0.0: " << "(" << pointOnCurve.X() << "," << pointOnCurve.Y() << "," << pointOnCurve.Z() <<")" << std::endl; 57 | 58 | pointOnCurve = bezierCurve->Value(0.5); 59 | std::cout << "Point at u = 0.5: " << "(" << pointOnCurve.X() << "," << pointOnCurve.Y() << "," << pointOnCurve.Z() <<")" << std::endl; 60 | 61 | pointOnCurve = bezierCurve->Value(1.0); 62 | std::cout << "Point at u = 1.0: " << "(" << pointOnCurve.X() << "," << pointOnCurve.Y() << "," << pointOnCurve.Z() <<")" << std::endl; 63 | 64 | //To evaluate the tangent vector, we can call the function "D1". For higher derivatives, we have D2,D3,...,DN 65 | gp_Vec tangentVector; 66 | bezierCurve->D1(0.0,pointOnCurve,tangentVector); 67 | std::cout << "Magnitude of tangent at 0.0: " << tangentVector.Magnitude() << std::endl; 68 | bezierCurve->D1(0.5,pointOnCurve,tangentVector); 69 | std::cout << "Magnitude of tangent at 0.5: " << tangentVector.Magnitude() << std::endl; 70 | bezierCurve->D1(1.0,pointOnCurve,tangentVector); 71 | std::cout << "Magnitude of tangent at 1.0: " << tangentVector.Magnitude() << std::endl; 72 | 73 | //If we integrate the magnitude of the tangent vector along the curve, we get 74 | //the length. OpenCASCADE provides numerical integration routines to perform this task, called 75 | //math_GaussSingleIntegration. /All we have to do is to implement a class that inherits 76 | //from math_Function and implements the function "Value", that for a given X value returns 77 | //the magnitude of the tangent. 78 | 79 | TangentMagnitude functionToBeIntegrated(bezierCurve); 80 | math_GaussSingleIntegration integrator(functionToBeIntegrated,firstParameter,lastParameter,5); 81 | 82 | if(integrator.IsDone()) 83 | { 84 | std::cout << "The length of the curve is approximately " << integrator.Value() << std::endl; 85 | } 86 | 87 | //Let's compute the length of the rotated and scaled curve 88 | functionToBeIntegrated.setCurve(rotatedCurve); 89 | math_GaussSingleIntegration rotatedIntegrator(functionToBeIntegrated,firstParameter,lastParameter,5); 90 | double rotatedLength = rotatedIntegrator.Value(); 91 | functionToBeIntegrated.setCurve(scaledCurve); 92 | math_GaussSingleIntegration scaledIntegrator(functionToBeIntegrated,firstParameter,lastParameter,5); 93 | double scaledLength = scaledIntegrator.Value(); 94 | 95 | std::cout << "Length of rotated curve is " << rotatedLength << std::endl; 96 | std::cout << "Length of scaled curve is " << scaledLength << std::endl; 97 | 98 | //If you run this example, you will see that rotation keeps the length of the curve, because 99 | //it is a rigid transformation, while scaling changes the length. 100 | 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /Chapter2_Geom/src/GeometryWriter.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorial by Laszlo Kudela 2 | //January 2016 3 | 4 | #include "../inc/GeometryWriter.hpp" 5 | 6 | #include "Geom_Curve.hxx" 7 | #include "BRepBuilderAPI_MakeEdge.hxx" 8 | #include "BRepBuilderAPI_MakeFace.hxx" 9 | #include "STEPControl_Writer.hxx" 10 | 11 | GeometryWriter::GeometryWriter() 12 | { 13 | 14 | } 15 | 16 | GeometryWriter::~GeometryWriter() 17 | { 18 | 19 | } 20 | 21 | void GeometryWriter::writeGeomEntityToStepFile(Handle_Geom_Curve curve, std::string fileName) 22 | { 23 | BRepBuilderAPI_MakeEdge edgeMaker; 24 | edgeMaker.Init(curve); 25 | TopoDS_Shape edge = edgeMaker.Shape(); 26 | 27 | STEPControl_Writer writer; 28 | writer.Transfer(edge,STEPControl_AsIs); 29 | writer.Write(fileName.c_str()); 30 | return; 31 | } 32 | 33 | void GeometryWriter::writeGeomEntityToStepFile(Handle_Geom_Surface surface, std::string fileName) 34 | { 35 | BRepBuilderAPI_MakeFace faceMaker; 36 | faceMaker.Init(surface,true,1E-6); 37 | TopoDS_Shape face = faceMaker.Shape(); 38 | 39 | STEPControl_Writer writer; 40 | writer.Transfer(face,STEPControl_AsIs); 41 | writer.Write(fileName.c_str()); 42 | return; 43 | } 44 | -------------------------------------------------------------------------------- /Chapter2_Geom/src/TangentMagnitude.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorial by Laszlo Kudela 2 | //January 2016 3 | 4 | 5 | #include "../inc/TangentMagnitude.hpp" 6 | 7 | #include "gp_Vec.hxx" 8 | #include "gp_Pnt.hxx" 9 | 10 | TangentMagnitude::TangentMagnitude (Handle_Geom_Curve curve) : myCurve(curve) 11 | { 12 | 13 | } 14 | TangentMagnitude::~TangentMagnitude () 15 | { 16 | 17 | } 18 | Standard_Boolean TangentMagnitude::Value(Standard_Real X, Standard_Real& F) 19 | { 20 | gp_Vec tangentVector; 21 | gp_Pnt pointLocation; 22 | 23 | myCurve->D1(X,pointLocation,tangentVector); 24 | 25 | F = tangentVector.Magnitude(); 26 | 27 | return Standard_True; 28 | } 29 | const Handle_Geom_Curve TangentMagnitude::getCurve() const 30 | { 31 | return myCurve; 32 | } 33 | void TangentMagnitude::setCurve(Handle_Geom_Curve curve) 34 | { 35 | myCurve = curve; 36 | return; 37 | } 38 | -------------------------------------------------------------------------------- /Chapter2_Geom/tests/main_test.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "Utilities/inc/catch.hpp" 3 | -------------------------------------------------------------------------------- /OtherExamples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT(otherexamples) 4 | 5 | CreateLibrary() 6 | 7 | FILE(GLOB RUNNERSOURCES "${CMAKE_CURRENT_SOURCE_DIR}/runners/*.cpp") 8 | 9 | FOREACH(RUNNERSOURCE ${RUNNERSOURCES}) 10 | 11 | CreateExecutable(${RUNNERSOURCE} otherexamples chapter1 TKernel TKMath TKSTL TKBO TKPrim TKSTEP ) 12 | 13 | ENDFOREACH(RUNNERSOURCE) 14 | 15 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/testrunners") 16 | FILE(GLOB TESTSOURCES "${CMAKE_CURRENT_SOURCE_DIR}/tests/*.cpp") 17 | ADD_EXECUTABLE(otherexamples_test ${TESTSOURCES}) 18 | TARGET_LINK_LIBRARIES(otherexamples_test otherexamples TKernel TKMath TKPrim) 19 | ADD_TEST(otherexamples_test "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/otherexamples_test") 20 | -------------------------------------------------------------------------------- /OtherExamples/inc/CreateCurvedPlateWithHole.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _CREATECURVEDPLATEWITHHOLE_HPP_ 2 | #define _CREATECURVEDPLATEWITHHOLE_HPP_ 3 | //OpenCASCADE tutorial by Laszlo Kudela 4 | //December 2015 5 | 6 | #include "TopoDS_Shape.hxx" 7 | 8 | namespace CreateCurvedPlateWithHole 9 | { 10 | 11 | TopoDS_Shape createCurvedPlateWithHole(); 12 | 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /OtherExamples/inc/StlPointsExtractor.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _STLPOINTEXTRACTOR_HPP_ 2 | #define _STLPOINTEXTRACTOR_HPP_ 3 | //OpenCASCADE tutorials by Laszlo Kudela 4 | //December 2015 5 | 6 | #include "Handle_TColgp_HArray1OfPnt.hxx" 7 | #include "TopoDS_Shape.hxx" 8 | 9 | class StlPointsExtractor 10 | { 11 | public: 12 | StlPointsExtractor (); 13 | virtual ~StlPointsExtractor (); 14 | 15 | static Handle_TColgp_HArray1OfPnt extractVerticesFromTopoDSShape(const TopoDS_Shape& shape); 16 | static TopoDS_Shape extractManifoldBoundaries(const TopoDS_Shape& shape); 17 | 18 | private: 19 | /* data */ 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /OtherExamples/runners/convertStepToStl.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorials by Laszlo Kudela 2 | //2016 May 3 | 4 | #include "STEPControl_Reader.hxx" 5 | #include "StlAPI_Writer.hxx" 6 | #include "TopoDS_Shape.hxx" 7 | #include "Standard_ConstructionError.hxx" 8 | 9 | int main(int argc, char *argv[]) 10 | { 11 | STEPControl_Reader reader; 12 | reader.ReadFile(argv[1]); 13 | reader.TransferRoots(); 14 | TopoDS_Shape stepShape = reader.OneShape(); 15 | 16 | try 17 | { 18 | StlAPI_Writer writer; 19 | writer.Write(stepShape,argv[2]); 20 | }catch(Standard_ConstructionError& e) 21 | { 22 | std::cout << e.GetMessageString() << std::endl; 23 | } 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /OtherExamples/runners/extractStlManifoldBoundaries.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorial by Laszlo Kudela 2 | //December 2015 3 | 4 | #include "../inc/CreateCurvedPlateWithHole.hpp" 5 | #include "../inc/StlPointsExtractor.hpp" 6 | #include "TopoDS_Shape.hxx" 7 | #include "TopoDS_Face.hxx" 8 | #include "TopoDS_Edge.hxx" 9 | #include "TopExp_Explorer.hxx" 10 | #include "TopExp.hxx" 11 | #include "TopoDS.hxx" 12 | #include "TopoDS_Builder.hxx" 13 | #include "TopTools_SequenceOfShape.hxx" 14 | #include "TopTools_ListOfShape.hxx" 15 | #include "TopTools_ListIteratorOfListOfShape.hxx" 16 | #include "TopTools_IndexedDataMapOfShapeListOfShape.hxx" 17 | 18 | #include "BRep_Tool.hxx" 19 | #include "BRepMesh_IncrementalMesh.hxx" 20 | 21 | #include "StlAPI.hxx" 22 | 23 | #include "STEPControl_Writer.hxx" 24 | 25 | int main(int argc, char *argv[]) 26 | { 27 | //Create a curved plate with hole 28 | std::cout << "Creating plate with hole... "; 29 | TopoDS_Shape plateWithHoleShape = CreateCurvedPlateWithHole::createCurvedPlateWithHole(); 30 | std::cout << "done" << std::endl; 31 | 32 | TopoDS_Face plateWithHoleFace; 33 | TopExp_Explorer explorer; 34 | //Make a triangulation out of it, write to STL 35 | for(explorer.Init(plateWithHoleShape,TopAbs_FACE,TopAbs_SHAPE);explorer.More();explorer.Next()) 36 | { 37 | plateWithHoleFace = TopoDS::Face(explorer.Current()); 38 | } 39 | std::cout << "Creating mesh..." << std::flush; 40 | BRepMesh_IncrementalMesh meshMaker(plateWithHoleFace,0.01,Standard_False); 41 | std::cout << " done." << std::endl; 42 | meshMaker.Perform(); 43 | std::cout << "Writing STL... " << std::flush; 44 | StlAPI::Write(plateWithHoleFace,"curvedPlateWithHole.stl",true); 45 | std::cout << "done" << std::endl; 46 | 47 | 48 | //Read STL, extract boundary edges of STL mesh 49 | std::cout << "Reading STL..." << std::flush; 50 | TopoDS_Shape stlShape; 51 | StlAPI::Read(stlShape,"curvedPlateWithHole.stl"); 52 | std::cout << "done" << std::endl; 53 | 54 | //This function call is the place wehre the actual work is done. 55 | //Check the source file if you want to know how it works! 56 | TopoDS_Shape collectorOfEdges = StlPointsExtractor::extractManifoldBoundaries(stlShape); 57 | 58 | //Write the result in STEP file 59 | STEPControl_Writer writer; 60 | writer.Transfer(collectorOfEdges,STEPControl_AsIs); 61 | writer.Write("curvePlateWithHoleEdges.stp"); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /OtherExamples/runners/extractStlPoints.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorials by Laszlo Kudela 2 | //December 2015 3 | 4 | #include "Chapter1_Basics/inc/WriteCoordinatesToFile.hpp" 5 | #include "OtherExamples/inc/StlPointsExtractor.hpp" 6 | 7 | #include "StlAPI.hxx" 8 | #include "TColgp_HArray1OfPnt.hxx" 9 | 10 | #include 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | 15 | if(argc < 2) 16 | { 17 | std::cout << "Usage: " << std::endl; 18 | std::cout << "extractStlPoints [InputSTLFile]" << std::endl; 19 | return 1; 20 | } 21 | 22 | char* inputFileName = argv[1]; 23 | 24 | TopoDS_Shape stlShape; 25 | std::cout << "Reading STL file " << inputFileName << " ..." << std::flush; 26 | 27 | StlAPI::Read(stlShape,inputFileName); 28 | 29 | std::cout << "done."; 30 | 31 | Handle_TColgp_HArray1OfPnt extractedPoints = StlPointsExtractor::extractVerticesFromTopoDSShape(stlShape); 32 | 33 | WriteCoordinatesToFile::writeCoordinatesToFile("stlOutput.txt",extractedPoints->Array1()); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /OtherExamples/runners/moveAndRotateAssem.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASADE tutorial by Laszlo Kudela 2 | //January 2016 3 | 4 | #include "BRepTools_ReShape.hxx" 5 | #include "BRepTools.hxx" 6 | #include "TopTools.hxx" 7 | #include "STEPControl_Writer.hxx" 8 | #include "Utilities/inc/constants.hpp" 9 | 10 | #include "BRepBuilderAPI_Transform.hxx" 11 | #include "gp_Trsf.hxx" 12 | #include "TopoDS.hxx" 13 | #include "TopoDS_Solid.hxx" 14 | #include "TopExp.hxx" 15 | #include "TopTools_IndexedMapOfShape.hxx" 16 | #include "TopExp_Explorer.hxx" 17 | #include "TopoDS_Compound.hxx" 18 | #include "STEPControl_Reader.hxx" 19 | 20 | #include 21 | 22 | int main(int argc, char *argv[]) 23 | { 24 | //In this tutorial, we read in a STEP file containing to solids 25 | //and modify the underlying solids in some way 26 | 27 | //The first argument of the program is the name of the STEP file 28 | 29 | if(argc < 2) 30 | { 31 | std::cout << "Usage: moveAndRotate InputFile" << std::endl; 32 | std::cout << "InputFile: a file in STP format" << std::endl; 33 | return 1; 34 | } 35 | 36 | //First, we read in a STEP file 37 | STEPControl_Reader reader; 38 | reader.ReadFile(argv[1]); 39 | 40 | std::cout << reader.TransferRoots() << " roots transferred." << std::endl; 41 | 42 | //The shape that was read in is stored in a single TopoDS_Shape 43 | //If this is an assembly file, the shape should be a compound 44 | TopoDS_Shape shape = reader.OneShape(); 45 | 46 | if(shape.ShapeType() != TopAbs_COMPOUND) 47 | { 48 | std::cout << "Error: the read shape is not a compound!" << std::endl; 49 | return 1; 50 | } 51 | 52 | //Next, we extract the first two solids that compose the compound shape 53 | //To this end, we have to "explore" the compound shape and find the solids 54 | //contained in it 55 | TopTools_IndexedMapOfShape mapOfShapes; 56 | TopExp::MapShapes(shape,TopAbs_SOLID,mapOfShapes); 57 | std::cout << mapOfShapes.Extent() << " solids found in STEP file." << std::endl; 58 | 59 | TopoDS_Solid firstSolid = TopoDS::Solid(mapOfShapes.FindKey(1)); 60 | TopoDS_Solid secondSolid = TopoDS::Solid(mapOfShapes.FindKey(2)); 61 | 62 | //We are going to move the second solid along the z axis in the negative direction 63 | //This needs a gp_Trsf object 64 | gp_Trsf translation; 65 | translation.SetTranslation(gp_Pnt(0.0,0.0,0.0),gp_Pnt(0.0,0.0,-50.0)); 66 | 67 | //Perform the translation 68 | BRepBuilderAPI_Transform translationTransformer(translation); 69 | translationTransformer.Perform(secondSolid,false); 70 | TopoDS_Solid solidAfterTranslation = TopoDS::Solid(translationTransformer.ModifiedShape(secondSolid)); 71 | 72 | //Next we rotate the first solid around the y axis by 45 degrees 73 | gp_Trsf rotation; 74 | rotation.SetRotation(gp::OY(),1.0 * PI / 4.0); 75 | BRepBuilderAPI_Transform rotationTransformer(rotation); 76 | rotationTransformer.Perform(solidAfterTranslation); 77 | TopoDS_Solid solidAfterRotation = TopoDS::Solid(rotationTransformer.ModifiedShape(solidAfterTranslation)); 78 | 79 | //Next, we replace the original shape in the compound by the new, rotated and transformed shape 80 | BRepTools_ReShape reShaper; 81 | reShaper.Replace(secondSolid,solidAfterRotation); 82 | shape = reShaper.Apply(shape); 83 | 84 | 85 | //Now we store the resulting solids in another STEP file 86 | STEPControl_Writer writer; 87 | writer.Transfer(shape,STEPControl_AsIs); 88 | writer.Write("moveAndRotate_output.stp"); 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /OtherExamples/src/CreateCurvedPlateWithHole.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorial by Laszlo Kudela 2 | //December 2015 3 | 4 | #include "../inc/CreateCurvedPlateWithHole.hpp" 5 | 6 | #include "TColgp_Array2OfPnt.hxx" 7 | #include "Geom_BezierSurface.hxx" 8 | #include "BRepBuilderAPI_MakeFace.hxx" 9 | #include "BRepPrimAPI_MakeCylinder.hxx" 10 | #include "BRepAlgoAPI_Cut.hxx" 11 | #include "TopoDS_Shape.hxx" 12 | 13 | namespace CreateCurvedPlateWithHole 14 | { 15 | 16 | TopoDS_Shape createCurvedPlateWithHole() 17 | { 18 | //Create a biquadratic bezier surface from control points 19 | TColgp_Array2OfPnt controlPoints(1,3,1,3); 20 | 21 | controlPoints.SetValue(1,1,gp_Pnt(-5.0,-5.0,0.0)); 22 | controlPoints.SetValue(2,1,gp_Pnt(0.0,-5.0,0.0)); 23 | controlPoints.SetValue(3,1,gp_Pnt(5.0,-5.0,0.0)); 24 | 25 | controlPoints.SetValue(1,2,gp_Pnt(-5.0,0.0,0.0)); 26 | controlPoints.SetValue(2,2,gp_Pnt(0.0,0.0,5.0)); 27 | controlPoints.SetValue(3,2,gp_Pnt(5.0,0.0,0.0)); 28 | 29 | controlPoints.SetValue(1,3,gp_Pnt(-5.0,5.0,0.0)); 30 | controlPoints.SetValue(2,3,gp_Pnt(0.0,5.0,0.0)); 31 | controlPoints.SetValue(3,3,gp_Pnt(5.0,5.0,0.0)); 32 | 33 | Handle_Geom_BezierSurface surface = new Geom_BezierSurface(controlPoints); 34 | 35 | //Create a TopoDS_Shape out of the Bezier surface 36 | TopoDS_Shape face = BRepBuilderAPI_MakeFace(surface,1E-6); 37 | 38 | //Create a cylinder that will cut a hole in the surface 39 | BRepPrimAPI_MakeCylinder cylinderMaker(1.0,10.0); 40 | TopoDS_Shape cylinder = cylinderMaker.Shape(); 41 | 42 | BRepAlgoAPI_Cut cutMaker(face,cylinder); 43 | 44 | TopoDS_Shape plateWithHole = cutMaker.Shape(); 45 | 46 | return plateWithHole; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /OtherExamples/src/StlPointsExtractor.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorials by Laszlo Kudela 2 | //December 2015 3 | // 4 | #include "../inc/StlPointsExtractor.hpp" 5 | #include "TopTools_ListIteratorOfListOfShape.hxx" 6 | #include "TopoDS_Builder.hxx" 7 | #include "TopoDS_Compound.hxx" 8 | #include "TopoDS_Edge.hxx" 9 | #include "TopExp_Explorer.hxx" 10 | #include "TopTools_IndexedDataMapOfShapeListOfShape.hxx" 11 | #include "TopTools_ListOfShape.hxx" 12 | 13 | #include "TopoDS.hxx" 14 | #include "TopoDS_Vertex.hxx" 15 | #include "TColgp_HArray1OfPnt.hxx" 16 | #include "TopExp.hxx" 17 | #include "TopTools_IndexedMapOfShape.hxx" 18 | 19 | #include "BRep_Tool.hxx" 20 | 21 | StlPointsExtractor::StlPointsExtractor() 22 | { 23 | 24 | } 25 | StlPointsExtractor::~StlPointsExtractor() 26 | { 27 | 28 | } 29 | Handle_TColgp_HArray1OfPnt StlPointsExtractor::extractVerticesFromTopoDSShape(const TopoDS_Shape& shape) 30 | { 31 | TopTools_IndexedMapOfShape vertices; 32 | TopExp::MapShapes(shape,TopAbs_VERTEX,vertices); 33 | 34 | Handle_TColgp_HArray1OfPnt result = new TColgp_HArray1OfPnt(1,vertices.Extent()); 35 | 36 | for(Standard_Integer i = 1;i<=vertices.Extent();i++) 37 | { 38 | TopoDS_Vertex vertex = TopoDS::Vertex(vertices.FindKey(i)); 39 | gp_Pnt currentGeometricPoint = BRep_Tool::Pnt(vertex); 40 | result->SetValue(i,currentGeometricPoint); 41 | } 42 | 43 | return result; 44 | 45 | } 46 | 47 | TopoDS_Shape StlPointsExtractor::extractManifoldBoundaries(const TopoDS_Shape& shape) 48 | { 49 | //For every edge in the triangulation, we pick those that have only one parent face 50 | //We will store the resulting edges in boundaryEdges 51 | TopTools_ListOfShape boundaryEdges; 52 | TopExp_Explorer explorer; 53 | 54 | TopTools_IndexedDataMapOfShapeListOfShape mapOfEdges; 55 | TopExp::MapShapesAndAncestors(shape,TopAbs_EDGE,TopAbs_FACE,mapOfEdges); 56 | std::cout << mapOfEdges.Extent() << " edges found in STL file" << std::endl; 57 | 58 | std::cout << "Extracting manifold edges " << std::endl; 59 | for(explorer.Init(shape,TopAbs_EDGE,TopAbs_SHAPE);explorer.More();explorer.Next()) 60 | { 61 | TopoDS_Edge currentEdge = TopoDS::Edge(explorer.Current()); 62 | const TopTools_ListOfShape& parentsOfCurrentEdge = mapOfEdges.FindFromKey(currentEdge); 63 | if(parentsOfCurrentEdge.Extent() == 1) 64 | { 65 | boundaryEdges.Append(currentEdge); 66 | } 67 | } 68 | 69 | std::cout << "Found " << boundaryEdges.Extent() << " boundary edges." << std::endl; 70 | 71 | TopoDS_Compound collectorOfEdges; 72 | TopoDS_Builder builder; 73 | builder.MakeCompound(collectorOfEdges); 74 | 75 | for(TopTools_ListIteratorOfListOfShape it( boundaryEdges );it.More();it.Next()) 76 | { 77 | builder.Add(collectorOfEdges,it.Value()); 78 | } 79 | 80 | return collectorOfEdges; 81 | 82 | } 83 | -------------------------------------------------------------------------------- /OtherExamples/tests/StlPointsExtractor_test.cpp: -------------------------------------------------------------------------------- 1 | //OpenCASCADE tutorial by Laszlo Kudela 2 | //December 2015 3 | 4 | #include "../inc/StlPointsExtractor.hpp" 5 | 6 | #include "Utilities/inc/catch.hpp" 7 | #include "Utilities/inc/constants.hpp" 8 | 9 | #include "TColgp_HArray1OfPnt.hxx" 10 | #include "BRepPrimAPI_MakeBox.hxx" 11 | #include "TopoDS_Shape.hxx" 12 | 13 | TEST_CASE("CheckNumberOfPoints","[StlPointsExtractor]") 14 | { 15 | //Create a simple box 16 | BRepPrimAPI_MakeBox boxMaker(10.0,20.0,30.0); 17 | TopoDS_Shape boxShape = boxMaker.Solid(); 18 | 19 | Handle_TColgp_HArray1OfPnt extractedPoints = StlPointsExtractor::extractVerticesFromTopoDSShape(boxShape); 20 | 21 | REQUIRE(extractedPoints->Length() == 8); 22 | } 23 | 24 | TEST_CASE("CheckPointLocations","[StlPointsExtractor]") 25 | { 26 | //Create a simple box 27 | BRepPrimAPI_MakeBox boxMaker(10.0,20.0,30.0); 28 | TopoDS_Shape boxShape = boxMaker.Solid(); 29 | 30 | Handle_TColgp_HArray1OfPnt extractedPoints = StlPointsExtractor::extractVerticesFromTopoDSShape(boxShape); 31 | 32 | gp_Pnt point = extractedPoints->Value(1); 33 | 34 | REQUIRE(point.X() == Approx(0.0).epsilon(1E-12)); 35 | REQUIRE(point.Y() == Approx(0.0).epsilon(1E-12)); 36 | REQUIRE(point.Z() == Approx(30.0).epsilon(1E-12)); 37 | 38 | point = extractedPoints->Value(2); 39 | REQUIRE(point.X() == Approx(0.0).epsilon(1E-12)); 40 | REQUIRE(point.Y() == Approx(0.0).epsilon(1E-12)); 41 | REQUIRE(point.Z() == Approx(0.0).epsilon(1E-12)); 42 | 43 | point = extractedPoints->Value(7); 44 | REQUIRE(point.X() == Approx(10.0).epsilon(1E-12)); 45 | REQUIRE(point.Y() == Approx(20.0).epsilon(1E-12)); 46 | REQUIRE(point.Z() == Approx(30.0).epsilon(1E-12)); 47 | 48 | } 49 | 50 | -------------------------------------------------------------------------------- /OtherExamples/tests/main_test.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "Utilities/inc/catch.hpp" 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OccTutorial 2 | [![Build Status](https://travis-ci.org/lvk88/OccTutorial.svg?branch=master)](https://travis-ci.org/lvk88/OccTutorial) 3 | 4 | This repository contains a set of tutorials for OpenCASCADE, the open source geometry kernel. 5 | You can read more about OpenCASCADE at http://www.opencascade.org. This series consists of chapters, 6 | each chapter demonstrating a small set of features offered by OpenCASCADE. Make sure you also follow 7 | the [blog](https://occtutorials.wordpress.com) where the discussions of each example is published. 8 | 9 | ## Where to start. 10 | If you are familiar with using CMAKE, GIT, and generally with building and compiling, proceed to the "Quick start" section. If you need a detailed explanation 11 | on how to check out the code, set up an IDE and build the first example, please go to [the setup section](https://github.com/lvk88/OccTutorial/wiki/Setup) in the Wiki. 12 | 13 | ## Quick start 14 | The tutorials are being written and tested in Ubuntu 15.10. For the quickest start, it is therefore recommended to follow the tutorials using Ubuntu. 15 | 16 | ### What if I am a Windows user? 17 | The quick and easy way would be to install an Ubuntu OS inside a Virtualbox on your Windows, e.g. following [this guide.](http://www.psychocats.net/ubuntu/virtualbox) This would give you access to a fully functioning Ubuntu operating system. Make sure you also [install the guest additions](http://askubuntu.com/questions/22743/how-do-i-install-guest-additions-in-a-virtualbox-vm), so that you will have access to 3D acceleration. 18 | 19 | ## Install OpenCASCADE 20 | Install OpenCASCADE using your the package manager of your Linux distribution. For example, on Ubuntu: 21 |
22 | sudo apt-get install liboce-*
23 | 
24 | To be able to visualize the geometric models in the earlier chapters, it is also recommended to install FreeCAD: 25 |
26 | sudo apt-get install freecad
27 | 
28 | 29 | ## Download the tutorial sources 30 | Make a folder for the tutorial sources, e.g. in your home folder 31 |
32 | cd ~
33 | mkdir occtutorial
34 | mkdir occtutorial/sources
35 | 
36 | Then, clone the repository from GIT: 37 |
38 | cd ~/occtutorial/sources
39 | git clone https://github.com/lvk88/OccTutorial.git
40 | 
41 | This will create ~/occtutorial/sources/OccTutorial. 42 | 43 | ##Build the tutorial 44 | The build system is based on CMAKE, and we are aiming for an out-of-source build. Therefore, we make a build folder: 45 |
46 | mkdir ~/occtutorial/build
47 | 
48 | Next, we run CMAKE to generate us the Makefiles: 49 |
50 | cd ~/occtutorial/build/
51 | cmake ~/occtutorial/sources/OccTutorial
52 | 
53 | If everything went without error, we can build the tutorials: 54 |
55 | cd ~/occtutorial/build
56 | make
57 | 
58 | This will build the tutorials into build/bin directory. Each executable represents a small example of OpenCASCADE functionality. 59 | ##Run the first demonstrative example 60 | Now that the tutorials are built, you can run the first demonstrative example. 61 |
62 | cd ~/occtutorial/build/bin
63 | ./chapter0
64 | 
65 | This will create a simple box with a cylindrical hole, and print out some of its physical properties. The source of this can be found in 66 | source/OccTutorial/Chapter0_Test/chapter0.cpp. It also creates an output file of the geometry in STEP format. You can open and examine it 67 | using FreeCad for example. The file is located in build/bin/boxWitHole.stp 68 | 69 | ##How are the tutorials organized 70 | The series is organized into Chapters, with each chapter focusing on one or two packages of OpenCASCADE. With the exception of Chapter0, every chapter 71 | consists of an "inc", "src", and "runners" folder. Obviously, inc contains the headers for the given chapter, src the source files. Runners is a special 72 | folder, which contains a set of driver files, each having its own main function. When building OccTutorials, the executable output will be compiled into 73 | @build/bin@ 74 | 75 | ## Where to go now? 76 | The tutorials are strongly under construction right now, but a detailed explanation of each source will be available at the [blog](https://occtutorials.wordpress.com) 77 | soon. Until then, the comments in the files explain more or less what each example is doing. 78 | -------------------------------------------------------------------------------- /Utilities/inc/constants.hpp: -------------------------------------------------------------------------------- 1 | #ifndef UTILITIES_CONSTANTS_HPP 2 | #define UTILITIES_CONSTANTS_HPP 3 | 4 | const double PI = 3.1415926535897; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /cmake/CreateExecutable.cmake: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 2 | 3 | function(CreateExecutable EXECUTABLESOURCE) 4 | 5 | get_filename_component(EXECUTABLEBINARY ${EXECUTABLESOURCE} NAME_WE) 6 | 7 | add_executable(${EXECUTABLEBINARY} ${EXECUTABLESOURCE}) 8 | target_link_libraries(${EXECUTABLEBINARY} ${ARGN}) 9 | 10 | endfunction(CreateExecutable) 11 | -------------------------------------------------------------------------------- /cmake/CreateLibrary.cmake: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 2 | 3 | macro(CreateLibrary) 4 | 5 | FILE(GLOB HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/inc/*.hpp") 6 | FILE(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") 7 | 8 | ADD_LIBRARY(${PROJECT_NAME} ${SOURCES} ${HEADERS}) 9 | TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${ARGN}) 10 | 11 | endmacro(CreateLibrary) 12 | --------------------------------------------------------------------------------