{ "cells": [ { "cell_type": "markdown", "id": "a0475cb8", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "# The 30 Degree Rule\n", "\n", "## Intro\n", "\n", "The 30 degree rule states that the cue ball, when colliding with a ball over a wide range of cut angles, will be deflected roughly 30 degrees from it's initial course after the collision. It is more of a *rule of thumb* used by pool players to improve their game, rather than a truism of pool physics.\n", "\n", "In this example, we will setup simulations that test the 30 degree rule and some of the physics equations defined by [Dr. Dave Billiards](https://drdavebilliards.com/).\n", "\n", "## Assumptions\n", "\n", "We'll use one of pooltool's simpler ball-ball models which assumes perfectly elastic and frictionless ball-ball collisions. Read more [here](https://ekiefl.github.io/2020/04/24/pooltool-theory/#section-ii-ball-ball-interactions).\n", "\n", "Importantly, the cue ball must be rolling (without slippage) when it contacts the object ball. Otherwise, the 30-degree rule will not hold. As an extreme example of this, a cue ball with no spin will deflect off the object ball along the [tangent line](https://billiards.colostate.edu/faq/stun/90-degree-rule/).\n", "\n", "## Definitions\n", "\n", "**The rule, stated in full:**\n", "\n", "> The 30° rule states that for a rolling cue ball (CB) shot, over a wide range of cut angles, between a 1/4-ball hit (49 degree cut) and 3/4-ball hit (14 degree cut), the CB will deflect or carom off by very close to 30° (the “natural angle“) from its original direction after hitting the object ball (OB). If you want to be more precise, the angle is a little more (about 34°) closer to a 1/2-ball hit and a little less (about 27°) closer to a 1/4-ball or 3/4-ball hit.\n", "\n", "*(source: [https://billiards.colostate.edu/faq/30-90-rules/30-degree-rule/](https://billiards.colostate.edu/faq/30-90-rules/30-degree-rule/))*\n", "\n", "**The carom angle**\n", "\n", "The carom angle is the angle that the rule claims is 30 degrees. Formally, it is the angle between the velocity of the cue ball directly before impact, and the velocity of the cue ball after the collision once the cue ball is no longer sliding on the cloth. We will see that this angle is independent of the cue's initial speed.\n", "\n", "**Ball-hit fraction and cut angle**\n", "\n", "- Ball-hit fraction, $f$, describes the fraction of overlap between the cue ball and object ball, projected in the direction of the aiming line.\n", "- Cut angle, $\\phi$, refers to the angle that the cue ball glances the object ball, where $0$ refers to a full ball hit (straight on), and $90$ refers to the lower bound of the thinnest hit possible.\n", "\n", "These two are visualized in this diagram, where $f = \\text{ball overlap} / (2R)$:\n", "\n", "\n", "\n", "*(source: [https://billiards.colostate.edu/technical_proofs/new/TP_A-23.pdf](https://billiards.colostate.edu/technical_proofs/new/TP_A-23.pdf))*\n", "\n", "Establishing the relationship between these quantities is important, since the 30 degree rule makes reference to both cut angle and ball-hit fraction. One can calculate the ball-hit fraction from cut angle with the following equation:\n", "\n", "$$\n", "f(\\phi) = 1 - \\sin{\\phi}\n", "$$" ] }, { "cell_type": "markdown", "id": "329f9243", "metadata": {}, "source": [ "## Simulating a collision\n", "\n", "To start, we'll need to create a billiards system. That means defining a table, a cue stick, and a collection of balls.\n", "\n", "We'll start with a table. Since we don't want collisions with cushions to interfere with our trajectory, let's make an unrealistically large $10\\text{m} \\times 10\\text{m}$ [Table](../autoapi/pooltool/index.rst#pooltool.Table)." ] }, { "cell_type": "code", "execution_count": 1, "id": "0ab855d2", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:49.959700Z", "iopub.status.busy": "2026-03-15T06:51:49.959391Z", "iopub.status.idle": "2026-03-15T06:51:52.468511Z", "shell.execute_reply": "2026-03-15T06:51:52.467319Z" }, "lines_to_next_cell": 2 }, "outputs": [], "source": [ "import pooltool as pt\n", "\n", "table_specs = pt.objects.BilliardTableSpecs(l=10, w=10)\n", "table = pt.Table.from_table_specs(table_specs)" ] }, { "cell_type": "markdown", "id": "c84af7d9", "metadata": {}, "source": [ "Next, we'll create two [Ball](../autoapi/pooltool/index.rst#pooltool.Ball) objects." ] }, { "cell_type": "code", "execution_count": 2, "id": "098c6d65", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:52.471464Z", "iopub.status.busy": "2026-03-15T06:51:52.471067Z", "iopub.status.idle": "2026-03-15T06:51:52.876446Z", "shell.execute_reply": "2026-03-15T06:51:52.875150Z" } }, "outputs": [], "source": [ "cue_ball = pt.Ball.create(\"cue\", xy=(2.5, 1.5))\n", "obj_ball = pt.Ball.create(\"obj\", xy=(2.5, 3.0))" ] }, { "cell_type": "markdown", "id": "5772615e", "metadata": {}, "source": [ "Next, we'll need a [Cue](../autoapi/pooltool/index.rst#pooltool.Cue)." ] }, { "cell_type": "code", "execution_count": 3, "id": "11a26169", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:52.879384Z", "iopub.status.busy": "2026-03-15T06:51:52.879173Z", "iopub.status.idle": "2026-03-15T06:51:52.883214Z", "shell.execute_reply": "2026-03-15T06:51:52.881763Z" } }, "outputs": [], "source": [ "cue = pt.Cue(cue_ball_id=\"cue\")" ] }, { "cell_type": "markdown", "id": "26714c28", "metadata": {}, "source": [ "Finally, we'll need to wrap these objects up into a [System](../autoapi/pooltool/index.rst#pooltool.System). We'll call this our system *template*, with the intention of reusing it for many different shots." ] }, { "cell_type": "code", "execution_count": 4, "id": "13b3d613", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:52.885844Z", "iopub.status.busy": "2026-03-15T06:51:52.885640Z", "iopub.status.idle": "2026-03-15T06:51:52.889024Z", "shell.execute_reply": "2026-03-15T06:51:52.888129Z" } }, "outputs": [], "source": [ "system_template = pt.System(\n", " table=table,\n", " cue=cue,\n", " balls=(cue_ball, obj_ball),\n", ")" ] }, { "cell_type": "markdown", "id": "937977d6", "metadata": {}, "source": [ "Let's set up a shot by aiming at the object ball with a cut angle of 30 degrees. There is a small clash in terminology here, because in pooltool, `phi` is an angle defined with respect to the table, not the cut angle:\n", "\n", "\n", "\n", "So in the function call below, `pt.aim.at_ball(system, \"obj\", cut=30)` returns the angle `phi` that the cue ball should be directed at such that a cut angle of 30 degrees with the object ball is achieved." ] }, { "cell_type": "code", "execution_count": 5, "id": "ef0802b2", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:52.891426Z", "iopub.status.busy": "2026-03-15T06:51:52.891217Z", "iopub.status.idle": "2026-03-15T06:51:53.004144Z", "shell.execute_reply": "2026-03-15T06:51:53.003050Z" } }, "outputs": [], "source": [ "# Creates a deep copy of the template\n", "system = system_template.copy()\n", "\n", "phi = pt.aim.at_ball(system, \"obj\", cut=30)\n", "system.cue.set_state(V0=3, phi=phi, b=0.4)" ] }, { "cell_type": "markdown", "id": "232cb6c2", "metadata": {}, "source": [ "Now, we [simulate](../autoapi/pooltool/index.rst#pooltool.simulate) the shot and then [continuize](../autoapi/pooltool/evolution/continuize/index.html#pooltool.evolution.continuize.continuize) it to store ball state data (like coordinates) in $10\\text{ms}$ timestep intervals." ] }, { "cell_type": "code", "execution_count": 6, "id": "d29a2bda", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:53.007176Z", "iopub.status.busy": "2026-03-15T06:51:53.006883Z", "iopub.status.idle": "2026-03-15T06:51:53.255275Z", "shell.execute_reply": "2026-03-15T06:51:53.253495Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "System simulated: True\n" ] } ], "source": [ "# Create a default physics engine, then overwrite ball-ball model with frictionless, elastic model.\n", "engine = pt.physics.PhysicsEngine()\n", "engine.resolver.ball_ball = pt.physics.ball_ball_models[pt.physics.BallBallModel.FRICTIONLESS_ELASTIC]()\n", "\n", "pt.simulate(system, engine=engine, inplace=True)\n", "pt.continuize(system, dt=0.01, inplace=True)\n", "\n", "print(f\"System simulated: {system.simulated}\")" ] }, { "cell_type": "markdown", "id": "0debc0af", "metadata": {}, "source": [ "## Visualizing the collision" ] }, { "cell_type": "markdown", "id": "cbd37f0d", "metadata": {}, "source": [ "If you have a graphics card, you can immediately visualize this shot in 3D with\n", "\n", "```python\n", "pt.show(system)\n", "```\n", "\n", "Since that can't be embedded into the documentation, we'll instead plot the trajectory of the cue ball and object ball by accessing ther historical states." ] }, { "cell_type": "code", "execution_count": 7, "id": "ffab2ecc", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:53.258426Z", "iopub.status.busy": "2026-03-15T06:51:53.258212Z", "iopub.status.idle": "2026-03-15T06:51:53.265826Z", "shell.execute_reply": "2026-03-15T06:51:53.264508Z" } }, "outputs": [ { "data": { "text/plain": [ "pooltool.objects.ball.datatypes.BallHistory" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cue_ball = system.balls[\"cue\"]\n", "obj_ball = system.balls[\"obj\"]\n", "cue_history = cue_ball.history_cts\n", "obj_history = obj_ball.history_cts\n", "type(cue_history)" ] }, { "cell_type": "markdown", "id": "3103fb30", "metadata": {}, "source": [ "The [BallHistory](../autoapi/pooltool/objects/index.rst#pooltool.objects.BallHistory) holds the ball's historical states, each stored as a [BallState](../autoapi/pooltool/objects/index.rst#pooltool.objects.BallState) object. Each attribute of the ball states can be concatenated into numpy arrays with the [BallHistory.vectorize](../autoapi/pooltool/objects/index.rst#pooltool.objects.BallHistory.vectorize) method." ] }, { "cell_type": "code", "execution_count": 8, "id": "e82a222e", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:53.268409Z", "iopub.status.busy": "2026-03-15T06:51:53.268141Z", "iopub.status.idle": "2026-03-15T06:51:53.274256Z", "shell.execute_reply": "2026-03-15T06:51:53.272910Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1305, 3, 3)\n", "(1305,)\n", "(1305,)\n" ] } ], "source": [ "rvw_cue, s_cue, t_cue = cue_history.vectorize()\n", "rvw_obj, s_obj, t_obj = obj_history.vectorize()\n", "\n", "print(rvw_cue.shape)\n", "print(s_cue.shape)\n", "print(t_cue.shape)" ] }, { "cell_type": "markdown", "id": "46a2bc8b", "metadata": {}, "source": [ "We can grab the xy-coordinates from the `rvw` array by with the following." ] }, { "cell_type": "code", "execution_count": 9, "id": "de1ed3f0", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:53.276677Z", "iopub.status.busy": "2026-03-15T06:51:53.276464Z", "iopub.status.idle": "2026-03-15T06:51:53.280828Z", "shell.execute_reply": "2026-03-15T06:51:53.279851Z" } }, "outputs": [ { "data": { "text/plain": [ "(1305, 2)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "coords_cue = rvw_cue[:, 0, :2]\n", "coords_obj = rvw_obj[:, 0, :2]\n", "coords_cue.shape" ] }, { "cell_type": "code", "execution_count": 10, "id": "9a2d85fe", "metadata": { "editable": true, "execution": { "iopub.execute_input": "2026-03-15T06:51:53.283225Z", "iopub.status.busy": "2026-03-15T06:51:53.283005Z", "iopub.status.idle": "2026-03-15T06:51:55.397244Z", "shell.execute_reply": "2026-03-15T06:51:55.396142Z" }, "lines_to_next_cell": 2, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import plotly.graph_objects as go\n", "import plotly.io as pio\n", "\n", "pio.renderers.default = \"sphinx_gallery\"\n", "\n", "fig = go.Figure()\n", "fig.add_trace(\n", " go.Scatter(x=coords_cue[:, 0], y=coords_cue[:, 1], mode=\"lines\", name=\"cue\")\n", ")\n", "fig.add_trace(\n", " go.Scatter(x=coords_obj[:, 0], y=coords_obj[:, 1], mode=\"lines\", name=\"obj\")\n", ")\n", "fig.update_layout(\n", " title=\"Ball trajectories\",\n", " xaxis_title=\"X [m]\",\n", " yaxis_title=\"Y [m]\",\n", " yaxis_scaleanchor=\"x\",\n", " yaxis_scaleratio=1,\n", " width=600,\n", " template=\"presentation\",\n", ")\n", "\n", "fig.show()" ] }, { "cell_type": "markdown", "id": "d714b7a7", "metadata": {}, "source": [ "## Calculating the carom angle\n", "\n", "One could calculate the carom angle for the above trajectory by manually splicing the trajectory coordinates of the cue ball and determining ball direction by comparing temporally adjacent coordinates. However, pooltool has much more precise methods for dissecting shot dynamics.\n", "\n", "As mentioned before, the carom angle is the angle between the cue ball velocity right before collision, and the cue ball velocity post-collision, once the ball has stopped sliding on the cloth. Hidden somewhere in the system **event list** one can find the events corresponding to these precise moments in time:" ] }, { "cell_type": "code", "execution_count": 11, "id": "2b72e729", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:55.399722Z", "iopub.status.busy": "2026-03-15T06:51:55.399499Z", "iopub.status.idle": "2026-03-15T06:51:55.405201Z", "shell.execute_reply": "2026-03-15T06:51:55.404298Z" } }, "outputs": [ { "data": { "text/plain": [ "[\n", " ├── type : none\n", " ├── time : 0\n", " └── agents : ('dummy',),\n", " \n", " ├── type : stick_ball\n", " ├── time : 0.0\n", " └── agents : ('cue_stick', 'cue'),\n", " \n", " ├── type : sliding_rolling\n", " ├── time : 6.467004657784513e-17\n", " └── agents : ('cue',),\n", " \n", " ├── type : ball_ball\n", " ├── time : 0.41327067829120856\n", " └── agents : ('cue', 'obj'),\n", " \n", " ├── type : sliding_rolling\n", " ├── time : 0.8533152351332376\n", " └── agents : ('cue',),\n", " \n", " ├── type : sliding_rolling\n", " ├── time : 0.8533152351332378\n", " └── agents : ('obj',)]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "system.events[:6]" ] }, { "cell_type": "markdown", "id": "c87c88a4", "metadata": {}, "source": [ "Programatically, we can pick out these two events of interest with event selection syntax.\n", "\n", "Since there is only one ball-ball collision, it's easy to select with [filter_type](../autoapi/pooltool/events/index.rst#pooltool.events.filter_type):" ] }, { "cell_type": "code", "execution_count": 12, "id": "826ceca7", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:55.407632Z", "iopub.status.busy": "2026-03-15T06:51:55.407398Z", "iopub.status.idle": "2026-03-15T06:51:55.412044Z", "shell.execute_reply": "2026-03-15T06:51:55.410929Z" } }, "outputs": [ { "data": { "text/plain": [ "\n", " ├── type : ball_ball\n", " ├── time : 0.41327067829120856\n", " └── agents : ('cue', 'obj')" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "collision = pt.events.filter_type(system.events, pt.EventType.BALL_BALL)[0]\n", "collision" ] }, { "cell_type": "markdown", "id": "37edcb1e", "metadata": {}, "source": [ "To get the event when the cue ball stops sliding, we can similarly try filtering by the sliding to rolling transition event:" ] }, { "cell_type": "code", "execution_count": 13, "id": "c1154201", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:55.414387Z", "iopub.status.busy": "2026-03-15T06:51:55.414175Z", "iopub.status.idle": "2026-03-15T06:51:55.418346Z", "shell.execute_reply": "2026-03-15T06:51:55.417552Z" } }, "outputs": [ { "data": { "text/plain": [ "[\n", " ├── type : sliding_rolling\n", " ├── time : 6.467004657784513e-17\n", " └── agents : ('cue',),\n", " \n", " ├── type : sliding_rolling\n", " ├── time : 0.8533152351332376\n", " └── agents : ('cue',),\n", " \n", " ├── type : sliding_rolling\n", " ├── time : 0.8533152351332378\n", " └── agents : ('obj',),\n", " \n", " ├── type : sliding_rolling\n", " ├── time : 2.9625555398608876\n", " └── agents : ('obj',),\n", " \n", " ├── type : sliding_rolling\n", " ├── time : 4.757678838982956\n", " └── agents : ('obj',),\n", " \n", " ├── type : sliding_rolling\n", " ├── time : 5.629048790973683\n", " └── agents : ('cue',),\n", " \n", " ├── type : sliding_rolling\n", " ├── time : 10.713553351961682\n", " └── agents : ('cue',)]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pt.events.filter_type(system.events, pt.EventType.SLIDING_ROLLING)" ] }, { "cell_type": "markdown", "id": "81d460b3", "metadata": {}, "source": [ "But there are many sliding to rolling transition events, and to make matters worse, they are shared by both the cue ball and the object ball. What we need is the **first** **sliding to rolling** transition that the **cue ball** undergoes **after** the **ball-ball** collision. We can achieve this multi-criteria query with [filter_events](../autoapi/pooltool/events/index.rst#pooltool.events.filter_events):" ] }, { "cell_type": "code", "execution_count": 14, "id": "2f0cea92", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:55.420729Z", "iopub.status.busy": "2026-03-15T06:51:55.420491Z", "iopub.status.idle": "2026-03-15T06:51:55.425208Z", "shell.execute_reply": "2026-03-15T06:51:55.424365Z" } }, "outputs": [ { "data": { "text/plain": [ "\n", " ├── type : sliding_rolling\n", " ├── time : 0.8533152351332376\n", " └── agents : ('cue',)" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "transition = pt.events.filter_events(\n", " system.events,\n", " pt.events.by_time(t=collision.time, after=True),\n", " pt.events.by_ball(\"cue\"),\n", " pt.events.by_type(pt.EventType.SLIDING_ROLLING),\n", ")[0]\n", "transition" ] }, { "cell_type": "markdown", "id": "dd8332a2", "metadata": {}, "source": [ "Now, we can dive into these two events and pull out the cue ball velocities we need to calculate the carom angle." ] }, { "cell_type": "code", "execution_count": 15, "id": "c3bdca19", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:55.427566Z", "iopub.status.busy": "2026-03-15T06:51:55.427331Z", "iopub.status.idle": "2026-03-15T06:51:55.431478Z", "shell.execute_reply": "2026-03-15T06:51:55.430463Z" }, "lines_to_next_cell": 2 }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The carom angle is 0.6 degrees\n" ] } ], "source": [ "# Velocity prior to impact\n", "velocity_initial = collision.get_ball(\"cue\", initial=True).vel[:2]\n", "\n", "# Velocity post sliding\n", "# We choose the \"final\" here for posterity, but the velocity is the same both before and after resolving the transition.\n", "velocity_final = transition.get_ball(\"cue\", initial=False).vel[:2]\n", "\n", "carom_angle = pt.ptmath.utils.angle_between_vectors(velocity_final, velocity_initial)\n", "\n", "print(f\"The carom angle is {carom_angle:.1f} degrees\")" ] }, { "cell_type": "markdown", "id": "3bbe7aef", "metadata": {}, "source": [ "## Carom angle as a function of cut angle" ] }, { "cell_type": "markdown", "id": "a3524ecc", "metadata": { "lines_to_next_cell": 2 }, "source": [ "We calculated the carom angle for a single cut angle, 30 degrees. Let's write a function called `get_carom_angle` so we can do that repeatedly for different cut angles." ] }, { "cell_type": "code", "execution_count": 16, "id": "f710dc79", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:55.434001Z", "iopub.status.busy": "2026-03-15T06:51:55.433726Z", "iopub.status.idle": "2026-03-15T06:51:55.438166Z", "shell.execute_reply": "2026-03-15T06:51:55.437239Z" }, "lines_to_next_cell": 2 }, "outputs": [], "source": [ "def get_carom_angle(system: pt.System) -> float:\n", " assert system.simulated\n", "\n", " collision = pt.events.filter_type(system.events, pt.EventType.BALL_BALL)[0]\n", " transition = pt.events.filter_events(\n", " system.events,\n", " pt.events.by_time(t=collision.time, after=True),\n", " pt.events.by_ball(\"cue\"),\n", " pt.events.by_type(pt.EventType.SLIDING_ROLLING),\n", " )[0]\n", "\n", " velocity_final = transition.get_ball(\"cue\", initial=False).state.rvw[1, :2]\n", " velocity_initial = collision.get_ball(\"cue\", initial=True).state.rvw[1, :2]\n", "\n", " return pt.ptmath.utils.angle_between_vectors(velocity_final, velocity_initial)" ] }, { "cell_type": "markdown", "id": "ca540c4f", "metadata": { "lines_to_next_cell": 2 }, "source": [ "`get_carom_angle` assumes the passed system has already been simulated, so we'll need another function to take care of that. We'll cue stick speed and cut angle as parameters." ] }, { "cell_type": "code", "execution_count": 17, "id": "bf386ee0", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:55.440538Z", "iopub.status.busy": "2026-03-15T06:51:55.440322Z", "iopub.status.idle": "2026-03-15T06:51:55.444043Z", "shell.execute_reply": "2026-03-15T06:51:55.443171Z" }, "lines_to_next_cell": 2 }, "outputs": [], "source": [ "def simulate_experiment(V0: float, cut_angle: float) -> pt.System:\n", " system = system_template.copy()\n", " phi = pt.aim.at_ball(system, \"obj\", cut=cut_angle)\n", " system.cue.set_state(V0=V0, phi=phi, b=0.4)\n", " pt.simulate(system, engine=engine, inplace=True)\n", " return system" ] }, { "cell_type": "markdown", "id": "2ba3e216", "metadata": { "lines_to_next_cell": 2 }, "source": [ "We'll also want the ball hit fraction:" ] }, { "cell_type": "code", "execution_count": 18, "id": "8673f181", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:55.446281Z", "iopub.status.busy": "2026-03-15T06:51:55.446072Z", "iopub.status.idle": "2026-03-15T06:51:55.449386Z", "shell.execute_reply": "2026-03-15T06:51:55.448431Z" } }, "outputs": [], "source": [ "import numpy as np\n", "\n", "def get_ball_hit_fraction(cut_angle: float) -> float:\n", " return 1 - np.sin(cut_angle * np.pi / 180)" ] }, { "cell_type": "markdown", "id": "336b59ec", "metadata": {}, "source": [ "With these functions, we are ready to simulate how carom angle varies as a function of cut angle." ] }, { "cell_type": "code", "execution_count": 19, "id": "a414c186", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:55.452202Z", "iopub.status.busy": "2026-03-15T06:51:55.451967Z", "iopub.status.idle": "2026-03-15T06:51:55.669598Z", "shell.execute_reply": "2026-03-15T06:51:55.668475Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "cut_angle=np.float64(2.0)\n", "cut_angle=np.float64(3.7551020408163263)\n", "cut_angle=np.float64(5.5102040816326525)\n", "cut_angle=np.float64(7.26530612244898)\n", "cut_angle=np.float64(9.020408163265305)\n", "cut_angle=np.float64(10.775510204081632)\n", "cut_angle=np.float64(12.53061224489796)\n", "cut_angle=np.float64(14.285714285714285)\n", "cut_angle=np.float64(16.04081632653061)\n", "cut_angle=np.float64(17.79591836734694)\n", "cut_angle=np.float64(19.551020408163264)\n", "cut_angle=np.float64(21.30612244897959)\n", "cut_angle=np.float64(23.06122448979592)\n", "cut_angle=np.float64(24.816326530612244)\n", "cut_angle=np.float64(26.57142857142857)\n", "cut_angle=np.float64(28.3265306122449)\n", "cut_angle=np.float64(30.081632653061224)\n", "cut_angle=np.float64(31.83673469387755)\n", "cut_angle=np.float64(33.59183673469388)\n", "cut_angle=np.float64(35.3469387755102)\n", "cut_angle=np.float64(37.10204081632653)\n", "cut_angle=np.float64(38.857142857142854)\n", "cut_angle=np.float64(40.61224489795918)\n", "cut_angle=np.float64(42.36734693877551)\n", "cut_angle=np.float64(44.12244897959184)\n", "cut_angle=np.float64(45.87755102040816)\n", "cut_angle=np.float64(47.63265306122449)\n", "cut_angle=np.float64(49.38775510204081)\n", "cut_angle=np.float64(51.14285714285714)\n", "cut_angle=np.float64(52.89795918367347)\n", "cut_angle=np.float64(54.6530612244898)\n", "cut_angle=np.float64(56.40816326530612)\n", "cut_angle=np.float64(58.16326530612245)\n", "cut_angle=np.float64(59.91836734693877)\n", "cut_angle=np.float64(61.6734693877551)\n", "cut_angle=np.float64(63.42857142857142)\n", "cut_angle=np.float64(65.18367346938776)\n", "cut_angle=np.float64(66.93877551020408)\n", "cut_angle=np.float64(68.6938775510204)\n", "cut_angle=np.float64(70.44897959183673)\n", "cut_angle=np.float64(72.20408163265306)\n", "cut_angle=np.float64(73.95918367346938)\n", "cut_angle=np.float64(75.71428571428571)\n", "cut_angle=np.float64(77.46938775510203)\n", "cut_angle=np.float64(79.22448979591836)\n", "cut_angle=np.float64(80.9795918367347)\n", "cut_angle=np.float64(82.73469387755102)\n", "cut_angle=np.float64(84.48979591836735)\n", "cut_angle=np.float64(86.24489795918367)\n", "cut_angle=np.float64(88.0)\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
phiftheta
02.0000000.9651010.086763
13.7551020.9345080.160719
25.5102040.9039770.229332
37.2653060.8735360.292464
49.0204080.8432140.350121
510.7755100.8130390.399313
612.5306120.7830390.442581
714.2857140.7532430.478738
816.0408160.7236780.508446
917.7959180.6943730.532765
\n", "
" ], "text/plain": [ " phi f theta\n", "0 2.000000 0.965101 0.086763\n", "1 3.755102 0.934508 0.160719\n", "2 5.510204 0.903977 0.229332\n", "3 7.265306 0.873536 0.292464\n", "4 9.020408 0.843214 0.350121\n", "5 10.775510 0.813039 0.399313\n", "6 12.530612 0.783039 0.442581\n", "7 14.285714 0.753243 0.478738\n", "8 16.040816 0.723678 0.508446\n", "9 17.795918 0.694373 0.532765" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "\n", "data = {\n", " \"phi\": [],\n", " \"f\": [],\n", " \"theta\": [],\n", "}\n", "\n", "V0 = 2.5\n", "\n", "for cut_angle in np.linspace(2, 88, 50):\n", " print(f\"{cut_angle=}\")\n", " system = simulate_experiment(V0, cut_angle)\n", " data[\"theta\"].append(get_carom_angle(system))\n", " data[\"f\"].append(get_ball_hit_fraction(cut_angle))\n", " data[\"phi\"].append(cut_angle)\n", "\n", "frame = pd.DataFrame(data)\n", "frame.head(10)" ] }, { "cell_type": "markdown", "id": "484d1311", "metadata": {}, "source": [ "From this dataframe we can make some plots. On top of the ball-hit fraction, plot, I'll create a box between a $1/4$ ball hit and a $3/4$ ball hit, since this is the carom angle range that the 30-degree rule is defined with respect to." ] }, { "cell_type": "code", "execution_count": 20, "id": "e6cf2257", "metadata": { "editable": true, "execution": { "iopub.execute_input": "2026-03-15T06:51:55.672392Z", "iopub.status.busy": "2026-03-15T06:51:55.672147Z", "iopub.status.idle": "2026-03-15T06:51:57.857480Z", "shell.execute_reply": "2026-03-15T06:51:57.856401Z" }, "slideshow": { "slide_type": "" }, "tags": [ "nbsphinx-thumbnail" ] }, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "\n", "x_min = 0.25\n", "x_max = 0.75\n", "y_min = frame.loc[(frame.f >= x_min) & (frame.f <= x_max), \"theta\"].min()\n", "y_max = frame.loc[(frame.f >= x_min) & (frame.f <= x_max), \"theta\"].max()\n", "box_data_x = [x_min, x_min, x_max, x_max, x_min]\n", "box_data_y = [y_min, y_max, y_max, y_min, y_min]\n", "\n", "fig, ax = plt.subplots()\n", "ax.plot(box_data_x, box_data_y, linestyle='--', color='gray', label='30-degree range')\n", "ax.scatter(frame['f'], frame['theta'], color='#1f77b4', label='Simulation')\n", "ax.set_title('Carom Angle vs Ball Hit Fraction', fontsize=20)\n", "ax.set_xlabel('Ball Hit Fraction (f)', fontsize=16)\n", "ax.set_ylabel('Carom Angle (theta, degrees)', fontsize=16)\n", "ax.tick_params(axis='both', which='major', labelsize=14)\n", "ax.legend(fontsize=14)\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "46238979", "metadata": {}, "source": [ "Between a $1/4$ and $3/4$ ball hit, there is a relative invariance in the carom angle, with a range of around 6 degrees.\n", "\n", "For your reference, here is the same plot but with cut angle $\\phi$ as the x-axis:" ] }, { "cell_type": "code", "execution_count": 21, "id": "78496980", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:57.860310Z", "iopub.status.busy": "2026-03-15T06:51:57.859966Z", "iopub.status.idle": "2026-03-15T06:51:57.973524Z", "shell.execute_reply": "2026-03-15T06:51:57.972190Z" }, "lines_to_next_cell": 2 }, "outputs": [ { "data": { "image/png": "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8+ZNXbbvCFadhYeH280hcpTHZA+OlydPHnEXXoSh+EIMJHyO/B+fI//H58j/hfJzlMHJSJFfJ1/XrFlTv65YsSLONhRrtNzHnlSpUmnwdODAATlx4kScyHHlypVaTbtixYpePXciIiIKXH4ZGNWtW1dHfGbNmiW7d+82X49psdGjR0vy5Mmlc+fO5uujoqJk//79cabNUMDRyBWyTLhCUcejR4/KCy+8oAEUERERkd8GRkmTJtW2HVhuX6NGDQ1w0ALkqaee0orXCI4KFChg3h+BT/HixeXnn3+OdZwuXbpo3aPZs2fLM888I4MGDZLWrVtLnz59pGDBgvL+++/79OdAftKIESNi5SmRf+Fz5P/4HPk/Pkf+j89RgLcEMWzbtk0Di02bNsn9+/eldOnSukoM/dIsde3aVSthowUI/m9di2js2LEyc+ZMTTrLnDmzPP/88xoU5ciRI4F/IiIiIvJnfh0YEREREUmoT6URERERJQYGRkRERESPMTAiIiIieoyBkQ9s375dGjduLBkzZtRaSZUrV5a5c+f64q7IDrRvmThxotSvX1/y5cunJR7QgLhVq1aydetWu5VhkdyfP39+XcGBlY9vv/22FhSlhDNu3DitLI/Lli1b+Dz5Caz6rVevnmTJkkVSpkypK3s7dOigi1os8fco4SFVeMGCBVK7dm3JmTOnpE6dWooWLSo9e/bU0jTW+Bw5f0DJi1avXm1KliyZKV26dKZXXnnF1L9/f1P+/PmR4G4aP348H+sEMnDgQH3MCxcubOrevbtp0KBBplatWpmSJEliCg8PN/3444+x9r9586apbNmyepv69evr7fEV3z/99NOmO3fu8LlLAHv27DGlSJHClCZNGn3sN2/ezOcpkT169MjUo0cP8+9Tnz599PejU6dOpnz58pnWr19v3pe/R4kD7zN4fnLmzGnq1auX6Z133jE1aNDAFBYWpu9F+L3ic+Q6BkZedP/+ff3DgT/su3btMl9/9epV05NPPmlKnjy56fjx4968S7Jj/vz5prVr18a5/o8//tDANVOmTKaYmBjz9cOHD9c/LPiDbyvAGj16NB9rH7t3756pfPnypkqVKplefPFFm4ERn6eEN3HiRH0uEBA9ePDA5t89A5+fhBcVFaUf9vABHO81liZMmKDPXbdu3fgcuYGBkRctX748zovQMH36dN02cuRI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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots()\n", "ax.scatter(frame['phi'], frame['theta'], color='#1f77b4')\n", "ax.set_title('Carom Angle vs Cut Angle', fontsize=20)\n", "ax.set_xlabel('Cut Angle (phi)', fontsize=16)\n", "ax.set_ylabel('Carom Angle (theta, degrees)', fontsize=16)\n", "ax.tick_params(axis='both', which='major', labelsize=14)\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "f2505b3c", "metadata": { "lines_to_next_cell": 2 }, "source": [ "## Comparison to theory\n", "\n", "Under the assumption of a perfectly elastic and frictionless ball-ball collision, Dr. Dave has calculated the theoretical carom angle $\\theta$ to be\n", "\n", "$$\n", "\\theta_{\\text{ideal}}(\\phi) = \\arctan{\\frac{\\sin\\phi \\times \\cos\\phi}{\\sin^2\\phi + \\frac{2}{5}}}\n", "$$\n", "\n", "*(source: [https://billiards.colostate.edu/technical_proofs/new/TP_B-13.pdf](https://billiards.colostate.edu/technical_proofs/new/TP_B-13.pdf))*\n", "\n", "Since pooltool's baseline physics engine makes the same assumptions, we should expect the results to be the same. Let's directly compare:" ] }, { "cell_type": "code", "execution_count": 22, "id": "79522ddc", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:57.976329Z", "iopub.status.busy": "2026-03-15T06:51:57.976113Z", "iopub.status.idle": "2026-03-15T06:51:58.327003Z", "shell.execute_reply": "2026-03-15T06:51:58.325705Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def get_theoretical_carom_angle(phi) -> float:\n", " return np.atan2(np.sin(phi) * np.cos(phi), (np.sin(phi) ** 2 + 2 / 5))\n", "\n", "phi_theory = np.linspace(0, np.pi / 2, 500)\n", "theta_theory = get_theoretical_carom_angle(phi_theory)\n", "\n", "phi_theory *= 180 / np.pi\n", "theta_theory *= 180 / np.pi\n", "f_theory = get_ball_hit_fraction(phi_theory)\n", "\n", "fig = go.Figure()\n", "fig.add_trace(\n", " go.Scatter(\n", " x=box_data_x,\n", " y=box_data_y,\n", " mode=\"lines\",\n", " name=\"30-degree range\",\n", " line=dict(dash=\"dash\", color=\"gray\"),\n", " )\n", ")\n", "fig.add_trace(\n", " go.Scatter(\n", " x=frame[\"f\"],\n", " y=frame[\"theta\"],\n", " mode=\"markers\",\n", " name=\"Simulation\",\n", " marker=dict(color=\"#1f77b4\"),\n", " )\n", ")\n", "fig.add_trace(go.Scatter(x=f_theory, y=theta_theory, mode=\"lines\", name=\"Theory\"))\n", "fig.update_layout(\n", " title=\"Carom Angle vs Ball Hit Fraction\",\n", " xaxis_title=\"Ball Hit Fraction (f)\",\n", " yaxis_title=\"Carom Angle (theta, degrees)\",\n", " template=\"presentation\",\n", ")\n", "fig.show()" ] }, { "cell_type": "markdown", "id": "b31dda08", "metadata": {}, "source": [ "A perfect match." ] }, { "cell_type": "markdown", "id": "d99aab20", "metadata": {}, "source": [ "## Impact speed independence\n", "\n", "Interestingly, the carom angle is independent of the speed:" ] }, { "cell_type": "code", "execution_count": 23, "id": "808557dc", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:58.330419Z", "iopub.status.busy": "2026-03-15T06:51:58.330158Z", "iopub.status.idle": "2026-03-15T06:51:58.415090Z", "shell.execute_reply": "2026-03-15T06:51:58.414178Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Carom angle for V0=1.000000 is 0.587676\n", "Carom angle for V0=1.157895 is 0.587676\n", "Carom angle for V0=1.315789 is 0.587676\n", "Carom angle for V0=1.473684 is 0.587676\n", "Carom angle for V0=1.631579 is 0.587676\n", "Carom angle for V0=1.789474 is 0.587676\n", "Carom angle for V0=1.947368 is 0.587676\n", "Carom angle for V0=2.105263 is 0.587676\n", "Carom angle for V0=2.263158 is 0.587676\n", "Carom angle for V0=2.421053 is 0.587676\n", "Carom angle for V0=2.578947 is 0.587676\n", "Carom angle for V0=2.736842 is 0.587676\n", "Carom angle for V0=2.894737 is 0.587676\n", "Carom angle for V0=3.052632 is 0.587676\n", "Carom angle for V0=3.210526 is 0.587676\n", "Carom angle for V0=3.368421 is 0.587676\n", "Carom angle for V0=3.526316 is 0.587676\n", "Carom angle for V0=3.684211 is 0.587676\n", "Carom angle for V0=3.842105 is 0.587676\n", "Carom angle for V0=4.000000 is 0.587676\n" ] } ], "source": [ "for V0 in np.linspace(1, 4, 20):\n", " system = simulate_experiment(V0, 30)\n", " carom_angle = get_carom_angle(system)\n", " print(f\"Carom angle for V0={V0:2f} is {carom_angle:4f}\")" ] }, { "cell_type": "markdown", "id": "d6b9356d", "metadata": {}, "source": [ "This doesn't mean that the trajectories are the same though. Here are the trajectories:" ] }, { "cell_type": "code", "execution_count": 24, "id": "f6c04d1e", "metadata": { "execution": { "iopub.execute_input": "2026-03-15T06:51:58.417450Z", "iopub.status.busy": "2026-03-15T06:51:58.417234Z", "iopub.status.idle": "2026-03-15T06:51:58.499189Z", "shell.execute_reply": "2026-03-15T06:51:58.497824Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import numpy as np\n", "import plotly.graph_objects as go\n", "\n", "\n", "def get_coordinates(system: pt.System):\n", " rvw, s, t = system.balls[\"cue\"].history_cts.vectorize()\n", " xy = rvw[:, 0, :2]\n", "\n", " return xy, s, t\n", "\n", "\n", "fig = go.Figure()\n", "\n", "for V0 in np.linspace(1, 3, 6):\n", " system = simulate_experiment(V0, 30)\n", " pt.continuize(system, dt=0.03, inplace=True)\n", " rvw, s, t = system.balls[\"cue\"].history_cts.vectorize()\n", " xy = rvw[:, 0, :2]\n", "\n", " fig.add_trace(\n", " go.Scatter(\n", " x=xy[:, 0],\n", " y=xy[:, 1],\n", " mode=\"lines\",\n", " name=f\"Speed {V0}\",\n", " showlegend=True,\n", " )\n", " )\n", "\n", "fig.update_layout(\n", " title=\"Ball trajectories\",\n", " xaxis_title=\"X [m]\",\n", " yaxis_title=\"Y [m]\",\n", " yaxis_scaleanchor=\"x\",\n", " yaxis_scaleratio=1,\n", " width=600,\n", " xaxis=dict(range=[1.5, 4.5]),\n", " yaxis=dict(range=[1.5, 4.5]),\n", " template=\"presentation\",\n", ")\n", "fig.show()" ] }, { "cell_type": "markdown", "id": "c3899152", "metadata": {}, "source": [ "Harder shots follow the *tangent line* (aka the line perpendicular to the line connected the balls' centers during contact) for longer, but they all converge to the same outgoing angle." ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "all", "notebook_metadata_filter": "all" }, "kernelspec": { "display_name": "pooltool-dev", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.0" } }, "nbformat": 4, "nbformat_minor": 5 }