<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: How to use JSL to realize the hanging valley dynamic graph? in Discussions</title>
    <link>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849286#M102533</link>
    <description>&lt;P&gt;&lt;A href="https://en.wikipedia.org/wiki/Kakeya_set" target="_blank"&gt;https://en.wikipedia.org/wiki/Kakeya_set&lt;/A&gt;&lt;A href="https://en.wikipedia.org/wiki/Kakeya_set" target="_self"&gt;https://en.wikipedia.org/wiki/Kakeya_set&lt;/A&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Sun, 23 Mar 2025 09:26:57 GMT</pubDate>
    <dc:creator>lala</dc:creator>
    <dc:date>2025-03-23T09:26:57Z</dc:date>
    <item>
      <title>How to use JSL to realize the hanging valley dynamic graph?</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849270#M102527</link>
      <description>&lt;P&gt;grok3&lt;/P&gt;
&lt;P&gt;Thanks Experts!&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;Names Default To Here( 1 );

//----------------------------------------------------------
// 1. Create a data table and add rows
//    We only need 0 to 180 degrees (semi-circle)
//----------------------------------------------------------
dt = New Table( "Radial Mesh Plot" );
dt &amp;lt;&amp;lt; Add Rows( 181 );  // 0 to 180 degrees, 181 points

//----------------------------------------------------------
// 2. Add column: theta (in radians)
//    From 0 to π (0 to 180 degrees)
//----------------------------------------------------------
dt &amp;lt;&amp;lt; New Column( "theta",
    Numeric,
    "Continuous",
    Formula(
        (Pi() / 180) * (Row() - 1)  // Row() starts at 1, so subtract 1
    )
);

//----------------------------------------------------------
// 3. Outer semi-circle (radius 3)
//    X = 3 * sin(theta)
//    Y = 3 * cos(theta)
//----------------------------------------------------------
dt &amp;lt;&amp;lt; New Column( "X_outer",
    Numeric,
    "Continuous",
    Formula(
        3 * Sin( :theta )
    )
);

dt &amp;lt;&amp;lt; New Column( "Y_outer",
    Numeric,
    "Continuous",
    Formula(
        3 * Cos( :theta )
    )
);

//----------------------------------------------------------
// 4. Inner curve (teardrop shape, scaled)
//    Cardioid-like equation: r = 1 - cos(theta)
//    Scaled to fit within the outer semi-circle, k = 1
//    X = (1 - cos(theta)) * sin(theta)
//    Y = (1 - cos(theta)) * cos(theta)
//----------------------------------------------------------
dt &amp;lt;&amp;lt; New Column( "X_inner",
    Numeric,
    "Continuous",
    Formula(
        (1 - Cos( :theta )) * Sin( :theta )
    )
);

dt &amp;lt;&amp;lt; New Column( "Y_inner",
    Numeric,
    "Continuous",
    Formula(
        (1 - Cos( :theta )) * Cos( :theta )
    )
);

//----------------------------------------------------------
// 5. Use Graph Builder to plot the basic graph
//    - Outer semi-circle and inner curve (as boundaries)
//    - Add fill and mesh via Graphics Script later
//----------------------------------------------------------
gb = Graph Builder(
    Size( 600, 600 ),
    Show Control Panel( 0 ),
    Variables(
        X( :X_outer ),
        Y( :Y_outer )
    ),
    Elements(
        Line(
            X( :X_outer ),
            Y( :Y_outer ),
            Legend( "Outer Semi-Circle" ),
            Connect Points( 1 ),
            Line Color( "Blue" ),
            Line Width( 2 )
        ),
        Line(
            X( :X_inner ),
            Y( :Y_inner ),
            Legend( "Inner Teardrop" ),
            Connect Points( 1 ),
            Line Color( "Blue" ),
            Line Width( 2 )
        )
    ),
    SendToReport(
        Dispatch(
            {},
            "X_outer",
            ScaleBox,
            {Min( -3.5 ), Max( 3.5 )}
        ),
        Dispatch(
            {},
            "Y_outer",
            ScaleBox,
            {Min( -1.5 ), Max( 3.5 )}
        )
    )
);

