diff --git a/toonz/sources/tnztools/assistants/assistantellipse.cpp b/toonz/sources/tnztools/assistants/assistantellipse.cpp
index 31a8965..dbca015 100644
--- a/toonz/sources/tnztools/assistants/assistantellipse.cpp
+++ b/toonz/sources/tnztools/assistants/assistantellipse.cpp
@@ -406,11 +406,27 @@ void TAssistantEllipse::drawParallelGrid(
   const TAffine &ellipseMatrix,
   const TPointD &grid0,
   const TPointD &grid1,
+  const TPointD *bound0,
+  const TPointD *bound1,
   bool perspective,
   bool perspectiveDepth,
   bool repeat,
   double alpha )
 {
+  struct {
+    const bool repeat;
+    const TAffine ellipseMatrixInv;
+    double convert(const TPointD &p) {
+      TPointD pp = ellipseMatrixInv*p;
+      if (repeat)
+        pp.x -= round(pp.x/2)*2;
+      if (!(fabs(pp.x) < 1 - TConsts::epsilon))
+        return pp.y < 0 ? -INFINITY : INFINITY;
+      return pp.y/sqrt(1 - pp.x*pp.x);
+    }
+  } helper = { repeat, ellipseMatrix.inv() };
+  
+  
   TAffine4 modelview, projection;
   glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a);
   glGetDoublev(GL_PROJECTION_MATRIX, projection.a);
