Asyptote 非官方包 arrows_pi.asy 不尊重垂直箭头的点顺序

Asyptote 非官方包 arrows_pi.asy 不尊重垂直箭头的点顺序

例如

draw((0.5,0)--(.5,1), EdgeArrows(), p=red);

draw((0.5,1)--(.5,0), EdgeArrows(), p=red);

得到相同的结果。网站:这个问题之后更正

原始包(根据该问题进行更正之前):

// Copyright (c) 2007, Philippe Ivaldi.
// Last modified: Mon Dec 31 15:29:19 CET 2007
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or (at
// your option) any later version.
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
// 02110-1301, USA.


arrowhead EdgeHead()
{
  arrowhead oa;
  oa.head=new path(path g, position position, pen p=currentpen, real size=0,
                   real angle=arrowangle)
    {
      if(size == 0) size=arrowsize(p);
      bool relative=position.relative;
      real position=position.position.x;
      if(relative) position=reltime(g,position);
      path r=subpath(g,position,0.0);
      pair x=point(r,0);
      real t=arctime(r,size);
      pair y=point(r,t);
      path base=y+2*size*I*dir(r,t)--y-2*size*I*dir(r,t);
      path left=rotate(-angle,x)*r;
      real[] T=arrowbasepoints(base,left,r);
      pair denom=point(right,T[1])-y;
      real factor=denom != 0 ? length((point(left,T[0])-y)/denom) : 1;
      path left=rotate(-angle,x)*r;
      real[] T=arrowbasepoints(base,left,r);
      return subpath(left,0,T[0])--y--cycle;
    };
  return oa;
}

arrowhead EdgeHead=EdgeHead();

arrowhead EdgeHookHead(real dir=arrowdir, real barb=arrowbarb)
{
  arrowhead oa;
  oa.head=new path(path g, position position, pen p=currentpen, real size=0,
                   real angle=arrowangle)
    {
      if(size == 0) size=arrowsize(p);
      angle *= arrowhookfactor;
      bool relative=position.relative;
      real position=position.position.x;
      if(relative) position=reltime(g,position);
      path r=subpath(g,position,0);
      pair x=point(r,0);
      real t=arctime(r,size);
      pair y=point(r,t);
      path base=y+2*size*I*dir(r,t)--y-2*size*I*dir(r,t);
      path left=rotate(-angle,x)*r;
      path right=rotate(angle,x)*r;
      real[] T=arrowbasepoints(base,left,right);
      pair denom=point(right,T[1])-y;
      real factor=denom != 0 ? length((point(left,T[0])-y)/denom) : 1;
      path left=rotate(-angle,x)*r;
      path right=rotate(angle*factor,x)*r;
      real[] T=arrowbasepoints(base,left,right);
      left=subpath(left,0,T[0]);
      right=subpath(right,T[1],0);
      pair pl0=point(left,0), pl1=relpoint(left,1);
      pair pr0=relpoint(right,0), pr1=relpoint(right,1);
      pair M=(pl1+pr0)/2;
      pair v=barb*unit(M-pl0);
      pl1=pl1+v; pr0=pr0+v;
      left=pl0{dir(-dir+degrees(M-pl0))}..pl1--M;
      right=M--pr0..pr1{dir(dir+degrees(pr1-M))};
      return left--y--cycle;
    };
  return oa;
}
arrowhead EdgeHookHead=EdgeHookHead();


arrowhead EdgeSimpleHead(real dir=arrowdir, real barb=arrowbarb)
{
  arrowhead oa;
  oa.head=new path(path g, position position, pen p=currentpen, real size=0,
                   real angle=arrowangle)
    {
      if(size == 0) size=arrowsize(p);
      bool relative=position.relative;
      real position=position.position.x;
      if(relative) position=reltime(g,position);
      path r=subpath(g,position,0);
      pair x=point(r,0);
      real t=arctime(r,size);
      pair y=point(r,t);
      path base=y+2*size*I*dir(r,t)--y-2*size*I*dir(r,t);
      path left=rotate(-angle,x)*r;
      path right=rotate(angle,x)*r;
      real[] T=arrowbasepoints(base,left,right);
      pair denom=point(right,T[1])-y;
      real factor=denom != 0 ? length((point(left,T[0])-y)/denom) : 1;
      path left=rotate(-angle,x)*r;
      path right=rotate(angle*factor,x)*r;
      real[] T=arrowbasepoints(base,left,right);
      return subpath(left,T[0],0);
    };
  return oa;
}
arrowhead EdgeSimpleHead=EdgeSimpleHead();


private real position(position position, real size, path g, bool center)
{
  bool relative=position.relative;
  real position=position.position.x;
  if(relative) {
    position *= arclength(g);
    if(center) position += 0.5*size;
    position=arctime(g,position);
  } else if(center)
    position=arctime(g,arclength(subpath(g,0,position))+0.5*size);
  return position;
}

arrowbar EdgeArrows(arrowhead head=EdgeHead,real size=0, real angle=arrowangle,
                    filltype filltype=FillDraw, position position=EndPoint,
                    real space=infinity)
{
  return new bool(picture pic, path g, pen p, margin margin) {
    pair direction;
    real sg=sgn(dot(N,space*I*dir(g,length(g)/2)));
    space = (space == infinity) ? 2*linewidth(p) : space/2;
    if (sg>=0)
      {
        direction=-space*I*dir(g,length(g)/2);
        sg=1;
      }
    else direction=space*I*dir(g,length(g)/2);
    picture tpic;
    tpic.add(new void (frame f, transform t) {
        drawarrow(f,head,t*shift(inverse(t)*(-direction))*g,p,
              size,sg*angle,filltype,position,true,margin,false);
        drawarrow(f,head,t*shift(inverse(t)*direction)*reverse(g),p,
              size,sg*angle,filltype,position,true,margin,false);
      });
    tpic.addPath(g,p);
    real sz=size;
    real gle=angle;
    filltype fl=filltype;
    addArrow(tpic,head,g,p,sz,gle,fl,position(position,size,g,false));
    add(pic,tpic);
    return false;
  };
};

arrowbar EdgeArrows=EdgeArrows();

答案1

编辑于 2016 年 5 月 5 日:

抱歉,我的第一个回答。你说得对,除了垂直方向,程序尊重顺序。事实上,顺序选择仅取决于路径中点处的法线和向量的标量积(0,1)。在垂直情况下,只有一种选择。所以我修改了程序。

arrowbar EdgeArrows(arrowhead head=EdgeHead,real size=0, real angle=arrowangle,
                    filltype filltype=FillDraw, position position=EndPoint,
                    real space=infinity)
{
  return new bool(picture pic, path g, pen p, margin margin) {
    pair direction;
    real sg=sgn(dot(N,space*I*dir(g,length(g)/2)));
    space = (space == infinity) ? 2*linewidth(p) : space/2;
    if (sg>0)
      {
        direction=-space*I*dir(g,length(g)/2);
        sg=1;
      }
    else direction=space*I*dir(g,length(g)/2);
    if (sg==0)
    {
     sg=sgn(dot(N,space*dir(g,length(g)/2)));
     if (sg >0)  direction=-space*I*dir(g,length(g)/2);
     if (sg <0)  direction=space*I*dir(g,length(g)/2);
    }
    picture tpic;
    tpic.add(new void (frame f, transform t) {
        drawarrow(f,head,t*shift(inverse(t)*(-direction))*g,p,
              size,sg*angle,filltype,position,true,margin,false);
        drawarrow(f,head,t*shift(inverse(t)*direction)*reverse(g),p,
              size,sg*angle,filltype,position,true,margin,false);
      });
    tpic.addPath(g,p);
    real sz=size;
    real gle=angle;
    filltype fl=filltype;
    addArrow(tpic,head,g,p,sz,gle,fl,position(position,size,g,false));
    add(pic,tpic);
    return false;
  };
};

我做了一些测试,看起来还不错。我希望它不会引入新的错误和奇怪的行为。

奥格

第一个答案:

该例程的目标是在路径的两端放置特殊点EdgeArrow(并绘制双线)。我认为该行为是预期的,并且放置不取决于点的顺序。也许可以编写这样的函数(仅适用于直线)。作为一种解决方法,我建议RevEdgeArrows在文件中添加一些例程。

arrowhead RevEdgeHead()
{           
  arrowhead oa;
  oa.head=new path(path g, position position, pen p=currentpen, real size=0,
                   real angle=arrowangle)
    {
      if(size == 0) size=arrowsize(p);
      bool relative=position.relative;
      real position=position.position.x;
      if(relative) position=reltime(g,position);
      path r=subpath(g,position,0.0);
      pair x=point(r,0);
      real t=arctime(r,size);
      pair y=point(r,t);
      path base=y+2*size*I*dir(r,t)--y-2*size*I*dir(r,t);
      path left=rotate(-angle,x)*r;
      real[] T=arrowbasepoints(base,left,r);
      pair denom=point(right,T[1])-y;
      real factor=denom != 0 ? length((point(left,T[0])-y)/denom) : 1;
      path left=rotate(angle,x)*r;
      real[] T=arrowbasepoints(base,left,r);
      return subpath(left,0,T[0])--y--cycle;
    };
  return oa;
}

arrowhead RevEdgeHead=RevEdgeHead();


arrowbar RevEdgeArrows(arrowhead head=RevEdgeHead,real size=0, real angle=arrowangle,
                    filltype filltype=FillDraw, position position=EndPoint,
                    real space=infinity)
{
  return new bool(picture pic, path g, pen p, margin margin) {
    pair direction;
    real sg=sgn(dot(N,space*I*dir(g,length(g)/2)));
    space = (space == infinity) ? 2*linewidth(p) : space/2;
    if (sg>=0)
      {
        direction=-space*I*dir(g,length(g)/2);
        sg=1;
      }
    else direction=space*I*dir(g,length(g)/2);
    picture tpic;
    tpic.add(new void (frame f, transform t) {
        drawarrow(f,head,t*shift(inverse(t)*(direction))*g,p,
              size,sg*angle,filltype,position,true,margin,false);
        drawarrow(f,head,t*shift(inverse(t)*-direction)*reverse(g),p,
              size,sg*angle,filltype,position,true,margin,false);
      });
    tpic.addPath(g,p);
    real sz=size;
    real gle=angle;
    filltype fl=filltype;
    addArrow(tpic,head,g,p,sz,gle,fl,position(position,size,g,false));
    add(pic,tpic);
    return false;
  };
};

arrowbar RevEdgeArrows=RevEdgeArrows();

然后

import arrows_pi;
size(10cm,10cm);
draw((0.5,0)--(.5,1), EdgeArrows(), p=red);
draw((1,1)--(1,0), RevEdgeArrows(), p=red);
draw((0,0)--(1,0),EdgeArrows(), p=blue);
draw((0,-1)--(1,-1),RevEdgeArrows(), p=blue);

给出

在此处输入图片描述

奥格

相关内容