commit d586fda6a50c562cce6f5473991e95c489738dda
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Mon Dec 16 16:42:49 2019 +0000

    Dynamics App: add checking a Dynamic4D.

diff --git a/src/main/java/org/distorted/examples/dynamic/DynamicActivity.java b/src/main/java/org/distorted/examples/dynamic/DynamicActivity.java
index a96583b..421e55d 100644
--- a/src/main/java/org/distorted/examples/dynamic/DynamicActivity.java
+++ b/src/main/java/org/distorted/examples/dynamic/DynamicActivity.java
@@ -41,8 +41,8 @@ import android.widget.Toast;
 
 public class DynamicActivity extends Activity implements OnSeekBarChangeListener, AdapterView.OnItemSelectedListener
     {
-    private TextView textD, textC, textN, textX;
-    private int p0,p1,p2;
+    private TextView textDuration, textCount, textNoise, textConvexity;
+    private int mNoise0,mNoise1,mNoise2,mNoise3;
     private int mDim, mMode;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -53,12 +53,12 @@ public class DynamicActivity extends Activity implements OnSeekBarChangeListener
       super.onCreate(savedState);
       setContentView(R.layout.dynamicslayout);
 
-      textD = findViewById(R.id.dynamicTextDuration);
-      textC = findViewById(R.id.dynamicTextCount);
-      textX = findViewById(R.id.dynamicTextConvexity);
-      textN = findViewById(R.id.dynamicTextNoise);
+      textDuration = findViewById(R.id.dynamicTextDuration);
+      textCount    = findViewById(R.id.dynamicTextCount);
+      textConvexity= findViewById(R.id.dynamicTextConvexity);
+      textNoise    = findViewById(R.id.dynamicTextNoise);
 
-      p0=p1=p2=0;
+      mNoise0=mNoise1=mNoise2=mNoise3=0;
       mDim = DynamicSurfaceView.DIM_2D;
       mMode= Dynamic1D.MODE_LOOP;
 
@@ -77,7 +77,7 @@ public class DynamicActivity extends Activity implements OnSeekBarChangeListener
 
       Spinner dimensionSpinner  = findViewById(R.id.dynamicSpinnerDimension);
       dimensionSpinner.setOnItemSelectedListener(this);
-      String[] dimensions = { "Dimension 1" , "Dimension 2" , "Dimension 3 (XY)" , "Dimension 3 (XZ)" };
+      String[] dimensions = { "Dimension 1" , "Dimension 2" , "Dimension 3 (XY)" , "Dimension 3 (XZ)" , "Dimension 4 (XY)" , "Dimension 4 (ZW)" };
 
       ArrayAdapter<String> adapterDim = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, dimensions );
       adapterDim.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@@ -230,6 +230,8 @@ public class DynamicActivity extends Activity implements OnSeekBarChangeListener
           case 1: setDim(DynamicSurfaceView.DIM_2D  ); break;
           case 2: setDim(DynamicSurfaceView.DIM_3DXY); break;
           case 3: setDim(DynamicSurfaceView.DIM_3DXZ); break;
+          case 4: setDim(DynamicSurfaceView.DIM_4DXY); break;
+          case 5: setDim(DynamicSurfaceView.DIM_4DZW); break;
           }
         }
       else if( spinnerID == R.id.dynamicSpinnerMode )
@@ -281,31 +283,37 @@ public class DynamicActivity extends Activity implements OnSeekBarChangeListener
         int i = (int)(v/100);
         float t = i/10.0f;
         view.setDuration((int)v);
