ab923da8deeb3fc3bd5d04fa84e36090c6bcb129
tdreszer
  Tue Apr 22 16:47:33 2014 -0700
Added a trap for when map items are written outside the track they are supposed to be for.  The trap is only on for genome-test and sandboxes.  I found one bug with it: gold in dense had wild map item ending coordinates.  Fixed.  Redmine #13087
diff --git src/hg/hgTracks/imageV2.c src/hg/hgTracks/imageV2.c
index 9a81869..fd8c4a3 100644
--- src/hg/hgTracks/imageV2.c
+++ src/hg/hgTracks/imageV2.c
@@ -999,52 +999,113 @@
     slice = imgTrackSliceAdd(imgTrack,type,img,title,width,height,offsetX,offsetY);
 return slice;
 }
 
 struct imgSlice *imgTrackSliceUpdateOrAdd(struct imgTrack *imgTrack,enum sliceType type,
                                           struct image *img,char *title,int width,int height,
                                           int offsetX,int offsetY)
 // Updates the slice or adds it
 {
 struct imgSlice *slice = imgTrackSliceGetByType(imgTrack,type);
 if (slice == NULL)
     return imgTrackSliceAdd(imgTrack,type,img,title,width,height,offsetX,offsetY);
 return sliceUpdate(slice,type,img,title,width,height,offsetX,offsetY);
 }
 
+int imgTrackCoordinates(struct imgTrack *imgTrack, int *leftX,int *topY,int *rightX,int *bottomY)
+// Fills in topLeft x,y and bottomRight x,y coordinates, returning topY.
+{
+int xLeft = 0,yTop = 0,xRight = 0,yBottom = 0;
+struct imgSlice *slice;
+for (slice = imgTrack->slices;slice != NULL;slice=slice->next)
+    {
+    if (revCmplDisp)
+        {
+        if (xLeft == 0 || xLeft > slice->offsetX - slice->width)
+            xLeft = slice->offsetX - slice->width;
+        if (xRight < slice->offsetX)
+            xRight = slice->offsetX;
+        }
+    else
+        {
+        if (xLeft == 0 || xLeft > slice->offsetX)
+            xLeft = slice->offsetX;
+        if (xRight < slice->offsetX + slice->width)
+            xRight = slice->offsetX + slice->width;
+        }
+    if (yTop == 0 || yTop > slice->offsetY)
+        yTop = slice->offsetY;
+    if (yBottom < slice->offsetY + slice->height)
+        yBottom = slice->offsetY + slice->height;
+    }
+if ( leftX != NULL)
+    *leftX     = xLeft;
+if ( topY != NULL)
+    *topY     = yTop;
+if ( rightX != NULL)
+    *rightX = xRight;
+if ( bottomY != NULL)
+    *bottomY = yBottom;
+return yTop;
+}
+#define imgTrackTopY(imgTrack) imgTrackCoordinates(imgTrack,NULL,NULL,NULL,NULL)
+
+int imgTrackBottomY(struct imgTrack *imgTrack)
+// Returns the Y coordinate of the bottom of the track.
+{
+int bottomY = 0;
+imgTrackCoordinates(imgTrack,NULL,NULL,NULL,&bottomY);
+return bottomY;
+}
+
 struct mapSet *imgTrackGetMapByType(struct imgTrack *imgTrack,enum sliceType type)
 // Gets the map assocated with a specific slice belonging to the imgTrack
 {
 struct imgSlice *slice = imgTrackSliceGetByType(imgTrack,type);
 if (slice == NULL)
     return NULL;
 return sliceGetMap(slice,FALSE); // Map could belong to image or could be slice specific
 }
 
 int imgTrackAddMapItem(struct imgTrack *imgTrack,char *link,char *title,
                        int topLeftX,int topLeftY,int bottomRightX,int bottomRightY, char *id)
 // Will add a map item to an imgTrack's appropriate slice's map.  Since a map item may span
 // slices, the imgTrack is in the best position to determine where to put the map item
 // returns count of map items added, which could be 0, 1 or more than one if item spans slices
 // NOTE: Precedence is given to first map item when adding items with same coordinates!
 {
 struct imgSlice *slice;
 char *imgFile = NULL;               // name of file that hold the image
 char *neededId = NULL; // id is only added it it is NOT the trackId.
 if (imgTrack->tdb == NULL || differentStringNullOk(id, imgTrack->tdb->track))
     neededId = id;
 
+// Trap surprising location s for map items, but only on test machines.
+if (hIsPrivateHost())
+    {
+    int leftX, topY, rightX, bottomY;
+    imgTrackCoordinates(imgTrack, &leftX, &topY, &rightX, &bottomY);
+    if (topLeftY < topY || bottomRightY > bottomY || topLeftX < leftX || bottomRightX > rightX)
+        {
+        char * name = (imgTrack->name != NULL ? imgTrack->name
+                                              : imgTrack->tdb != NULL ? imgTrack->tdb->track
+                                                                      : imgFile);
+        warnWithBackTrace("imgTrackAddMapItem(%s,%s) mapItem(%d:%d,%d:%d) spills over track bounds(%d:%d,%d:%d)",
+             name,title,topLeftX,topLeftY,bottomRightX,bottomRightY,leftX,topY,rightX,bottomY);
+        }
+    }
+
 int count = 0;
 for (slice = imgTrack->slices;slice != NULL;slice=slice->next)
     {
     if (slice->type == stButton) // Buttons don't have maps.  Overlap will be ignored!
         continue;
     if (slice->parentImg != NULL)
         {
         if (imgFile == NULL)
             imgFile = slice->parentImg->file;
         }
     if (topLeftX     < (slice->offsetX + slice->width-1)
     && bottomRightX > (slice->offsetX + 1)
     && topLeftY     < (slice->offsetY + slice->height-1)
     && bottomRightY > (slice->offsetY + 1)) // Overlap of a pixel or 2 is tolerated
         {