更新

更新

我想制作这里描绘的场景的渐近线版本: https://www.youtube.com/watch?v=kE6aC51LMv0 输出最好是矢量图形。尽管如此,我还是得到了以下结果:

//import settings;
settings.outformat = "png";
settings.render = 32;
//settings.antialias = 32;
settings.prc = false;

import graph3;

size (6cm, 0);
//triple cam = (50, 70, 10);
//triple lookAt = O;
//currentprojection = perspective(cam, target = lookAt);

//currentprojection=perspective(
//camera=(80,13,30),
//up=(Z),
//target=(1,1,1),
//zoom=0.01,
//angle=0,
//autoadjust=false;

currentprojection=perspective(
camera=(72.0192787736514,-39.5035415631105,24.2748528122902),
up=(-0.0105388868685802,0.00596444269179909,0.0425371172389632),
target=(0.999999999999988,0.999999999999999,1),
zoom=0.00872308215245425,
angle=6.49698942740468,
autoadjust=false);

//real x_centre = 3;
//real y_centre = 3;
real x_centre = 4;
real y_centre = 0;
real rad = 1.5;
triple vertex=(0,0,1);
path p2 = (x_centre,y_centre-rad)..(x_centre+rad,y_centre)..(x_centre,y_centre+rad)..(x_centre-rad,y_centre)..cycle;
path3 p = path3 (p2);
triple f(pair t)
{
    real s=1-t.x; // scale factor for cross section
    return(t.x*vertex+xscale3(s)*yscale3(s)*point(p,t.y*length(p)));
}

surface sph=shift(0,0,.5)*scale3(.5)*unitsphere;

draw(surface(f,(0, 0),(1,1),30,30,Spline),gray+opacity(.3));
draw(sph,paleblue);
draw(p,gray);

triple[] inter;
for(int i=0; i<size(p2);++i)
{
    //draw(point(p,i)--vertex,gray(.3));
    //path3 intray=point(p,i)--vertex;
    //inter.push(intersectionpoints(intray,sph);
}

triple map_to_sphere(triple P1)
{
    real xs=(2*P1.x)/(1+((P1.x)^2)+((P1.y)^2));
    real ys=(2*P1.y)/(1+((P1.x)^2)+((P1.y)^2));
    real zs=(-1+((P1.x)^2)+((P1.y)^2))/(1+((P1.x)^2)+((P1.y)^2));
    return(xs,ys,zs);
}
triple tst=(5.5,0,0);
dot((map_to_sphere(tst)),2bp+green);

xaxis3("$x$",Arrow3);
yaxis3("$y$",Arrow3);
//zaxis3("$z$",Arrow3);

输出结果为: 在此处输入图片描述 解释:由于我无法使用该intersectionpoints()函数(出现持续的语法错误),我采取了以下策略:在平面上创建一个圆并绘制圆锥曲面。对于单位圆的 4 个节点,找到它们在单位球上的投影。根据这 4 个新点构造一个圆。不幸的是,我陷入了困境,如渲染图所示。问题是绿点应该位于球体表面圆的顶部,而现在它漂浮在太空中。我想我以错误的方式实现了数学运算(但是当我尝试明确解决它时,只会得到更大的混乱)。由于我是新手,我使用了来自以下两个来源的代码:

http://asy.gmaths.net/forum/geometrie-espace-f9/intersection-sphere-cone-oblique-t48.html?sid=64f141c0adc9c39e5cb6abe9c44e7de6

http://sourceforge.net/p/asymptote/discussion/409349/thread/8d7f6aa2/

顺便说一下,我使用的是 64 位 Win 7。我也知道ghostscript如果该错误在某种程度上很重要(即,它已被修复),则将其报告为错误。

附注:我将非常感激能够得到解释的解决方案。

更新

我添加了 OG 建议的几行代码,这次 Asymptote 启动了,但从未完成该过程。我认为我之前的代码示例太长了,所以这次我创建了一个 MWE(或在这种情况下为最小错误示例)。它在这里:

settings.render = 4;
settings.prc = false;

import graph3;
size (6cm, 0);

surface sph=shift(0,0,.5)*scale3(.5)*unitsphere;
path3 line=(0,0,1)--(1,1,0);
triple[] tmp;
//tmp[0]=(1,1,1); // Just to make sure I understand how arrays work :)
tmp=intersectionpoints(line,sph,1e-6); // Asymptote freezes because of this line
draw(sph,lightblue+opacity(.8));
draw(line);
dot(tmp[0],1bp+deepgreen);

所发生的情况是,Asymptote 进程(asy.exe *32在我的情况下)仅消耗大约 30Mb 的内存,但似乎冻结了(类似于无限循环,但这里没有循环)。

所以,我想知道这是 Asymptote 的内部错误还是我仍然错误地使用了该intersectionpoints()函数?

PS 欢迎对原始问题提出任何解决方案(无论是否使用所提到的有问题的功能)。

更新 2

当模糊测试值从 更改为 时,1e-6代码1e-4可以正常工作。根据记录,我在具有 16GB RAM 的 Core i7 机器上运行 64 位 Win7 操作系统。OG 报告称,在1e-6具有 Core i5 的 64 位 Linux 操作系统上,代码可以正确运行模糊测试。

答案1

交点并不难计算。只需写下线的参数化,放入条件“属于球体”即可。您会找到两个解决方案(一个是 (0,0,1)),另一个是您想要的。这里没有数学 :) 我更喜欢啤酒(而不是名声)。

我修改了你的代码。

settings.render = 0;
settings.prc = false;

import graph3;
import solids;
size (6cm, 0);
//currentprojection=perspective(10*2,0.5*2,6*2);
currentprojection=perspective(10,0.5,6);
dotfactor=2.5;
//grid3(gridroutine=XYXgrid(),Step=1,step=.5);

pen def_front=cmyk(black)+linewidth(.5);
pen def_front_red=cmyk(red)+linewidth(.3);
pen def_back=gray(.5)+dotted+linewidth(.3)+linetype(new real[] {4,2});
pen def_back_solid=gray(.5)+linewidth(.3);
pen def_back_red=cmyk(red)+dotted+linewidth(.3)+linetype(new real[] {4,2});

real x_centre = 1.5;
real y_centre = 1.5;
real rad = 1;
triple vertex=(0,0,1);
path p2 = (x_centre,y_centre-rad)..(x_centre+rad,y_centre)..(x_centre,y_centre+rad)..(x_centre-rad,y_centre)..cycle;
path3 p = path3(p2);

surface sph=shift(0,0,.5)*scale3(.5)*unitsphere;
revolution b=sphere((0,0,0.5),0.5); // Used because of silhouette()
//path3 line=(0,0,1)--(1,1,0);
//triple[] tmp;
//tmp[0]=(1,1,1); // Just to make sure I understand how arrays work :)
//tmp=intersectionpoints(line,sph,1e-4); // Asymptote freezes on this line

draw(b,1,frontpen=def_front,backpen=def_back,longitudinalpen=nullpen); // Draw equator
draw(p,def_front_red); // Draw the circle in the plane

triple[] inter;
int cntr = 0;
for (int i = 0; i < size(p2); ++i)
  {
    path3 intray=point(p,i)--vertex;
    triple pM=point(p,i);
    triple pint=(0,0,1)+scale3(1/(1+(pM.x)^2+(pM.y)^2))*(pM.x,pM.y,-1);
    inter.push(pint);
    draw(point(p,i)--inter[cntr],def_back_solid);
    draw(inter[cntr]--vertex,def_back);
    cntr = cntr + 1;
  }
draw(inter[0]..inter[1]..inter[2]..inter[3]..cycle,def_front_red);
draw(b.silhouette(),def_front);
draw(inter[1]--point(p,1),def_back_solid); // Correct the incorrect overlap of the red circle and the lines
draw(inter[2]--point(p,2),def_back_solid);
draw(inter[3]--point(p,3),def_back_solid);
draw((3,-1.5,0)--(3,3,0)--(-2.5,3,0)--(-2.5,-1.5,0)--cycle,def_back_solid);

