Friday, January 31, 2025

Connecting C++ to Python using Boost.Python...


Gyan.... Knowledge...Wisdom... my wife Reema reciting her own poem...

So here we go...

 Boost.Python is a powerful library that enables seamless integration between C++ and Python. It allows C++ functions and classes to be exposed to Python, enabling direct interaction between the two languages.

As I was playing around with Boost.Python, I made my existing Factory Pattern project written in C++ to expose itself to the python using Boost.Python library.

The most important part is the following lines of code. This is kind of self explanatory - how we expose the C++ classes and methods to Python code.

// Expose Singleton Factory to Python

BOOST_PYTHON_MODULE(FactoryPattern) {

using namespace boost::python;


class_<Food, boost::noncopyable>("Food", no_init)

.def("getName", pure_virtual(&Food::getName));


class_<Biscuit, bases<Food>>("Biscuit")

.def("getName", &Biscuit::getName); // Ensure Biscuit has getName


class_<Chocolate, bases<Food>>("Chocolate")

.def("getName", &Chocolate::getName); // Ensure Chocolate has getName


class_<Factory, boost::noncopyable>("Factory", no_init)

.def("getInstance", &Factory::getInstance, return_value_policy<reference_existing_object>())

.staticmethod("getInstance")

.def("makeFood", &Factory::makeFood, return_value_policy<manage_new_object>());

}

Here's the complete source code of the C++ Factory Pattern... We will have to make a shared object (so) from this C++ project.

/*

* Food.h

*

* Created on: Mar 10, 2021

* Author: som

*/


#ifndef FOOD_H_

#define FOOD_H_

#include <string>


using namespace std;


class Food {

public:

virtual string getName() = 0;


virtual ~Food(){


}

};



#endif /* FOOD_H_ */




/*

* Chocolate.h

*

* Created on: Mar 10, 2021

* Author: som

*/


#ifndef CHOCOLATE_H_

#define CHOCOLATE_H_


#include <iostream>

#include "Food.h"


class Chocolate: public Food {

public:

Chocolate();

virtual ~Chocolate();

string getName();

};



#endif /* CHOCOLATE_H_ */




/*

* Chocolate.cpp

*

* Created on: Mar 10, 2021

* Author: som

*/


#include "Chocolate.h"



Chocolate::Chocolate() {

// TODO Auto-generated constructor stub

cout<<"Chocolate is made..."<<endl;


}


Chocolate::~Chocolate() {

// TODO Auto-generated destructor stub

}


string Chocolate::getName(){

return "It's a Chocolate";

}



/*

* Biscuit.h

*

* Created on: Mar 10, 2021

* Author: som

*/


#ifndef BISCUIT_H_

#define BISCUIT_H_


#include "Food.h"


class Biscuit: public Food {

public:

Biscuit();

string getName();

~Biscuit();

};


#endif /* BISCUIT_H_ */



/*

* Biscuit.cpp

*

* Created on: Mar 10, 2021

* Author: som

*/

#include <iostream>

#include "Biscuit.h"

using namespace std;



Biscuit::Biscuit() {

// TODO Auto-generated constructor stub

cout<<"Biscuit is made..."<<endl;


}


Biscuit::~Biscuit(){}



string Biscuit::getName(){

return "It's a Biscuit";

}




/*

* Factory.h

*

* Created on: Mar 10, 2021

* Author: som

*/


#ifndef FACTORY_H_

#define FACTORY_H_


#include <boost/python.hpp>

#include <iostream>

#include <string>


#include "Biscuit.h"

#include "Chocolate.h"


using namespace std;


class Factory{

public:

static Factory* instance;

static Factory* getInstance();


Food* makeFood(const string& type);


private:

Factory(){}


// Delete copy constructor & assignment operator (Singleton pattern)

Factory(const Factory&) = delete;

Factory& operator=(const Factory&) = delete;

};




#endif /* FACTORY_H_ */




/*

* Factory.cpp

*

* Created on: Jan 30, 2025

* Author: som

*/

#include "Factory.h"