-        textD.setText(getString(R.string.duration_placeholder, (int)t ));
+        textDuration.setText(getString(R.string.duration_placeholder, (int)t ));
         }
       else if( id == R.id.dynamicSeekCount )
         {
         float count = progress*0.05f;
         view.setCount(count);
-        textC.setText(getString(R.string.count_placeholder, count ));
+        textCount.setText(getString(R.string.count_placeholder, count ));
         }
       else if( id == R.id.dynamicSeekConvexity )
         {
         float convexity = progress/25.0f - 1.0f;
         view.setConvexity(convexity);
-        textX.setText(getString(R.string.convexity_placeholder, convexity ));
+        textConvexity.setText(getString(R.string.convexity_placeholder, convexity ));
         }
       else
         {
         switch(id)
           {
-          case R.id.dynamicSeekNoise0  : p0 = progress; break;
-          case R.id.dynamicSeekNoise1  : p1 = progress; break;
-          case R.id.dynamicSeekNoise2  : p2 = progress; break;
+          case R.id.dynamicSeekNoise0  : mNoise0 = progress; break;
+          case R.id.dynamicSeekNoise1  : mNoise1 = progress; break;
+          case R.id.dynamicSeekNoise2  : mNoise2 = progress; break;
+          case R.id.dynamicSeekNoise3  : mNoise3 = progress; break;
           }
 
-        view.setNoise(p0/100.0f,p1/100.0f,p2/100.0f);
-        textN.setText(getString(R.string.noise2_placeholder, (p0/100.f) , (p1/100.f), (p2/100.f) ));
+        float n0 = mNoise0/100.f;
+        float n1 = mNoise1/100.f;
+        float n2 = mNoise2/100.f;
+        float n3 = mNoise3/100.f;
+
+        view.setNoise(n0,n1,n2,n3);
+        textNoise.setText(getString(R.string.noise3_placeholder, n0,n1,n2,n3 ));
         }
       }
 
diff --git a/src/main/java/org/distorted/examples/dynamic/DynamicSurfaceView.java b/src/main/java/org/distorted/examples/dynamic/DynamicSurfaceView.java
index 12bd0c1..fb028ca 100644
--- a/src/main/java/org/distorted/examples/dynamic/DynamicSurfaceView.java
+++ b/src/main/java/org/distorted/examples/dynamic/DynamicSurfaceView.java
@@ -34,9 +34,11 @@ import org.distorted.library.type.Dynamic;
 import org.distorted.library.type.Dynamic1D;
 import org.distorted.library.type.Dynamic2D;
 import org.distorted.library.type.Dynamic3D;
+import org.distorted.library.type.Dynamic4D;
 import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static3D;
+import org.distorted.library.type.Static4D;
 
 import java.lang.ref.WeakReference;
 
@@ -48,6 +50,10 @@ public class DynamicSurfaceView extends GLSurfaceView
     public static final int DIM_2D   = 1; 
     public static final int DIM_3DXY = 2; 
     public static final int DIM_3DXZ = 3; 
+    public static final int DIM_4DXY = 4;
+    public static final int DIM_4DZW = 5;
+
+    private static final int MAX_DIM = 4;
 
     static final int NUM_POINTS = 250;
     private static final Object lock = new Object();
@@ -60,13 +66,14 @@ public class DynamicSurfaceView extends GLSurfaceView
     private Dynamic1D di1D;
     private Dynamic2D di2D;
     private Dynamic3D di3D;
+    private Dynamic4D di4D;
     
     private Paint mPaint;
     private int mMoving;
     private int mDuration;
     private int mPosition;
     private long mDiffTime, mLastTime, mStartTime;
-    private float mNoise0, mNoise1, mNoise2;
+    private float[] mNoise = new float[MAX_DIM];
     private float mCount;
 
     private int mSize1, mSize2, mSizeT, mAvg;
@@ -77,12 +84,14 @@ public class DynamicSurfaceView extends GLSurfaceView
     private Static1D p1D;
     private Static2D p2D;
     private Static3D p3D;
+    private Static4D p4D;
 
     private Static1D p1N;
     private Static2D p2N;
     private Static3D p3N;
+    private Static4D p4N;
 
-    private float[] mPoints = new float[3*NUM_POINTS];
+    private float[] mPoints = new float[MAX_DIM*NUM_POINTS];
     private boolean mRunning;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -98,31 +107,32 @@ public class DynamicSurfaceView extends GLSurfaceView
       mPaint.setStyle(Style.FILL);
       mPaint.setAntiAlias(true);
 
