O2Plib.db
Class DbBoundary

java.lang.Object
  extended by O2Plib.db.DbBoundary

public class DbBoundary
extends java.lang.Object

Class DbBoundary supports spot boundary analysis data structures (chain-coded) and functions for representing spot boundaries in DbSpot for the Open2Dprot system.

[TODO] debug.

This algorithm is based on an algorithm for region splitting based on chain codes used in bone marrow smear image analysis described in: Lemkin, P.: An approach to region splitting. Computer Graphics and Image Processing, 10: 281-288 (1979).

This code was derived and refactored from GELLAB-II sg2gii and libr C language files.

This work was produced by Peter Lemkin of the National Cancer Institute, an agency of the United States Government. As a work of the United States Government there is no associated copyright. It is offered as open source software under the Mozilla Public License (version 1.1) subject to the limitations noted in the accompanying LEGAL file. This notice must be included with the code. The Open2Dprot Mozilla and Legal files are available on http://Open2Dprot.sourceforge.net/.

Version:
$Date: 2005/10/21 16:01:38 $ $Revision: 1.14 $
Author:
P. Lemkin, NCI-Frederick, Frederick, MD, 21702
See Also:
Open2Dprot Home

Field Summary
 float[] a2a1Diff
          angle difference of notch will be < 180 in a notch
static int BND_SMOOTHING_FILTER_WIDTH
          For 180 micron/pixel.
 byte[] chainCode
          chain code [0:lth-1]
 DbSample dbSample
           
 DbSpot dbSpot
           
static boolean DBUG_FULL_BND
          Debugging
static boolean dbugFlag
          Debugging flag
 int[] entranceX
           
 int[] entranceY
           
 int[] exitX
           
 int[] exitY
           
static char[] hexToAscii
          hex mapping array: {"0123456789abcdef"}
static int INITIAL_MAXBND
          Initial boundary size
 boolean isCompressedChainCode
          Sizes of sub-objects.
 int lth
          length of boundary
static int maxBndAlloc
          initial boundary size allocation
static int maxX
          Minimum enclosing rectangle: RIGHT most x
static int maxY
          Minimum enclosing rectangle: BOTTOM most y
static int minX
          Minimum enclosing rectangle: LEFT most x
static int minY
          Minimum enclosing rectangle: TOP most y
 float[] smoothedChainCode
          chain code [0:lth-1]
static int smoothingFilterWidth
          initial smoothing filter width allocation
static java.lang.String VERSION
          Version for this module
 int x0
          First pixel (needed if using chain code)
 int[] xb
          x coordinates[0:lth-1]
static java.awt.Point xyPoint
          working (x,y) point
 int y0
          First pixel (needed if using chain code)
 int[] yb
          y coordinates[0:lth-1]
 
Constructor Summary
DbBoundary(DbSample dbSample)
          DbBoundary() - Constructor
DbBoundary(DbSample dbSample, DbSpot dbSpot)
          DbBoundary() - Constructor
 
Method Summary
static boolean calcMinEnclosingRectangle(java.awt.Point[] xyList, int xyListSize)
          calcMinEnclosingRectangle() - compute minimum rectangle from the xyList[] of (x,y) points.
 void compressChainCode()
          compressChainCode() - Compress the bnd.chainCode[] and from 8-bits to 4-bit nibbles and shrink the arrays.
 java.lang.String cvChainCode2Str(int ssfFmtMode, boolean useRunLengthCompression)
          cvChainCode2Str() - If a chain code exists in a boundary data structure then map it to a String:
 boolean cvtBoundaryToChainCode()
          cvtBoundaryToChainCode() - Compute the clockwise chain code from the boundary.
 java.awt.Point cvtChainCode_to_nextXY(int x, int y, int i)
          cvtChainCode_to_nextXY() - Given (x,y) and the i'th chainCode generate a new (x,y) based on the chain code direction.
 void cvtMER_RLMs_to_chainCode(int minX, int maxX, int minY, int maxY, int[] eX, int[] xX, int[] eY, int[] xY)
          cvtMER_RLMs_to_chainCode() - given the M.E.R., R.L.Ms, convert a boundary and compressed chain code in a DbBoundary boundary object.
 void deleteBnd()
          deleteBnd() - delete the boundary data structure data, but keep the empty object.
 int findBoundary(java.awt.Point[] xyList, int xyListTop, boolean justXYCflag)
          findBoundary() - given the xyList of points in a spot, search the list to to find a boundary.
 int findBoundary2(java.awt.Point[] xyList, int xyListTop, boolean justXYCflag)
          findBoundary2() - given the xyList of points in a spot, search the list to to find a boundary.
 void init()
          init() - init any globals required on a per-spot basis.
 int pushXYbndInterpolateLine(DbBoundary bnd, int x1, int y1, int x2, int y2)
          pushXYbndInterpolateLine() - interpolate two int points (x1,y1) to point (x2,y2) into a list of x,y coordinates which are pushed into bnd.
 int pushXYboundary(int x2, int y2)
          pushXYboundary() - push (x,y) into this boundary if (x,y)[1:lth] NEQ top pixel.
 boolean reallocBnd(int newBndSize, boolean justXYCflag)
          reallocBnd() - grow the MAX boundary arrays for this boundary to a new size.
 void resetBnd(boolean justXYCflag)
          resetBnd() - reset a boundary to size 0.