@@ -419,26 +435,42 @@ void TAssistantEllipse::drawParallelGrid(
   
   double pixelSize = sqrt(tglGetPixelSize2());
   double minStep = (perspective ? 5 : 10)*pixelSize;
-  TAffine ellipseMatrixInv = ellipseMatrix.inv();
 
   const TAffine &em = ellipseMatrix;
   double r = sqrt(0.5*(norm2(TPointD(em.a11, em.a21)) + norm2(TPointD(em.a12, em.a22))));
   double actualMinStep = minStep/r;
-  TPointD g0 = ellipseMatrixInv*grid0;
-  TPointD g1 = ellipseMatrixInv*grid1;
-  if (repeat)
-    { g0.x -= round(0.5*g0.x)*2.0; g1.x -= round(0.5*g1.x)*2.0; }
-  if (fabs(g0.x) >= 1.0 - TConsts::epsilon) return;
-  if (fabs(g1.x) >= 1.0 - TConsts::epsilon) return;
-  double gs0 = g0.y/sqrt(1.0 - g0.x*g0.x);
-  double gs1 = g1.y/sqrt(1.0 - g1.x*g1.x);
-  if (fabs(gs0) >= 1.0 - TConsts::epsilon) return;
-  if (fabs(gs1) >= 1.0 - TConsts::epsilon) return;
-
+  
+  // convert grid
+  double gs0 = helper.convert(grid0);
+  double gs1 = helper.convert(grid1);
+  if (!(fabs(gs0) < 1 - TConsts::epsilon)) return;
+  if (!(fabs(gs1) < 1 - TConsts::epsilon)) return;
+  
+  // convert bounds
+  double bs0 = -INFINITY, bs1 = INFINITY;
+  if (bound0 && bound1) {
+    bs0 = helper.convert(*bound0);
+    bs1 = helper.convert(*bound1);
+  } else
+  if (bound0) {
+    bs0 = helper.convert(*bound0);
+    if (bs0 < 0) bs1 = -INFINITY;
+  } else
+  if (bound1) {
+    bs1 = helper.convert(*bound1);
+    if (bs1 < 0) bs0 = INFINITY;
+  }
+  
+  if (bs0 > bs1) std::swap(bs0, bs1);
+  bs0 -= TConsts::epsilon;
+  bs1 += TConsts::epsilon;
+  
+  // prepare ranges
   TAngleRangeSet ranges;
   ranges.add( TAngleRangeSet::fromDouble(0.0), TAngleRangeSet::fromDouble(M_PI) );
 
   if (perspectiveDepth) {
+    // draw perspective depth
     if (!( fabs(gs0) > TConsts::epsilon
         && fabs(gs1) > TConsts::epsilon
         && fabs(gs0) < 1 - TConsts::epsilon
@@ -461,10 +493,13 @@ void TAssistantEllipse::drawParallelGrid(
       double curAlpha = (curStep - actualMinStep)/actualMinStep;
       if (curAlpha < 0) { if (i == i0) continue; else break; }
       if (curAlpha > 1) curAlpha = 1;
-        
+      
+      x *= sign;
+      if (x < bs0 || bs1 < x) continue;
+      
       drawEllipseRanges(
         ranges,
-        ellipseMatrix*TAffine::scale(sign, x*sign),
+        ellipseMatrix*TAffine::scale(sign, x),
         screenMatrixInv,
         pixelSize,
         alpha * curAlpha );
@@ -494,6 +529,7 @@ void TAssistantEllipse::drawParallelGrid(
         if (curAlpha < 0) { if (i == i0) continue; else break; }
         if (curAlpha > 1) curAlpha = 1;
       }
+      if (x < bs0 || bs1 < x) continue;
         
       drawEllipseRanges(
         ranges,
@@ -506,13 +542,15 @@ void TAssistantEllipse::drawParallelGrid(
     // draw linear
     double dx = fabs(gs1 - gs0);
     if (dx < actualMinStep) return;
-    for(double x = gs0 + ceil((-1.0 - gs0)/dx)*dx; x < 1.0; x += dx)
+    for(double x = gs0 + ceil((-1.0 - gs0)/dx)*dx; x < 1.0; x += dx) {
+      if (x < bs0 || bs1 < x) continue;
       drawEllipseRanges(
         ranges,
         ellipseMatrix*TAffine::scale(x < 0.0 ? -1.0 : 1.0, x),
         screenMatrixInv,
         pixelSize,
         alpha );
+    }
   }
 }
 
@@ -566,6 +604,8 @@ void TAssistantEllipse::draw(
       ellipseMatrix,
       m_grid0.position,
       m_grid1.position,
+      nullptr,
+      nullptr,
       getPerspective(),
       getPerspectiveDepth(),
       getRepeat(),
diff --git a/toonz/sources/tnztools/assistants/assistantellipse.h b/toonz/sources/tnztools/assistants/assistantellipse.h
index 0838cf2..394ea96 100644
--- a/toonz/sources/tnztools/assistants/assistantellipse.h
+++ b/toonz/sources/tnztools/assistants/assistantellipse.h
@@ -110,6 +110,8 @@ public:
     const TAffine &ellipseMatrix,
     const TPointD &grid0,
     const TPointD &grid1,
+    const TPointD *bound0,
+    const TPointD *bound1,
     bool perspective,
     bool perspectiveDepth,
     bool repeat,
diff --git a/toonz/sources/tnztools/assistants/assistantfisheye.cpp b/toonz/sources/tnztools/assistants/assistantfisheye.cpp
index d91fca4..6ebfe5f 100644
--- a/toonz/sources/tnztools/assistants/assistantfisheye.cpp
+++ b/toonz/sources/tnztools/assistants/assistantfisheye.cpp
@@ -24,6 +24,7 @@ public:
   const TStringId m_idCircle;
   const TStringId m_idGrid;
   const TStringId m_idGridDepth;
+  const TStringId m_idFlipGrids;
 
 protected:
   TAssistantPoint &m_center;
@@ -40,6 +41,7 @@ public:
     m_idCircle("circle"),
     m_idGrid("grid"),
     m_idGridDepth("gridDepth"),
+    m_idFlipGrids("flipGrids"),
     m_center( addPoint("center", TAssistantPoint::CircleCross) ),
     m_a( addPoint("a", TAssistantPoint::CircleFill, TPointD(200,   0)) ),
     m_b( addPoint("b", TAssistantPoint::Circle,     TPointD(  0, 200)) ),
@@ -51,6 +53,7 @@ public:
     addProperty( new TBoolProperty(m_idCircle.str(), getCircle()) );
     addProperty( new TBoolProperty(m_idGrid.str(), getGrid()) );
     addProperty( new TBoolProperty(m_idGridDepth.str(), getGridDepth()) );
+    addProperty( new TBoolProperty(m_idFlipGrids.str(), getFlipGrids()) );
   }
 
   static QString getLocalName()
@@ -61,6 +64,7 @@ public:
     setTranslation(m_idCircle, tr("Circle"));
     setTranslation(m_idGrid, tr("Grid"));
     setTranslation(m_idGridDepth, tr("Depth Grid"));
+    setTranslation(m_idFlipGrids, tr("Flip Grids"));
   }
 
   inline bool getCircle() const
@@ -69,6 +73,8 @@ public:
     { return data()[m_idGrid].getBool(); }
   inline bool getGridDepth() const
     { return data()[m_idGridDepth].getBool(); }
+  inline bool getFlipGrids() const
+    { return data()[m_idFlipGrids].getBool(); }
 
   void onDataChanged(const TVariant &value) override {
     TAssistant::onDataChanged(value);
@@ -120,6 +126,17 @@ private:
     m_gridD1.position = dgD1*da0/la0*da1 + dgD1*db0/lb0*db1 + center;
   }
 
+  void fixGridD1() {
+    TAffine em = calcEllipseMatrix();
+    TAffine emi = em.inv();
+    TPointD d0 = emi*m_gridD0.position;
+    TPointD d1 = emi*m_gridD1.position;
+    double l0 = norm2(d0);
+    double l1 = norm2(d1);
+    if ( l0 > TConsts::epsilon*TConsts::epsilon
+      && l1 > TConsts::epsilon*TConsts::epsilon )
+      m_gridD1.position = em*( d0*sqrt(l1/l0) );
+  }
 
 public:
   void onMovePoint(TAssistantPoint &point, const TPointD &position) override {
@@ -138,6 +155,9 @@ public:
     } else
     if (&point == &m_a || &point == &m_b) {
       fixBAndGrid(prevCenter, prevA, prevB);
+    } else
+    if (&point == &m_gridD0 || &point == &m_gridD1) {
+      fixGridD1();
     }
   }
 
@@ -204,9 +224,13 @@ public:
   }
 
 public:
-  void draw(TToolViewer *viewer, bool enabled) const override {
+  void draw(TToolViewer*, bool enabled) const override {
     TAffine ellipseMatrix = calcEllipseMatrix();
     if (ellipseMatrix.isZero()) return;
+    
+    TAffine ellipseMatrix2 = ellipseMatrix;
+    std::swap(ellipseMatrix.a11, ellipseMatrix.a12);
+    std::swap(ellipseMatrix.a21, ellipseMatrix.a22);
 
     // common data about viewport
     const TRectD oneBox(-1.0, -1.0, 1.0, 1.0);
@@ -219,6 +243,7 @@ public:
     double pixelSize = sqrt(tglGetPixelSize2());
     const double crossSize = 0.1;
     double alpha = getDrawingAlpha(enabled);
+    double gridAlpha = getDrawingGridAlpha();
     
     drawSegment( ellipseMatrix*TPointD(-crossSize, 0.0),
                  ellipseMatrix*TPointD( crossSize, 0.0), pixelSize, alpha);
@@ -226,50 +251,57 @@ public:
                  ellipseMatrix*TPointD(0.0,  crossSize), pixelSize, alpha);
     TAssistantEllipse::drawEllipse(ellipseMatrix, matrixInv, pixelSize, alpha);
 
+    const TPointD *bound = getGrid() && getGridDepth() ? &m_gridD0.position : nullptr;
+    const TPointD *boundA = nullptr;
+    const TPointD *boundB = bound;
+    if (getFlipGrids()) std::swap(boundA, boundB);
+    
     if (getGrid()) {
       TAssistantEllipse::drawParallelGrid(
-        ellipseMatrix,
-        m_grid0.position,
-        m_grid1.position,
-        true,
-        false,
-        false,
-        getDrawingGridAlpha() );
-      
-      std::swap(ellipseMatrix.a11, ellipseMatrix.a12);
-      std::swap(ellipseMatrix.a21, ellipseMatrix.a22);
-      
+        ellipseMatrix, m_grid0.position, m_grid1.position,
+        boundA, boundB, true, false, false, gridAlpha );
       TAssistantEllipse::drawParallelGrid(
-        ellipseMatrix,
-        m_grid0.position,
-        m_grid1.position,
-        true,
-        false,
-        false,
-        getDrawingGridAlpha() );
+        ellipseMatrix2, m_grid0.position, m_grid1.position,
+        boundA, boundB, true, false, false, gridAlpha );
     }
 
     if (getGridDepth()) {
       TAssistantEllipse::drawParallelGrid(
-        ellipseMatrix,
-        m_gridD0.position,
-        m_gridD1.position,
-        false,
-        true,
-        false,
-        getDrawingGridAlpha() );
-      
-      std::swap(ellipseMatrix.a11, ellipseMatrix.a12);
-      std::swap(ellipseMatrix.a21, ellipseMatrix.a22);
-      
+        ellipseMatrix, m_gridD0.position, m_gridD1.position,
+        boundB, boundA, false, true, false, gridAlpha );
       TAssistantEllipse::drawParallelGrid(
-        ellipseMatrix,
-        m_gridD0.position,
-        m_gridD1.position,
-        false,
-        true,
-        false,
-        getDrawingGridAlpha() );
+        ellipseMatrix2, m_gridD0.position, m_gridD1.position,
+        boundB, boundA, false, true, false, gridAlpha );
+    }
+    
+    if (bound) {
+      TPointD b = ellipseMatrix.inv()*(*bound);
+      double r = norm2(b);
+      if (r < 1 - TConsts::epsilon) {
+        double bx = b.x/sqrt(1 - b.y*b.y);
+        double by = b.y/sqrt(1 - b.x*b.x);
+        
+        TAngleRangeSet ranges;
+        ranges.add( TAngleRangeSet::fromDouble(-M_PI/2), TAngleRangeSet::fromDouble(M_PI/2) );
+        TAssistantEllipse::drawEllipseRanges(
+          ranges,
+          ellipseMatrix*TAffine::scale(bx, 1),
+          matrixInv,
+          pixelSize,
+          alpha );
+        
+        ranges.clear();
+        ranges.add( TAngleRangeSet::fromDouble(0.0), TAngleRangeSet::fromDouble(M_PI) );
+        TAssistantEllipse::drawEllipseRanges(
+          ranges,
+          ellipseMatrix*TAffine::scale(1, by),
+          matrixInv,
+          pixelSize,
+          alpha );
+        
+        TPointD bb = bound == boundA ? TPointD(0, 0) : b/sqrt(r);
+        drawSegment( ellipseMatrix*b, ellipseMatrix*bb, pixelSize, alpha );
+      }
     }
   }
 };