diff --git a/src/viewport.cpp b/src/viewport.cpp
index 6469b10c54..c41c2d3094 100644
--- a/src/viewport.cpp
+++ b/src/viewport.cpp
@@ -1886,6 +1886,18 @@ bool ScrollWindowTo(int x, int y, int z, Window *w, bool instant)
 	return true;
 }
 
+/**
+ * Scrolls the viewport in a window to a given location.
+ * @param tile    Desired tile to center on.
+ * @param w       %Window containing the viewport.
+ * @param instant Jump to the location instead of slowly moving to it.
+ * @return Destination of the viewport was changed (to activate other actions when the viewport is already at the desired position).
+ */
+bool ScrollWindowToTile(TileIndex tile, Window *w, bool instant)
+{
+	return ScrollWindowTo(TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE, -1, w, instant);
+}
+
 /**
  * Scrolls the viewport of the main window to a given location.
  * @param tile    Desired tile to center on.
diff --git a/src/viewport_func.h b/src/viewport_func.h
index 1e3c77107e..cc90a93b25 100644
--- a/src/viewport_func.h
+++ b/src/viewport_func.h
@@ -64,6 +64,7 @@ void SetTileSelectBigSize(int ox, int oy, int sx, int sy);
 
 void ViewportDoDraw(const ViewPort *vp, int left, int top, int right, int bottom);
 
+bool ScrollWindowToTile(TileIndex tile, Window *w, bool instant = false);
 bool ScrollWindowTo(int x, int y, int z, Window *w, bool instant = false);
 
 bool ScrollMainWindowToTile(TileIndex tile, bool instant = false);
diff --git a/src/waypoint_gui.cpp b/src/waypoint_gui.cpp
index 71c96b7fbe..c6e84d21bc 100644
--- a/src/waypoint_gui.cpp
+++ b/src/waypoint_gui.cpp
@@ -34,10 +34,20 @@ enum WaypointWindowWidgets {
 	WAYPVW_SHOW_VEHICLES,
 };
 
+/** GUI for accessing waypoints and buoys. */
 struct WaypointWindow : Window {
 private:
-	VehicleType vt;
-	Waypoint *wp;
+	VehicleType vt; ///< Vehicle type using the waypoint.
+	Waypoint *wp;   ///< Waypoint displayed by the window.
+
+	/**
+	 * Get the center tile of the waypoint.
+	 * @return The center tile if the waypoint exists, otherwise the tile with the waypoint name.
+	 */
+	TileIndex GetCenterTile() const
+	{
+		return this->wp->IsInUse() ? this->wp->train_station.GetCenterTile() : this->wp->xy;
+	}
 
 public:
 	WaypointWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
@@ -57,7 +67,7 @@ public:
 		this->flags4 |= WF_DISABLE_VP_SCROLL;
 
 		NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(WAYPVW_VIEWPORT);
-		nvp->InitializeViewport(this, this->wp->xy, ZOOM_LVL_MIN);
+		nvp->InitializeViewport(this, this->GetCenterTile(), ZOOM_LVL_MIN);
 
 		this->OnInvalidateData(0);
 	}
@@ -84,9 +94,9 @@ public:
 		switch (widget) {
 			case WAYPVW_CENTERVIEW: // scroll to location
 				if (_ctrl_pressed) {
-					ShowExtraViewPortWindow(this->wp->xy);
+					ShowExtraViewPortWindow(this->GetCenterTile());
 				} else {
-					ScrollMainWindowToTile(this->wp->xy);
+					ScrollMainWindowToTile(this->GetCenterTile());
 				}
 				break;
 
@@ -108,9 +118,7 @@ public:
 		/* Disable the widget for waypoints with no use */
 		this->SetWidgetDisabledState(WAYPVW_SHOW_VEHICLES, !this->wp->IsInUse());
 
-		int x = TileX(this->wp->xy) * TILE_SIZE;
-		int y = TileY(this->wp->xy) * TILE_SIZE;
-		ScrollWindowTo(x, y, -1, this, true);
+		ScrollWindowToTile(this->GetCenterTile(), this, true);
 	}
 
 	virtual void OnResize()