Thursday, February 11, 2016

Finding the Intersection of Lines

The classical y = m*x+n line equation fails when finding intersections with vertical lines. Normally, the intersection point of two lines is found as follows:

Y = m1*x+n1 = m2*x+n2 --> x = (n2-n1)/(m1-m2)

Consider the following example, which clearly has an intersection at x = 1 and y = 0.5:

The classical equation for line AB results in m1 = infinity and n1 = -infinity, and for CD results in m2 = 0.5, n2 = 0. When you plug these values into x = (n2-n1)/(m1- m2), you get x = (0 - (-infinity)) / (infinity - 0.5) = infinity/infinity = NaN.

You could try to solve this problem using a bunch of if statements to check if a line is vertical, horizontal etc which would be prone to bugs. Or you could use parametric line equations:

Applying the above parametric formula to our example problem, we obtain the following equations:

Line1: P1 = A + (B - A) * t
Line2: P2 = C + (D - C) * u

To find the intersection point we equate P1 to P2:

A + (B - A) * t  = C + (D - C) * u.

Using scalar components:
Ax + (Bx-Ax)*t = Cx + (Dx-Cx)*u --> Ax-Cx = (Ax-Bx)*t + (Dx-Cx)*t
Ay + (By-Ay)*t = Cy + (Dy-Cy)*u --> Ay-Cy = (Ay-By)*t + (Dy-Cy)*t

Rearranging into matrix form:

| Ax-Bx, Dx-Cx | |t|  = |Ax-Cx|
| Ay-By, Dy-Cy | |u| = |Ay-Cy|

We can solve this M*TU = K system and obtain t and u values: TU = M^-1*K. t and u are -0.25 and 0.5 respectively. Finally to get intersection x,y coordinates, we can use

xIntersect = Ax + (Bx-Ax)*t
yIntersect = Ay + (By-Ay)*t

Which gives us the correct result of (1, 0.5)

An additional benefit of the parametric line equation is that it can easily be extended to three dimensional space. It is also used in calculating intersection lines with a planes.

Lesson learnt: Don't use y = m*x+n, instead use P = A + (B - A) * t

Wednesday, January 27, 2016

Basic Software Design Report

A software design report should contain as a minimum the following:
  • Definition of problem
  • Detailed description of inputs from outside and outputs to outside (definition, data type), i.e. API
  • Sequence diagram of main flow
  • Class diagram showing most important classes
  • Explanation of non-trivial algorithms

Sunday, November 08, 2015

Scrolling terrain map with wrap around

I started to work on a clone of the classic game Lunar Lander (see my GitHub repo). The reason I work on games is not that I want to be a game programmer but because there are lots of challenges that help becoming a better software developer and it is more fun coding games, i.e. it is more probable that I will keep my motivation and have a working prototype in the end.

Friday, October 09, 2015

Exception handling in Thread and SwingWorker

Exception handling in SwingWorker differs from Thread. When using a Thread if an exception is thrown inside run(), it is propagated up the chain and you can handle it outside if you want. When an exception occurs in SwingWorker.doInBackground(), you have to handle it in the done() method. The following code demonstrates this. If you delete the done() method, it will run but the exception will be lost.
/**
 * Demonstrates difference of SwingWorker and Thread when an exception occurs. In SwingWorker, if you don't catch the exception in done(), it gets lost.
 */
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("Thread.run");
            throw new IllegalArgumentException();
        }
    }).start();

    new SwingWorker() {
        @Override
        protected Object doInBackground() throws Exception {
            System.out.println("SwingWorker.doInBackground");
            if (true) {
                throw new IllegalArgumentException();
            }
            return null;
        }
        @Override
        protected void done() {
            try {
                get();
            } catch (InterruptedException e) {
                System.out.println("Caught exception: " + e);
            } catch (ExecutionException e) {
                System.out.println("Caught exception: " + e);
            }
        }
    }.execute();
}

Output:
For more information see How should I handle exceptions when using SwingWorker?

Tuesday, October 06, 2015

Less Medicine, More Health

Less Medicine, More Health was especially relevant to me because my mother (65 years old) underwent colonoscopy as part of a routine control in which the doctor removed a few polyps and one of them had cancer cells close to the colon wall. Three out of four doctors said that she must have an operation which would remove a quarter of her colon (without saying anything about the risks of the operation). Only one doctor pointed out that may be all the cancer cells were taken out during the polyp removal, the risks and probability of success of the operation (which were horrible numbers). In the end my mother reasoned that the operation was not worth it. This was 6 months ago. Today she is alive and well, tending her garden.

Almost everybody has some sort of abnormality that won't hurt him but becomes a problem due to early diagnosis, i.e. you would be better of if did not perform the checks in the first place. Lesson: Don't do full checkups, only deal with things that you have symptoms of.

It shows the importance of randomization and biases that can be overlooked when performing medical trials, for example a trial based on volunteers can be biased because health conscious individuals are healthier than the average.

Thursday, September 17, 2015

Scrolling vs. Navigating in JTabbedPane

It is possible to programatically move between the tabs of a JTabbedPane:

There are two mechanisms: Navigating and scrolling. Their difference is that navigation changes the selected tab while scrolling shifts the view but does not change the selected tab.

Monday, August 31, 2015

Working with a junior developer

When I (a senior developer) have to supervise someone new (a junior developer) - who can be a new employee or an intern - I use the following steps to get the junior up to speed without taking too much of my time:

Note how it starts with an informal discussion of the problem to be solved. I sit down with the junior, tell him what I know about the problem, draw some sketches on a white board. The critical step is to let him write a problem definition document that repeats what we have talked about. When I review the document, I can verify that the junior has understood the problem well. This pattern repeats with design and test documents. It reduces my burden of supervision (I don't have to write anything) and helps the senior to really understand - not just "hear" - the problem. And last but not least, we get good documentation. Win-win...