Ejemplo n.º 1
0
BOOL CcdrawDoc::AddNode(CNode &node, double d)
{
	int i,k;
	CSegment segm;
	CArcSegment asegm;
	CComplex c,a0,a1,a2;
	double x,y;
	double R;

	x=node.x; y=node.y;

	// test to see if ``too close'' to existing node...
	for (i=0;i<nodelist.GetSize();i++)
		if(nodelist[i].GetDistance(x,y)<d) return FALSE;

	// can't put a node on top of a block label; do same sort of test.
	for (i=0;i<blocklist.GetSize();i++)
		if(blocklist[i].GetDistance(x,y)<d) return FALSE;

	// if all is OK, add point in to the node list...
	nodelist.Add(node);

	// test to see if node is on an existing line; if so, 
	// break into two lines;
	k=(int) linelist.GetSize();
	for(i=0;i<k;i++)
	{
		if (fabs(ShortestDistance(x,y,i))<d)
		{
			segm=linelist[i];
			linelist[i].n1=(int) nodelist.GetSize()-1;
			segm.n0=(int) nodelist.GetSize()-1;
			linelist.Add(segm);
		}
	}

	// test to see if node is on an existing arc; if so, 
	// break into two arcs;
	k=(int) arclist.GetSize();
	for(i=0;i<k;i++)
	{
		if (ShortestDistanceFromArc(CComplex(x,y),arclist[i])<d)
		{
			a0.Set(nodelist[arclist[i].n0].x,nodelist[arclist[i].n0].y);
			a1.Set(nodelist[arclist[i].n1].x,nodelist[arclist[i].n1].y);
			a2.Set(x,y);
			GetCircle(arclist[i],c,R);
			asegm=arclist[i];
			arclist[i].n1=(int) nodelist.GetSize()-1;
			arclist[i].ArcLength=arg((a2-c)/(a0-c))*180./PI;
			asegm.n0=(int) nodelist.GetSize()-1;
			asegm.ArcLength=arg((a1-c)/(a2-c))*180./PI;
			arclist.Add(asegm);
		}
	}
	return TRUE;
}
Ejemplo n.º 2
0
bool GameEntity::HitTest(GameEntity & ge)
{
	if(shapeType==S_Circle)
	{
		if(ge.GetShape()==S_Circle)
		{
			return HitTestCircles(GetCircle(),ge.GetCircle());
		}
		else if(ge.GetShape()==S_Box)
		{
			//这个暂时没做
			return false;
		}
		else if(ge.GetShape()==S_Beam)
		{
			return HitTestBeamCircle(ge.GetBeam(),circle);
		}
	}
	else if(shapeType==S_Box)
	{
		if(ge.GetShape()==S_Circle)
		{
			//这个暂时没做 circle box
			return false;
		}
		else if(ge.GetShape()==S_Box)
		{
			//这个暂时没做 box box
			return false;
		}
		else if(ge.GetShape()==S_Beam)
		{
			return HitTestBeamBox(ge.GetBeam(),box);
		}
	}
	else if(shapeType==S_Beam)
	{
		if(ge.GetShape()==S_Circle)
		{
			//beam circle
			return HitTestBeamCircle(beam,ge.GetCircle());
		}
		else if(ge.GetShape()==S_Box)
		{
			return HitTestBeamBox(beam,ge.GetBox());
		}
		else if(ge.GetShape()==S_Beam)
		{
			//这个暂时没做 beam beam
			return false;
		}
	}


	return false;
}
Ejemplo n.º 3
0
void Entity::GetFOV(GameMap &CurrentMap)
{
	vector<Tile>::iterator it;
	//reset all to invis
	for(it = CurrentMap.TileMap.begin(); it != CurrentMap.TileMap.end(); it++)
	{
		(*it).Visible = false;
	}
	Circle.clear();
	GetCircle(CurrentMap);
	vector<int>::iterator nit;
	for(nit = Circle.begin(); nit != Circle.end(); nit++)
	{
		CurrentMap.Bresenham(y, x, CurrentMap.TileMap[(*nit)].y, CurrentMap.TileMap[(*nit)].x);
	}
}
Ejemplo n.º 4
0
// TSnap::IsTree
TEST(alg, IsTree) {
  PNGraph Graph;
  int RootNId;

  Graph = GetSingleNode();
  EXPECT_EQ(1,TSnap::IsTree(Graph,RootNId));

  Graph = GetTree();
  EXPECT_EQ(1,TSnap::IsTree(Graph,RootNId));

  Graph = GetForest();
  EXPECT_EQ(0,TSnap::IsTree(Graph,RootNId));

  Graph = GetCircle();
  EXPECT_EQ(0,TSnap::IsTree(Graph,RootNId));
}
Ejemplo n.º 5
0
void Monster::GetFOVNPC(GameMap &CurrentMap)
{
	vector<int> ReturnedTiles;
	vector<Tile>::iterator it;
	Circle.clear();
	VisTiles.clear();
	GetCircle(CurrentMap);
	vector<int>::iterator nit;
	for(nit = Circle.begin(); nit != Circle.end(); nit++)
	{
		ReturnedTiles.clear();
		ReturnedTiles = CurrentMap.BresenhamNPC(y, x, CurrentMap.TileMap[(*nit)].y, CurrentMap.TileMap[(*nit)].x);
		for(int i = 0; i < ReturnedTiles.size(); i++)
			VisTiles.push_back(ReturnedTiles[i]);
	}
	
}
Ejemplo n.º 6
0
double CbelaviewDoc::ShortestDistanceFromArc(CComplex p, CArcSegment &arc)
{
	double R,d,l,z;
	CComplex a0,a1,c,t;

	a0.Set(nodelist[arc.n0].x,nodelist[arc.n0].y);
	a1.Set(nodelist[arc.n1].x,nodelist[arc.n1].y);
	GetCircle(arc,c,R);
	d=abs(p-c);
	
	if(d==0) return R;
	
	t=(p-c)/d;
	l=abs(p-c-R*t);
	z=arg(t/(a0-c))*180/PI;
	if ((z>0) && (z<arc.ArcLength)) return l;
	
	z=abs(p-a0);
	l=abs(p-a1);
	if(z<l) return z;
	return l;
}
Ejemplo n.º 7
0
BOOL CcdrawDoc::WriteDXF(CString fname)
{
	int i,j,k;
	double x0,y0,x1,y1,R,dt;
	double extmaxx,extminx,extmaxy,extminy;
	BOOL laze[256];
	int nlaze;
	char lay[256];
	CComplex c,p,s;
	FILE *fp;
	
	if ((fp=fopen(fname,"wt"))==NULL) return FALSE;

	if (nodelist.GetSize()<2){
		extmaxx=1;
		extmaxy=1;
		extminx=0;
		extminy=0;
	}
	else{
		extminx=nodelist[0].x;
		extminy=nodelist[1].y;
		extmaxx=extminx;
		extmaxy=extminy;
		for(i=1;i<nodelist.GetSize();i++)
		{
			if(nodelist[i].x<extminx) extminx=nodelist[i].x;
			if(nodelist[i].x>extmaxx) extmaxx=nodelist[i].x;
			if(nodelist[i].y<extminy) extminy=nodelist[i].y;
			if(nodelist[i].y>extmaxy) extmaxy=nodelist[i].y;
		}
		
	}
	
	for(i=0;i<arclist.GetSize();i++)
	{
		k=(int) ceil(arclist[i].ArcLength/arclist[i].MaxSideLength);
		dt=arclist[i].ArcLength*PI/(((double) k)*180.);
		GetCircle(arclist[i],c,R);
		p.Set(nodelist[arclist[i].n0].x,nodelist[arclist[i].n0].y);
		s=exp(I*dt);
		for(j=0;j<k;j++){
			p=(p-c)*s+c;
			if(p.re<extminx) extminx=p.re;
			if(p.re>extmaxx) extmaxx=p.re;
			if(p.im<extminy) extminy=p.im;
			if(p.im>extmaxy) extmaxy=p.im;
		}
	}

	p.Set(extminx,extminy); s.Set(extmaxx,extmaxy);
	R=0.025*abs(s-p);

	// check out which layers are actually called out;
	for(i=0,nlaze=0;i<256;i++) laze[i]=FALSE;
	for(i=0;i<linelist.GetSize();i++)
		if(linelist[i].InGroup!=0)
		{
			for(j=0,k=FALSE;j<nlaze;j++)
			{
				if(laze[j]==linelist[i].InGroup)
				{
					k=TRUE;
					j=nlaze;
				}
			}
			if((k==FALSE) && (nlaze<256)){
				laze[nlaze]=linelist[i].InGroup;
				nlaze++;
			}
		}

	for(i=0;i<arclist.GetSize();i++)
		if(arclist[i].InGroup!=0)
		{
			for(j=0,k=FALSE;j<nlaze;j++)
			{
				if(laze[j]==arclist[i].InGroup)
				{
					k=TRUE;
					j=nlaze;
				}
			}
			if((k==FALSE) && (nlaze<256)){
				laze[nlaze]=arclist[i].InGroup;
				nlaze++;
			}
		}

	fprintf(fp,"  0\nSECTION\n  2\nHEADER\n  9\n");
	fprintf(fp,"$INSBASE\n 10\n0.0000\n 20\n0.0000\n  9\n");
	fprintf(fp,"$EXTMIN\n 10\n%f\n 20\n%f\n  9\n",extminx-R,extminy-R);
	fprintf(fp,"$EXTMAX\n 10\n%f\n 20\n%f\n  9\n",extmaxx+R,extmaxy+R);
	fprintf(fp,"$LIMMIN\n 10\n%f\n 20\n%f\n  9\n",extminx-R,extminy-R);
	fprintf(fp,"$LIMMAX\n 10\n%f\n 20\n%f\n  9\n",extmaxx+R,extmaxy+R);
	fprintf(fp,"$TEXTSTYLE\n  7\nSTANDARD\n  9\n$CLAYER\n");
	fprintf(fp,"  8\ndefault\n  0\nENDSEC\n  0\n");
	fprintf(fp,"SECTION\n  2\nTABLES\n  0\n");
	fprintf(fp,"TABLE\n  2\nLTYPE\n 70\n4948253\n  0\n");
	fprintf(fp,"LTYPE\n  2\nCONTINUOUS\n 70\n    64\n  3\n");
	fprintf(fp,"Solid line\n 72\n    65\n 73\n     0\n 40\n0.0\n  0\nENDTAB\n  0\n");
	fprintf(fp,"TABLE\n  2\nLAYER\n 70\n     5\n  0\n");
	fprintf(fp,"LAYER\n  2\ndefault\n 70\n    64\n 62\n     7\n  6\n");
	fprintf(fp,"CONTINUOUS\n  0\n");

	for(i=0;i<nlaze;i++)
	{
		fprintf(fp,"LAYER\n  2\nlayer%i\n 70\n    64\n 62\n     7\n  6\n",laze[i]);
		fprintf(fp,"CONTINUOUS\n  0\n");
	}

	fprintf(fp,"ENDTAB\n  0\nTABLE\n  2\n");
	fprintf(fp,"STYLE\n 70\n     1\n  0\nSTYLE\n  2\nSTANDARD\n 70\n");
	fprintf(fp,"     0\n 40\n0.0\n 41\n1.0\n 50\n0.0\n 71\n     0\n");
	fprintf(fp," 42\n0.2\n  3\ntxt\n  4\n\n  0\nENDTAB\n  0\n");
	fprintf(fp,"TABLE\n  2\nVIEW\n 70\n     0\n  0\nENDTAB\n  0\n");
	fprintf(fp,"ENDSEC\n  0\nSECTION\n  2\nBLOCKS\n  0\nENDSEC\n");
	fprintf(fp,"  0\nSECTION\n  2\nENTITIES\n  0\n");

	for(i=0;i<linelist.GetSize();i++)
	{
		x0=nodelist[linelist[i].n0].x;
		y0=nodelist[linelist[i].n0].y;
		x1=nodelist[linelist[i].n1].x;
		y1=nodelist[linelist[i].n1].y;
		if (linelist[i].InGroup==0) sprintf(lay,"default");
		else sprintf(lay,"layer%i",linelist[i].InGroup);
		fprintf(fp,"LINE\n  8\n%s\n 10\n%f\n 20\n%f\n 30\n0.0\n 11\n%f\n 21\n%f\n 31\n0.0\n  0\n",
			lay,x0,y0,x1,y1);
	}

	for(i=0;i<arclist.GetSize();i++)
	{
		GetCircle(arclist[i],c,R);
		x0=arg(nodelist[arclist[i].n0].CC()-c)*180./PI;
		x1=arg(nodelist[arclist[i].n1].CC()-c)*180./PI;
		if (x0<0) x0+=360.;
		if (x1<0) x1+=360.;
		if (arclist[i].InGroup==0) sprintf(lay,"default");
		else sprintf(lay,"layer%i",arclist[i].InGroup);
		fprintf(fp,"ARC\n  8\n%s\n",lay);
		fprintf(fp," 10\n%f\n 20\n%f\n 30\n%f\n 40\n%f\n 50\n%f\n 51\n%f\n  0\n",
			c.re,c.im,0.,R,x0,x1);
	}

	fprintf(fp,"ENDSEC\n  0\nEOF\n");

	fclose(fp);

	return TRUE;
}
Ejemplo n.º 8
0
BOOL CcdrawDoc::AddArcSegment(CComplex p0, CComplex p1, CArcSegment &asegm, double tol)
{
	int i,j,k;
	CSegment segm;
	CArcSegment newarc;
	CComplex c,p[2];
	CArray< CComplex, CComplex&> newnodes;
	double R,d,dmin,t;

	asegm.n0=ClosestNode(p0.re,p0.im);
	asegm.n1=ClosestNode(p1.re,p1.im);

	newnodes.RemoveAll();

	// don't add if line is degenerate
	if (asegm.n0==asegm.n1) return FALSE;

	// don't add if the arc is already in the list;
	for(i=0;i<arclist.GetSize();i++){
		if ((arclist[i].n0==asegm.n0) && (arclist[i].n1==asegm.n1) &&
			(fabs(arclist[i].ArcLength-asegm.ArcLength)<1.e-02)) return FALSE;
		// arcs are ``the same'' if start and end points are the same, and if
		// the arc lengths are relatively close (but a lot farther than
		// machine precision...
	}

	// add proposed arc to the linelist
	asegm.IsSelected=FALSE;
	
	// check to see if there are intersections
	for(i=0;i<linelist.GetSize();i++)
	{
		j=GetLineArcIntersection(linelist[i],asegm,p);
		if(j>0) for(k=0;k<j;k++) newnodes.Add(p[k]);
	}
	for(i=0;i<arclist.GetSize();i++)
	{
		j=GetArcArcIntersection(asegm,arclist[i],p);
		if(j>0) for(k=0;k<j;k++) newnodes.Add(p[k]);
	}

	// add nodes at intersections
	if (tol==0)
	{
		if (nodelist.GetSize()<2) t=1.e-08;
		else{
			CComplex p0,p1;
			p0=nodelist[0].CC();
			p1=p0;
			for(i=1;i<nodelist.GetSize();i++)
			{
				if(nodelist[i].x<p0.re) p0.re=nodelist[i].x;
				if(nodelist[i].x>p1.re) p1.re=nodelist[i].x;
				if(nodelist[i].y<p0.im) p0.im=nodelist[i].y;
				if(nodelist[i].y>p1.im) p1.im=nodelist[i].y;
			}
			t=abs(p1-p0)*CLOSE_ENOUGH;
		}
	}
	else t=tol;

	for(i=0;i<newnodes.GetSize();i++) 
		AddNode(newnodes[i].re,newnodes[i].im,t);

	// add proposed arc segment;
	arclist.Add(asegm);

	// check to see if proposed arc passes through other points;
    // if so, delete arc and create arcs that link intermediate points;
    // does this by recursive use of AddArcSegment;
	UnselectAll();
	GetCircle(asegm,c,R);
    if (tol==0) dmin=fabs(R*PI*asegm.ArcLength/180.)*1.e-05;
	else dmin=tol;
    k=(int) arclist.GetSize()-1;
			
    for(i=0;i<nodelist.GetSize();i++)
    {
        if( (i!=asegm.n0) && (i!=asegm.n1) )
        {
           	d=ShortestDistanceFromArc(CComplex(nodelist[i].x,nodelist[i].y), arclist[k]);
            if (d<dmin){
				CComplex a0,a1,a2;
				a0.Set(nodelist[asegm.n0].x,nodelist[asegm.n0].y);
				a1.Set(nodelist[asegm.n1].x,nodelist[asegm.n1].y);
				a2.Set(nodelist[i].x,nodelist[i].y);
                arclist[k].ToggleSelect();
                DeleteSelectedArcSegments();

				newarc=asegm;
				newarc.n1=i;
				newarc.ArcLength=arg((a2-c)/(a0-c))*180./PI;
                AddArcSegment(newarc,dmin);

				newarc=asegm;
				newarc.n0=i;
				newarc.ArcLength=arg((a1-c)/(a2-c))*180./PI;
                AddArcSegment(newarc,dmin);

                i=(int) nodelist.GetSize();
            }
        }
    }
   
	return TRUE;
}
Ejemplo n.º 9
0
// Call triangle to order segments on the boundary properly
BOOL ChdrawDoc::FunnyOnWritePoly() 
{
	FILE *fp;
	int i,j,k,l,t,n,n0,n1,n2;
	double z,R,dL;
	CComplex a0,a1,a2,c;
	CComplex b0,b1,b2;
	char instring[1024];
	CString s;
	CArray< CNode, CNode&>             nodelst;
	CArray< CSegment, CSegment&>       linelst;
	CArray< CArcSegment, CArcSegment&> arclst;
	CArray< CBlockLabel, CBlockLabel&> blocklst;
	CArray< CPeriodicBoundary, CPeriodicBoundary&> pbclst;
	CArray< CCommonPoint, CCommonPoint& >ptlst;
	CNode node;
	CSegment segm;
	CPeriodicBoundary pbc;
	CCommonPoint pt;

	nodelst.RemoveAll();
	linelst.RemoveAll();
	pbclst.RemoveAll();
	ptlst.RemoveAll();

	UpdateUndo();

	// calculate length used to kludge fine meshing near input node points
	for (i=0,z=0;i<linelist.GetSize();i++)
	{	
		a0.Set(nodelist[linelist[i].n0].x,nodelist[linelist[i].n0].y);
		a1.Set(nodelist[linelist[i].n1].x,nodelist[linelist[i].n1].y);
		z += (abs(a1-a0)/((double) linelist.GetSize()));
	}
	dL=z/LineFraction;

	// copy node list as it is;
	for(i=0;i<nodelist.GetSize();i++) nodelst.Add(nodelist[i]);

	// discretize input segments
	for(i=0;i<linelist.GetSize();i++)
	{
		// abuse the IsSelected flag to carry a notation
		// of which line or arc in the input geometry a
		// particular segment is associated with
		segm=linelist[i];
		segm.IsSelected=i;
		a0.Set(nodelist[linelist[i].n0].x,nodelist[linelist[i].n0].y);
		a1.Set(nodelist[linelist[i].n1].x,nodelist[linelist[i].n1].y);

		if (linelist[i].MaxSideLength==-1) k=1;
		else{
			z=abs(a1-a0);
			k=(int) ceil(z/linelist[i].MaxSideLength);
		}

		if (k==1) // default condition where discretization on line is not specified
		{
			if ((abs(a1-a0)<(3.*dL)) || (!theApp.d_SmartMesh)) linelst.Add(segm); // line is too short to add extra points
			else{
				// add extra points at a distance of dL from the ends of the line.
				// this forces Triangle to finely mesh near corners
				for(j=0;j<3;j++)
				{
					if(j==0)
					{
						a2=a0+dL*(a1-a0)/abs(a1-a0);
						node.x=a2.re; node.y=a2.im;
						l=(int) nodelst.GetSize();
						nodelst.Add(node);
						segm.n0=linelist[i].n0;
						segm.n1=l;
						linelst.Add(segm);
					}

					if(j==1)
					{
						a2=a1+dL*(a0-a1)/abs(a1-a0);
						node.x=a2.re; node.y=a2.im;
						l=(int) nodelst.GetSize();
						nodelst.Add(node);
						segm.n0=l-1;
						segm.n1=l;
						linelst.Add(segm);
					}

					if(j==2)
					{
						l=(int) nodelst.GetSize()-1;
						segm.n0=l;
						segm.n1=linelist[i].n1;
						linelst.Add(segm);
					}
					
				}
			}
		}
		else{
			for(j=0;j<k;j++)
			{
				a2=a0+(a1-a0)*((double) (j+1))/((double) k);
				node.x=a2.re; node.y=a2.im;
				if(j==0){
					l=(int) nodelst.GetSize();
					nodelst.Add(node);
					segm.n0=linelist[i].n0;
					segm.n1=l;
					linelst.Add(segm);
				}
				else if(j==(k-1))
				{
					l=(int) nodelst.GetSize()-1;
					segm.n0=l;
					segm.n1=linelist[i].n1;
					linelst.Add(segm);
				}
				else{
					l=(int) nodelst.GetSize();
					nodelst.Add(node);
					segm.n0=l-1;
					segm.n1=l;
					linelst.Add(segm);
				}
			}
		}
	}

	// discretize input arc segments
	for(i=0;i<arclist.GetSize();i++)
	{
		segm.IsSelected=i+(int) linelist.GetSize();
		a2.Set(nodelist[arclist[i].n0].x,nodelist[arclist[i].n0].y);
		k=(int) ceil(arclist[i].ArcLength/arclist[i].MaxSideLength);
		segm.BoundaryMarker=arclist[i].BoundaryMarker;
		segm.InConductor=arclist[i].InConductor;
		GetCircle(arclist[i],c,R);
		a1=exp(I*arclist[i].ArcLength*PI/(((double) k)*180.));

		if(k==1){
			segm.n0=arclist[i].n0;
			segm.n1=arclist[i].n1;
			linelst.Add(segm);
		}
		else for(j=0;j<k;j++)
		{
			a2=(a2-c)*a1+c;
			node.x=a2.re; node.y=a2.im;
			if(j==0){
				l=(int) nodelst.GetSize();
				nodelst.Add(node);
				segm.n0=arclist[i].n0;
				segm.n1=l;
				linelst.Add(segm);
			}
			else if(j==(k-1))
			{
				l=(int) nodelst.GetSize()-1;
				segm.n0=l;
				segm.n1=arclist[i].n1;
				linelst.Add(segm);
			}
			else{
				l=(int) nodelst.GetSize();
				nodelst.Add(node);
				segm.n0=l-1;
				segm.n1=l;
				linelst.Add(segm);
			}
		}
	}

	// create correct output filename;
	CString pn = GetPathName();
	CString plyname=pn.Left(pn.ReverseFind('.')) + ".poly";
	
	// check to see if we are ready to write a datafile;
	
	if ((fp=fopen(plyname,"wt"))==NULL){
		MsgBox("Couldn't write to specified .poly file");
		Undo();  UnselectAll();
		return FALSE;
	}
	
	// write out node list
	fprintf(fp,"%i	2	0	1\n",nodelst.GetSize());
	for(i=0;i<nodelst.GetSize();i++)
	{
		fprintf(fp,"%i	%.17g	%.17g	%i\n",
			     i,nodelst[i].x,nodelst[i].y,0);
	}

	// write out segment list
	fprintf(fp,"%i	1\n",linelst.GetSize());
	for(i=0;i<linelst.GetSize();i++)
	{
		t=-(linelst[i].IsSelected+2);
		fprintf(fp,"%i	%i	%i	%i\n",i,linelst[i].n0,linelst[i].n1,t);
	}

	// write out list of holes;
	for(i=0,j=0;i<blocklist.GetSize();i++)
		if(blocklist[i].BlockType=="<No Mesh>") j++;
	fprintf(fp,"%i\n",j);
	for(i=0,k=0;i<blocklist.GetSize();i++)
		if(blocklist[i].BlockType=="<No Mesh>")
		{
			fprintf(fp,"%i	%.17g	%.17g\n",k,blocklist[i].x,blocklist[i].y);
			k++;
		}

	// figure out a good default mesh size for block labels where 
	// mesh size isn't explicitly specified
	CComplex xx,yy;
	double DefaultMeshSize;
	if (nodelst.GetSize()>1)
	{
		xx=nodelst[0].CC(); yy=xx;
		for(k=0;k<nodelst.GetSize();k++)
		{
			if (nodelst[k].x<Re(xx)) xx.re=nodelst[k].x;
			if (nodelst[k].y<Im(xx)) xx.im=nodelst[k].y;
			if (nodelst[k].x>Re(yy)) yy.re=nodelst[k].x;
			if (nodelst[k].y>Im(yy)) yy.im=nodelst[k].y;
		}
		DefaultMeshSize=pow((double)(abs(yy - xx) / BoundingBoxFraction), (double)2);
		if (!theApp.d_SmartMesh) DefaultMeshSize=abs(yy-xx);
	}
	else DefaultMeshSize=-1;

	// write out regional attributes
	fprintf(fp,"%i\n",blocklist.GetSize()-j);
	for(i=0,k=0;i<blocklist.GetSize();i++)
		if(blocklist[i].BlockType!="<No Mesh>")
		{
			fprintf(fp,"%i	%.17g	%.17g	",k,blocklist[i].x,blocklist[i].y);
			fprintf(fp,"%i	",k+1);
			if ((blocklist[i].MaxArea>0) && (blocklist[i].MaxArea<DefaultMeshSize))
				fprintf(fp,"%.17g\n",blocklist[i].MaxArea);
			else fprintf(fp,"%.17g\n",DefaultMeshSize);
			k++;
		}

	fclose(fp);

	//call triangle
	CString rootname="\"" + pn.Left(pn.ReverseFind('.')) + "\"";
	char CommandLine[512];
	sprintf(CommandLine,"\"%striangle.exe\" -p -P -q%f -e -A -a -z -Q -I %s",
		BinDir,MinAngle,rootname);

	STARTUPINFO StartupInfo = {0};
	PROCESS_INFORMATION ProcessInfo;
	StartupInfo.cb = sizeof(STARTUPINFO);
	StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
	StartupInfo.wShowWindow = SW_SHOWNOACTIVATE|SW_MINIMIZE;
	if (CreateProcess(NULL,CommandLine, NULL, NULL, FALSE,
		0, NULL, NULL, &StartupInfo, &ProcessInfo)){

		if(bLinehook==FALSE) WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
		else{
			DWORD ExitCode;
			hProc=ProcessInfo.hProcess;
			do{
				GetExitCodeProcess(ProcessInfo.hProcess,&ExitCode);
				((CFemmApp *)AfxGetApp())->line_hook(lua,NULL);	
				Sleep(1);
			} while(ExitCode==STILL_ACTIVE);
			hProc=NULL;
		}

	}
	else
	{
		MsgBox("Couldn't spawn triangle.exe");
		Undo();  UnselectAll();
		return FALSE;
	}
	
	DWORD ExitCode;
	GetExitCodeProcess(
		ProcessInfo.hProcess,	// handle to the process 
		&ExitCode 				// address to receive termination status 
	);
	CloseHandle(ProcessInfo.hProcess);
	CloseHandle(ProcessInfo.hThread);
	if (ExitCode!=0)
	{
		MsgBox("Call to triangle was unsuccessful");
		Undo();  UnselectAll();
		return FALSE;
	}
//#endif

	// So far, so good.  Now, read back in the .edge file
	// to make sure the points in the segments and arc
	// segments are ordered in a consistent way so that
	// the (anti)periodic boundary conditions can be applied.

	//read meshlines;
	plyname=pn.Left(pn.ReverseFind('.')) + ".edge";
	if((fp=fopen(plyname,"rt"))==NULL){
		MsgBox("Call to triangle was unsuccessful");
		Undo();  UnselectAll();
		return FALSE;
	}
	fgets(instring,1024,fp);
	sscanf(instring,"%i",&k);
	UnselectAll();	// abuse IsSelected again to keep a
					// tally of how many subsegments each
					// entity is sliced into.
	
	ptlst.SetSize(linelist.GetSize()+arclist.GetSize());
	for(i=0;i<ptlst.GetSize();i++) ptlst[i].t=0;

	for(i=0;i<k;i++)
	{
		fgets(instring,1024,fp);
		sscanf(instring,"%i	%i	%i	%i",&l,&n0,&n1,&j);
		if(j!=0)
		{
			j=-(j+2); // convert back to the `right' numbering

			// store a reference line that we can use to
			// determine whether or not this is a
			// boundary segment w/out re-running triangle.
			if (ptlst[j].t==0)
			{
				ptlst[j].t=1;
				if(n0<n1){
					ptlst[j].x=n0;
					ptlst[j].y=n1;
				}
				else{
					ptlst[j].x=n1;
					ptlst[j].y=n0;
				}
			}

			if(j<linelist.GetSize())
			{
				// deal with segments
				linelist[j].IsSelected++;
				
				if((linelist[j].n0==n1) || (linelist[j].n1==n0))
				{
					t=linelist[j].n0;
					linelist[j].n0=linelist[j].n1;
					linelist[j].n1=t;
				}
			}
			else{
				// deal with arc segments;
				// Can't just flip the point order with
				// impunity in the arc segments, so we flip
				// a marker which denotes which side the
				// normal is on.
			
				j=j-(int) linelist.GetSize();
				arclist[j].IsSelected++;
				if((arclist[j].n0==n1) || (arclist[j].n1==n0))
					arclist[j].NormalDirection=FALSE;
				if((arclist[j].n0==n0) || (arclist[j].n1==n1))
					arclist[j].NormalDirection=TRUE;
			}
		}
	}
	fclose(fp);

	// figure out which segments / arcsegments are on the
	// boundary and force an appropriate mesh density on 
	// these based on how many divisions are in the first
	// trial meshing of the domain.

	// paw through the element list to find out how many
	// elements each reference segment appears in.  If a 
	// segment is on the boundary, it ought to appear in just
	// one element.  Otherwise, it appears in two.
	plyname=pn.Left(pn.ReverseFind('.')) + ".ele";
	if((fp=fopen(plyname,"rt"))==NULL){
		MsgBox("Call to triangle was unsuccessful");
		Undo();  UnselectAll();
		return FALSE;
	}
	fgets(instring,1024,fp);
	sscanf(instring,"%i",&k);
	for(i=0;i<k;i++)
	{
		fgets(instring,1024,fp);
		sscanf(instring,"%i	%i	%i	%i",&j,&n0,&n1,&n2);
		// Sort out the three nodes...
		if (n0>n1) { n=n0; n0=n1; n1=n; }
		if (n1>n2) { n=n1; n1=n2; n2=n; }
		if (n0>n1) { n=n0; n0=n1; n1=n; }

		// now, check to see if any of the test segments
		// are sides of this node...
		for(j=0;j<ptlst.GetSize();j++)
		{
			if ((n0==ptlst[j].x) && (n1==ptlst[j].y)) ptlst[j].t--;
			if ((n0==ptlst[j].x) && (n2==ptlst[j].y)) ptlst[j].t--;
			if ((n1==ptlst[j].x) && (n2==ptlst[j].y)) ptlst[j].t--;
		}
	}
	fclose(fp);

	// impose "new" mesh constraints on bdry arcs and segments....
	for(i=0;i<linelist.GetSize();i++)
	{
		if (ptlst[i].t==0) linelist[i].MaxSideLength=
			LineLength(i)/((double) linelist[i].IsSelected);
	}
	for(i=0;i<arclist.GetSize();i++)
	{
		if (ptlst[i+linelist.GetSize()].t==0){
			// alter maxsidelength, but do it in such
			// a way that it carries only 4 significant
			// digits.  There's no use in carrying double
			// precision here, because it looks crappy
			// when you open up the arc segment to see
			// its properties.
			char kludge[32];
			arclist[i].MaxSideLength=
			arclist[i].ArcLength/((double) arclist[i].IsSelected);
			sprintf(kludge,"%.1e",arclist[i].MaxSideLength);
			sscanf(kludge,"%lf",&arclist[i].MaxSideLength);
		}
	}
	ptlst.RemoveAll();	

		// want to impose explicit discretization only on
		// the boundary arcs and segments.  After the meshing
		// is done, spacing on boundary segments should be
		// restored to the value that was there before meshing
		// was called, but the arc segments should keep the
		// "new" MaxSideLength--this is used in other places
		// and must always be consistent with the the mesh.

	
	// Now, do a shitload of checking to make sure that
	// the PBCs haven't been defined by the user
	// in a messed up way.

	// First, search through defined bc's for periodic ones;
	for(i=0;i<lineproplist.GetSize();i++)
	{
		if ((lineproplist[i].BdryFormat==4) ||
			(lineproplist[i].BdryFormat==5)){
			pbc.BdryName=lineproplist[i].BdryName;
			pbc.BdryFormat=lineproplist[i].BdryFormat-4; // 0 for pbc, 1 for apbc
			pbclst.Add(pbc);
		}
	}

	for(i=0;i<linelist.GetSize();i++)
	{
		for(j=0;j<pbclst.GetSize();j++)
		{
			if (pbclst[j].BdryName==linelist[i].BoundaryMarker)
			{
				// A pbc or apbc can only be applied to 2 segs
				// at a time.  If it is applied to multiple segs
				// at the same time, flag it and kick it out.
				if (pbclst[j].nseg==2)
				{
					MsgBox("An (anti)periodic BC is assigned to more than two segments");
					Undo();  UnselectAll();
					return FALSE;
				}
				pbclst[j].seg[pbclst[j].nseg]=i;
				pbclst[j].nseg++;
			}
		}
	}
	
	for(i=0;i<arclist.GetSize();i++)
	{
		for(j=0;j<pbclst.GetSize();j++)
		{
			if (pbclst[j].BdryName==arclist[i].BoundaryMarker)
			{
				// A pbc or apbc can only be applied to 2 arcs
				// at a time.  If it is applied to multiple arcs
				// at the same time, flag it and kick it out.
				if (pbclst[j].narc==2)
				{
					MsgBox("An (anti)periodic BC is assigned to more than two arcs");
					Undo();  UnselectAll();
					return FALSE;
				}
				pbclst[j].seg[pbclst[j].narc]=i;
				pbclst[j].narc++;
			}
		}
	}

	j=0;
	while(j<pbclst.GetSize())
	{
		// check for a bc that is a mix of arcs and segments.
		// this is an error, and it should get flagged.
		if ((pbclst[j].nseg>0) && (pbclst[j].narc>0))
		{
			MsgBox("Can't mix arcs and segments for (anti)periodic BCs");
			Undo();  UnselectAll();
			return FALSE;
		}

		
		// remove any periodic BC's that aren't actually in play
		if((pbclst[j].nseg<2) && (pbclst[j].narc<2)) pbclst.RemoveAt(j);
		else j++;
	}

	for(j=0;j<pbclst.GetSize();j++)
	{
		// check to see if adjoining entries are applied
		// to objects of compatible size/shape, and
		// reconcile meshing on the objects.
		
		// for segments:
		if(pbclst[j].nseg>0){
			
			// make sure that lines are pretty much the same length
			if(fabs(LineLength(pbclst[j].seg[0])
		           -LineLength(pbclst[j].seg[1]))>1.e-06)
			{
				MsgBox("(anti)periodic BCs applied to dissimilar segments");
				Undo();  UnselectAll();
				return FALSE;
			}
			
			// make sure that both lines have the same spacing
			double len1,len2,len;
			len1=linelist[pbclst[j].seg[0]].MaxSideLength;
			len2=linelist[pbclst[j].seg[1]].MaxSideLength;
			
			if(len1<=0) len1=len2;
			if(len2<=0) len2=len1;
			len=min(len1,len2);

			linelist[pbclst[j].seg[0]].MaxSideLength=len;
			linelist[pbclst[j].seg[1]].MaxSideLength=len;
		}

		// for arc segments:
		if(pbclst[j].narc>0){
			
			// make sure that arcs are pretty much the 
			// same arc length
			if(fabs(arclist[pbclst[j].seg[0]].ArcLength
		           -arclist[pbclst[j].seg[1]].ArcLength)>1.e-06)
			{
				MsgBox("(anti)periodic BCs applied to dissimilar arc segments");
				Undo();  UnselectAll();
				return FALSE;
			}

			// make sure that both lines have the same spacing
			double len1,len2,len;
			len1=arclist[pbclst[j].seg[0]].MaxSideLength;
			len2=arclist[pbclst[j].seg[1]].MaxSideLength;
	
			len=min(len1,len2);

			arclist[pbclst[j].seg[0]].MaxSideLength=len;
			arclist[pbclst[j].seg[1]].MaxSideLength=len;
		}
	}

	// write out new poly and write out adjacent
	// boundary nodes in a separate .pbc file.
	
	// kludge things a bit and use IsSelected to denote
	// whether or not a line or arc has already been processed.
	UnselectAll();
	nodelst.RemoveAll();
	linelst.RemoveAll();

	// first, add in existing nodes
	for(n=0;n<nodelist.GetSize();n++) nodelst.Add(nodelist[n]);

	for(n=0;n<pbclst.GetSize();n++)
	{
		if (pbclst[n].nseg!=0) // if this pbc is a line segment...
		{
			int s0,s1;
			CNode node0,node1;

			s0=pbclst[n].seg[0];
			s1=pbclst[n].seg[1];
			linelist[s0].IsSelected=TRUE;
			linelist[s1].IsSelected=TRUE;
			
			// make is so that first point on first line
			// maps to first point on second line...
			t=linelist[s1].n1;
			linelist[s1].n1=linelist[s1].n0;
			linelist[s1].n0=t;

			// store number of sub-segments in k
			if (linelist[s0].MaxSideLength==-1) k=1;
			else{
				a0=nodelist[linelist[s0].n0].CC();
				a1=nodelist[linelist[s0].n1].CC();
				b0=nodelist[linelist[s1].n0].CC();
				b1=nodelist[linelist[s1].n1].CC();
				z=abs(a1-a0);
				k=(int) ceil(z/linelist[s0].MaxSideLength);
			}

			// add segment end points to the list;
			pt.x=linelist[s0].n0;
			pt.y=linelist[s1].n0;
			pt.t=pbclst[n].BdryFormat;
			ptlst.Add(pt);
			pt.x=linelist[s0].n1;
			pt.y=linelist[s1].n1;
			pt.t=pbclst[n].BdryFormat;
			ptlst.Add(pt);
	
			if (k==1){
				// catch the case in which the line
				// doesn't get subdivided.
				linelst.Add(linelist[s0]);
				linelst.Add(linelist[s1]);
			}
			else{
				segm=linelist[s0];
				for(j=0;j<k;j++)
				{
					a2=a0+(a1-a0)*((double) (j+1))/((double) k);
					b2=b0+(b1-b0)*((double) (j+1))/((double) k);
					node0.x=a2.re; node0.y=a2.im;
					node1.x=b2.re; node1.y=b2.im;
					if(j==0){
						l=(int) nodelst.GetSize();
						nodelst.Add(node0);
						segm.n0=linelist[s0].n0;
						segm.n1=l;
						linelst.Add(segm);
						pt.x=l;

						l=(int) nodelst.GetSize();
						nodelst.Add(node1);
						segm.n0=linelist[s1].n0;
						segm.n1=l;
						linelst.Add(segm);
						pt.y=l;

						pt.t=pbclst[n].BdryFormat;
						ptlst.Add(pt);
					}
					else if(j==(k-1))
					{
						// last subdivision--no ptlst
						// entry associated with this one.
						l=(int) nodelst.GetSize()-2;
						segm.n0=l;
						segm.n1=linelist[s0].n1;
						linelst.Add(segm);

						l=(int) nodelst.GetSize()-1;
						segm.n0=l;
						segm.n1=linelist[s1].n1;
						linelst.Add(segm);
					}
					else{
						l=(int) nodelst.GetSize();
						
						nodelst.Add(node0);
						nodelst.Add(node1);

						segm.n0=l-2;
						segm.n1=l;
						linelst.Add(segm);

						segm.n0=l-1;
						segm.n1=l+1;
						linelst.Add(segm);
						
						pt.x=l;
						pt.y=l+1;
						pt.t=pbclst[n].BdryFormat;
						ptlst.Add(pt);
					}
				}
			}
		}
		else{  // if this pbc is an arc segment...
		
			int s0,s1;
			int p0[2],p1[2];
			CNode node0,node1;
			CComplex bgn0,bgn1,c0,c1,d0,d1;
			double r0,r1;
			
			s0=pbclst[n].seg[0];
			s1=pbclst[n].seg[1];
			arclist[s0].IsSelected=TRUE;
			arclist[s1].IsSelected=TRUE;

			k=(int) ceil(arclist[s0].ArcLength/arclist[s0].MaxSideLength);
			segm.BoundaryMarker=arclist[s0].BoundaryMarker;
			segm.InConductor=arclist[s0].InConductor;
			GetCircle(arclist[s0],c0,r0);
			GetCircle(arclist[s1],c1,r1);

			if (arclist[s0].NormalDirection==0){ 
				bgn0=nodelist[arclist[s0].n0].CC();
				d0=exp(I*arclist[s0].ArcLength*PI/(((double) k)*180.));
				p0[0]=arclist[s0].n0;
				p0[1]=arclist[s0].n1;
			}
			else{
				bgn0=nodelist[arclist[s0].n1].CC();
				d0=exp(-I*arclist[s0].ArcLength*PI/(((double) k)*180.));
				p0[0]=arclist[s0].n1;
				p0[1]=arclist[s0].n0;
			}
	
			if (arclist[s1].NormalDirection!=0){ 
				bgn1=nodelist[arclist[s1].n0].CC();
				d1=exp(I*arclist[s1].ArcLength*PI/(((double) k)*180.));
				p1[0]=arclist[s1].n0;
				p1[1]=arclist[s1].n1;
			}
			else{
				bgn1=nodelist[arclist[s1].n1].CC();
				d1=exp(-I*arclist[s1].ArcLength*PI/(((double) k)*180.));
				p1[0]=arclist[s1].n1;
				p1[1]=arclist[s1].n0;
			}

			// add arc segment end points to the list;
			pt.x=p0[0]; pt.y=p1[0]; pt.t=pbclst[n].BdryFormat;
			ptlst.Add(pt);
			pt.x=p0[1]; pt.y=p1[1]; pt.t=pbclst[n].BdryFormat;
			ptlst.Add(pt);
	
			if (k==1){

				// catch the case in which the line
				// doesn't get subdivided.
				segm.n0=p0[0]; segm.n1=p0[1];
				linelst.Add(segm);
				segm.n0=p1[0]; segm.n1=p1[1];
				linelst.Add(segm);
			}
			else{
				for(j=0;j<k;j++)
				{
					bgn0=(bgn0-c0)*d0+c0;
					node0.x=bgn0.re; node0.y=bgn0.im;

					bgn1=(bgn1-c1)*d1+c1;
					node1.x=bgn1.re; node1.y=bgn1.im;

					if(j==0){
						l=(int) nodelst.GetSize();
						nodelst.Add(node0);
						segm.n0=p0[0];
						segm.n1=l;
						linelst.Add(segm);
						pt.x=l;

						l=(int) nodelst.GetSize();
						nodelst.Add(node1);
						segm.n0=p1[0];
						segm.n1=l;
						linelst.Add(segm);
						pt.y=l;

						pt.t=pbclst[n].BdryFormat;
						ptlst.Add(pt);
					}
					else if(j==(k-1))
					{
						// last subdivision--no ptlst
						// entry associated with this one.
						l=(int) nodelst.GetSize()-2;
						segm.n0=l;
						segm.n1=p0[1];
						linelst.Add(segm);

						l=(int) nodelst.GetSize()-1;
						segm.n0=l;
						segm.n1=p1[1];
						linelst.Add(segm);
					}
					else{
						l=(int) nodelst.GetSize();
						
						nodelst.Add(node0);
						nodelst.Add(node1);

						segm.n0=l-2;
						segm.n1=l;
						linelst.Add(segm);

						segm.n0=l-1;
						segm.n1=l+1;
						linelst.Add(segm);
						
						pt.x=l;
						pt.y=l+1;
						pt.t=pbclst[n].BdryFormat;
						ptlst.Add(pt);
					}
				}
				
			}
		}
	}
	
	// Then, do the rest of the lines and arcs in the
	// "normal" way and write .poly file.

	// discretize input segments
	for(i=0;i<linelist.GetSize();i++)
	if(linelist[i].IsSelected==FALSE){			
		
		a0.Set(nodelist[linelist[i].n0].x,nodelist[linelist[i].n0].y);
		a1.Set(nodelist[linelist[i].n1].x,nodelist[linelist[i].n1].y);
		if (linelist[i].MaxSideLength==-1) k=1;
		else{
			z=abs(a1-a0);
			k=(int) ceil(z/linelist[i].MaxSideLength);
		}

		segm=linelist[i];
		if (k==1) // default condition where discretization on line is not specified
		{
			if ((abs(a1-a0)<(3.*dL)) || (!theApp.d_SmartMesh)) linelst.Add(segm); // line is too short to add extra points
			else{
				// add extra points at a distance of dL from the ends of the line.
				// this forces Triangle to finely mesh near corners
				for(j=0;j<3;j++)
				{
					if(j==0)
					{
						a2=a0+dL*(a1-a0)/abs(a1-a0);
						node.x=a2.re; node.y=a2.im;
						l=(int) nodelst.GetSize();
						nodelst.Add(node);
						segm.n0=linelist[i].n0;
						segm.n1=l;
						linelst.Add(segm);
					}

					if(j==1)
					{
						a2=a1+dL*(a0-a1)/abs(a1-a0);
						node.x=a2.re; node.y=a2.im;
						l=(int) nodelst.GetSize();
						nodelst.Add(node);
						segm.n0=l-1;
						segm.n1=l;
						linelst.Add(segm);
					}

					if(j==2)
					{
						l=(int) nodelst.GetSize()-1;
						segm.n0=l;
						segm.n1=linelist[i].n1;
						linelst.Add(segm);
					}
					
				}
			}
		}
		else{
			for(j=0;j<k;j++)
			{
				a2=a0+(a1-a0)*((double) (j+1))/((double) k);
				node.x=a2.re; node.y=a2.im;
				if(j==0){
					l=(int) nodelst.GetSize();
					nodelst.Add(node);
					segm.n0=linelist[i].n0;
					segm.n1=l;
					linelst.Add(segm);
				}
				else if(j==(k-1))
				{
					l=(int) nodelst.GetSize()-1;
					segm.n0=l;
					segm.n1=linelist[i].n1;
					linelst.Add(segm);
				}
				else{
					l=(int) nodelst.GetSize();
					nodelst.Add(node);
					segm.n0=l-1;
					segm.n1=l;
					linelst.Add(segm);
				}
			}
		}
	}

	// discretize input arc segments
	for(i=0;i<arclist.GetSize();i++)
	if(arclist[i].IsSelected==FALSE){
		a2.Set(nodelist[arclist[i].n0].x,nodelist[arclist[i].n0].y);
		k=(int) ceil(arclist[i].ArcLength/arclist[i].MaxSideLength);
		segm.BoundaryMarker=arclist[i].BoundaryMarker;
		segm.InConductor   =arclist[i].InConductor;
		GetCircle(arclist[i],c,R);
		a1=exp(I*arclist[i].ArcLength*PI/(((double) k)*180.));

		if(k==1){
			segm.n0=arclist[i].n0;
			segm.n1=arclist[i].n1;
			linelst.Add(segm);
		}
		else for(j=0;j<k;j++)
		{
			a2=(a2-c)*a1+c;
			node.x=a2.re; node.y=a2.im;
			if(j==0){
				l=(int) nodelst.GetSize();
				nodelst.Add(node);
				segm.n0=arclist[i].n0;
				segm.n1=l;
				linelst.Add(segm);
			}
			else if(j==(k-1))
			{
				l=(int) nodelst.GetSize()-1;
				segm.n0=l;
				segm.n1=arclist[i].n1;
				linelst.Add(segm);
			}
			else{
				l=(int) nodelst.GetSize();
				nodelst.Add(node);
				segm.n0=l-1;
				segm.n1=l;
				linelst.Add(segm);
			}
		}
	}


	// create correct output filename;
	pn = GetPathName();
	plyname=pn.Left(pn.ReverseFind('.')) + ".poly";
	
	// check to see if we are ready to write a datafile;
	
	if ((fp=fopen(plyname,"wt"))==NULL){
		MsgBox("Couldn't write to specified .poly file");
		Undo();  UnselectAll();
		return FALSE;
	}
	
	// write out node list
	fprintf(fp,"%i	2	0	1\n",nodelst.GetSize());
	for(i=0;i<nodelst.GetSize();i++)
	{
		// include boundary marker;
		for(j=0,t=0;j<nodeproplist.GetSize();j++)
				if(nodeproplist[j].PointName==nodelst[i].BoundaryMarker) t=j+2;

		// include conductor number;
		for(j=0;j<circproplist.GetSize();j++)
				if(circproplist[j].CircName==nodelst[i].InConductor) t+=((j+1)*0x10000);

		fprintf(fp,"%i	%.17g	%.17g	%i\n",i,nodelst[i].x,nodelst[i].y,t);
	}

	// write out segment list
	fprintf(fp,"%i	1\n",linelst.GetSize());
	for(i=0;i<linelst.GetSize();i++)
	{
		// include boundary marker;
		for(j=0,t=0;j<lineproplist.GetSize();j++)
				if(lineproplist[j].BdryName==linelst[i].BoundaryMarker) t=-(j+2);

		// include conductor number;
		for(j=0;j<circproplist.GetSize();j++)
			if(circproplist[j].CircName==linelst[i].InConductor)
				t-=((j+1)*0x10000);
			
		fprintf(fp,"%i	%i	%i	%i\n",i,linelst[i].n0,linelst[i].n1,t);
	}

	// write out list of holes;
	for(i=0,j=0;i<blocklist.GetSize();i++)
		if(blocklist[i].BlockType=="<No Mesh>") j++;
	fprintf(fp,"%i\n",j);
	for(i=0,k=0;i<blocklist.GetSize();i++)
		if(blocklist[i].BlockType=="<No Mesh>")
		{
			fprintf(fp,"%i	%.17g	%.17g\n",k,blocklist[i].x,blocklist[i].y);
			k++;
		}
	
	// write out regional attributes
	fprintf(fp,"%i\n",blocklist.GetSize()-j);
	for(i=0,k=0;i<blocklist.GetSize();i++)
		if(blocklist[i].BlockType!="<No Mesh>")
		{
			fprintf(fp,"%i	%.17g	%.17g	",k,blocklist[i].x,blocklist[i].y);
			fprintf(fp,"%i	",k+1);
			if ((blocklist[i].MaxArea>0) && (blocklist[i].MaxArea<DefaultMeshSize))
				fprintf(fp,"%.17g\n",blocklist[i].MaxArea);
			else fprintf(fp,"%.17g\n",DefaultMeshSize);
			k++;
		}
	fclose(fp);

	// Make sure to prune out any duplications in the ptlst	
	for(k=0;k<ptlst.GetSize();k++) ptlst[k].Order();
	k=0;
	while((k+1) < ptlst.GetSize())
	{
		j=k+1;
		while(j < ptlst.GetSize())
		{
			if((ptlst[k].x==ptlst[j].x) && (ptlst[k].y==ptlst[j].y))
				ptlst.RemoveAt(j);
			else j++;
		}
		k++;
	}

	// used to have a check to eliminate the case where a point
	// and its companion are the same point--actually, this shouldn't
	// be a problem just to let the algorithm deal with this
	// as usual.

	// One last error check--each point must have only one companion point.
	// however, it would be possible to screw up in the definition of the BCs
	// so that this isn't the case.  Look through the points to try and catch
	// this one.
/*
	// let's let this check go away for a minute...

	for(k=0,n=FALSE;(k+1)<ptlst.GetSize();k++)
	{
		for(j=k+1;j<ptlst.GetSize();j++)
		{
			if(ptlst[k].x==ptlst[j].x) n=TRUE;
			if(ptlst[k].y==ptlst[j].y) n=TRUE;
			if(ptlst[k].x==ptlst[j].y) n=TRUE;
			if(ptlst[k].y==ptlst[j].x) n=TRUE;
		}
	}
	if (n==TRUE){
		MsgBox("Nonphysical (anti)periodic boundary assignments");
		Undo();  UnselectAll();
		return FALSE;
	}
*/
	// write out a pbc file containing a list of linked nodes
	plyname=pn.Left(pn.ReverseFind('.')) + ".pbc";
	if ((fp=fopen(plyname,"wt"))==NULL){
		MsgBox("Couldn't write to specified .pbc file");
		Undo();  UnselectAll();
		return FALSE;
	}
	fprintf(fp,"%i\n",ptlst.GetSize());
	for(k=0;k<ptlst.GetSize();k++) 
		fprintf(fp,"%i	%i	%i	%i\n",k,ptlst[k].x,ptlst[k].y,ptlst[k].t);
	fclose(fp);

	// call triangle with -Y flag.

	rootname="\"" + pn.Left(pn.ReverseFind('.')) + "\"";
	sprintf(CommandLine,"\"%striangle.exe\" -p -P -q%f -e -A -a -z -Q -I -Y %s",
		BinDir,MinAngle,rootname);

	StartupInfo.cb = sizeof(STARTUPINFO);
	StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
	StartupInfo.wShowWindow = SW_SHOWNOACTIVATE|SW_MINIMIZE;
	if (CreateProcess(NULL,CommandLine, NULL, NULL, FALSE,
		0, NULL, NULL, &StartupInfo, &ProcessInfo)){

		if(bLinehook==FALSE) WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
		else{
			DWORD ExitCode;
			hProc=ProcessInfo.hProcess;
			do{
				GetExitCodeProcess(ProcessInfo.hProcess,&ExitCode);
				((CFemmApp *)AfxGetApp())->line_hook(lua,NULL);	
				Sleep(1);
			} while(ExitCode==STILL_ACTIVE);
			hProc=NULL;
		}

	}
	else
	{
		MsgBox("Couldn't spawn triangle.exe");
		Undo();  UnselectAll();
		return FALSE;
	}
	
	GetExitCodeProcess(
		ProcessInfo.hProcess,	// handle to the process 
		&ExitCode 				// address to receive termination status 
	);
	CloseHandle(ProcessInfo.hProcess);
	CloseHandle(ProcessInfo.hThread);
	if (ExitCode!=0)
	{
		MsgBox("Call to triangle was unsuccessful");
		Undo();  UnselectAll();
		return FALSE;
	}

	UnselectAll();

	// Now restore boundary segment discretizations that have
	// been mucked up in the process...
	for(i=0;i<linelist.GetSize();i++)
		linelist[i]=undolinelist[i];
	
	// and save the latest version of the document to make sure
	// any changes to arc discretization get propagated into
	// the solution description....
	OnSaveDocument(pn);

	return TRUE;
}
Ejemplo n.º 10
0
// What we do in the normal case is OnWritePoly
BOOL ChdrawDoc::OnWritePoly() 
{
	FILE *fp;
	int i,j,k,l,t;
	double z,R,dL;
	CComplex a0,a1,a2,c;
	CString s;
	CArray< CNode, CNode&>             nodelst;
	CArray< CSegment, CSegment&>       linelst;
	CArray< CArcSegment, CArcSegment&> arclst;
	CArray< CBlockLabel, CBlockLabel&> blocklst;
	CNode node;
	CSegment segm;

	nodelst.RemoveAll();
	linelst.RemoveAll();

	// calculate length used to kludge fine meshing near input node points
	for (i=0,z=0;i<linelist.GetSize();i++)
	{	
		a0.Set(nodelist[linelist[i].n0].x,nodelist[linelist[i].n0].y);
		a1.Set(nodelist[linelist[i].n1].x,nodelist[linelist[i].n1].y);
		z += (abs(a1-a0)/((double) linelist.GetSize()));
	}
	dL=z/LineFraction;

	// copy node list as it is;
	for(i=0;i<nodelist.GetSize();i++) nodelst.Add(nodelist[i]);

	// discretize input segments
	for(i=0;i<linelist.GetSize();i++)
	{
		a0.Set(nodelist[linelist[i].n0].x,nodelist[linelist[i].n0].y);
		a1.Set(nodelist[linelist[i].n1].x,nodelist[linelist[i].n1].y);
		if (linelist[i].MaxSideLength==-1) k=1;
		else{
			z=abs(a1-a0);
			k=(int) ceil(z/linelist[i].MaxSideLength);
		}

		if (k==1) // default condition where discretization on line is not specified
		{
			if ((abs(a1-a0)<(3.*dL)) || (!theApp.d_SmartMesh)) linelst.Add(linelist[i]); // line is too short to add extra points
			else{
				// add extra points at a distance of dL from the ends of the line.
				// this forces Triangle to finely mesh near corners
				segm=linelist[i];
				for(j=0;j<3;j++)
				{
					if(j==0)
					{
						a2=a0+dL*(a1-a0)/abs(a1-a0);
						node.x=a2.re; node.y=a2.im;
						l=(int) nodelst.GetSize();
						nodelst.Add(node);
						segm.n0=linelist[i].n0;
						segm.n1=l;
						linelst.Add(segm);
					}

					if(j==1)
					{
						a2=a1+dL*(a0-a1)/abs(a1-a0);
						node.x=a2.re; node.y=a2.im;
						l=(int) nodelst.GetSize();
						nodelst.Add(node);
						segm.n0=l-1;
						segm.n1=l;
						linelst.Add(segm);
					}

					if(j==2)
					{
						l=(int) nodelst.GetSize()-1;
						segm.n0=l;
						segm.n1=linelist[i].n1;
						linelst.Add(segm);
					}
					
				}
			}
		}
		else{
			segm=linelist[i];
			for(j=0;j<k;j++)
			{
				a2=a0+(a1-a0)*((double) (j+1))/((double) k);
				node.x=a2.re; node.y=a2.im;
				if(j==0){
					l=(int) nodelst.GetSize();
					nodelst.Add(node);
					segm.n0=linelist[i].n0;
					segm.n1=l;
					linelst.Add(segm);
				}
				else if(j==(k-1))
				{
					l=(int) nodelst.GetSize()-1;
					segm.n0=l;
					segm.n1=linelist[i].n1;
					linelst.Add(segm);
				}
				else{
					l=(int) nodelst.GetSize();
					nodelst.Add(node);
					segm.n0=l-1;
					segm.n1=l;
					linelst.Add(segm);
				}
			}
		}
	}

	// discretize input arc segments
	for(i=0;i<arclist.GetSize();i++)
	{
		a2.Set(nodelist[arclist[i].n0].x,nodelist[arclist[i].n0].y);
		k=(int) ceil(arclist[i].ArcLength/arclist[i].MaxSideLength);
		segm.BoundaryMarker=arclist[i].BoundaryMarker;
		segm.InConductor=arclist[i].InConductor;

		GetCircle(arclist[i],c,R);
		a1=exp(I*arclist[i].ArcLength*PI/(((double) k)*180.));

		if(k==1){
			segm.n0=arclist[i].n0;
			segm.n1=arclist[i].n1;
			linelst.Add(segm);
		}
		else for(j=0;j<k;j++)
		{
			a2=(a2-c)*a1+c;
			node.x=a2.re; node.y=a2.im;
			if(j==0){
				l=(int) nodelst.GetSize();
				nodelst.Add(node);
				segm.n0=arclist[i].n0;
				segm.n1=l;
				linelst.Add(segm);
			}
			else if(j==(k-1))
			{
				l=(int) nodelst.GetSize()-1;
				segm.n0=l;
				segm.n1=arclist[i].n1;
				linelst.Add(segm);
			}
			else{
				l=(int) nodelst.GetSize();
				nodelst.Add(node);
				segm.n0=l-1;
				segm.n1=l;
				linelst.Add(segm);
			}
		}
	}


	// create correct output filename;
	CString pn = GetPathName();
	CString plyname=pn.Left(pn.ReverseFind('.')) + ".poly";
	
	// check to see if we are ready to write a datafile;
	
	if ((fp=fopen(plyname,"wt"))==NULL){
		MsgBox("Couldn't write to specified .poly file");
		return FALSE;
	}
	
	// write out node list
	fprintf(fp,"%i	2	0	1\n",nodelst.GetSize());
	for(i=0;i<nodelst.GetSize();i++)
	{
		// include boundary marker
		for(j=0,t=0;j<nodeproplist.GetSize();j++)
				if(nodeproplist[j].PointName==nodelst[i].BoundaryMarker) t=j+2;

		// include conductor number;
		for(j=0;j<circproplist.GetSize();j++)
				if(circproplist[j].CircName==nodelst[i].InConductor) t+=((j+1)*0x10000);

		fprintf(fp,"%i	%.17g	%.17g	%i\n",i,nodelst[i].x,nodelst[i].y,t);
	}

	// write out segment list
	fprintf(fp,"%i	1\n",linelst.GetSize());
	for(i=0;i<linelst.GetSize();i++)
	{
		// include boundary marker
		for(j=0,t=0;j<lineproplist.GetSize();j++)
				if(lineproplist[j].BdryName==linelst[i].BoundaryMarker) t=-(j+2);

		// include conductor number;
		for(j=0;j<circproplist.GetSize();j++)
				if(circproplist[j].CircName==linelst[i].InConductor) t-=((j+1)*0x10000);


		fprintf(fp,"%i	%i	%i	%i\n",i,linelst[i].n0,linelst[i].n1,t);
	}

	// write out list of holes;
	for(i=0,j=0;i<blocklist.GetSize();i++)
		if(blocklist[i].BlockType=="<No Mesh>") j++;
	fprintf(fp,"%i\n",j);
	for(i=0,k=0;i<blocklist.GetSize();i++)
		if(blocklist[i].BlockType=="<No Mesh>")
		{
			fprintf(fp,"%i	%.17g	%.17g\n",k,blocklist[i].x,blocklist[i].y);
			k++;
		}
	
	// figure out a good default mesh size for block labels where 
	// mesh size isn't explicitly specified
	CComplex xx,yy;
	double DefaultMeshSize;
	if (nodelst.GetSize() > 1)
	{
		xx = nodelst[0].CC(); yy = xx;
		for (k = 0; k < nodelst.GetSize(); k++)
		{
			if (nodelst[k].x < Re(xx)) xx.re = nodelst[k].x;
			if (nodelst[k].y < Im(xx)) xx.im = nodelst[k].y;
			if (nodelst[k].x > Re(yy)) yy.re = nodelst[k].x;
			if (nodelst[k].y > Im(yy)) yy.im = nodelst[k].y;
		}
		DefaultMeshSize = pow((double)(abs(yy - xx) / BoundingBoxFraction), (double)2);
		if (!theApp.d_SmartMesh) DefaultMeshSize = abs(yy - xx);
	}
	else DefaultMeshSize=-1;

	// write out regional attributes
	fprintf(fp,"%i\n",blocklist.GetSize()-j);
	for(i=0,k=0;i<blocklist.GetSize();i++)
		if(blocklist[i].BlockType!="<No Mesh>")
		{
			fprintf(fp,"%i	%.17g	%.17g	",k,blocklist[i].x,blocklist[i].y);
			fprintf(fp,"%i	",k+1);
			if ((blocklist[i].MaxArea>0) && (blocklist[i].MaxArea<DefaultMeshSize))
				fprintf(fp,"%.17g\n",blocklist[i].MaxArea);
			else fprintf(fp,"%.17g\n",DefaultMeshSize);
			k++;
		}
	fclose(fp);

	// write out a trivial pbc file
	plyname=pn.Left(pn.ReverseFind('.')) + ".pbc";
	if ((fp=fopen(plyname,"wt"))==NULL){
		MsgBox("Couldn't write to specified .pbc file");
		return FALSE;
	}
	fprintf(fp,"0\n");
	fclose(fp);

	//call triangle

	CString rootname="\"" + pn.Left(pn.ReverseFind('.')) + "\"";
	char CommandLine[512];
	sprintf(CommandLine,"\"%striangle.exe\" -p -P -q%f -e -A -a -z -Q -I %s",
		BinDir,MinAngle,rootname);

	STARTUPINFO StartupInfo = {0};
	PROCESS_INFORMATION ProcessInfo;
	StartupInfo.cb = sizeof(STARTUPINFO);
	StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
	StartupInfo.wShowWindow = SW_SHOWNOACTIVATE|SW_MINIMIZE;
	if (CreateProcess(NULL,CommandLine, NULL, NULL, FALSE,
		0, NULL, NULL, &StartupInfo, &ProcessInfo)){
	
		if(bLinehook==FALSE) WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
		else
		{
			DWORD ExitCode;
			hProc=ProcessInfo.hProcess;
			do{
				GetExitCodeProcess(ProcessInfo.hProcess,&ExitCode);
				((CFemmApp *)AfxGetApp())->line_hook(lua,NULL);	
				Sleep(1);
			} while(ExitCode==STILL_ACTIVE);
			hProc=NULL;
		} 
	
	}
	else
	{
		MsgBox("Couldn't spawn triangle.exe");
		return FALSE;
	}
	
	DWORD ExitCode;
	GetExitCodeProcess(
		ProcessInfo.hProcess,	// handle to the process 
		&ExitCode 				// address to receive termination status 
	);
	CloseHandle(ProcessInfo.hProcess);
	CloseHandle(ProcessInfo.hThread);
	if (ExitCode!=0)
	{
		MsgBox("Call to triangle was unsuccessful");
		return FALSE;
	}

	return TRUE;
}