You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于ggtern中线型(geom_segment)与平滑数据(geom_smooth_tern)交点的技术问询

Finding Intersection Between geom_segment and geom_smooth_tern in ggtern

Hey there! Let's walk through how to calculate the intersection point between your ternary segment (geom_segment) and the smoothed curve from geom_smooth_tern. Here's a step-by-step approach tailored to your setup:

1. Extract the Smoothed Curve Data First

The geom_smooth_tern with loess doesn't just plot your raw data—it generates a set of fitted points that form the smooth line. To work with this curve, we first need to extract these fitted points from your ggtern plot object:

# Assume your complete ggtern plot is stored in 'tern_plot'
tern_plot <- ggtern() +
  geom_smooth_tern(data = dataTernNaCl, aes(x = NaCl, y = H2O, z = Na2SO4), 
                   method = loess, se = FALSE, color = "blue") +
  geom_segment(data = your_segment_data, # Replace with your segment's dataframe
               aes(x = x_start, y = y_start, z = z_start,
                   xend = x_end, yend = y_end, zend = z_end))

# Extract all plot data layers
plot_build <- ggplot_build(tern_plot)
plot_data <- plot_build$data

# Locate the smooth curve data layer (look for "smooth_tern" geom type)
smooth_layer_idx <- which(sapply(plot_data, function(layer) layer$geom) == "smooth_tern")
smooth_curve_data <- plot_data[[smooth_layer_idx]]

Now smooth_curve_data contains the x/y/z coordinates of every point on your blue smoothed line.

2. Handle Ternary Coordinate Constraints

In ternary plots, the three coordinates always sum to a constant (e.g., 1 for normalized ratios, 100 for percentages). This means we can reduce the problem to 2D by expressing one variable in terms of the other two (e.g., z = total - x - y, where total is your sum constant).

3. Parameterize Both the Curve and Segment

To find the intersection, we'll define continuous functions for both the smooth curve and your segment using parameterization:

Parameterize the Smooth Curve

We'll use a parameter s (ranging from 0 to 1) to represent positions along the smooth curve, then create interpolation functions for x and y:

# Create a sequence of parameter values for the smooth curve
s_vals <- seq(0, 1, length.out = nrow(smooth_curve_data))

# Build interpolation functions for x and y as functions of s
x_smooth <- approxfun(s_vals, smooth_curve_data$x)
y_smooth <- approxfun(s_vals, smooth_curve_data$y)

Parameterize the Segment

For your segment, use a parameter t (ranging from 0 to 1, where 0 is the start and 1 is the end) to define its x/y coordinates:

# Replace these with your actual segment start/end values
x_start <- your_segment_data$x_start
y_start <- your_segment_data$y_start
x_end <- your_segment_data$x_end
y_end <- your_segment_data$y_end

# Segment parameterization functions
x_segment <- function(t) x_start + t * (x_end - x_start)
y_segment <- function(t) y_start + t * (y_end - y_start)

4. Solve for the Intersection

We need to find values of s and t where the x/y coordinates of the curve and segment match. We'll use a root-finding function from the rootSolve package to solve this system of equations:

library(rootSolve)

# Define an error function that returns the difference between curve and segment coordinates
error_function <- function(st_params) {
  s <- st_params[1]
  t <- st_params[2]
  c(
    x_smooth(s) - x_segment(t),
    y_smooth(s) - y_segment(t)
  )
}

# Initial guess for s and t (adjust if needed for your specific plot)
initial_guess <- c(0.5, 0.5)

# Solve for the intersection parameters
solution <- multiroot(error_function, start = initial_guess)

# Extract the solution values
s_solution <- solution$root[1]
t_solution <- solution$root[2]

5. Calculate and Validate the Intersection Point

Finally, compute the actual intersection coordinates and check if it lies within your segment's bounds (t must be between 0 and 1):

# Calculate intersection coordinates
total <- 100 # Replace with your coordinate sum (e.g., 1 if normalized)
intersect_x <- x_segment(t_solution)
intersect_y <- y_segment(t_solution)
intersect_z <- total - intersect_x - intersect_y

# Validate if the intersection is on the segment
if (t_solution >= 0 & t_solution <= 1) {
  cat("Intersection found:\n")
  cat(sprintf("NaCl: %.4f, H2O: %.4f, Na2SO4: %.4f\n", intersect_x, intersect_y, intersect_z))
} else {
  cat("No valid intersection within the segment's range.\n")
}

Key Notes

  • Normalization: Ensure your ternary coordinates sum to a consistent constant before starting—this simplifies the math drastically.
  • Multiple Intersections: If your segment crosses the smooth curve more than once, you may need to test different initial guesses for s and t to find all solutions.
  • Approximation Alternative: For a simpler (but slightly less precise) method, you can treat the smooth curve as a series of straight lines between its fitted points, then calculate intersections between each of those lines and your segment.

内容的提问来源于stack exchange,提问作者Christian S.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:41:53