//----------------------------------------------------------
// 6. Add fill and radial mesh
//    Use Graphics Script to draw the filled area and mesh lines
//----------------------------------------------------------
frame = (gb &amp;lt;&amp;lt; Report)[FrameBox(1)];
frame &amp;lt;&amp;lt; Add Graphics Script(
    // Fill the area (using Polygon)
    Fill Color( "Blue" );
    Transparency( 0.5 );  // Semi-transparent fill
    points = {};
    // Add points from the outer semi-circle
    For( i = 1, i &amp;lt;= 181, i++,
        points[i] = {dt:X_outer[i], dt:Y_outer[i]}
    );
    // Add points from the inner curve (in reverse to close the polygon)
    For( i = 181, i &amp;gt;= 1, i--,
        points[362 - i] = {dt:X_inner[i], dt:Y_inner[i]}
    );
    Polygon( points );
    
    // Draw radial mesh lines (every 5 degrees)
    Pen Color( "Blue" );
    Pen Size( 1 );
    For( i = 1, i &amp;lt;= 181, i += 5,  // Every 5 degrees
        Line(
            {dt:X_inner[i], dt:Y_inner[i]},
            {dt:X_outer[i], dt:Y_outer[i]}
        )
    );
);&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="挂谷.gif" style="width: 208px;"&gt;&lt;img src="https://community.jmp.com/t5/image/serverpage/image-id/74120iCAC811D03BDB0B36/image-size/large?v=v2&amp;amp;px=999" role="button" title="挂谷.gif" alt="挂谷.gif" /&gt;&lt;/span&gt;&lt;/P&gt;</description>
      <pubDate>Sun, 23 Mar 2025 03:56:31 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849270#M102527</guid>
      <dc:creator>lala</dc:creator>
      <dc:date>2025-03-23T03:56:31Z</dc:date>
    </item>
    <item>
      <title>Re: How to use JSL to realize the hanging valley dynamic graph?</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849280#M102528</link>
      <description>&lt;P&gt;Is this a suggestion how JSL should look in the future?&lt;/P&gt;</description>
      <pubDate>Sun, 23 Mar 2025 08:08:33 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849280#M102528</guid>
      <dc:creator>hogi</dc:creator>
      <dc:date>2025-03-23T08:08:33Z</dc:date>
    </item>
    <item>
      <title>Re: How to use JSL to realize the hanging valley dynamic graph?</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849281#M102529</link>
      <description>&lt;P class="_tgt transPara grammarSection"&gt;&lt;SPAN class="transSent" data-group="0-0"&gt;Just curious how to draw this motion picture in JSL.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="_tgt transPara grammarSection"&gt;&lt;SPAN class="transSent" data-group="1-0"&gt;AI writing JSL is still impossible to complete the implementation.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="_tgt transPara grammarSection"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="_tgt transPara grammarSection"&gt;Thanks Experts!&lt;/P&gt;</description>
      <pubDate>Sun, 23 Mar 2025 08:36:44 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849281#M102529</guid>
      <dc:creator>lala</dc:creator>
      <dc:date>2025-03-23T08:36:44Z</dc:date>
    </item>
    <item>
      <title>Re: How to use JSL to realize the hanging valley dynamic graph?</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849283#M102530</link>
      <description>&lt;P&gt;I fixed the Elements command - and got this plot:&lt;/P&gt;