static void setDbugFlag(boolean debugFlag)
          setDbugFlag() - set the debug flag
static void setDefaultSizes(int smoothingFilterWidth, int maxBndAlloc)
          setDefaultSizes() - sets the default sizes.
 boolean smoothChainCode()
          smoothChainCode() - smooth the chain code and return it in the same boundary.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

VERSION

public static final java.lang.String VERSION
Version for this module

See Also:
Constant Field Values

DBUG_FULL_BND

public static final boolean DBUG_FULL_BND
Debugging

See Also:
Constant Field Values

INITIAL_MAXBND

public static final int INITIAL_MAXBND
Initial boundary size

See Also:
Constant Field Values

BND_SMOOTHING_FILTER_WIDTH

public static final int BND_SMOOTHING_FILTER_WIDTH
For 180 micron/pixel. Chain code smoothing filter width

See Also:
Constant Field Values

maxBndAlloc

public static int maxBndAlloc
initial boundary size allocation


smoothingFilterWidth

public static int smoothingFilterWidth
initial smoothing filter width allocation


xyPoint

public static java.awt.Point xyPoint
working (x,y) point


hexToAscii

public static char[] hexToAscii
hex mapping array: {"0123456789abcdef"}


dbugFlag

public static boolean dbugFlag
Debugging flag


dbSample

public DbSample dbSample

dbSpot

public DbSpot dbSpot

minX

public static int minX
Minimum enclosing rectangle: LEFT most x


maxX

public static int maxX
Minimum enclosing rectangle: RIGHT most x


minY

public static int minY
Minimum enclosing rectangle: TOP most y


maxY

public static int maxY
Minimum enclosing rectangle: BOTTOM most y


entranceX

public int[] entranceX

entranceY

public int[] entranceY

exitX

public int[] exitX

exitY

public int[] exitY

x0

public int x0
First pixel (needed if using chain code)


y0

public int y0
First pixel (needed if using chain code)


isCompressedChainCode

public boolean isCompressedChainCode
Sizes of sub-objects. If true, then chainCode[] and smoothedChainCode[] are compressed from 8-bits to 4-bit nibbles.


lth

public int lth
length of boundary


xb

public int[] xb
x coordinates[0:lth-1]


yb

public int[] yb
y coordinates[0:lth-1]


chainCode

public byte[] chainCode
chain code [0:lth-1]


smoothedChainCode

public float[] smoothedChainCode
chain code [0:lth-1]


a2a1Diff

public float[] a2a1Diff
angle difference of notch will be < 180 in a notch

Constructor Detail

DbBoundary

public DbBoundary(DbSample dbSample)
DbBoundary() - Constructor


DbBoundary

public DbBoundary(DbSample dbSample,
                  DbSpot dbSpot)
DbBoundary() - Constructor

Method Detail

setDbugFlag

public static void setDbugFlag(boolean debugFlag)
setDbugFlag() - set the debug flag

Parameters:
debugFlag - to set

setDefaultSizes

public static void setDefaultSizes(int smoothingFilterWidth,
                                   int maxBndAlloc)
setDefaultSizes() - sets the default sizes.

Parameters:
smoothingFilterWidth -
maxBndAlloc -

init

public void init()
init() - init any globals required on a per-spot basis. i.e. Do what you have to do...