cntr = 0;
for (int i = 0; i < size(p2); ++i)
  {
    dot(point(p,i),cmyk(red));
    dot(inter[cntr],cmyk(red));
    cntr = cntr + 1;
  }

答案2

注意:我修改了代码几次(主要是一些小的修饰性改动)。所以,下面是我最终使用的代码(请原谅所有注释代码,其中一部分专用于创建光栅输出)。我没有注释掉我的代码,因为我是提问者 :),但如果需要一些解释,请将其作为评论发布,我很乐意回答。

settings.render = 0;
settings.prc = false;

import graph3;
import solids;
size (6cm, 0);
//currentprojection=perspective(10*2,0.5*2,6*2);
currentprojection=perspective(10,0.5,6);
dotfactor=2.5;
//grid3(gridroutine=XYXgrid(),Step=1,step=.5);

pen def_front=cmyk(black)+linewidth(.5);
pen def_front_red=cmyk(red)+linewidth(.3);
pen def_back=gray(.5)+dotted+linewidth(.3)+linetype(new real[] {4,2});
pen def_back_solid=gray(.5)+linewidth(.3);
pen def_back_red=cmyk(red)+dotted+linewidth(.3)+linetype(new real[] {4,2});

real x_centre = 1.5;
real y_centre = 1.5;
real rad = 1;
triple vertex=(0,0,1);
path p2 = (x_centre,y_centre-rad)..(x_centre+rad,y_centre)..(x_centre,y_centre+rad)..(x_centre-rad,y_centre)..cycle;
path3 p = path3(p2);

surface sph=shift(0,0,.5)*scale3(.5)*unitsphere;
revolution b=sphere((0,0,0.5),0.5); // Used because of silhouette()
//path3 line=(0,0,1)--(1,1,0);
//triple[] tmp;
//tmp[0]=(1,1,1); // Just to make sure I understand how arrays work :)
//tmp=intersectionpoints(line,sph,1e-4); // Asymptote freezes on this line

draw(b,1,frontpen=def_front,backpen=def_back,longitudinalpen=nullpen); // Draw equator
draw(p,def_front_red); // Draw the circle in the plane

triple[] inter;
int cntr = 0;
for (int i = 0; i < size(p2); ++i)
{
    path3 intray=point(p,i)--vertex;
    triple[] tmp=intersectionpoints(intray,sph,1e-4);
    for (int j=0; j<tmp.length; ++j)
    {
        inter.push(tmp[j]);
    }
    draw(point(p,i)--inter[cntr],def_back_solid);
    draw(inter[cntr]--vertex,def_back);
    cntr = cntr + 2;
}

draw(inter[0]..inter[2]..inter[4]..inter[6]..cycle,def_front_red);
//draw(sph,surfacepen=material(diffusepen=0.5*blue + opacity(0.5), emissivepen=0.5*white));
//draw(line);
//dot(inter[0],2bp+deepgreen);
//dot(inter[2],2bp+deepgreen);
//dot(inter[4],2bp+deepgreen);
//dot(inter[6],2bp+deepgreen);
draw(b.silhouette(),def_front);
draw(inter[2]--point(p,1),def_back_solid); // Correct the incorrect overlap of the red circle and the lines
draw(inter[4]--point(p,2),def_back_solid);
draw(inter[6]--point(p,3),def_back_solid);
draw((3,-1.5,0)--(3,3,0)--(-2.5,3,0)--(-2.5,-1.5,0)--cycle,def_back_solid);

cntr = 0;
for (int i = 0; i < size(p2); ++i)
{
    dot(point(p,i),cmyk(red));
    dot(inter[cntr],cmyk(red));
    cntr = cntr + 2;
}

输出结果如下: 在此处输入图片描述

相关内容