# ForCAD - A Fortran library for geometric modeling

**URL:** <https://fortran-lang.discourse.group/t/forcad-a-fortran-library-for-geometric-modeling/7747>\
**Category:** Announcements\
**Created:** [April 1, 2024, 6:28pm UTC](https://fortran-lang.discourse.group/t/forcad-a-fortran-library-for-geometric-modeling/7747 "2024-04-01T18:28:23Z")\
**Posts on this page:** 10\
**Page:** 2

<div class="post-metadata">

**Author:** ![Ali](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ali/32/751_2.png) [@Ali](https://fortran-lang.discourse.group/u/Ali)\
**Post date:** [May 30, 2024, 2:24pm UTC](https://fortran-lang.discourse.group/t/forcad-a-fortran-library-for-geometric-modeling/7747/21 "2024-05-30T14:24:39Z")

</div>

I am currently on vacation, so for simplicity, I will explain with a curve example:

**How to Describe a Curve?**

To describe a curve in physical space, you discretize your parametric space, which ranges from 0 to 1. These points are saved in X\_{t}. Then you map these points X\_{t} to physical space, and you can visualize your curve in physical space with coordinates X\_{g}. (For simplicity, I didn’t draw the control points X\_{c}.)

 ![Curve Example](https://global.discourse-cdn.com/free1/uploads/fortran_lang/original/2X/b/bef773378e209ef1c82a43245b804db1104ccf4b.jpeg)

If the resolution is low (i.e., the number of discrete points in parametric space X\_{t} is small), your curve will have a low resolution and appear as a set of lines. If you increase the resolution (i.e., increase the number of discrete points in parametric space \hat{X}\_{t}), you can draw your curve with more points, resulting in a better resolution \hat{X}\_{g}.

(Both curves X\_{g} and \hat{X}\_{g} are the same but drawn with different resolutions.)

**The Idea Behind `nearest_point()`:**

Now, let’s say you have a point P and you want to find the closest point on the curve. The `nearest_point()` function compares the coordinates of point P with the coordinates of X\_{gi} and finds the closest point on the curve. If your resolution is low, the accuracy of finding the closest point is reduced. If you increase the resolution, the accuracy will improve.

To call the function:

```fortran
call curve%nearest_point(P, nearest_Xg, nearest_Xt, id)

```

Here, you provide the coordinates of point P. Depending on the resolution of your curve, the `nearest_point()` subroutine finds the nearest X\_{gi} on the curve and gives the corresponding parametric coordinates X\_{ti} and the id of this point (i). For instance, in this example, for the finest curve, the id of the closest point on the curve is 2.

This is an approximated solution that depends on the discretization. It is also possible to find the exact point, but this feature is not yet implemented in ForCAD.

---

<div class="post-metadata">

**Author:** ![Rob777](https://avatars.discourse-cdn.com/v4/letter/r/9e8a1a/32.png) [@Rob777](https://fortran-lang.discourse.group/u/Rob777)\
**Post date:** [May 30, 2024, 2:49pm UTC](https://fortran-lang.discourse.group/t/forcad-a-fortran-library-for-geometric-modeling/7747/22 "2024-05-30T14:49:43Z")

</div>

Hi @Ali ,

thank you for your time dedicated to that explanation, I got that…

I don’t agree with some things you wrote, i.e. “If the resolution is low (i.e., the number of discrete points in parametric space Xt is small, your curve will have a low resolution and appear as a set of lines”.  
The point is to interpolate those points with for example a cubic spline!

Anyway for simplicity let’s say you have interpolated those given points with a cubic spline or a NURBS, so that now we can even forget about them…

I don’t see the point using Xg to find the closest point…you use Xgi only to find the NURBS representation…

By the way, I’m just saying that a realistic/engineering use case would need to find the closest point based on the NURBS description of the surface, thereby giving the closest point with an arbitrary accuracy!  
Have a look at those functions in the SISL library…it is a really good library built over the years by experts…

Have a great day

---

<div class="post-metadata">

**Author:** ![Ali](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ali/32/751_2.png) [@Ali](https://fortran-lang.discourse.group/u/Ali)\
**Post date:** [May 30, 2024, 9:34pm UTC](https://fortran-lang.discourse.group/t/forcad-a-fortran-library-for-geometric-modeling/7747/23 "2024-05-30T21:34:59Z")

</div>

> [@Rob777](#):
>
> I don’t agree with some things you wrote, for example, “If the resolution is low (i.e., the number of discrete points in parametric space Xt is small, your curve will have a low resolution and appear as a set of lines.” The point is to interpolate those points with, for example, a cubic spline!

Please take a look at the NURBS description in [The NURBS Book](https://doi.org/10.1007/978-3-642-97385-7) or [Wikipedia](https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline):  
 ![grafik](https://global.discourse-cdn.com/free1/uploads/fortran_lang/original/2X/7/7895408f6795dcd8d67f21fee80a9fbbeb593338.png)

In ForCAD, X\_{gi}(X\_{ti}) is C(u), u is X\_{ti}, and X\_c are P (As I mentioned, I didn’t draw control points in the last figure). The NURBS Basis function in ForCAD is T\_{gc} instead of R:

X\_{gi}(X\_{ti}) = T\_{gc}(X\_{ti}) \cdot X\_c

If you evaluate your curve only with three points, you get three points on the curve, as shown in the last picture. If you evaluate the curve with more points, you get a better resolution. Could you tell me which parts you don’t agree with?

---

<div class="post-metadata">

**Author:** ![Rob777](https://avatars.discourse-cdn.com/v4/letter/r/9e8a1a/32.png) [@Rob777](https://fortran-lang.discourse.group/u/Rob777)\
**Post date:** [May 30, 2024, 9:47pm UTC](https://fortran-lang.discourse.group/t/forcad-a-fortran-library-for-geometric-modeling/7747/24 "2024-05-30T21:47:23Z")

</div>

You don’t have to evaluate the curve with three points, once you have the NURBS description of a curve, you can use an (almost) arbitrary precision to evaluate the curve/surface…

---

<div class="post-metadata">

**Author:** ![Ali](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ali/32/751_2.png) [@Ali](https://fortran-lang.discourse.group/u/Ali)\
**Post date:** [May 31, 2024, 1:40am UTC](https://fortran-lang.discourse.group/t/forcad-a-fortran-library-for-geometric-modeling/7747/25 "2024-05-31T01:40:42Z")

</div>

> [@Rob777](#):
>
> You don’t have to evaluate the curve with three points

Did I mention that? No! 😉 You **don’t have to** evaluate a curve with three points. That was just an example that I could easily draw on paper to show that the number of evaluation points determines the visualized resolution of the curve.

> [@Rob777](#):
>
> You don’t have to evaluate the curve with three points, once you have the NURBS description of a curve, you can use an (almost) arbitrary precision to evaluate the curve/surface…

The precision you refer to is related to the distances between the evaluation points. This means you can specify either the number of points or the distance between each point as a measure of precision. Both approaches can achieve the same result.

---

<div class="post-metadata">

**Author:** ![Ali](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ali/32/751_2.png) [@Ali](https://fortran-lang.discourse.group/u/Ali)\
**Post date:** [June 28, 2024, 3:34pm UTC](https://fortran-lang.discourse.group/t/forcad-a-fortran-library-for-geometric-modeling/7747/26 "2024-06-28T15:34:14Z")

</div>

**v0.6.0** is released with some new features:

- Added `ansatz()` procedures to compute shape functions, derivatives of shape functions and (`dV`, `dA` and `dL`). These can be used for IGA.
- Added `nearest_point2()` to compute the nearest point on a NURBS object using optimization (Newton Method).
- Added a generic method `derivative2()` to compute the second derivative of NURBS objects.
- Added `cmp_elemFace*()` to extract element connectivity of faces.
- Added `cmp_degreeFace()` to extract the degrees of faces.
- Added `cmp_length()` to compute the length of a NURBS curve.
- Added `cmp_area()` to compute the area of a NURBS surface.
- Added `cmp_volume()` to compute the volume of a NURBS volume.
  - The `gauss_legendre()` subroutine from `stdlib` is used for integration.

Full Changelog: [CHANGELOG.md](https://github.com/gha3mi/forcad/blob/main/CHANGELOG.md)

I am considering adding a new GUI to visualize and modify NURBS objects. Would OpenGL be a good choice for this purpose? If you have any suggestions, please let me know.

---

<div class="post-metadata">

**Author:** ![aerosayan](https://avatars.discourse-cdn.com/v4/letter/a/8c91f0/32.png) [@aerosayan](https://fortran-lang.discourse.group/u/aerosayan)\
**Post date:** [June 29, 2024, 5:08pm UTC](https://fortran-lang.discourse.group/t/forcad-a-fortran-library-for-geometric-modeling/7747/27 "2024-06-29T17:08:09Z")

</div>

Amazing!

I wanted to ask a question. How do you handle errors or failable operations?

For example: In OpenCASCADE (C++ codebase), even simple operations such as chamfer, fillet, etc. would crash the code. Over the last few years, they’ve worked hard to use C++ exceptions, and handle those errors.

Since Fortran lacks a dedicated error handling system, it can become difficult.

---

<div class="post-metadata">

**Author:** ![Ali](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ali/32/751_2.png) [@Ali](https://fortran-lang.discourse.group/u/Ali)\
**Post date:** [June 30, 2024, 12:49pm UTC](https://fortran-lang.discourse.group/t/forcad-a-fortran-library-for-geometric-modeling/7747/28 "2024-06-30T12:49:26Z")

</div>

Thanks! Yes, it is difficult! For now, I use `error stop` as I mainly use pure procedures. You can see an example here: [forcad/src/forcad\_nurbs\_volume.f90 at f59ff9c058df9c68da298fa83e42bd123df35f4d · gha3mi/forcad · GitHub](https://github.com/gha3mi/forcad/blob/f59ff9c058df9c68da298fa83e42bd123df35f4d/src/forcad_nurbs_volume.f90#L554C1-L577C85).

In a next version, I plan to remove `error stop` and add an optional integer variable for status or implement a `check_status()` method. Are there any other smart solutions?

---

<div class="post-metadata">

**Author:** ![WaveHello](https://avatars.discourse-cdn.com/v4/letter/w/ac91a4/32.png) [@WaveHello](https://fortran-lang.discourse.group/u/WaveHello)\
**Post date:** [October 20, 2025, 2:05am UTC](https://fortran-lang.discourse.group/t/forcad-a-fortran-library-for-geometric-modeling/7747/29 "2025-10-20T02:05:13Z")

</div>

I came across this library: [GitHub - BerkeleyLab/assert: A library for the run-time checking of program invariants and for providing diagnostic error output inside pure procedures](https://github.com/BerkeleyLab/assert). I haven’t used it but it might be helpful.

---

<div class="post-metadata">

**Author:** ![Ali](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ali/32/751_2.png) [@Ali](https://fortran-lang.discourse.group/u/Ali)\
**Post date:** [October 20, 2025, 5:05am UTC](https://fortran-lang.discourse.group/t/forcad-a-fortran-library-for-geometric-modeling/7747/30 "2025-10-20T05:05:21Z")

</div>

Thanks @WaveHello!

In the latest version of ForCAD, I’ve added basic error and warning handling. To enable it, define the `FOR_DEBUG` preprocessor flag during compilation.

Within the derived types `nurbs_curve`, `nurbs_surface` and `nurbs_volume`, there is now an `err` component that can be displayed in certain situations using `call nurbs%err%print()`.  
It doesn’t yet cover all possible errors, but it currently detects some issues.

For example:

```fortran
program test

    use forcad, only: rk, nurbs_surface

    implicit none

    type(nurbs_surface) :: shape
    real(rk) :: Xc(4,3)
    real(rk) :: Wc(3)

    Xc(1,:) = [0.0_rk, 0.0_rk, 0.0_rk]
    Xc(2,:) = [2.0_rk, 0.0_rk, 0.0_rk]
    Xc(3,:) = [0.0_rk, 2.0_rk, 0.0_rk]
    Xc(4,:) = [2.0_rk, 2.0_rk, 0.0_rk]

    Wc = [1.0_rk, 2.0_rk, 1.0_rk]

    call shape%set(&
        knot1 = [0.0_rk, 0.0_rk, 1.0_rk, 1.0_rk], &
        knot2 = [0.0_rk, 0.0_rk, 1.0_rk, 1.0_rk], &
        Xc = Xc, &
        Wc = Wc)

    call shape%err%print()

end program

```

This produces the following output:

```bash
[E101] (set1) forcad_nurbs_surface: Weights length mismatch: size(Wc) must equal number of control points. [Provide Wc with size(Wc) == nc(1)*nc(2).]

```

[edited: README needs to be updated to include it.]

[Previous page](https://fortran-lang.discourse.group/t/forcad-a-fortran-library-for-geometric-modeling/7747.md?page=1)