resetBnd

public void resetBnd(boolean justXYCflag)
resetBnd() - reset a boundary to size 0.

Parameters:
usersBnd - is the boundary to reset
justXYCflag - If set, just create xy & chainCode data structs

reallocBnd

public boolean reallocBnd(int newBndSize,
                          boolean justXYCflag)
reallocBnd() - grow the MAX boundary arrays for this boundary to a new size. Copy the old data and free the old storage.

Parameters:
newBndSize - is the new maximum size
justXYCflag - If set, just create XY & ChainCode data structs
Returns:
return true if reallocated, false if no change.

deleteBnd

public void deleteBnd()
deleteBnd() - delete the boundary data structure data, but keep the empty object.


pushXYboundary

public int pushXYboundary(int x2,
                          int y2)
pushXYboundary() - push (x,y) into this boundary if (x,y)[1:lth] NEQ top pixel. Grow the structure lists if need be.

Parameters:
bnd - is the boundary to push
x2 - is the X coordinate to push
y2 - is the Y coordiante to push
Returns:
the length.

pushXYbndInterpolateLine

public int pushXYbndInterpolateLine(DbBoundary bnd,
                                    int x1,
                                    int y1,
                                    int x2,
                                    int y2)
pushXYbndInterpolateLine() - interpolate two int points (x1,y1) to point (x2,y2) into a list of x,y coordinates which are pushed into bnd. The # points interpolated is returned.
Algorithm taken from Lemkin etal, Comput. in Biomed. Res., 12, 517-544 (1979). [NOTE] NOT_USED_AT_THIS_TIME

Parameters:
bnd - is the boundary to draw the line into
x1 - starting X coordinate
y1 - starting Y coordinate
x2 - ending X coordinate
y2 - ending Y coordinate
Returns:
# of points interpoated

cvChainCode2Str

public java.lang.String cvChainCode2Str(int ssfFmtMode,
                                        boolean useRunLengthCompression)
cvChainCode2Str() - If a chain code exists in a boundary data structure then map it to a String:
 If ssfFmtMode is  short, xml or tab-delim,
   " <#-codes-N>,,=c1c2c3c4...cN"
 else if ssfFmtMode is  long,
   " chainCode[#<#-codes-N>,x0=,y0=]{R|C}=c1c2c3c4...cN"
 where: {R|C} means "R" if run length encoding, "C" if just chain code.
 if R.L. compression is used,
 the run length is coded as a letter "a"=1, "b"=2, ..., "z"=26
 (26 being max run length), followed by the code cj.
 E.g. c4b6e5 ==> 4446655555

Parameters:
ssfFmtMode - if false, use longSSF form
useRunLengthCompression - if true, use run length compression

cvtMER_RLMs_to_chainCode

public void cvtMER_RLMs_to_chainCode(int minX,
                                     int maxX,
                                     int minY,
                                     int maxY,
                                     int[] eX,
                                     int[] xX,
                                     int[] eY,
                                     int[] xY)
cvtMER_RLMs_to_chainCode() - given the M.E.R., R.L.Ms, convert a boundary and compressed chain code in a DbBoundary boundary object. If the bnd does not exist or is too small, grow it if need be. NOTE: this is faster than doing it piecemeal.

Parameters:
minX - is minimum enclosing rectangle (M.E.R)
maxX - is M.E.R
minY - is M.E.R
maxY - is M.E.R
eX - is the run length map (R.L.M.)
xX - is the RLM
eY - is the RLM
xY - is the RLM
bnd - is the output bnd w/C-code

compressChainCode

public void compressChainCode()
compressChainCode() - Compress the bnd.chainCode[] and from 8-bits to 4-bit nibbles and shrink the arrays. Set the bnd.isCompressedChainCode flag to true. NOTE: data is packed left to right nibbles.
         Left(odd) Right(even)
         --------  ----------
 byte 1:  cCode1    cCode2
 byte 2:  cCode3    cCode4
           . . .

 ARGS IN:  bnd(chainCode,lth)
 ARGS OUT: bnd(chainCode)

Parameters:
bnd - is existing chain codes

cvtChainCode_to_nextXY

public java.awt.Point cvtChainCode_to_nextXY(int x,
                                             int y,
                                             int i)