&lt;P&gt;Is this a suggestion how JSL should look in the future?&lt;BR /&gt;&lt;BR /&gt;after fixing the arguments of the element function, the plot is generated and looks like this:&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="hogi_0-1742719016641.png" style="width: 400px;"&gt;&lt;img src="https://community.jmp.com/t5/image/serverpage/image-id/74121iAB97C81DD8CC198F/image-size/medium?v=v2&amp;amp;px=400" role="button" title="hogi_0-1742719016641.png" alt="hogi_0-1742719016641.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Seems that the AI misinterpreted your command.&lt;BR /&gt;One can see the "teardrop" which is mentioned in the comments - but it's not there in the input animation.&lt;/P&gt;</description>
      <pubDate>Sun, 23 Mar 2025 08:40:11 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849283#M102530</guid>
      <dc:creator>hogi</dc:creator>
      <dc:date>2025-03-23T08:40:11Z</dc:date>
    </item>
    <item>
      <title>Re: How to use JSL to realize the hanging valley dynamic graph?</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849284#M102531</link>
      <description>&lt;P class="_tgt transPara grammarSection"&gt;&lt;SPAN class="transSent" data-group="0-0"&gt;I just got this code from the AI,&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="_tgt transPara grammarSection"&gt;&lt;SPAN class="transSent" data-group="1-0"&gt;I just gave this GIF to GPT-o1, it supports GIF reading, it writes JSL, but this JSL is not implemented.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="_tgt transPara grammarSection"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="_tgt transPara grammarSection"&gt;&lt;SPAN class="transSent" data-group="3-0"&gt;grok3 does not support GIF, so I will GPT-o1 written JSL and the existing problems to grok3 to modify.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="_tgt transPara grammarSection"&gt;&lt;SPAN class="transSent" data-group="4-0"&gt;It was modified to get the JSL above.&lt;/SPAN&gt;&lt;SPAN class="transSent" data-group="4-1"&gt;It doesn't live up to the look I gave the original GIF.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="_tgt transPara grammarSection"&gt;&lt;SPAN class="transSent" data-group="5-0"&gt;But I wouldn't change it at all.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="_tgt transPara grammarSection"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="_tgt transPara grammarSection"&gt;Thanks Experts!&lt;/P&gt;</description>
      <pubDate>Sun, 23 Mar 2025 09:13:49 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849284#M102531</guid>
      <dc:creator>lala</dc:creator>
      <dc:date>2025-03-23T09:13:49Z</dc:date>
    </item>
    <item>
      <title>Re: How to use JSL to realize the hanging valley dynamic graph?</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849285#M102532</link>
      <description>&lt;P&gt;In some month when the issue with Halluzinations is reduced this new way of writing code will speed up our work tremendously!&lt;/P&gt;</description>
      <pubDate>Sun, 23 Mar 2025 09:23:40 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849285#M102532</guid>
      <dc:creator>hogi</dc:creator>
      <dc:date>2025-03-23T09:23:40Z</dc:date>
    </item>
    <item>
      <title>Re: How to use JSL to realize the hanging valley dynamic graph?</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849286#M102533</link>
      <description>&lt;P&gt;&lt;A href="https://en.wikipedia.org/wiki/Kakeya_set" target="_blank"&gt;https://en.wikipedia.org/wiki/Kakeya_set&lt;/A&gt;&lt;A href="https://en.wikipedia.org/wiki/Kakeya_set" target="_self"&gt;https://en.wikipedia.org/wiki/Kakeya_set&lt;/A&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 23 Mar 2025 09:26:57 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849286#M102533</guid>
      <dc:creator>lala</dc:creator>
      <dc:date>2025-03-23T09:26:57Z</dc:date>
    </item>
    <item>
      <title>Re: How to use JSL to realize the hanging valley dynamic graph?</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849290#M102535</link>
      <description>&lt;P&gt;intermediate step via Python:&lt;BR /&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="SteinerCurve.gif" style="width: 400px;"&gt;&lt;img src="https://community.jmp.com/t5/image/serverpage/image-id/74123i97856F8A659B4C56/image-size/medium?v=v2&amp;amp;px=400" role="button" title="SteinerCurve.gif" alt="SteinerCurve.gif" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-SPOILER&gt;&lt;BR /&gt;
&lt;P&gt; &lt;/P&gt;
&lt;PRE&gt;import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

# Parameters
r_inner = 1  # Radius of the inner circle
r_outer = 3  # Radius of the outer circle
a = 1        # Amplitude factor