-      mMoving = -1;
       mDuration = 10000;
       mCount    = 0.0f;
       mPosition = 0;
-      mNoise0   = 0.0f;
-      mNoise1   = 0.0f;
-      mNoise2   = 0.0f;
       mDiffTime = -1;
       mLastTime = -1;
       mStartTime= -1;
+      mMoving   = -1;
+      mRunning  = false;
 
-      mRunning = false;
+      for(int i=0; i<MAX_DIM; i++) mNoise[i] = 0.0f;
 
       clearPoints();
 
       di1D = new Dynamic1D(mDuration,mCount);
-      p1N  = new Static1D(mNoise0);
+      p1N  = new Static1D(mNoise[0]);
       di2D = new Dynamic2D(mDuration,mCount);
-      p2N  = new Static2D(mNoise0,mNoise1);
+      p2N  = new Static2D(mNoise[0],mNoise[1]);
       di3D = new Dynamic3D(mDuration,mCount);
-      p3N  = new Static3D(mNoise0,mNoise1,mNoise2);
+      p3N  = new Static3D(mNoise[0],mNoise[1],mNoise[2]);
+      di4D = new Dynamic4D(mDuration,mCount);
+      p4N  = new Static4D(mNoise[0],mNoise[1],mNoise[2],mNoise[3]);
 
       di1D.setAccessType(Dynamic.ACCESS_TYPE_SEQUENTIAL);
       di2D.setAccessType(Dynamic.ACCESS_TYPE_SEQUENTIAL);
       di3D.setAccessType(Dynamic.ACCESS_TYPE_SEQUENTIAL);