Factory* Factory::instance = NULL;


Factory* Factory:: getInstance(){

if(Factory::instance == NULL){

Factory::instance = new Factory();

}

return Factory::instance;

}


Food* Factory::makeFood(const string& type){

if(type.compare("bi") == 0){

return new Biscuit();

}

if(type.compare("ch") == 0){

return new Chocolate();

}


return NULL;

}


// Expose Singleton Factory to Python

BOOST_PYTHON_MODULE(FactoryPattern) {

using namespace boost::python;


class_<Food, boost::noncopyable>("Food", no_init)

.def("getName", pure_virtual(&Food::getName));


class_<Biscuit, bases<Food>>("Biscuit")

.def("getName", &Biscuit::getName); // Ensure Biscuit has getName


class_<Chocolate, bases<Food>>("Chocolate")

.def("getName", &Chocolate::getName); // Ensure Chocolate has getName


class_<Factory, boost::noncopyable>("Factory", no_init)

.def("getInstance", &Factory::getInstance, return_value_policy<reference_existing_object>())

.staticmethod("getInstance")

.def("makeFood", &Factory::makeFood, return_value_policy<manage_new_object>());

}


Here's the project settings for the C++ code...








And here's the python script to access the C++ methods.


import FactoryPattern

factory = FactoryPattern.Factory.getInstance()

biscuit = factory.makeFood("bi")
print(biscuit.getName()) # Expected: "Biscuit"

chocolate = factory.makeFood("ch")
print(chocolate.getName()) # Expected: "Chocolate"


Here's a short video showing the output in a Python workspace...



Jai Hind... Jai Bharat...

By the way... there is another way to connect your Python code

to C++ - that is SWIG...


I explored SWIG sometimes back.


Here we go...



Thursday, January 30, 2025

Fluid Simulation and its importance for a career in Computer Graphics -- my exploration continues...

 Fluid simulation is a key area in computer graphics that models the motion and behavior of liquids, gases, and other fluid-like substances. It is highly valuable for careers in VFX, game development, animation, and scientific visualization.

What is Fluid Simulation?

Fluid simulation is the process of using numerical methods to approximate the behavior of liquids and gases. There are two main approaches:

  1. Grid-Based (Eulerian) Simulation

    • Uses a fixed 3D grid (voxels) to store velocity, pressure, and density.
    • Common in smoke, fire, and large-scale water simulations.
    • Examples: Navier-Stokes solvers, Mantaflow, OpenVDB
  2. Particle-Based (Lagrangian) Simulation

    • Uses particles that move with the fluid.
    • Ideal for splashes, droplets, and foam.
    • Examples: SPH (Smoothed Particle Hydrodynamics), FLIP, PIC
  3. Hybrid Methods

    • Combines both grid-based and particle-based approaches
    • Used in high-quality liquid simulations for films and games.
    • Example: FLIP fluids (used in Houdini, Blender Mantaflow)

Why is Fluid Simulation Important for a Career in Computer Graphics?

1️⃣ VFX & Animation Industry 🎬

  • Used in Hollywood movies for realistic water, explosions, and smoke.
  • Example: Houdini's FLIP & Pyro Solver (used in Marvel movies, Pixar, DreamWorks).
  • Tools to Learn: Houdini, Blender Mantaflow, Maya Bifrost, RealFlow

2️⃣ Game Development 🎼

  • Fluid physics makes games more immersive.
  • Used for realistic water, blood splatter, fog, and lava.
  • Example: Unreal Engine Niagara, Unity Visual Effects Graph, NVIDIA Flex
  • Tools to Learn: Unity, Unreal Engine, Frostbite (EA), CryEngine

3️⃣ CAD, Engineering & Scientific Simulations 🏗️

  • Simulations for aerodynamics, weather forecasting, and biomedical applications.
  • Example: CFD (Computational Fluid Dynamics) for car designs (used in F1, Tesla).
  • Tools to Learn: OpenFOAM, ANSYS Fluent, SimScale

