Converting vector of TopoDS_Solid to vector of TopoDS_Shape in OpenCASCADE

OCCUtils provides Shapes::FromSolids  to convert a std::vector<TopoDS_Solid> to a std::vector<TopoDS_Shape> in OpenCASCADE:

#include <occutils/Shape.hxx>

using namespace OCCUtils;

std::vector<TopoDS_Solid> solids = /* ... */;
std::vector<TopoDS_Shape> shapes = Shapes::FromSolids(solids);

In case you need to do it manually without using OCCUtils, use this snippet:

#include <algorithm>

// Create return vector
std::vector<TopoDS_Shape> shapes;
shapes.reserve(solids.size());
// Do the copying
std::copy(solids.begin(), solids.end(), std::back_inserter(shapes));

 

Posted by Uli Köhler in OpenCASCADE

Python subprocess.check_output(): Set working directory

If you have code that uses subprocess.check_output() to call a command like

subprocess.check_output("ls .", shell=True)

you can use the cwd=... argument of subprocess.check_output() to define the working directory. Example:

subprocess.check_output("ls .", cwd="../", shell=True)

cwd means change working directory and is interpreted relative to the current working directory. However, you can also use absolute paths:

subprocess.check_output("ls .", cwd="/etc/", shell=True)

 

Posted by Uli Köhler in Python

Minimal nginx WebSocket reverse-proxy example

If you have a nginx config clause like

location /app/ {
    proxy_pass http://app-server;
}

you can easily make it reverse-proxy Websocket connections as well by adding these clauses inside location { ... }:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";

Full example:

location /app/ {
    proxy_pass http://app-server;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
}

 

Posted by Uli Köhler in nginx

Minimal local nginx setup using Docker

If you have not installed Docker, see our guide at How to install docker and docker-compose on Ubuntu in 30 seconds

1. Create your nginx config file (my-nginx.conf). This is a template that reverse proxys TechOverflow:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    location / {
        proxy_pass https://techoverflow.net;
        proxy_http_version 1.1;
    }
}

3. Start nginx using docker:

docker run -it -p 80:80 --rm -v $(pwd)/my-nginx.conf:/etc/nginx/conf.d/default.conf nginx:latest

4. Go to http://localhost and see the result!

Explanation of the docker command:

  • docker run -it: Create a new docker container and run it in interactive mode (i.e. it will not run in the background, once you kill the command, nginx will exit)
  • -p 80:80: Makes port 80 of the nginx server (the standard HTTP port) available on the host’s port 80. The first 80 is the host port whereas the second port 80 is the container’s port.
  • --rm: Once the container is stopped, delete it!
  • -v $(pwd)/my-nginx.conf:/etc/nginx/conf.d/default.conf: Map my-nginx.conf in the current directory ($(pwd)) to /etc/nginx/conf.d/default.conf on the container.
  • nginx:latest: In the container run the official nginx image from DockerHub in the latest version.

Explanation of the nginx config file:

  • server { ... }: Everything inside this blog will belong together. You can
  • listen 80 default_server; Listen on port 80 (the standard HTTP port) and make this the default server, i.e. respond to any domain name that does not have any other server configured.
  • listen [::]:80 default_server; Same as the previous line, but for IPv6. [::] means: Listen on all IPv6 addresses.
  • location / { ... }: Everything inside this block is valid for any URL starting with / i.e. any URL at all. In clauses like location /app { ... } the content of the clause would be valid for URLs starting with /app only, e.g. http://localhost/app/ or http://localhost/app/dashboard.
  • proxy_pass https://techoverflow.net; Redirect requests to the current location (/) to the server https://techoverflow.net using a reverse proxy.
  • proxy_http_version 1.1; This sets the HTTP version that nginx uses to make the requests to https://techoverflow.net. This is not always neccessary but might increase compatibility.
Posted by Uli Köhler in Docker, nginx

Python bottle minimal redirect example

To redirect in bottle, use this snippet:

response.status = 303
response.set_header('Location', 'https://techoverflow.net')

303 is the HTTP response code See Other. In certain applications you might want to use 301 (permanent redirect) or 307 (temporary redirect) instead.

Full example:

#!/usr/bin/env python3
from bottle import route, run, response

@route('/')
def redirect():
    response.status = 303
    response.set_header('Location', 'https://techoverflow.net')

run(host='localhost', port=9000)

 

Posted by Uli Köhler in Python

Python bottle minimal example