+      di4D.setAccessType(Dynamic.ACCESS_TYPE_SEQUENTIAL);
 
       if(!isInEditMode())
         {
@@ -178,6 +188,7 @@ public class DynamicSurfaceView extends GLSurfaceView
       di1D.setMode(mode);  
       di2D.setMode(mode);
       di3D.setMode(mode);
+      di4D.setMode(mode);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -189,6 +200,7 @@ public class DynamicSurfaceView extends GLSurfaceView
       di1D.setDuration(duration);
       di2D.setDuration(duration);
       di3D.setDuration(duration);
+      di4D.setDuration(duration);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -200,6 +212,7 @@ public class DynamicSurfaceView extends GLSurfaceView
       di1D.setCount(count);
       di2D.setCount(count);
       di3D.setCount(count);
+      di4D.setCount(count);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -209,23 +222,27 @@ public class DynamicSurfaceView extends GLSurfaceView
       di1D.setConvexity(convexity);
       di2D.setConvexity(convexity);
       di3D.setConvexity(convexity);
+      di4D.setConvexity(convexity);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    public void setNoise(float noise0, float noise1, float noise2)
+    public void setNoise(float noise0, float noise1, float noise2, float noise3)
       {
-      mNoise0 = noise0;
-      mNoise1 = noise1;
-      mNoise2 = noise2;
+      mNoise[0] = noise0;
+      mNoise[1] = noise1;
+      mNoise[2] = noise2;
+      mNoise[3] = noise3;
 
-      p1N.set(mNoise0);
-      p2N.set(mNoise0,mNoise1);
-      p3N.set(mNoise0,mNoise1,mNoise2);
+      p1N.set(mNoise[0]);
+      p2N.set(mNoise[0],mNoise[1]);
+      p3N.set(mNoise[0],mNoise[1],mNoise[2]);
+      p4N.set(mNoise[0],mNoise[1],mNoise[2], mNoise[3]);
 
       di1D.setNoise(p1N);
       di2D.setNoise(p2N);
       di3D.setNoise(p3N);
+      di4D.setNoise(p4N);
       }
     
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -234,7 +251,8 @@ public class DynamicSurfaceView extends GLSurfaceView
       {
       if( currentDim != dim )
         {
-        if( !(currentDim==DIM_3DXY && dim==DIM_3DXZ) && !(currentDim==DIM_3DXZ && dim==DIM_3DXY) )
+        if( !(currentDim==DIM_3DXY && dim==DIM_3DXZ) && !(currentDim==DIM_3DXZ && dim==DIM_3DXY) &&
+            !(currentDim==DIM_4DXY && dim==DIM_4DZW) && !(currentDim==DIM_4DZW && dim==DIM_4DXY)  )
           {
           resetPoints();
           }
@@ -260,20 +278,35 @@ public class DynamicSurfaceView extends GLSurfaceView
         {
         switch(currentDim)
           {
-          case DIM_1D: drawHorizontalAxis(c,"x");
-                       drawPath(c,di1D,1,time);
-                       drawRedPoints1D(c);
-                       break;
-          case DIM_2D: drawHorizontalAxis(c,"x");
-                       drawVerticalAxis  (c,"y");
-                       drawPath(c,di2D,1,time);
-                       drawRedPoints2D(c);
-                       break;
-          default    : drawHorizontalAxis(c,"x");
-                       drawVerticalAxis  (c, currentDim==DIM_3DXY ? "y" : "z" );
-                       drawPath(c,di3D,(currentDim==DIM_3DXY ? 1:2),time);
-                       drawRedPoints3D(c);
-                       break;
+          case DIM_1D  : drawHorizontalAxis(c,"x");
+                         drawPath(c,di1D,0,1,time);
+                         drawRedPoints1D(c);
+                         break;
+          case DIM_2D  : drawHorizontalAxis(c,"x");
+                         drawVerticalAxis  (c,"y");
+                         drawPath(c,di2D,0,1,time);
+                         drawRedPoints2D(c);
+                         break;
+          case DIM_3DXY: drawHorizontalAxis(c,"x");
+                         drawVerticalAxis  (c,"y");
+                         drawPath(c,di3D,0,1,time);
+                         drawRedPoints3D(c);
+                         break;
+          case DIM_3DXZ: drawHorizontalAxis(c,"x");
+                         drawVerticalAxis  (c,"z");
+                         drawPath(c,di3D,0,2,time);
+                         drawRedPoints3D(c);
+                         break;
+          case DIM_4DXY: drawHorizontalAxis(c,"x");
+                         drawVerticalAxis  (c,"y");
+                         drawPath(c,di4D,0,1,time);
+                         drawRedPoints4D(c);
+                         break;
+          case DIM_4DZW: drawHorizontalAxis(c,"z");
+                         drawVerticalAxis  (c,"w");
+                         drawPath(c,di4D,2,3,time);
+                         drawRedPoints4D(c);
+                         break;
           }
         }
 
@@ -284,7 +317,7 @@ public class DynamicSurfaceView extends GLSurfaceView
 
     private void clearPoints()
       {
-      for(int i=0; i<3*NUM_POINTS; i++)
+      for(int i=0; i<MAX_DIM*NUM_POINTS; i++)
          {
          mPoints[i] = -100000.0f;
          }
@@ -304,6 +337,8 @@ public class DynamicSurfaceView extends GLSurfaceView
           case DIM_2D  : di2D.removeAll(); break;
           case DIM_3DXY:
           case DIM_3DXZ: di3D.removeAll(); break;
+          case DIM_4DXY:
+          case DIM_4DZW: di4D.removeAll(); break;
           }
 
         DynamicActivity act = mAct.get();
@@ -324,6 +359,7 @@ public class DynamicSurfaceView extends GLSurfaceView
       di1D.resetToBeginning();
       di2D.resetToBeginning();
       di3D.resetToBeginning();
+      di4D.resetToBeginning();
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -356,7 +392,7 @@ public class DynamicSurfaceView extends GLSurfaceView
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    private void drawPath(Canvas c, Dynamic dyn, int index, long time)
+    private void drawPath(Canvas c, Dynamic dyn, int indexH, int indexW, long time)
       {
       int len = dyn.getNumPoints();
 
@@ -368,10 +404,10 @@ public class DynamicSurfaceView extends GLSurfaceView
 
           if( dyn.getDimension()==1 )
             {
-            mPoints[3*mPosition+index] = halfScreenHeight;
+            mPoints[MAX_DIM*mPosition+indexW] = halfScreenHeight;
             }
 
-          if( dyn.get(mPoints,3*mPosition, time-mStartTime, mDiffTime) )
+          if( dyn.get(mPoints,MAX_DIM*mPosition, time-mStartTime, mDiffTime) )
             {
             stopDynamic();
             }
@@ -385,7 +421,7 @@ public class DynamicSurfaceView extends GLSurfaceView
                                    : 0xff - (mPosition+NUM_POINTS-i)*0xff/(NUM_POINTS-1);
 
           mPaint.setColor( 0xffffff + ((color&0xff)<<24) );
-          c.drawCircle(mPoints[3*i], mPoints[3*i+index] , mSize1, mPaint );
+          c.drawCircle(mPoints[MAX_DIM*i+indexH], mPoints[MAX_DIM*i+indexW] , mSize1, mPaint );
           }
         }
       }
@@ -429,6 +465,21 @@ public class DynamicSurfaceView extends GLSurfaceView
         }
       }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void drawRedPoints4D(Canvas c)
