diff --git a/toonz/sources/tnztools/modifiers/modifiersimplify.cpp b/toonz/sources/tnztools/modifiers/modifiersimplify.cpp
index 85b66b3..df889c0 100644
--- a/toonz/sources/tnztools/modifiers/modifiersimplify.cpp
+++ b/toonz/sources/tnztools/modifiers/modifiersimplify.cpp
@@ -55,6 +55,7 @@ TModifierSimplify::modifyTrack(
     const TTrackPoint &p1 = track[i];
     if (!subTrack.empty() && tdistance2(p1.position, p0.position) < step2) {
       if (p0.pressure < p1.pressure) p0.pressure = p1.pressure;
+      if (i == track.size() - 1) p0.position = p1.position;
       p0.tilt          = p1.tilt;
       p0.time          = p1.time;
       p0.final         = p1.final;
@@ -71,8 +72,9 @@ TModifierSimplify::modifyTrack(
   if (track.fixedFinished())
     subTrack.fix_all();
   else
+  if (track.fixedSize())
     subTrack.fix_to(
-      subTrack.floorIndex( subTrack.indexByOriginalIndex(track.fixedSize()) ));
+      subTrack.floorIndex( subTrack.indexByOriginalIndex(track.fixedSize()-1) ));
   
   track.resetChanges();
 }
diff --git a/toonz/sources/tnztools/modifiers/modifiersmooth.cpp b/toonz/sources/tnztools/modifiers/modifiersmooth.cpp
index 449623f..953ea68 100644
--- a/toonz/sources/tnztools/modifiers/modifiersmooth.cpp
+++ b/toonz/sources/tnztools/modifiers/modifiersmooth.cpp
@@ -19,7 +19,7 @@ TModifierSmooth::Modifier::Modifier(TTrackHandler &handler, int radius):
 TTrackPoint
 TModifierSmooth::Modifier::calcPoint(double originalIndex) {
   return smoothedTrack
-       ? smoothedTrack->interpolateLinear(originalIndex)
+       ? smoothedTrack->interpolateLinear(originalIndex + radius)
        : TTrackModifier::calcPoint(originalIndex);
 }
 
diff --git a/toonz/sources/tnztools/modifiers/modifiertangents.cpp b/toonz/sources/tnztools/modifiers/modifiertangents.cpp
index c7f11e0..60a8704 100644
--- a/toonz/sources/tnztools/modifiers/modifiertangents.cpp
+++ b/toonz/sources/tnztools/modifiers/modifiertangents.cpp
@@ -100,8 +100,11 @@ TModifierTangents::modifyTrack(
   if (start > 1) --start;
   if (start < 0) start = 0;
   subTrack.truncate(start);
-  for(int i = start; i < track.size(); ++i)
-    subTrack.push_back(track[i], false);
+  for(int i = start; i < track.size(); ++i) {
+    TTrackPoint p = track[i];
+    p.originalIndex = i;
+    subTrack.push_back(p, false);
+  }
   
   // update tangents
   modifier->tangents.resize(start);
diff --git a/toonz/sources/tnztools/toonzvectorbrushtool.cpp b/toonz/sources/tnztools/toonzvectorbrushtool.cpp
index bb58efc..cc70f9c 100644
--- a/toonz/sources/tnztools/toonzvectorbrushtool.cpp
+++ b/toonz/sources/tnztools/toonzvectorbrushtool.cpp
@@ -509,6 +509,8 @@ ToonzVectorBrushTool::ToonzVectorBrushTool(std::string name, int targetType)
     , m_rasterTrack(0)
     , m_styleId(0)
     , m_targetType(targetType)
+    , m_snapped()
+    , m_snappedSelf()
     , m_modifiedRegion()
     , m_bluredBrush(0)
     , m_active(false)
@@ -963,6 +965,12 @@ void ToonzVectorBrushTool::inputPaintTracks(const TTrackList &tracks) {
     --track.pointsAdded;
   }
   
+  bool loop = m_snappedSelf
+           && track.fixedFinished()
+           && !track.empty()
+           && areAlmostEqual(track.front().position, track.back().position);
+  m_track.setLoop(loop);
+  
   invalidateRect += m_track.getLastModifiedRegion();
 
   TPointD halfThick(m_maxThick * 0.5, m_maxThick * 0.5);
@@ -1040,15 +1048,24 @@ void ToonzVectorBrushTool::handleMouseEvent(MouseEventType type,
   if (control != m_inputmanager.state.isKeyPressed(TKey::control))
     m_inputmanager.keyEvent(control, TKey::control, t, nullptr);
 
+  TPointD snappedPos = pos;
+  bool pickerMode = getViewer() && getViewer()->getGuidedStrokePickerMode();
+  bool snapEnabled = !pickerMode && (alt != m_snap.getValue());
+  snap(pos, snapEnabled, m_active);
+  if (m_snapped)
+    snappedPos = m_snapPoint;
+  if (m_snappedSelf && type == ME_UP)
+    snappedPos = m_snapPointSelf;
+  
   if (type == ME_MOVE) {
     qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
-    THoverList hovers(1, pos);
+    THoverList hovers(1, snappedPos);
     m_inputmanager.hoverEvent(hovers);
   } else
-  if (getViewer() && getViewer()->getGuidedStrokePickerMode()) {
-    if (type == ME_DOWN) getViewer()->doPickGuideStroke(pos);
+  if (pickerMode) {
+    if (type == ME_DOWN) getViewer()->doPickGuideStroke(snappedPos);
   } else {
-    m_inputmanager.trackEvent(e.isTablet(), 0, pos,
+    m_inputmanager.trackEvent(e.isTablet(), 0, snappedPos,
                               &e.m_pressure, nullptr,
                               type == ME_UP, t);
     m_inputmanager.processTracks();
@@ -1305,117 +1322,108 @@ void ToonzVectorBrushTool::flushTrackPoint() {
 
 //-------------------------------------------------------------------------------------------------------------
 
-void ToonzVectorBrushTool::checkStrokeSnapping(bool beforeMousePress,
-                                               bool invertCheck) {
-  if (Preferences::instance()->getVectorSnappingTarget() == 1)
-    return; // 0 - strokes, 1 - guides, 2 - all
+void ToonzVectorBrushTool::snap(const TPointD &pos, bool snapEnabled, bool withSelfSnap) {
+  bool oldSnapped      = m_snapped;
+  bool oldSnappedSelf  = m_snappedSelf;
+  TPointD oldPoint     = m_snapPoint;
+  TPointD oldPointSelf = m_snapPointSelf;
   
-  m_dragDraw = true;
+  m_snapped = m_snappedSelf = false;
   
-  if (invertCheck == m_snap.getValue())
-    return;
+  if (snapEnabled) { // snapping is active
+    double minDistance2 = m_minDistance2;
     
-  TVectorImageP vi(getImage(false));
-  if (!vi)
-    return;
-  
-  TPointD point;
-  bool found = false;
-  double minDistance2 = m_minDistance2;
-  int count = vi->getStrokeCount();
-  for(int i = 0; i < count; ++i) {
-    double w, d2;
-    TStroke *stroke = vi->getStroke(i);
-    if (!stroke->getNearestW(m_mousePos, w, d2) || d2 >= minDistance2)
-      continue;
-    minDistance2 = d2;
-    w = w > 0.001 ? (w < 0.999 ? w : 1.0) : 0.0;
-    point = stroke->getPoint(w);
-    found = true;
-  }
-  
-  if (beforeMousePress) {
-    if (found) {
-      m_firstSnapPoint = point;
-      m_foundFirstSnap = true;
-    }
-    return;
-  }
-  
-  if (!found) {
-    // compare to first point of current stroke
-    TPointD p = m_track.getFirstPoint();
-    double d2 = tdistance2(m_mousePos, p);
-    if (!(d2 < m_minDistance2))
-      return;
-    point        = p;
-    minDistance2 = d2;
-    m_snapSelf   = true;
-  }
-  
-  m_lastSnapPoint = point;
-  m_foundLastSnap = true;
-  if (minDistance2 < 2.0)
-    m_dragDraw = false;
-}
-
-//-------------------------------------------------------------------------------------------------------------
+    // 0 - strokes, 1 - guides, 2 - all
+    int target = Preferences::instance()->getVectorSnappingTarget();
+
+    // snap to guides
+    if (target != 0) {
+      if (TToolViewer *viewer = getViewer()) {
+        // find nearest vertical guide
+        int cnt = viewer->getVGuideCount();
+        for(int i = 0; i < cnt; ++i) {
+          double guide = viewer->getVGuide(i);
+          double d2 = guide - pos.y;
+          d2 *= d2; // we work with square of the distance
+          if (d2 < minDistance2) {
+            m_snapped = true;
+            m_snapPoint.x = pos.x;
+            m_snapPoint.y = guide;
+            minDistance2 = d2;
+          }
+        }
 
-void ToonzVectorBrushTool::checkGuideSnapping(bool beforeMousePress,
-                                              bool invertCheck) {
-  if (Preferences::instance()->getVectorSnappingTarget() == 0)
-    return; // 0 - strokes, 1 - guides, 2 - all
-  if (invertCheck == m_snap.getValue())
-    return;
-  TToolViewer *viewer = getViewer();
-  if (!viewer)
-    return;
+        // find nearest horizontal guide
+        cnt = viewer->getHGuideCount();
+        for(int i = 0; i < cnt; ++i) {
+          double guide = viewer->getHGuide(i);
+          double d2 = guide - pos.x;
+          d2 *= d2; // we work with square of the distance
+          if (d2 < minDistance2) {
+            m_snapped = true;
+            m_snapPoint.x = guide;
+            m_snapPoint.y = pos.y;
+            minDistance2 = d2;
+          }
+        }
+      }
+    }
 
-  // choose snaping fields to work
-  bool    &m_foundSnap = beforeMousePress ? m_foundFirstSnap : m_foundLastSnap;
-  TPointD &m_snapPoint = beforeMousePress ? m_firstSnapPoint : m_lastSnapPoint;
+    // snap to strokes
+    if (target != 1) {
+      if (TVectorImageP vi = getImage(false)) {
+        int count = vi->getStrokeCount();
+        for(int i = 0; i < count; ++i) {
+          double w, d2;
+          TStroke *stroke = vi->getStroke(i);
+          if (!stroke->getNearestW(pos, w, d2) || d2 >= minDistance2)
+            continue;
+          minDistance2 = d2;
+          w = w > 0.001 ? (w < 0.999 ? w : 1.0) : 0.0;
+          m_snapped = true;
+          m_snapPoint = stroke->getPoint(w);
+        }
+      }
+    
+      // finally snap to first point of track (self snap)
+      if (withSelfSnap && !m_track.isEmpty()) {
+        TPointD p = m_track.getFirstPoint();
+        double d2 = tdistance2(pos, p);
+        if (d2 < m_minDistance2) {
+          m_snappedSelf = true;
+          m_snapPointSelf = p;
+        }
+      }
+    }
+  } // snapping is active
   
-  // init min distance, with using snapPoint found by checkStrokeSnapping
-  double minDistance2 = m_minDistance2;
-  if (m_foundSnap) {
-    double d2 = tdistance2(m_snapPoint, m_mousePos);
-    if (d2 < minDistance2) minDistance2 = d2;
+  // invalidate rect
+  TRectD invalidateRect;
+  double radius = 8.0*m_pixelSize;
+  TPointD halfSize(radius, radius);
+
+  if ( oldSnapped != m_snapped
+    || !areAlmostEqual(oldPoint, m_snapPoint) )
+  {
+    if (oldSnapped) invalidateRect += TRectD(oldPoint - halfSize, oldPoint + halfSize);
+    if (m_snapped)  invalidateRect += TRectD(m_snapPoint - halfSize, m_snapPoint + halfSize);
   }
   
-  // find nearest vertical guide
-  int cnt = viewer->getVGuideCount();
-  for(int i = 0; i < cnt; ++i) {
-    double guide = viewer->getVGuide(i);
-    double d2 = guide - m_mousePos.y;
-    d2 *= d2; // we work with square of the distance
-    if (d2 < minDistance2) {
-      m_foundSnap = true;
-      m_snapPoint.x = m_mousePos.x;
-      m_snapPoint.y = guide;
-      m_snapSelf = false;
-      minDistance2 = d2;
-    }
-  }
-
-  // find nearest horizontal guide
-  cnt = viewer->getHGuideCount();
-  for(int i = 0; i < cnt; ++i) {
-    double guide = viewer->getHGuide(i);
-    double d2 = guide - m_mousePos.x;
-    d2 *= d2; // we work with square of the distance
-    if (d2 < minDistance2) {
-      m_foundSnap = true;
-      m_snapPoint.x = guide;
-      m_snapPoint.y = m_mousePos.y;
-      m_snapSelf = false;
-      minDistance2 = d2;
-    }
+  if ( oldSnappedSelf != m_snappedSelf
+    || !areAlmostEqual(oldPointSelf, m_snapPointSelf) )
+  {
+    if (oldSnappedSelf) invalidateRect += TRectD(oldPointSelf - halfSize, oldPointSelf + halfSize);
+    if (m_snappedSelf)  invalidateRect += TRectD(m_snapPointSelf - halfSize, m_snapPointSelf + halfSize);
   }
+  
+  if (!invalidateRect.isEmpty())
+    invalidate(invalidateRect);
 }
 
 //-------------------------------------------------------------------------------------------------------------
 
 void ToonzVectorBrushTool::draw() {
+  m_pixelSize = getPixelSize();
   m_inputmanager.draw();
   
   /*--ショートカットでのツール切り替え時に赤点が描かれるのを防止する--*/
@@ -1423,29 +1431,19 @@ void ToonzVectorBrushTool::draw() {
       !Preferences::instance()->getShow0ThickLines())
     return;
 
-  TImageP img = getImage(false, 1);
-
-  // Draw track
+  // draw track
   tglColor(m_isPrompting ? TPixel32::Green : m_currentColor);
   m_track.drawAllFragments();
-
-  m_pixelSize  = getPixelSize();
   
-  // snapping
-  TVectorImageP vi = img;
-  if (m_snap.getValue() != m_altPressed) {
-    double thick = 6.0 * m_pixelSize;
-    if (m_foundFirstSnap) {
-      tglColor(TPixelD(0.1, 0.9, 0.1));
-      tglDrawCircle(m_firstSnapPoint, thick);
-    }
-
-    TThickPoint point2;
-
-    if (m_foundLastSnap) {
-      tglColor(TPixelD(0.1, 0.9, 0.1));
-      tglDrawCircle(m_lastSnapPoint, thick);
-    }
+  // draw snapping
+  double snapMarkRadius = 6.0 * m_pixelSize;
+  if (m_snapped) {
+    tglColor(TPixelD(0.1, 0.9, 0.1));
+    tglDrawCircle(m_snapPoint, snapMarkRadius);
+  }
+  if (m_snappedSelf) {
+    tglColor(TPixelD(0.9, 0.9, 0.1));
+    tglDrawCircle(m_snapPointSelf, snapMarkRadius);
   }
 
   // frame range
diff --git a/toonz/sources/tnztools/toonzvectorbrushtool.h b/toonz/sources/tnztools/toonzvectorbrushtool.h
index b43d5b1..6b64f7a 100644
--- a/toonz/sources/tnztools/toonzvectorbrushtool.h
+++ b/toonz/sources/tnztools/toonzvectorbrushtool.h
@@ -156,14 +156,14 @@ public:
                            bool autoGroup = false, bool autoFill = false,
                            bool drawFirstStroke = true,
                            bool drawLastStroke = true, bool withUndo = true);
-  void checkGuideSnapping(bool beforeMousePress, bool invertCheck);
-  void checkStrokeSnapping(bool beforeMousePress, bool invertCheck);
   bool doGuidedAutoInbetween(TFrameId cFid, const TVectorImageP &cvi,
                              TStroke *cStroke, bool breakAngles,
                              bool autoGroup = false, bool autoFill = false,
                              bool drawStroke = true);
 
-private:
+protected:
+  void snap(const TPointD &pos, bool snapEnabled, bool withSelfSnap = false);
+
   enum MouseEventType { ME_DOWN, ME_DRAG, ME_UP, ME_MOVE };
   void handleMouseEvent(MouseEventType type, const TPointD &pos,
                         const TMouseEvent &e);
@@ -211,6 +211,12 @@ protected:
   int m_col, m_firstFrame, m_veryFirstFrame,
       m_veryFirstCol, m_targetType;
   double m_pixelSize, m_currThickness, m_minDistance2;
+  
+  bool m_snapped; // bwtodo: init
+  bool m_snappedSelf;
+  TPointD m_snapPoint;
+  TPointD m_snapPointSelf;
+  
   bool m_foundFirstSnap = false, m_foundLastSnap = false, m_dragDraw = true,
        m_altPressed = false, m_snapSelf = false;
   TRectD m_modifiedRegion;