Minimal hello world-like example using the bottle HTTP server:

#!/usr/bin/env python3
from bottle import route, run

@route('/')
def index():
    return "Hello bottle!"

run(host='localhost', port=9000)

Run this file (and keep it running) and then navigate to http://localhost:9000 to see the Hello bottle! message.

In case you see this error message:

Traceback (most recent call last):
  File "./server.py", line 2, in <module>
    from bottle import route, run
ModuleNotFoundError: No module named 'bottle'

you need to install bottle using

sudo pip3 install bottle

or

sudo pip install bottle

depending on which Python version and configuration you use.

Posted by Uli Köhler in Python

Octave: Use ‘qt’ graphics_toolkit() if available, ‘gnuplot’ else

This code uses the "qt" graphics toolkit only if available and defaults to using "gnuplot" else:

gts = available_graphics_toolkits()
qt_available = any(strcmp(gts, 'qt'))
if qt_available
  graphics_toolkit("qt")
else
  graphics_toolkit("gnuplot")
endif

See Octave: Check if cell array of strings contains string for details on how to check if a string like "qt" is in a cell array of strings like the one returned by available_graphics_toolkits().

Posted by Uli Köhler in Octave

Octave: Check if cell array of strings contains string

If you have a cell array of strings in Octave like this:

arr = {"a", "bc", "def"}

you can check if it contains a specific string like "a" using

contains_a = any(strcmp(arr, 'a'))

Example:

arr = {"a", "bc", "def"}

contains_a = any(strcmp(arr, 'a'))
contains_x = any(strcmp(arr, 'x'))

disp(contains_a) # 1
disp(contains_x) # 0

 

Posted by Uli Köhler in Octave

Octave equivalent to Python’s print

In Python you can use print:

print("foobar")

whereas in Octave you can use disp:

disp("foobar")

You can print numbers using print in Python:

x = 1
print(x)

and also using disp in Octave:

x = 1
disp(x)

Note that you can use multiple argument to print in Python:

x = 1
print("The value of x is", x)

whereas in Octave you need to use disp together with cstrcat:

disp(cstrcat("The value of x is ", num2str(x)))

 

Posted by Uli Köhler in Octave

How to check if file access time is enabled on Windows

Open a command prompt (no admin command prompt required) and run this command:

fsutil behavior query disablelastaccess

For me, this prints

DisableLastAccess = 3  (Systemverwaltet, aktiviert)

indicating that access timestamps are activated.

Posted by Uli Köhler in Windows

Computing distance between gp_Pnt and gp_Ax1 in OpenCASCADE

OCCUtils provides convenience functions for computing the orthogonal direction to two directions:

#include <occutils/Axis.hxx>
using namespace OCCUtils;

gp_Ax1 axis = /* ... */;
gp_Pnt pnt = /* ... */;
double distance = Axis::Distance(axis, pnt);

Alternatively, you can also use Point::Distance() which internally just calls Axis::Distance() but might make your code more readable under some circumstances. Note that the argument order is inverted!

#include <occutils/Point.hxx>
using namespace OCCUtils;

gp_Ax1 axis = /* ... */;
gp_Pnt pnt = /* ... */;
double distance = Point::Distance(pnt, axis);

In case you can’t use OCCUtils, here’s the code to do it manually:

double distance = gp_Lin(axis).Distance(pnt);
Posted by Uli Köhler in C/C++, OpenCASCADE

How to check if gp_Ax1 contains gp_Pnt in OpenCASCADE

OCCUtils provides convenience functions for computing the orthogonal direction to two directions:

#include <occutils/Axis.hxx>
using namespace OCCUtils;

gp_Ax1 axis = /* ... */;
gp_Png point = /* ... */;
bool pointIsOnAxis = Axis::Contains(axis, point);

In case you can’t use OCCUtils, here’s the code to do it manually:

gp_Lin(axis).Contains(pnt, Precision::Confusion());
Posted by Uli Köhler in C/C++, OpenCASCADE

How to get gp_Dir orthogonal to two gp_Dirs in OpenCASCADE

OCCUtils provides convenience functions for computing the orthogonal direction to two directions:

#include <occutils/Direction.hxx>
using namespace OCCUtils;

gp_Dir dir1 = /* ... */;
gp_Dir dir2 = /* ... */;
gp_Dir orthogonalDirection = Direction::Orthogonal(dir1, dir2);

In case you can’t use OCCUtils, here’s the code to do it manually:

gp_Dir orthogonalDirection = dir1.Crossed(dir2);

The function used is called Crossed() since the mathematical operation being used is the cross product between the two direction vectors.

 

Posted by Uli Köhler in C/C++, OpenCASCADE

How to get midpoint/center between points in OpenCASCADE

OCCUtils provides convenience functions for getting the midpoint (also called the center) between 2 or more points:

#include <occutils/Point.hxx>
using namespace OCCUtils;

gp_Pnt p1 = /* ... */;
gp_Pnt p2 = /* ... */;
gp_Pnt midpointOfP1AndP2 = Point::Midpoint({p1, p2});

You can also call Point::Midpoint() with a std::vector<gp_Pnt>.

In case you can’t use OCCUtils, here’s the code to do it manually:

double x = 0.0, y = 0.0, z = 0.0;
for (const gp_Pnt &pnt : points) {
    x += pnt.X();
    y += pnt.Y();
    z += pnt.Z();
}
size_t size = points.size();
gp_Pnt midpoint(x / size, y / size, z / size);

 

 

Posted by Uli Köhler in C/C++, OpenCASCADE

How to compute volume of TopoDS_Shape / TopoDS_Solid in OpenCASCADE

OCCUtils provides a convenience function to do this:

#include <occutils/Shape.hxx>

using namespace OCCUtils;

TopoDS_Shape myShape = /* ... */;

double volume = Shape::Volume(myShape);

In case you need to do this without OCCUtils, use

GProp_GProps gprops;
BRepGProp::VolumeProperties(shape, gprops);
double volume = gprops.Mass();

 

Posted by Uli Köhler in C/C++, OpenCASCADE

Towards a docker-based build of C/C++ applications

Note: Based on this post I have published buildock on GitHub.

Many C/C++ programmers and project managers know the pain of creating a reproducible build environment for all developers: Works for me is a common meme not without a reason.

My approach is to dockerize not neccessarily the application itself but the build system, encapsulating both the specific compiler version and the system around it plus all required system-level libraries in a Docker image.

Take the obligatory Hello World in C++:

// main.cpp
#include <iostream>
using namespace std;

int main() {
    cout << "Hello, World!" << endl;
    return 0;
}

and the corresponding Makefile:

all:
        g++ -o helloworld main.cpp

How can we compile this simple project without installing a compiler and GNU make on the local computer (no cheating by using build servers allowed)?

Actually it’s rather simple:

docker run --user $(id -u):$(id -g) -v $PWD:/app -it ulikoehler/ubuntu-gcc-make make

Breaking it down:

  • docker run: Create a new docker container and run a command in it
  • --user $(id -u):$(id -g): This makes the docker container run with the current user’s ID and the current user’s group – both for preventing the compiler to create output files as root and to safeguard against some IT security risks. Also see How to run docker container as current user & group
  • -v $PWD:/app: Mount the current directory ($PWD) on /app in the container. Since the Dockerfile used to build the container contains the WORKDIR /app directive, whatever command we run in the container will by default be executed in the /app directory – and therefore in the current local directory on the host.
  • -it runs the container in interactive mode, i.e. keypressed are passed down to the command you are running. Also, this means that our command will only finish when the container has finished executing.
  • ulikoehler/ubuntu-gcc-make: This is the image we’re using for that example. It’s nothing more than an ubuntu:18.04 base image with build-essentials and make installed and WORKDIR set to /app
  • make: This is the command we’ll run in the container. You can use any command here, even no command is possible (in which case the container’s default command will be used – in case of ulikoehler/ubuntu-gcc-make that is CMD [ "/usr/bin/make" ])

Here’s the complete Dockerfile used to generate ulikoehler/ubuntu-gcc-make:

FROM ubuntu:18.04
RUN apt update && apt -y install build-essential make && rm -rf /var/lib/apt/lists/*
WORKDIR /app
CMD [ "/usr/bin/make" ]
Posted by Uli Köhler in Build systems, C/C++, Container, Docker

How to have multiple Dockerfiles in one directory

Usually you build a docker image like

docker build -t myimagename .

but using this method you can only have one Dockerfile in each directory.

In case you don’t want to have separate directories for your Dockerfiles you can use the -f argument to docker build:

docker build -f FirstDockerfile .

Note that you still need to add . at the end so docker build knows where to COPY files from if you have COPY or similar statements in your Dockerfile.

Posted by Uli Köhler in Docker