cvtChainCode_to_nextXY() - Given (x,y) and the i'th chainCode generate a new (x,y) based on the chain code direction.
   (0,0)
       3 2 1
       4 8 0
       5 6 7
            (nrows,ncols)
 ARGS IN: x, y, bnd, i
 ARGS OUT: x, y

Parameters:
x[] - is the previous x and new x
y[] - is the previous y and new y
bnd - is the boundary data structure
i - is the i'th chain code.
Returns:
xyPoint.(x,y), else null if bnd is messed up.

cvtBoundaryToChainCode

public boolean cvtBoundaryToChainCode()
cvtBoundaryToChainCode() - Compute the clockwise chain code from the boundary.
 ARGS IN: bnd.(x[], y[], lth)
 ARGS OUT: bnd.(chainCode[])

Returns:
false if bnd is messed up.

smoothChainCode

public boolean smoothChainCode()
smoothChainCode() - smooth the chain code and return it in the same boundary.
 ARGS IN: bnd.(chainCode[], lth)
 ARGS IN: bnd.(smoothedChainCode[])

Returns:
false if filter width is illegal (eg. if > boundary!)

calcMinEnclosingRectangle

public static boolean calcMinEnclosingRectangle(java.awt.Point[] xyList,
                                                int xyListSize)
calcMinEnclosingRectangle() - compute minimum rectangle from the xyList[] of (x,y) points. The data is saved in the static [minX:maxX, minY:maxY].

Parameters:
xyList - of Points
xyListSize - is max size of data.
Returns:
true if the rectangle exists

findBoundary

public int findBoundary(java.awt.Point[] xyList,
                        int xyListTop,
                        boolean justXYCflag)
findBoundary() - given the xyList of points in a spot, search the list to to find a boundary. Then convert the X and Y R.L.M.s CLOCKWISE to a bnd object.

[NOTE] This is the current method for analyzing the RLM.

Use the M.E.R. from the xyList data structure. If an existing bnd is given it will use it otherwise it will create one. NOTE: bnd.lth = xyListTop. Example of top view of blob:

               eY[x]
                |
                |
                v
                         ____       __
          ____          /   |      /  \
 eX[y]   /    \        /    |     /    \
 -->    /      \      /     |____/      \
       /        \____/                  |

              concavity    concavity

        ALGORITHM: Analyze the RLM to generate the boundary.

 The trick with this algorithm is to traverse the 4 RLM edges
 in a CLOCKWISE manner. When you finish an edge, use the last
 mapped point+1 on the next edge as the starting axis value for
 the next edge.
 We may to interpolate the point with the previous one pushed
 and that is done in pushXYboundary() which will terminate
 pushing a boundary if a point to be added ever is the same
 as the first point.

Parameters:
xyList - is the list of points in the spot to analyze
xyListTop - is the max # of points in the xyList[] to use which may be less than xyList.length.
justXYCflag - if just want to create x, y c-code structure
Returns:
size of boundary.

findBoundary2

public int findBoundary2(java.awt.Point[] xyList,
                         int xyListTop,
                         boolean justXYCflag)
findBoundary2() - given the xyList of points in a spot, search the list to to find a boundary. Then convert the X and Y R.L.M.s CLOCKWISE to a bnd object.

[NOTE] This is a new method for analyzing the RLM - still being constructured.

Use the M.E.R. from the xyList data structure. If an existing bnd is given it will use it otherwise it will create one. NOTE: bnd.lth = xyListTop. Example of top view of blob:

               eY[x]
                |
                |
                v
                         ____       __
          ____          /   |      /  \
 eX[y]   /    \        /    |     /    \
 -->    /      \      /     |____/      \
       /        \____/                  |

              concavity    concavity

        ALGORITHM: Analyze the RLM to generate the boundary.

 The trick with this algorithm is to traverse the 4 RLM edges
 in a CLOCKWISE manner. When you finish an edge, use the last
 mapped point+1 on the next edge as the starting axis value for
 the next edge.
 We may to interpolate the point with the previous one pushed
 and that is done in pushXYboundary() which will terminate
 pushing a boundary if a point to be added ever is the same
 as the first point.

Parameters:
xyList - is the list of points in the spot to analyze
xyListTop - is the max # of points in the xyList[] to use which may be less than xyList.length.
justXYCflag - if just want to create x, y c-code structure
Returns:
size of boundary.