グロク3
専門家の皆さん、ありがとう!
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 << Add Rows( 181 ); // 0 to 180 degrees, 181 points
//----------------------------------------------------------
// 2. Add column: theta (in radians)
// From 0 to π (0 to 180 degrees)
//----------------------------------------------------------
dt << 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 << New Column( "X_outer",
Numeric,
"Continuous",
Formula(
3 * Sin( :theta )
)
);
dt << 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 << New Column( "X_inner",
Numeric,
"Continuous",
Formula(
(1 - Cos( :theta )) * Sin( :theta )
)
);
dt << 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 << Report)[FrameBox(1)];
frame << 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 <= 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 >= 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 <= 181, i += 5, // Every 5 degrees
Line(
{dt:X_inner[i], dt:Y_inner[i]},
{dt:X_outer[i], dt:Y_outer[i]}
)
);
);

第二段階: JSL

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 << get values(), :y_deltoid << 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 << Local Data Filter( Add Filter( columns( :angle ), Modeling Type( :angle, Nominal ), Where( :angle == 0 ) ) );
f = Function( {a},
::myrow = Try( (ldf << Get Filtered Rows())[1], 1 )
);
fch = ldf << make filter change handler( f );