4️⃣ Machine Learning & AI in Fluid Simulation đŸ€–

  • AI can speed up simulations using deep learning (e.g., Neural Fluid Simulation).
  • Example: Google’s AI FluidNet, NVIDIA's AI-driven smoke & fire simulation
  • Tools to Learn: PyTorch, TensorFlow, Taichi, JAX, CUDA

How to Get Started?

1️⃣ Learn the Basics

  • Study Navier-Stokes equations and basic physics behind fluids.
  • Try JavaFX or Python (Mantaflow, OpenFOAM) to experiment.

2️⃣ Experiment with Simulation Tools

  • Blender Mantaflow (Beginner)
  • Houdini (Professional VFX)
  • Unity/Unreal Engine (Game fluids)
  • OpenFOAM/ANSYS (Scientific applications)

3️⃣ Develop Your Own Fluid Simulation Algorithms

  • Try coding FLIP/SPH algorithms in Java, C++, or Python.
  • Learn GPU acceleration (CUDA, OpenCL, Vulkan) to optimize performance.

4️⃣ Specialize in a Field

  • Movies/VFX? → Learn Houdini, RealFlow, Blender
  • Games? → Learn Unity, Unreal Engine, NVIDIA Flex
  • Scientific Simulation? → Learn OpenFOAM, CFD, Python ML for fluids
Here's my exploration of openFOAM....

Enjoy...

Jai Hind...

Tuesday, January 28, 2025

B-Spline curve in Javafx...

 A B-spline (Basis Spline) is a type of smooth, piecewise-defined curve commonly used in computer graphics, computer-aided design (CAD), and other computational fields. It generalizes BĂ©zier curves by providing greater flexibility and control over the shape of the curve while maintaining important mathematical properties like smoothness and continuity.


Key Properties of B-Splines

  1. Piecewise Polynomial:

    • A B-spline curve is defined by connecting multiple polynomial segments, ensuring a smooth transition between them.
  2. Control Points:

    • A B-spline is influenced by a set of control points. These points do not necessarily lie on the curve, but they define its general shape.
  3. Degree (Order):

    • The degree of the B-spline determines the complexity of the curve segments (linear, quadratic, cubic, etc.).
    • Higher-degree B-splines produce smoother curves.
  4. Knots:

    • A knot vector is used to divide the curve into segments and determines how the control points influence the curve. Knots can be uniform (evenly spaced) or non-uniform (custom spacing).
  5. Continuity:

    • The continuity of a B-spline curve depends on its degree and the knot vector. It ensures smooth transitions between segments (e.g., C0,C1,C2C^0, C^1, C^2 continuity).
  6. Local Control:

    • Modifying a control point affects only a portion of the curve, making B-splines highly versatile for designing complex shapes.

Mathematical Definition

A B-spline curve is defined as:

C(t)=i=0nNi,k(t)PiC(t) = \sum_{i=0}^{n} N_{i,k}(t) \mathbf{P}_i
  • Pi\mathbf{P}_i: Control points.

  • Ni,k(t)N_{i,k}(t): Basis functions of degree kk, calculated recursively using the Cox-de Boor recursion formula:

    Ni,0(t)={1if tit<ti+10otherwiseN_{i,0}(t) = \begin{cases} 1 & \text{if } t_i \leq t < t_{i+1} \\ 0 & \text{otherwise} \end{cases} Ni,k(t)=ttiti+ktiNi,k1(t)+ti+k+1tti+k+1ti+1Ni+1,k1(t)N_{i,k}(t) = \frac{t - t_i}{t_{i+k} - t_i} N_{i,k-1}(t) + \frac{t_{i+k+1} - t}{t_{i+k+1} - t_{i+1}} N_{i+1,k-1}(t)
  • tt: Parametric value in the range of the knot vector.


Applications of B-Splines

  1. CAD and CAM:

    • Used for designing and manufacturing complex surfaces and shapes.
  2. Animation:

    • Smooth interpolation of motion paths or object deformation.
  3. Data Fitting:

    • Approximate noisy data points with smooth curves.
  4. Computer Graphics:

    • Modeling free-form curves and surfaces (e.g., NURBS, a special type of B-spline).
  5. Image Processing:

    • Resampling and interpolation of image data.

Advantages of B-Splines

  • Greater flexibility than BĂ©zier curves.
  • Local control ensures efficiency in complex modeling tasks.
  • Customizable smoothness and continuity.
  • Can represent a BĂ©zier curve or polynomial curve as a special case.



And here we go... the source code of B-Spline implemented in Javafx...

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.shape.Path;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.CubicCurveTo;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.List;

public class BSplineDemo extends Application {

private final List<Circle> controlPoints = new ArrayList<>();
private final Path bSplinePath = new Path();

@Override
public void start(Stage primaryStage) {
// Create the main pane
Pane pane = new Pane();
pane.setStyle("-fx-background-color: #f4f4f4");

// Add initial control points
addControlPoint(pane, 100, 200);
addControlPoint(pane, 200, 100);
addControlPoint(pane, 300, 250);
addControlPoint(pane, 400, 150);
addControlPoint(pane, 500, 200);

// Configure the B-spline path
bSplinePath.setStroke(Color.BLACK);
bSplinePath.setStrokeWidth(2);
bSplinePath.setFill(null);

// Add path and points to the pane
pane.getChildren().add(bSplinePath);
updateBSpline();

// Create the scene
Scene scene = new Scene(pane, 600, 400);
primaryStage.setTitle("B-Spline Demo");
primaryStage.setScene(scene);
primaryStage.show();
}

// Adds a draggable control point
private void addControlPoint(Pane pane, double x, double y) {
Circle point = new Circle(x, y, 8, Color.RED);
point.setStroke(Color.BLACK);
point.setStrokeWidth(1);
point.setOnMouseDragged(event -> {
point.setCenterX(event.getX());
point.setCenterY(event.getY());
updateBSpline();
});
controlPoints.add(point);
pane.getChildren().add(point);
}

// Updates the B-spline path
private void updateBSpline() {
if (controlPoints.size() < 4) {
bSplinePath.getElements().clear(); // Clear path if not enough points
return;
}

bSplinePath.getElements().clear();

// Use the de Boor algorithm for cubic B-spline interpolation
for (int i = 1; i < controlPoints.size() - 2; i++) {
Circle p0 = controlPoints.get(i - 1);
Circle p1 = controlPoints.get(i);
Circle p2 = controlPoints.get(i + 1);
Circle p3 = controlPoints.get(i + 2);

// Define cubic curve control points
double x1 = (p0.getCenterX() + 4 * p1.getCenterX() + p2.getCenterX()) / 6;
double y1 = (p0.getCenterY() + 4 * p1.getCenterY() + p2.getCenterY()) / 6;

double x2 = (p1.getCenterX() + 4 * p2.getCenterX() + p3.getCenterX()) / 6;
double y2 = (p1.getCenterY() + 4 * p2.getCenterY() + p3.getCenterY()) / 6;

double xControl1 = (2 * p1.getCenterX() + p2.getCenterX()) / 3;
double yControl1 = (2 * p1.getCenterY() + p2.getCenterY()) / 3;

double xControl2 = (p1.getCenterX() + 2 * p2.getCenterX()) / 3;
double yControl2 = (p1.getCenterY() + 2 * p2.getCenterY()) / 3;

// First point
if (i == 1) {
bSplinePath.getElements().add(new MoveTo(x1, y1));
}

// Add cubic segment
bSplinePath.getElements().add(new CubicCurveTo(xControl1, yControl1, xControl2, yControl2, x2, y2));
}
}

public static void main(String[] args) {
launch(args);
}
}

Bezier curve revisited - an implementation using Javafx...

 Cubic BĂ©zier curves...

Four points P0, P1, P2 and P3 in the plane or in higher-dimensional space define a cubic BĂ©zier curve. The curve starts at P0 going toward P1 and arrives at P3 coming from the direction of P2. Usually, it will not pass through P1 or P2; these points are only there to provide directional information. The distance between P1 and P2 determines "how far" and "how fast" the curve moves towards P1 before turning towards P2.

Writing BPi,Pj,Pk(t) for the quadratic BĂ©zier curve defined by points PiPj, and Pk, the cubic BĂ©zier curve can be defined as an affine combination of two quadratic BĂ©zier curves:

The explicit form of the curve is:


Any series of 4 distinct points can be converted to a cubic BĂ©zier curve that goes through all 4 points in order. Given the starting and ending point of some cubic BĂ©zier curve, and the points along the curve corresponding to t = 1/3 and t = 2/3, the control points for the original BĂ©zier curve can be recovered.

Here's how it looks like - an experimentation...


And here's the source code of the experimentation (JavaFx application)...

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.CubicCurve;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class BezierCurveDemo extends Application {

@Override
public void start(Stage primaryStage) {
// Main pane
Pane pane = new Pane();

// Control points
Circle start = createControlPoint(100, 300, Color.RED); // Start point
Circle control1 = createControlPoint(200, 100, Color.BLUE); // First control point
Circle control2 = createControlPoint(400, 100, Color.BLUE); // Second control point
Circle end = createControlPoint(500, 300, Color.RED); // End point

// Lines to show the control points
Line line1 = new Line();
Line line2 = new Line();

line1.startXProperty().bind(start.centerXProperty());
line1.startYProperty().bind(start.centerYProperty());
line1.endXProperty().bind(control1.centerXProperty());
line1.endYProperty().bind(control1.centerYProperty());
line1.setStroke(Color.LIGHTGRAY);

line2.startXProperty().bind(control2.centerXProperty());
line2.startYProperty().bind(control2.centerYProperty());
line2.endXProperty().bind(end.centerXProperty());
line2.endYProperty().bind(end.centerYProperty());
line2.setStroke(Color.LIGHTGRAY);

// Bezier Curve
CubicCurve bezierCurve = new CubicCurve();
bezierCurve.setStroke(Color.BLACK);
bezierCurve.setFill(null);
bezierCurve.setStrokeWidth(2);

bezierCurve.startXProperty().bind(start.centerXProperty());
bezierCurve.startYProperty().bind(start.centerYProperty());
bezierCurve.controlX1Property().bind(control1.centerXProperty());
bezierCurve.controlY1Property().bind(control1.centerYProperty());
bezierCurve.controlX2Property().bind(control2.centerXProperty());
bezierCurve.controlY2Property().bind(control2.centerYProperty());
bezierCurve.endXProperty().bind(end.centerXProperty());
bezierCurve.endYProperty().bind(end.centerYProperty());

// Add everything to the pane
pane.getChildren().addAll(line1, line2, bezierCurve, start, control1, control2, end);

// Create scene and display
Scene scene = new Scene(pane, 600, 400);
primaryStage.setTitle("Bezier Curve Demo");
primaryStage.setScene(scene);
primaryStage.show();
}

// Helper function to create control points
private Circle createControlPoint(double x, double y, Color color) {
Circle circle = new Circle(8, color);
circle.setCenterX(x);
circle.setCenterY(y);

// Make control points draggable
circle.setOnMouseDragged(event -> {
circle.setCenterX(event.getX());
circle.setCenterY(event.getY());
});

return circle;
}

public static void main(String[] args) {
launch(args);
}
}

Sunday, January 26, 2025

Birthday gift - from a young son to his Dad...

 


The best birthday gift for a software engineer dad from his son, a budding software engineer, is a piece of software work.

It's not just lifeless code and syntaxes... 

it symbolizes the connection between the two souls, the planning and execution from the Guru, and the receptive power of the child and his capability to create something out of nothing.

It holds a lot of emotion...

It symbolizes injecting light into a soul and enlightening him, helping him acquire skills and knowledge. It symbolizes the dream of a family to see their son stand up on his own feet and rise by showing his skill to the universe.

It all started when my son was just 6 years old...

watch...



Now we are all waiting for that moment when our son will contribute to the growth story of Bharat.

Jai Hind...Jai Bharat...

Friday, January 24, 2025

Bezier Curve - my exploration of Computer Graphics goes on...

A BĂ©zier curve is a parametric curve frequently used in computer graphics and related fields to model smooth and scalable shapes. It is defined by control points, where the curve starts at the first control point and ends at the last control point. The intermediate control points influence the curvature but do not lie on the curve itself.

The mathematical representation of a BĂ©zier curve is:

are the control points.

where the polynomials

  • BĂ©zier curves are widely used in:

  • Computer-aided design (CAD).
  • Font design.
  • Animation paths.
Here's the Python script to create a simple application using freeCAD...

import FreeCAD
import FreeCADGui
import Part
from PySide2 import QtWidgets, QtCore


class BezierCurveApp(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("BĂ©zier Curve in FreeCAD")

        # UI Layout
        layout = QtWidgets.QVBoxLayout()

        # Input for control points
        self.control_points_input = QtWidgets.QTextEdit()
        self.control_points_input.setPlaceholderText(
            "Enter control points as x,y,z (one per line):\nExample:\n0,0,0\n10,15,0\n20,5,0\n30,10,0"
        )
        layout.addWidget(self.control_points_input)

        # Button to create BĂ©zier curve
        self.create_curve_btn = QtWidgets.QPushButton("Create BĂ©zier Curve")
        self.create_curve_btn.clicked.connect(self.create_bezier_curve)
        layout.addWidget(self.create_curve_btn)

        # Button to clear the workspace
        self.clear_workspace_btn = QtWidgets.QPushButton("Clear Workspace")
        self.clear_workspace_btn.clicked.connect(self.clear_workspace)
        layout.addWidget(self.clear_workspace_btn)

        self.setLayout(layout)

    def parse_control_points(self):
        """Parse control points from the input text."""
        points = []
        lines = self.control_points_input.toPlainText().strip().split("\n")
        for line in lines:
            try:
                x, y, z = map(float, line.split(","))
                points.append(FreeCAD.Vector(x, y, z))
            except ValueError:
                QtWidgets.QMessageBox.warning(self, "Invalid Input", "Invalid control point format!")
                return None
        return points

    def create_bezier_curve(self):
      """Create a BĂ©zier curve based on the input control points."""
      # Ensure an active document exists
      if not FreeCAD.ActiveDocument:
          FreeCAD.newDocument("BezierCurveDemo")
  
      points = self.parse_control_points()
      if not points:
          return
  
      if len(points) < 2:
          QtWidgets.QMessageBox.warning(self, "Invalid Input", "At least two control points are required!")
          return
  
      # Create the BĂ©zier curve
      bezier_curve = Part.BezierCurve()
      bezier_curve.setPoles(points)
      curve_object = FreeCAD.ActiveDocument.addObject("Part::Feature", "BezierCurve")
      curve_object.Shape = bezier_curve.toShape()
      FreeCAD.ActiveDocument.recompute()
  
      QtWidgets.QMessageBox.information(self, "Success", "BĂ©zier curve created!")


    def clear_workspace(self):
        """Clear all objects from the workspace."""
        if FreeCAD.ActiveDocument:
            FreeCAD.ActiveDocument.clearAllObjects()
            FreeCAD.ActiveDocument.recompute()
            QtWidgets.QMessageBox.information(self, "Workspace Cleared", "All objects have been removed.")


def show_bezier_curve_app():
    """Display the BĂ©zier Curve UI application."""
    app = BezierCurveApp()

    # Wrap the app in a QDockWidget
    dock_widget = QtWidgets.QDockWidget("BĂ©zier Curve App", FreeCADGui.getMainWindow())
    dock_widget.setWidget(app)
    FreeCADGui.getMainWindow().addDockWidget(QtCore.Qt.RightDockWidgetArea, dock_widget)


# Run the application
show_bezier_curve_app()

And here's my today's recording of Bezier curve of Computer Graphics...



And here's the experimentation of my young son Ridit using Bezier curve to animate a path of a slithering snake in Blender.



Enjoy...