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

How to run docker container as current user & group

If you want to prevent your docker container creating files as root, use

--user $(id -u):$(id -g)

as an argument to docker run. Example:

docker run --user $(id -u):$(id -g) -it -v $(pwd):/app myimage

 

Posted by Uli Köhler in Container, Docker, Linux

How to compute surface normal in OpenCASCADE

OCCUtils provides a convenient utility to compute the Normal of a surface (represented by a GeomAdaptor_Surface) in OpenCASCADE:

#include <occutils/Surface.hxx>

using namespace OCCUtils;

GeomAdaptor_Surface surf = /* ... */;

gp_Ax1 surfaceNormal = Surface::Normal(surf);

// ...or just get the direction
gp_Dir surfaceDirection = Surface::NormalDirection(surf);

This function computes the normal vector at specific U/V coordinates which default to (0,0). You can also give custom U/V coordinates:

gp_Ax1 normal = Surface::Normal(surf, 1.0 /* u */, -4.5 /* v */);

In case you can’t use OCCUtils and you need to do it manually, here’s how you can do it:

#include <GeomLProp_SLProps.hxx>

GeomLProp_SLProps props(surf.Surface(), u, v, 1 /* max 1 derivation */, precision);
gp_Ax1 axis(props.Value(), props.Normal());

props.Value() returns the point on the surface at the given U/V coordinates.

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

How to fix mongorestore ‘E11000 duplicate key error collection’

Problem:

You are trying to run mongorestore my-backup, but you see large numbers of warning messages like this one:

- E11000 duplicate key error collection: mydb.mycollection index: _id_ dup key: { : "MyKey" }

Solution:

By default, mongorestore does not overwrite or delete any existing documents. You need to tell it to drop each collection immediately before importing it from the backup:

mongorestore --drop my-backup

Any documents not in the backup will be permanently lost after running this!

Note that this will not drop collections that are not present in the backup.

Also see mongodump/mongorestore minimal examples

Posted by Uli Köhler in Databases