public void build () throws ExceptionInvalidParam
   {
      if ( upperXBound <= lowerXBound
            || upperZBound <= lowerZBound
            || destWidth <= 0
            || destHeight <= 0
            || sourceModule == null
            || destNoiseMap == null)
         throw new ExceptionInvalidParam ("Invalid parameter in NoiseMapBuilderPlane");

      // Resize the destination noise map so that it can store the new output
      // values from the source model.
      destNoiseMap.setSize (destWidth, destHeight);

      // Create the plane model.
      Plane planeModel = new Plane();
      planeModel.setModule (sourceModule);

      double xExtent = upperXBound - lowerXBound;
      double zExtent = upperZBound - lowerZBound;
      double xDelta  = xExtent / (double)destWidth ;
      double zDelta  = zExtent / (double)destHeight;
      double xCur    = lowerXBound;
      double zCur    = lowerZBound;
      
      // Fill every point in the noise map with the output values from the model.
      for (int z = 0; z < destHeight; z++)
      {
         xCur = lowerXBound;
         for (int x = 0; x < destWidth; x++)
         {
            double finalValue;

            if (!isSeamlessEnabled)
               finalValue = planeModel.getValue (xCur, zCur);
            else
            {
               double swValue, seValue, nwValue, neValue;
               swValue = planeModel.getValue (xCur, zCur);
               seValue = planeModel.getValue (xCur + xExtent, zCur);
               nwValue = planeModel.getValue (xCur, zCur + zExtent);
               neValue = planeModel.getValue (xCur + xExtent, zCur + zExtent);
               double xBlend = 1.0 - ((xCur - lowerXBound) / xExtent);
               double zBlend = 1.0 - ((zCur - lowerZBound) / zExtent);
               double z0 = Interp.linearInterp (swValue, seValue, xBlend);
               double z1 = Interp.linearInterp (nwValue, neValue, xBlend);
               finalValue = Interp.linearInterp (z0, z1, zBlend);
            }
            
            destNoiseMap.setValue(x, z, finalValue);
            xCur += xDelta;
         }
         zCur += zDelta;
         setCallback (z);
      }
   }