Si al final de la extracción de puntos de ContourPlot
, esta es una manera fácil de hacerlo:
points = Cases[
[email protected][Sin[x] Sin[y] == 1/2, {x, -3, 3}, {y, -3, 3}],
Line[pts_] -> pts,
Infinity
]
Join @@ points (* if you don't want disjoint components to be separate *)
EDITAR
Parece que ContourPlot
no produce contornos muy precisos. Son, por supuesto, significaba para el trazado y son lo suficientemente buenos para eso, pero los puntos no se encuentran precisamente en los contornos:
In[78]:= Take[Join @@ points /. {x_, y_} -> Sin[x] Sin[y] - 1/2, 10]
Out[78]= {0.000163608, 0.0000781187, 0.000522698, 0.000516078,
0.000282781, 0.000659909, 0.000626086, 0.0000917416, 0.000470424,
0.0000545409}
Podemos tratar de llegar a nuestro propio método para trazar el contorno, pero es un montón de problemas hacerlo de una manera general. Aquí hay un concepto que funciona para problemas diferentes funciones que tienen contornos lisos:
de inicio desde algún punto (pt0
), y encontrar la intersección con el contorno a lo largo del gradiente de f
.
Ahora tenemos un punto en el contorno. Mover a lo largo de la tangente del contorno por un paso fijo (resolution
), a continuación, repita desde el paso 1.
He aquí una implementación básica que sólo funciona con las funciones que se pueden diferenciar simbólicamente:
rot90[{x_, y_}] := {y, -x}
step[f_, pt : {x_, y_}, pt0 : {x0_, y0_}, resolution_] :=
Module[
{grad, grad0, t, contourPoint},
grad = D[f, {pt}];
grad0 = grad /. Thread[pt -> pt0];
contourPoint =
grad0 t + pt0 /. [email protected][f /. Thread[pt -> grad0 t + pt0], {t, 0}];
Sow[contourPoint];
grad = grad /. Thread[pt -> contourPoint];
contourPoint + rot90[grad] resolution
]
result = Reap[
NestList[step[Sin[x] Sin[y] - 1/2, {x, y}, #, .5] &, {1, 1}, 20]
];
ListPlot[{result[[1]], result[[-1, 1]]}, PlotStyle -> {Red, Black},
Joined -> True, AspectRatio -> Automatic, PlotMarkers -> Automatic]

Los puntos rojos son los "puntos de partida", mientras que los puntos negros son la traza del contorno.
EDIT 2
Tal vez sea una solución más fácil y mejor usar una técnica similar para hacer los puntos que obtenemos de ContourPlot
más precisa. Comience desde el punto inicial, luego avance a lo largo del gradiente hasta que crucemos el contorno.
Tenga en cuenta que esta implementación también funcionará con funciones que no se pueden diferenciar simbólicamente. Simplemente defina la función como f[x_?NumericQ, y_?NumericQ] := ...
si este es el caso.
f[x_, y_] := Sin[x] Sin[y] - 1/2
refine[f_, pt0 : {x_, y_}] :=
Module[{grad, t},
grad = N[{Derivative[1, 0][f][x, y], Derivative[0, 1][f][x, y]}];
pt0 + grad*t /. FindRoot[f @@ (pt0 + grad*t), {t, 0}]
]
points = Join @@ Cases[
[email protected][f[x, y] == 0, {x, -3, 3}, {y, -3, 3}],
Line[pts_] -> pts,
Infinity
]
refine[f, #] & /@ points
Útil, gracias! –
@ Kasper, sinceramente, no creo que haya una forma * más fácil * que extraer contornos. Si tiene requisitos específicos sobre precisión/ubicación de puntos y/o si puede proporcionarnos más información sobre su función, entonces podríamos encontrar una solución mejor, pero probablemente sea más complicada. – Szabolcs
Esto le da el contorno f [x, y] == 1/2, no el contorno f [x, y] == 0 según lo solicitado, de lo contrario, creo que esta es una buena solución. –