# Function of the deltoid curve
def deltoid(t):
    x = (r_outer - r_inner) * np.cos(t) + a * np.cos((r_outer - r_inner) / r_inner * t)
    y = (r_outer - r_inner) * np.sin(t) - a * np.sin((r_outer - r_inner) / r_inner * t)
    return x, y

# 1. Parametric equation of the deltoid curve
t = np.linspace(0, 2 * np.pi, 1000)
x_deltoid, y_deltoid = deltoid(t)
deltoid_coordinates = np.column_stack((x_deltoid, y_deltoid))

# 2. Outer circle
theta_outer = np.linspace(0, 2 * np.pi, 1000)
x_outer = r_outer * np.cos(theta_outer)
y_outer = r_outer * np.sin(theta_outer)

# 3. Inner circle
theta_inner = np.linspace(0, 2 * np.pi, 1000)
x_inner = r_inner * np.cos(theta_inner)
y_inner = r_inner * np.sin(theta_inner)

# Compute the tangent
def tangent(x, slope, intercept):
    return slope * x + intercept

# Compute the derivatives to determine the tangent
def compute_tangent(t0):
    x0, y0 = deltoid(t0)
    
    h = 1e-5
    dx_dt = deltoid(t0 + h)[0] - deltoid(t0)[0]
    dy_dt = deltoid(t0 + h)[1] - deltoid(t0)[1]
    
    slope = dy_dt / dx_dt
    intercept = y0 - slope * x0
    return x0, y0, slope, intercept

# Function to compute the squared distance between a point on the tangent and a point on the deltoid
def distance_to_tangent(t, slope, intercept):
    x, y = deltoid(t)
    y_tangent = slope * x + intercept
    return (y - y_tangent)**2

# Function to compute the distance between a point and the tangent
def distance_to_line(point, slope, intercept):
    x, y = point
    # Analytical geometry: Distance of a point (x, y) from a line y = mx + b
    distance = abs(slope * x - y + intercept) / np.sqrt(slope**2 + 1)
    return distance