+      {
+      int len = di4D.getNumPoints();
+
+      for(int curr=0; curr<len; curr++)
+        {
+        p4D = di4D.getPoint(curr);
+
+        if( currentDim==DIM_4DXY ) drawRedPoint(c,curr+"", p4D.get1(), p4D.get2());
+        else                       drawRedPoint(c,curr+"", p4D.get3(), p4D.get4());
+        }
+      }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     private void drawRedPoint(Canvas c, String label, float width, float height)
@@ -443,92 +494,134 @@ public class DynamicSurfaceView extends GLSurfaceView
 
     private void addNewPoint(int x, int y)
       {
-      float gx,gy,gz;
+      float gx,gy,gz,gw;
       int len;
+      int minDist = (mAvg*mAvg)/100;
 
       switch(currentDim)
         {
-        case DIM_1D: len = di1D.getNumPoints();
+        case DIM_1D : len = di1D.getNumPoints();
 
-                     for(int g=0; g<len; g++)
-                       {
-                       p1D = di1D.getPoint(g);  
-                       gx = p1D.get1();
+                      for(int g=0; g<len; g++)
+                        {
+                        p1D = di1D.getPoint(g);
+                        gx = p1D.get1();
                                     
-                       if( (x-gx)*(x-gx) < (mAvg*mAvg/100) )
-                         {
-                         mMoving = g;
-                         break;
-                         }
-                       }
-                     if( mMoving <0 )
-                       {
-                       synchronized(lock)
-                         {
-                         di1D.add(new Static1D(x));
-                         mAct.get().setNumRedPoints(len+1);
-                         }
-                       }
-                     break;
-        case DIM_2D: len = di2D.getNumPoints();
+                        if( (x-gx)*(x-gx) < minDist )
+                          {
+                          mMoving = g;
+                          break;
+                          }
+                        }
+                      if( mMoving <0 )
+                        {
+                        synchronized(lock)
+                          {
+                          di1D.add(new Static1D(x));
+                          mAct.get().setNumRedPoints(len+1);
+                          }
+                        }
+                      break;
+        case DIM_2D : len = di2D.getNumPoints();
                                  
-                     for(int g=0; g<len; g++)
-                       {
-                       p2D = di2D.getPoint(g);  
-                       gx = p2D.get1();
-                       gy = p2D.get2();
+                      for(int g=0; g<len; g++)
+                        {
+                        p2D = di2D.getPoint(g);
+                        gx = p2D.get1();
+                        gy = p2D.get2();
                                     
-                       if( (x-gx)*(x-gx) + (y-gy)*(y-gy) < (mAvg*mAvg/100) )
-                         {
-                         mMoving = g;
-                         break;
-                         }
-                       }
-                     if( mMoving <0 )
-                       {
-                       synchronized(lock)
-                         {
-                         di2D.add(new Static2D(x,y));
-                         mAct.get().setNumRedPoints(len+1);
-                         }
-                       }
-                     break;
-        default    : len = di3D.getNumPoints();
+                        if( (x-gx)*(x-gx) + (y-gy)*(y-gy) < minDist )
+                          {
+                          mMoving = g;
+                          break;
+                          }
+                        }
+                      if( mMoving <0 )
+                        {
+                        synchronized(lock)
+                          {
+                          di2D.add(new Static2D(x,y));
+                          mAct.get().setNumRedPoints(len+1);
+                          }
+                        }
+                      break;
+        case DIM_3DXY:
+        case DIM_3DXZ:len = di3D.getNumPoints();
                                  
-                     for(int g=0; g<len; g++)
-                       {
-                       p3D = di3D.getPoint(g);  
-                       gx = p3D.get1();
-                       gy = p3D.get2();
-                       gz = p3D.get3();
+                      for(int g=0; g<len; g++)
+                        {
+                        p3D = di3D.getPoint(g);
+                        gx = p3D.get1();
+                        gy = p3D.get2();
+                        gz = p3D.get3();
                                
-                     if( currentDim==DIM_3DXY )
-                       {
-                       if( (x-gx)*(x-gx) + (y-gy)*(y-gy) < (mAvg*mAvg/100) )
-                         {
-                         mMoving = g;
-                         break;
-                         }
-                       }
-                     if( currentDim==DIM_3DXZ )
-                       {
-                       if( (x-gx)*(x-gx) + (y-gz)*(y-gz) < (mAvg*mAvg/100) )
-                         {
-                         mMoving = g;
-                         break;
-                         }
-                       }
-                     }
-                   if( mMoving <0 )
-                     { 
-                     synchronized(lock)
-                       {
-                       if( currentDim==DIM_3DXY ) di3D.add(new Static3D(x,y, halfScreenHeight));
-                       if( currentDim==DIM_3DXZ ) di3D.add(new Static3D(x, halfScreenHeight,y));
-                       mAct.get().setNumRedPoints(len+1);
-                       }
-                     }
-                   break; 
+                        if( currentDim==DIM_3DXY )
+                          {
+                          if( (x-gx)*(x-gx) + (y-gy)*(y-gy) < minDist )
+                            {
+                            mMoving = g;
+                            break;
+                            }
+                          }
+                        if( currentDim==DIM_3DXZ )
+                          {
+                          if( (x-gx)*(x-gx) + (y-gz)*(y-gz) < minDist )
+                            {
+                            mMoving = g;
+                            break;
+                            }
+                          }
+                        }
+
+                      if( mMoving <0 )
+                        {
+                        synchronized(lock)
+                          {
+                          if( currentDim==DIM_3DXY ) di3D.add(new Static3D(x,y, halfScreenHeight));
+                          if( currentDim==DIM_3DXZ ) di3D.add(new Static3D(x, halfScreenHeight,y));
+                          mAct.get().setNumRedPoints(len+1);
+                          }
+                        }
+                      break;
+        case DIM_4DXY:
+        case DIM_4DZW:len = di4D.getNumPoints();
+
+                      for(int g=0; g<len; g++)
+                        {
+                        p4D = di4D.getPoint(g);
+                        gx = p4D.get1();
+                        gy = p4D.get2();
+                        gz = p4D.get3();
+                        gw = p4D.get4();
+
+                        if( currentDim==DIM_4DXY )
+                          {
+                          if( (x-gx)*(x-gx) + (y-gy)*(y-gy) < minDist )
+                            {
+                            mMoving = g;
+                            break;
+                            }
+                          }
+                        if( currentDim==DIM_4DZW )
+                          {
+                          if( (x-gz)*(x-gz) + (y-gw)*(y-gw) < minDist )
+                            {
+                            mMoving = g;
+                            break;
+                            }
+                          }
+                        }
+
+                      if( mMoving <0 )
+                        {
+                        synchronized(lock)
+                          {
+                          if( currentDim==DIM_4DXY ) di4D.add(new Static4D(x,y, halfScreenWidth, halfScreenHeight));
+                          if( currentDim==DIM_4DZW ) di4D.add(new Static4D( halfScreenWidth, halfScreenHeight,x,y));
+                          mAct.get().setNumRedPoints(len+1);
+                          }
+                        }
+                      break;
         }
       }
     
@@ -539,11 +632,12 @@ public class DynamicSurfaceView extends GLSurfaceView
       int prev = mPosition-1;
       if( prev<0 ) prev = NUM_POINTS-1;
 
-      float xdiff = mPoints[3*prev  ]-mPoints[3*mPosition  ];
-      float ydiff = mPoints[3*prev+1]-mPoints[3*mPosition+1];
-      float zdiff = mPoints[3*prev+2]-mPoints[3*mPosition+2];
+      float xdiff = mPoints[MAX_DIM*prev  ]-mPoints[MAX_DIM*mPosition  ];
+      float ydiff = mPoints[MAX_DIM*prev+1]-mPoints[MAX_DIM*mPosition+1];
+      float zdiff = mPoints[MAX_DIM*prev+2]-mPoints[MAX_DIM*mPosition+2];
+      float wdiff = mPoints[MAX_DIM*prev+3]-mPoints[MAX_DIM*mPosition+3];
 
-      float dist = (float)Math.sqrt( xdiff*xdiff + ydiff*ydiff + zdiff*zdiff );
+      float dist = (float)Math.sqrt( xdiff*xdiff + ydiff*ydiff + zdiff*zdiff + wdiff*wdiff);
       float speed= mDiffTime<=0 ? 0: dist / mDiffTime;
       float timepoint = ((float)(time-mStartTime))/mDuration;
 