# Function to compute the two intersection points without scipy
def find_closest_points(slope, intercept):
    # Split the deltoid coordinates into three sections
    split1 = deltoid_coordinates[:len(deltoid_coordinates) // 3]
    split2 = deltoid_coordinates[len(deltoid_coordinates) // 3:2 * len(deltoid_coordinates) // 3]
    split3 = deltoid_coordinates[2 * len(deltoid_coordinates) // 3:]

    # Compute the minimum distance of the tangent point to each split
    split1_min_distance = min([distance_to_line(point, slope, intercept) for point in split1])
    split2_min_distance = min([distance_to_line(point, slope, intercept) for point in split2])
    split3_min_distance = min([distance_to_line(point, slope, intercept) for point in split3])

    # Determine the split with the smallest distance
    min_distances = [split1_min_distance, split2_min_distance, split3_min_distance]
    split_to_remove = np.argmin(min_distances)

    # Remove the split with the smallest distance
    splits = [split1, split2, split3]
    valid_splits = [split for i, split in enumerate(splits) if i != split_to_remove]

    # Find the point with the smallest distance in the remaining splits
    closest_points = []
    for split in valid_splits:
        distances = [distance_to_line(point, slope, intercept) for point in split]
        min_index = np.argmin(distances)
        closest_points.append(split[min_index])

    # Extract the coordinates of the two points
    (x1, y1), (x2, y2) = closest_points

    return (x1, y1), (x2, y2)

# Path to save the GIF animation
gif_path = "SteinerCurve.gif"

# Create images for the GIF animation
images = []
frames = np.linspace(0, 2 * np.pi, 100)

# Add the code in the loop
for t0 in frames:
    # Compute the point and tangent for the current t0
    x0, y0, slope, intercept = compute_tangent(t0)

    # Find the two points on the deltoid closest to the tangent
    (x1, y1), (x2, y2) = find_closest_points(slope, intercept)

    # Compute the distance between the two points
    distance = np.sqrt((x2 - x1)**2 + (y2 - y1)**2)

    # Compute the midpoint between the two points
    midpoint_x = (x1 + x2) / 2
    midpoint_y = (y1 + y2) / 2

    # Create the figure
    fig, ax = plt.subplots(figsize=(8, 8))
    ax.plot(x_deltoid, y_deltoid, label="Deltoid Curve")
    ax.plot(x_outer, y_outer, linestyle="--")
    ax.plot(x_inner, y_inner, linestyle="--")
    ax.plot([x1, x2], [y1, y2], 'ro')  # Mark the two points
    ax.plot(midpoint_x, midpoint_y, 'bo')  # Mark the midpoint
    ax.plot([x1, x2], [y1, y2], color="green")  # Draw the line between the points
    ax.plot(x0, y0, 'ko')  # Mark the tangent point in black
    
    # Limit the plot area
    ax.set_xlim(-3, 3)
    ax.set_ylim(-3, 3)
    
    ax.set_aspect('equal', 'box')
    ax.set_xlabel("x")
    ax.set_ylabel("y")
    ax.grid(True)
    
    # Save the image in a temporary buffer
    fig.canvas.draw()
    image = np.frombuffer(fig.canvas.tostring_argb(), dtype='uint8')
    image = image.reshape(fig.canvas.get_width_height()[::-1] + (4,))
    image = image[:, :, [1, 2, 3]]  # Convert ARGB to RGB
    images.append(Image.fromarray(image))
    plt.close(fig)

# Save the images as a GIF
images[0].save(gif_path, save_all=True, append_images=images[1:], duration=50, loop=0)

print(f"GIF animation saved at: {gif_path}")&amp;nbsp;&lt;/PRE&gt;
&lt;/LI-SPOILER&gt;</description>
      <pubDate>Sun, 23 Mar 2025 12:28:46 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849290#M102535</guid>
      <dc:creator>hogi</dc:creator>
      <dc:date>2025-03-23T12:28:46Z</dc:date>
    </item>
    <item>
      <title>Re: How to use JSL to realize the hanging valley dynamic graph?</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849291#M102536</link>
      <description>&lt;P class="_tgt transPara grammarSection"&gt;&lt;SPAN class="transSent" data-group="0-0"&gt;Excellent work.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="_tgt transPara grammarSection"&gt;&lt;SPAN class="transSent" data-group="1-0"&gt;Can experts share this code?&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="_tgt transPara grammarSection"&gt;&lt;SPAN class="transSent highlight" data-group="2-0"&gt;Thank you very much!&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Sun, 23 Mar 2025 12:50:18 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849291#M102536</guid>
      <dc:creator>lala</dc:creator>
      <dc:date>2025-03-23T12:50:18Z</dc:date>
    </item>
    <item>
      <title>Re: How to use JSL to realize the hanging valley dynamic graph?</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849293#M102537</link>
      <description>&lt;P&gt;second step: JSL&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="steiner.gif" style="width: 400px;"&gt;&lt;img src="https://community.jmp.com/t5/image/serverpage/image-id/74131iBBF4ABDB92351380/image-size/medium?v=v2&amp;amp;px=400" role="button" title="steiner.gif" alt="steiner.gif" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt; &lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;Names Default To Here( 1 );
// Parameters
r_inner = 1;  // Radius of the inner circle
r_outer = 3;  // Radius of the outer circle
a = 1;        // Amplitude factor

// Function for the deltoid curve
deltoid = Function( {t, r_inner, r_outer, a},
	{default local},
	x = (r_outer - r_inner) * Cos( t ) + a * Cos( (r_outer - r_inner) / r_inner * t );
	y = (r_outer - r_inner) * Sin( t ) - a * Sin( (r_outer - r_inner) / r_inner * t );
	Return( Eval List( {x, y} ) );
);

deltoid_coordinates = Transform Each( {i}, As List( Transpose( 1 :: 999 ) ),
	t = 2 * Pi() * (i - 1) / 999;
	deltoid( t, r_inner, r_outer, a );
);

nr = N Items( deltoid_coordinates );
nsplit = Round( nr / 3 );
splits = Eval List( {deltoid_coordinates[1 :: nsplit], deltoid_coordinates[nsplit + 1 :: 2 * nsplit], deltoid_coordinates[2 * nsplit + 1 :: nr]} );

// Function for the outer circle
myCircle = Function( {t, r},
	{default local},
	x = r * Cos( t );
	y = r * Sin( t );
	Return( Eval List( {x, y} ) );
);

// Compute the tangent
compute_tangent = Function( {t0, r_inner, r_outer, a},
	{default local},
	point = deltoid( t0, r_inner, r_outer, a );
	x0 = point[1];
	y0 = point[2];
    
	h = 1e-5;
	dx_dt = deltoid( t0 + h, r_inner, r_outer, a )[1] - deltoid( t0, r_inner, r_outer, a )[1];
	dy_dt = deltoid( t0 + h, r_inner, r_outer, a )[2] - deltoid( t0, r_inner, r_outer, a )[2];
    
	slope = dy_dt / dx_dt;
	intercept = y0 - slope * x0;
    
	Return( Eval List( {x0, y0, slope, intercept} ) );
);

// Function to compute the distance between a point and a line
distance_to_line = Function( {point, slope, intercept},
	{default local},
	x = point[1];
	y = point[2];
	Return( Abs( slope * x - y + intercept ) / Sqrt( slope ^ 2 + 1 ) );
);

// Function to compute intersection points
find_closest_points = Function( {slope, intercept, splits},
	{default local}, 
    // Split the deltoid coordinates into three sections

    
	// Compute the minimum distance for each section
	min_distances = Transform Each( {split}, Eval List( splits ),
		Min( Transform Each( {point}, split, distance_to_line( point, slope, intercept ) ) )
	);
    
	split_to_remove = Loc Min( Matrix( min_distances ) );
    
    // Select remaining valid sections
	valid_splits = Remove( Eval List( splits ), split_to_remove );
    
    // Find the closest point with the smallest distance
	closest_points = {};
	For Each( {split}, valid_splits, 
    
		min_pos = Loc Min( Matrix( Transform Each( {point}, split, distance_to_line( point, slope, intercept ) ) ) );
		Insert Into( closest_points, split[min_pos] );
	);
    
	Return( closest_points );
);

// Create a new table
dt = New Table( "Deltoid Data",
	Add Rows( 999 ), 

// Create columns for the table
	New Column( "angle", Numeric ),
	New Column( "x_deltoid", Numeric ),
	New Column( "y_deltoid", Numeric ),
	New Column( "x_inner", Numeric ),
	New Column( "y_inner", Numeric ),
	New Column( "x_outer", Numeric ),
	New Column( "y_outer", Numeric ),
	New Column( "x_0", Numeric ),
	New Column( "y_0", Numeric ),
	New Column( "x_1", Numeric ),
	New Column( "y_1", Numeric ),
	New Column( "x_2", Numeric ),
	New Column( "y_2", Numeric ),
	New Column( "x_center", Numeric ),
	New Column( "y_center", Numeric )
);

angles = 2 * Pi() * (As List( Transpose( 1 :: 999 ) ) - 1) / 999;
dt[0, "angle"] = angles;

dt[0, {"x_deltoid", "y_deltoid"}] = deltoid_coordinates;

dt[0, {"x_inner", "y_inner"}] = Transform Each( {t}, angles, myCircle( t, r_inner ) );
dt[0, {"x_outer", "y_outer"}] = Transform Each( {t}, angles, myCircle( t, r_outer ) );

dt[0, {"x_0", "y_0"}] = Transform Each( {t}, angles, compute_tangent( t, r_inner, r_outer, a )[{1, 2}] );

dt[0, {"x_1", "y_1", "x_2", "y_2"}] = Transform Each( {t}, angles,
	{slope, intersect} = compute_tangent( t, r_inner, r_outer, a )[{3, 4}];
	find_closest_points( slope, intersect, splits );
);

dt[0, "x_center"] = (dt[0, "x_1"] + dt[0, "x_2"]) / 2;
dt[0, "y_center"] = (dt[0, "y_1"] + dt[0, "y_2"]) / 2;

::myrow = 1;

New Window( "deltoid", 

	V List Box(

		gb = Graph Builder(
			Size( 466, 471 ),
			Show Control Panel( 0 ),
			Summary Statistic( "Median" ),
			Graph Spacing( 4 ),
			Variables(
				X( :x_0 ),
				X( :x_1, Position( 1 ) ),
				X( :x_center, Position( 1 ) ),
				X( :x_2, Position( 1 ) ),
				Y( :y_0 ),
				Y( :y_1, Position( 1 ) ),
				Y( :y_center, Position( 1 ) ),
				Y( :y_2, Position( 1 ) )
			),
			Elements(
				Line(
					X( 1 ),
					X( 2 ),
					X( 4 ),
					Y( 1 ),
					Y( 2 ),
					Y( 4 ),
					Legend( 33 ),
					Ordering( "Within Row" ),
					Connection( "Arrow" ),
					Summary Statistic( "Mean" )
				),
				Points( X( 1 ), Y( 1 ), Legend( 34 ) ),
				Points( X( 2 ), Y( 2 ), Legend( 35 ) ),
				Points( X( 4 ), Y( 4 ), Legend( 36 ) ),
				Points( X( 3 ), Y( 3 ), Legend( 37 ) )
			), 

			SendToReport(
				Dispatch( {}, {:x_0}, ScaleBox, {Min( -2.96728319980322 ), Max( 3.31428686472806 ), Inc( 1 ), Minor Ticks( 4 )} ),
				Dispatch( {}, {:y_0}, ScaleBox, {Min( -3.05132715458842 ), Max( 3.20702958989834 ), Inc( 1 ), Minor Ticks( 1 )} ),
				Dispatch( {}, "400", ScaleBox,
					{Legend Model( 34, Properties( 0, {Marker Size( 12 )}, Item ID( "y_0", 1 ) ) ), Legend Model(
						35,
						Properties( 0, {Marker Size( 12 )}, Item ID( "y_1", 1 ) )
					), Legend Model( 36, Properties( 0, {Marker Size( 12 )}, Item ID( "y_2", 1 ) ) ), Legend Model(
						37,
						Properties( 0, {Marker Size( 12 )}, Item ID( "y_center", 1 ) )
					)}
				),
				Dispatch( {}, "Graph Builder", FrameBox,
					{Marker Drawing Mode( "Outlined" ), Reference Line Order( 3 ), Add Graphics Script(
						2,
						Description( "" ),
						Pen Color( "black" );
						Line( :x_deltoid &amp;lt;&amp;lt; get values(), :y_deltoid &amp;lt;&amp;lt; get values() );

						Pen Color( "red" );
						XY Function( Cos( x ), Sin( x ), x, Min( 0 ), Max( 2 * Pi() ), inc( 0.001 ) );

						XY Function( 3 * Cos( x ), 3 * Sin( x ), x, Min( 0 ), Max( 2 * Pi() ), inc( 0.001 ) );
				
						Pen Color( "blue" );
						Pen Size( 3 );
				
						Line( {:x_1[::myrow], :y_1[::myrow]}, {:x_2[::myrow], :y_2[::myrow]} );
					)}
				)
			)
		)
	)
);


ldf = gb &amp;lt;&amp;lt; Local Data Filter( Add Filter( columns( :angle ), Modeling Type( :angle, Nominal ), Where( :angle == 0 ) ) );

f = Function( {a},
	::myrow = Try( (ldf &amp;lt;&amp;lt; Get Filtered Rows())[1], 1 )
);
		
fch = ldf &amp;lt;&amp;lt; make filter change handler( f );&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 23 Mar 2025 15:42:47 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-use-JSL-to-realize-the-hanging-valley-dynamic-graph/m-p/849293#M102537</guid>
      <dc:creator>hogi</dc:creator>
      <dc:date>2025-03-23T15:42:47Z</dc:date>
    </item>
  </channel>
</rss>