@@ -584,6 +678,10 @@ public class DynamicSurfaceView extends GLSurfaceView
                                                          break;
                                           case DIM_3DXZ: di3D.setPoint(mMoving, xDown, (int)di3D.getPoint(mMoving).get2(), yDown);
                                                          break;
+                                          case DIM_4DXY: di4D.setPoint(mMoving, xDown, yDown, (int)di4D.getPoint(mMoving).get3(), (int)di4D.getPoint(mMoving).get4());
+                                                         break;
+                                          case DIM_4DZW: di4D.setPoint(mMoving, (int)di4D.getPoint(mMoving).get1(), (int)di4D.getPoint(mMoving).get2(), xDown, yDown);
+                                                         break;
                                           }
                                         }                           
                                       break;
diff --git a/src/main/res/layout/dynamicslayout.xml b/src/main/res/layout/dynamicslayout.xml
index 2917555..7be8d98 100644
--- a/src/main/res/layout/dynamicslayout.xml
+++ b/src/main/res/layout/dynamicslayout.xml
@@ -164,6 +164,14 @@
                 android:layout_height="wrap_content"
                 android:layout_weight="1"
                 android:paddingLeft="5dp"
+                android:paddingRight="5dp" />
+
+            <SeekBar
+                android:id="@+id/dynamicSeekNoise3"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:paddingLeft="5dp"
                 android:paddingRight="10dp" />
         </LinearLayout>
 
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index aa08fd4..0f6a1d5 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -119,7 +119,7 @@
     <string name="duration_placeholder">Duration: %1$d s</string>
     <string name="count_placeholder">Count: %1$.2f</string>
     <string name="convexity_placeholder">Convexity: %1$.2f</string>
-    <string name="noise2_placeholder">Noise: %1$.2f %2$.2f %3$.2f</string>
+    <string name="noise3_placeholder">Noise: %1$.2f %2$.2f %3$.2f %4$.2f</string>
 
     <string name="example_monalisa">Mona Lisa</string>
     <string name="example_monalisa_subtitle">The basics of Distortions.</string>
