1 /***************************************************************************
2  * plot.cpp is part of Math Graphic Library
3  * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin@gmail.ru>       *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU Lesser General Public License  as       *
7  *   published by the Free Software Foundation; either version 3 of the    *
8  *   License, or (at your option) any later version.                       *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU Lesser General Public     *
16  *   License along with this program; if not, write to the                 *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 #include <algorithm>
21 #include "mgl2/plot.h"
22 #include "mgl2/eval.h"
23 #include "mgl2/data.h"
24 #include "mgl2/base.h"
25 //-----------------------------------------------------------------------------
26 //
27 //	Plot by formulas series
28 //
29 //-----------------------------------------------------------------------------
mgl_fplot(HMGL gr,const char * eqY,const char * pen,const char * opt)30 void MGL_EXPORT mgl_fplot(HMGL gr, const char *eqY, const char *pen, const char *opt)
31 {
32 	if(eqY==0 || eqY[0]==0)	return;		// nothing to plot
33 	double r = gr->SaveState(opt);
34 	long n = (mgl_isnan(r) || r<=0) ? 100:long(r+0.5);
35 	long nm = gr->FaceNum?gr->FaceNum*n:10000, nd = gr->FaceNum?gr->FaceNum*10:1000;
36 
37 	mglDataS x, y;
38 	x.dat.reserve(nm);	y.dat.reserve(nm);
39 
40 	mglFormula *eq = new mglFormula(eqY);
41 	// initial data filling
42 	x.clear();	y.clear();
43 	if(gr->Min.x>0 && gr->Max.x>100*gr->Min.x)
44 	{
45 		double d = log(2*gr->Max.x/gr->Min.x)/(n-1);
46 		for(long i=0;i<n;i++)
47 		{	double xx = 2*gr->Max.x*exp(d*i)/(2*gr->Max.x/gr->Min.x+exp(d*i));
48 			x.dat.push_back(xx);	y.dat.push_back(eq->Calc(xx));	}
49 	}
50 	else if(gr->Max.x<0 && gr->Min.x<100*gr->Max.x)
51 	{
52 		double d = log(2*gr->Min.x/gr->Max.x)/(n-1);
53 		for(long i=0;i<n;i++)
54 		{	double xx = 2*gr->Min.x*exp(d*i)/(2*gr->Min.x/gr->Max.x+exp(d*i));
55 			x.dat.push_back(xx);	y.dat.push_back(eq->Calc(xx));	}
56 	}
57 	else
58 	{
59 		double d = (gr->Max.x - gr->Min.x)/(n-1.);
60 		for(long i=0;i<n;i++)
61 		{	double xx = gr->Min.x + i*d;
62 			x.dat.push_back(xx);	y.dat.push_back(eq->Calc(xx));	}
63 	}
64 
65 	bool check=true;
66 	double ym=fabs(gr->Max.y - gr->Min.y)/nd;
67 	while(check && long(x.dat.size())<nm)
68 	{
69 		if(gr->NeedStop())	{	delete eq;	return;	}
70 		check = false;
71 		for(long i=1;i<long(x.size());i++)
72 		{
73 			double xs=(x[i]+x[i-1])/2;
74 			double ys=(y[i]+y[i-1])/2, yr=eq->Calc(xs);
75 			if(fabs(yr-ys)>ym)	// bad approximation here
76 			{
77 				x.dat.insert(x.dat.begin()+i,xs);
78 				y.dat.insert(y.dat.begin()+i,yr);
79 				check = true;	i++;
80 			}
81 		}
82 	}
83 	delete eq;	mgl_plot_xy(gr,&x,&y,pen,0);
84 }
85 //-----------------------------------------------------------------------------
mgl_fplot_xyz(HMGL gr,const char * eqX,const char * eqY,const char * eqZ,const char * pen,const char * opt)86 void MGL_EXPORT mgl_fplot_xyz(HMGL gr, const char *eqX, const char *eqY, const char *eqZ, const char *pen, const char *opt)
87 {
88 	double r = gr->SaveState(opt);
89 	long n = (mgl_isnan(r) || r<=0) ? 100:long(r+0.5);
90 	long nm = gr->FaceNum?gr->FaceNum*n:10000, nd = gr->FaceNum?gr->FaceNum*10:1000;
91 
92 	mglDataS x, y, z, t;
93 	x.dat.reserve(nm);	y.dat.reserve(nm);
94 	z.dat.reserve(nm);	t.dat.reserve(nm);
95 	mglFormula *ex, *ey, *ez;
96 	ex = new mglFormula(eqX ? eqX : "0");
97 	ey = new mglFormula(eqY ? eqY : "0");
98 	ez = new mglFormula(eqZ ? eqZ : "0");
99 	t.clear();	x.clear();	y.clear();	z.clear();
100 	for(long i=0;i<n;i++)	// initial data filling
101 	{
102 		double tt = i/(n-1.);	t.push_back(tt);
103 		x.push_back(ex->Calc(0,0,t[i]));
104 		y.push_back(ey->Calc(0,0,t[i]));
105 		z.push_back(ez->Calc(0,0,t[i]));
106 	}
107 
108 	bool check=true;
109 	double xm=fabs(gr->Max.x-gr->Min.x)/nd, ym=fabs(gr->Max.y-gr->Min.y)/nd, zm=fabs(gr->Max.z-gr->Min.z)/nd;
110 	while(check && long(x.dat.size())<nm)
111 	{
112 		if(gr->NeedStop())	{	delete ex;	delete ey;	delete ez;	return;	}
113 		check = false;
114 		for(long i=1;i<long(t.size());i++)
115 		{
116 			double ts=(t[i]+t[i-1])/2;
117 			double xs=(x[i]+x[i-1])/2, xr=ex->Calc(0,0,ts);
118 			double ys=(y[i]+y[i-1])/2, yr=ey->Calc(0,0,ts);
119 			double zs=(z[i]+z[i-1])/2, zr=ez->Calc(0,0,ts);
120 			if(fabs(xr-xs)>xm || fabs(yr-ys)>ym || fabs(zr-zs)>zm)	// bad approximation here
121 			{
122 				t.dat.insert(t.dat.begin()+i,ts);
123 				x.dat.insert(x.dat.begin()+i,xr);
124 				y.dat.insert(y.dat.begin()+i,yr);
125 				z.dat.insert(z.dat.begin()+i,zr);
126 				check = true;	i++;
127 			}
128 		}
129 	}
130 	delete ex;	delete ey;	delete ez;
131 	mgl_plot_xyz(gr,&x,&y,&z,pen,0);
132 }
133 //-----------------------------------------------------------------------------
mgl_fplot_(uintptr_t * gr,const char * fy,const char * stl,const char * opt,int ly,int ls,int lo)134 void MGL_EXPORT mgl_fplot_(uintptr_t *gr, const char *fy, const char *stl, const char *opt, int ly, int ls, int lo)
135 {	char *s=new char[ly+1];	memcpy(s,fy,ly);	s[ly]=0;
136 	char *p=new char[ls+1];	memcpy(p,stl,ls);	p[ls]=0;
137 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
138 	mgl_fplot(_GR_, s, p, o);
139 	delete []s;		delete []p;	delete []o;	}
140 //-----------------------------------------------------------------------------
mgl_fplot_xyz_(uintptr_t * gr,const char * fx,const char * fy,const char * fz,const char * stl,const char * opt,int lx,int ly,int lz,int ls,int lo)141 void MGL_EXPORT mgl_fplot_xyz_(uintptr_t *gr, const char *fx, const char *fy, const char *fz, const char *stl, const char *opt, int lx, int ly, int lz, int ls, int lo)
142 {	char *sx=new char[lx+1];	memcpy(sx,fx,lx);	sx[lx]=0;
143 	char *sy=new char[ly+1];	memcpy(sy,fy,ly);	sy[ly]=0;
144 	char *sz=new char[lz+1];	memcpy(sz,fz,lz);	sz[lz]=0;
145 	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
146 	char *p=new char[ls+1];		memcpy(p,stl,ls);	p[ls]=0;
147 	mgl_fplot_xyz(_GR_, sx, sy, sz, p, o);
148 	delete []sx;	delete []sy;	delete []sz;	delete []p;	delete []o;	}
149 //-----------------------------------------------------------------------------
150 //
151 //	Radar series
152 //
153 //-----------------------------------------------------------------------------
mgl_radar(HMGL gr,HCDT a,const char * pen,const char * opt)154 void MGL_EXPORT mgl_radar(HMGL gr, HCDT a, const char *pen, const char *opt)
155 {
156 	long n = a->GetNx(), ny=a->GetNy();
157 	if(n<2)	{	gr->SetWarn(mglWarnLow,"Radar");	return;	}
158 	mglData x(n+1,ny), y(n+1,ny);
159 	double m=a->Minimal(), r=gr->SaveState(opt);
160 	if(mgl_isnan(r) || r<0)	r = m<0 ? -m:0;
161 	double *co=new double[2*n];
162 	for(long i=0;i<n;i++)	{	co[i]=cos(2*i*M_PI/n);	co[i+n]=sin(2*i*M_PI/n);	}
163 	for(long j=0;j<ny;j++)
164 	{
165 		for(long i=0;i<n;i++)
166 		{
167 			double v = a->v(i,j);
168 			x.a[i+(n+1)*j] = (r+v)*co[i];
169 			y.a[i+(n+1)*j] = (r+v)*co[i+n];
170 		}
171 		x.a[n+(n+1)*j] = r+a->v(0,j);	y.a[n+(n+1)*j] = 0;
172 	}
173 	mgl_plot_xy(gr,&x,&y,pen,0);
174 	if(mglchr(pen,'#'))	// draw "grid"
175 	{
176 		m = 1.1*(a->Maximal()+r);
177 		x.Create(2);	y.Create(2);
178 		for(long i=0;i<n;i++)
179 		{
180 			x.a[1]=m*co[i];		y.a[1]=m*co[i+n];
181 			mgl_plot_xy(gr,&x,&y,"k",0);
182 		}
183 		if(r>0)
184 		{
185 			x.Create(101);	y.Create(101);
186 			for(long i=0;i<91;i++)
187 			{	x.a[i]=r*mgl_cos[(4*i)%360];	y.a[i]=r*mgl_cos[(270+4*i)%360];	}
188 			mgl_plot_xy(gr,&x,&y,"k",0);
189 		}
190 	}
191 	delete []co;
192 }
193 //-----------------------------------------------------------------------------
mgl_radar_(uintptr_t * gr,uintptr_t * a,const char * pen,const char * opt,int l,int lo)194 void MGL_EXPORT mgl_radar_(uintptr_t *gr, uintptr_t *a, const char *pen, const char *opt, int l,int lo)
195 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
196 	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
197 	mgl_radar(_GR_, _DA_(a),s,o);	delete []s;	delete []o;	}
198 //-----------------------------------------------------------------------------
199 //
200 //	Candle series
201 //
202 //-----------------------------------------------------------------------------
mgl_candle_xyv(HMGL gr,HCDT x,HCDT v1,HCDT v2,HCDT y1,HCDT y2,const char * pen,const char * opt)203 void MGL_EXPORT mgl_candle_xyv(HMGL gr, HCDT x, HCDT v1, HCDT v2, HCDT y1, HCDT y2, const char *pen, const char *opt)
204 {
205 	long n=v1->GetNx(),pal,nx=x->GetNx();
206 	if(n<2)	{	gr->SetWarn(mglWarnLow,"Candle");	return;	}
207 	if(nx<n || v2->GetNx()!=n)	{	gr->SetWarn(mglWarnDim,"Candle");	return;	}
208 	bool d1=false,d2=false;
209 	if(!y1)	{	y1 = new mglData(n);	d1=true;	((mglData *)y1)->Fill(NAN,NAN);	}
210 	if(!y2)	{	y2 = new mglData(n);	d2=true;	((mglData *)y2)->Fill(NAN,NAN);	}
211 	if(y1->GetNx()!=n || y2->GetNx()!=n)
212 	{	if(d1)	delete y1;	if(d2)	delete y2;
213 		gr->SetWarn(mglWarnDim,"Candle");	return;	}
214 	static int cgid=1;	gr->StartGroup("Candle",cgid++);
215 	gr->SaveState(opt);	gr->SetPenPal(pen,&pal);	gr->SetMask(pen);
216 	long kq = gr->AllocPnts(8*n);
217 	bool sh = mglchr(pen,'!');
218 	bool wire = mglchr(pen,'#');
219 
220 	double dv=nx>n?1:0;
221 	if(mglchr(pen,'<'))	dv = 1;
222 	if(mglchr(pen,'^'))	dv = 0;
223 	if(mglchr(pen,'>'))	dv =-1;
224 	double zm = gr->AdjustZMin();
225 	double c1=gr->NextColor(pal), c2=c1;
226 	bool col2 = (gr->GetNumPal(pal)==2 && !sh);
227 	if(col2)	c2 = gr->NextColor(pal);
228 #pragma omp parallel for
229 	for(long i=0;i<n;i++)
230 	{
231 		double m1=v1->v(i),	m2 = v2->v(i),	xx = x->v(i);
232 		double d = i<nx-1 ? x->v(i+1)-xx : xx-x->v(i-1), c;
233 		double x1 = xx + d/2*(dv-gr->BarWidth);
234 		double x2 = x1 + gr->BarWidth*d;	xx = (x1+x2)/2;
235 		if(sh)	c = gr->NextColor(pal,i);
236 		else if(wire)	c = (i>0 && m2>v2->v(i-1))?c2:c1;
237 		else	c = (m1>m2)?c1:c2;
238 		long iq = kq+8*i;
239 		gr->AddPntQ(iq,mglPoint(xx,y1->v(i),zm),c);
240 		gr->AddPntQ(iq+1,mglPoint(xx,m1,zm),c);
241 		gr->AddPntQ(iq+2,mglPoint(xx,y2->v(i),zm),c);
242 		gr->AddPntQ(iq+3,mglPoint(xx,m2,zm),c);
243 		gr->AddPntQ(iq+4,mglPoint(x1,m1,zm),c);
244 		gr->AddPntQ(iq+5,mglPoint(x2,m1,zm),c);
245 		gr->AddPntQ(iq+6,mglPoint(x1,m2,zm),c);
246 		gr->AddPntQ(iq+7,mglPoint(x2,m2,zm),c);
247 	}
248 	for(long i=0;i<n;i++)
249 	{
250 		long iq = kq+8*i;
251 		gr->line_plot(iq,  iq+1);	gr->line_plot(iq+2,iq+3);
252 		gr->line_plot(iq+4,iq+5);	gr->line_plot(iq+4,iq+6);
253 		gr->line_plot(iq+7,iq+5);	gr->line_plot(iq+7,iq+6);
254 		if(v1->v(i)>v2->v(i) || (col2 && !wire))	gr->quad_plot(iq+4,iq+5,iq+6,iq+7);
255 	}
256 	if(d1)	delete y1;
257 	if(d2)	delete y2;
258 	gr->EndGroup();
259 }
260 //-----------------------------------------------------------------------------
mgl_candle_yv(HMGL gr,HCDT v1,HCDT v2,HCDT y1,HCDT y2,const char * pen,const char * opt)261 void MGL_EXPORT mgl_candle_yv(HMGL gr, HCDT v1, HCDT v2, HCDT y1, HCDT y2, const char *pen, const char *opt)
262 {
263 	gr->SaveState(opt);
264 	mglDataV x(v1->GetNx()+1);
265 	x.Fill(gr->Min.x,gr->Max.x);
266 	mgl_candle_xyv(gr,&x,v1,v2,y1,y2,pen,0);
267 }
268 //-----------------------------------------------------------------------------
mgl_candle(HMGL gr,HCDT v1,HCDT y1,HCDT y2,const char * pen,const char * opt)269 void MGL_EXPORT mgl_candle(HMGL gr, HCDT v1, HCDT y1, HCDT y2, const char *pen, const char *opt)
270 {
271 	mglData v2(v1);
272 	v2.Roll('x',1);	v2.a[0]=NAN;
273 	mgl_candle_yv(gr,v1,&v2,y1,y2,pen,opt);
274 }
275 //-----------------------------------------------------------------------------
mgl_candle_xyv_(uintptr_t * gr,uintptr_t * x,uintptr_t * v1,uintptr_t * v2,uintptr_t * y1,uintptr_t * y2,const char * pen,const char * opt,int l,int lo)276 void MGL_EXPORT mgl_candle_xyv_(uintptr_t *gr, uintptr_t *x, uintptr_t *v1, uintptr_t *v2, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt,int l,int lo)
277 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
278 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
279 	mgl_candle_xyv(_GR_,_DA_(x),_DA_(v1),_DA_(v2),_DA_(y1),_DA_(y2),s,o);	delete []s;	delete []o;	}
280 //-----------------------------------------------------------------------------
mgl_candle_yv_(uintptr_t * gr,uintptr_t * v1,uintptr_t * v2,uintptr_t * y1,uintptr_t * y2,const char * pen,const char * opt,int l,int lo)281 void MGL_EXPORT mgl_candle_yv_(uintptr_t *gr, uintptr_t *v1, uintptr_t *v2, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt,int l,int lo)
282 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
283 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
284 	mgl_candle_yv(_GR_,_DA_(v1),_DA_(v2),_DA_(y1),_DA_(y2),s,o);	delete []s;	delete []o;	}
285 //-----------------------------------------------------------------------------
mgl_candle_(uintptr_t * gr,uintptr_t * y,uintptr_t * y1,uintptr_t * y2,const char * pen,const char * opt,int l,int lo)286 void MGL_EXPORT mgl_candle_(uintptr_t *gr, uintptr_t *y, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt,int l,int lo)
287 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
288 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
289 	mgl_candle(_GR_,_DA_(y),_DA_(y1),_DA_(y2),s,o);
290 	delete []s;	delete []o;	}
291 //-----------------------------------------------------------------------------
292 //
293 //	Plot series
294 //
295 //-----------------------------------------------------------------------------
mglPointAmglPointA296 struct mglPointA {	mglPoint p;	bool orig;	mglPointA(const mglPoint &pp, bool o) : p(pp), orig(o) {}	};
mgl_pnt_prepare(const mglPoint & p1,const mglPoint & p2,HCDT xx,HCDT yy,HCDT zz,HCDT cc)297 std::vector<mglPointA> static mgl_pnt_prepare(const mglPoint &p1, const mglPoint &p2, HCDT xx, HCDT yy, HCDT zz, HCDT cc)
298 {
299 	std::vector<mglPointA> out;
300 	long n = xx->GetNx();
301 	mglPoint p(xx->v(0),yy->v(0),zz->v(0),cc?cc->v(0):0);
302 	if(p>p1 && p<p2)	out.push_back(mglPointA(p,true));
303 	else	out.push_back(mglPointA(mglPoint(NAN),true));
304 	for(long i=1;i<n;i++)
305 	{
306 		mglPoint q(xx->v(i),yy->v(i),zz->v(i),cc?cc->v(i):0);
307 		double x1,x2,y1,y2,z1,z2,t;
308 		x1=mgl_d(p1.x, p.x, q.x);	x2=mgl_d(p2.x, p.x, q.x);	if(x2<x1)	{	t=x1;	x1=x2;	x2=t;	}
309 		y1=mgl_d(p1.y, p.y, q.y);	y2=mgl_d(p2.y, p.y, q.y);	if(y2<y1)	{	t=y1;	y1=y2;	y2=t;	}
310 		z1=mgl_d(p1.z, p.z, q.z);	z2=mgl_d(p2.z, p.z, q.z);	if(z2<z1)	{	t=z1;	z1=z2;	z2=t;	}
311 		double d1 = mgl_isnum(x1)?x1:0, d2 = mgl_isnum(x2)?x2:1;
312 		if(y1>d1)	d1=y1;
313 		if(y2<d2)	d2=y2;
314 		if(z1>d1)	d1=z1;
315 		if(z2<d2)	d2=z2;
316 		if(d1>0 && d1<1)	out.push_back(mglPointA(p+d1*(q-p),false));
317 		if(d2>0 && d2<1)	out.push_back(mglPointA(p+d2*(q-p),false));
318 		if(d1<1 && d2>=1)	out.push_back(mglPointA(q,true));
319 		else if(i==n-1)	out.push_back(mglPointA(mglPoint(NAN),true));
320 		p = q;
321 	}
322 	return out;
323 }
mgl_pnt_copy(HCDT xx,HCDT yy,HCDT zz,HCDT cc)324 std::vector<mglPointA> static mgl_pnt_copy(HCDT xx, HCDT yy, HCDT zz, HCDT cc)
325 {
326 	std::vector<mglPointA> out;
327 	long n = xx->GetNx();
328 	for(long i=0;i<n;i++)
329 		out.push_back(mglPointA(mglPoint(xx->v(i),yy->v(i),zz->v(i),cc?cc->v(i):0),true));
330 	return out;
331 }
332 //-----------------------------------------------------------------------------
333 void MGL_EXPORT mgl_mark(HMGL gr, double x, double y, double z,const char *mark);
mgl_plot_xyz(HMGL gr,HCDT x,HCDT y,HCDT z,const char * pen,const char * opt)334 void MGL_EXPORT mgl_plot_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt)
335 {
336 	static int cgid=1;
337 	long n=y->GetNx(),pal;
338 	if(n<2 && !mgl_check_dim0(gr,x,y,z,0,"Plot"))
339 	{
340 		gr->StartGroup("Plot",cgid++);
341 		gr->SaveState(opt);
342 
343 		char mk = gr->SetPenPal(pen);
344 		if(mk)
345 		{
346 			long k = gr->AddPnt(mglPoint(x->v(0),y->v(0),z->v(0)),gr->CDef,mglPoint(NAN),-1,3);
347 			gr->mark_plot(k,mk,gr->GetPenWidth()); 	gr->AddActive(k);
348 		}
349 		gr->EndGroup(); return;
350 	}
351 	if(mgl_check_dim1(gr,x,y,z,0,"Plot"))	return;
352 
353 	gr->StartGroup("Plot",cgid++);
354 	gr->SaveState(opt);
355 	long m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();	m = z->GetNy() > m ? z->GetNy() : m;
356 	char mk=gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
357 	bool sh = mglchr(pen,'!'), orig = !mglchr(pen,'a');
358 
359 	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n, dx = n>d?n/d:1;
360 	for(long j=0;j<m;j++)
361 	{
362 		if(gr->NeedStop())	break;
363 		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0, mz = j<z->GetNy() ? j:0;
364 		gr->NextColor(pal);
365 		mglDataR xx(x,mx), yy(y,my), zz(z,mz);
366 		const std::vector<mglPointA> &pp = orig ? mgl_pnt_copy(&xx, &yy, &zz, 0) :
367 			mgl_pnt_prepare(gr->Min, gr->Max, &xx, &yy, &zz, 0);
368 		size_t num = pp.size();
369 		long kq = gr->AllocPnts(num);
370 #pragma omp parallel for
371 		for(msize i=0;i<num;i++)
372 		{	double c = sh ? gr->NextColor(pal,i):gr->CDef;
373 			gr->AddPntQ(kq+i, pp[i].p, c);	}
374 		if(mk)	for(size_t i=0;i<num;i+=dx)
375 			if(pp[i].orig)	gr->mark_plot(kq+i, mk);
376 		if(num>1)
377 		{
378 			gr->arrow_plot(kq,kq+1,gr->Arrow1);
379 			gr->arrow_plot(kq+num-1,kq+num-2,gr->Arrow2);
380 		}
381 		gr->curve_plot(num, kq);
382 	}
383 	gr->EndGroup();
384 }
385 //-----------------------------------------------------------------------------
mgl_plot_xy(HMGL gr,HCDT x,HCDT y,const char * pen,const char * opt)386 void MGL_EXPORT mgl_plot_xy(HMGL gr, HCDT x, HCDT y, const char *pen, const char *opt)
387 {
388 	gr->SaveState(opt);
389 	mglDataV z(y->GetNx());	z.Fill(gr->AdjustZMin());
390 	mgl_plot_xyz(gr,x,y,&z,pen,0);
391 }
392 //-----------------------------------------------------------------------------
mgl_plot(HMGL gr,HCDT y,const char * pen,const char * opt)393 void MGL_EXPORT mgl_plot(HMGL gr, HCDT y, const char *pen, const char *opt)
394 {
395 	long n=y->GetNx();
396 	if(n<2)	{	gr->SetWarn(mglWarnLow,"Plot");	return;	}
397 	gr->SaveState(opt);
398 	mglDataV x(n), z(n);
399 	x.Fill(gr->Min.x,gr->Max.x);	z.Fill(gr->AdjustZMin());
400 	mgl_plot_xyz(gr,&x,y,&z,pen,0);
401 }
402 //-----------------------------------------------------------------------------
mgl_plot_xyz_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * pen,const char * opt,int l,int lo)403 void MGL_EXPORT mgl_plot_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int l,int lo)
404 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
405 	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
406 	mgl_plot_xyz(_GR_, _DA_(x),_DA_(y),_DA_(z),s,o);	delete []s;	delete []o;	}
407 //-----------------------------------------------------------------------------
mgl_plot_xy_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,const char * pen,const char * opt,int l,int lo)408 void MGL_EXPORT mgl_plot_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
409 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
410 	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
411 	mgl_plot_xy(_GR_, _DA_(x),_DA_(y),s,o);	delete []s;	delete []o;	}
412 //-----------------------------------------------------------------------------
mgl_plot_(uintptr_t * gr,uintptr_t * y,const char * pen,const char * opt,int l,int lo)413 void MGL_EXPORT mgl_plot_(uintptr_t *gr, uintptr_t *y,	const char *pen, const char *opt,int l,int lo)
414 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
415 	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
416 	mgl_plot(_GR_, _DA_(y),s,o);	delete []s;	delete []o;	}
417 //-----------------------------------------------------------------------------
418 //
419 //	Tens series
420 //
421 //-----------------------------------------------------------------------------
mgl_tens_xyz(HMGL gr,HCDT x,HCDT y,HCDT z,HCDT c,const char * pen,const char * opt)422 void MGL_EXPORT mgl_tens_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT c, const char *pen, const char *opt)
423 {
424 	long m,n=y->GetNx(), pal;
425 	if(mgl_check_dim1(gr,x,y,z,0,"Tens"))	return;
426 
427 	gr->SaveState(opt);
428 	static int cgid=1;	gr->StartGroup("Tens",cgid++);
429 	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();	m = z->GetNy() > m ? z->GetNy() : m;
430 	char mk=gr->SetPenPal(pen, &pal);	gr->Reserve(2*n*m);
431 	long ss=gr->AddTexture(pen);
432 	bool orig = !mglchr(pen,'a');
433 
434 	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n, dx = n>d?n/d:1;
435 	for(long j=0;j<m;j++)
436 	{
437 		if(gr->NeedStop())	break;
438 		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
439 		long mz = j<z->GetNy() ? j:0, mc = j<c->GetNy() ? j:0;
440 		mglDataR xx(x,mx), yy(y,my), zz(z,mz), cc(c,mc);
441 		const std::vector<mglPointA> &pp = orig ? mgl_pnt_copy(&xx, &yy, &zz, &cc) :
442 			mgl_pnt_prepare(gr->Min, gr->Max, &xx, &yy, &zz, &cc);
443 
444 		size_t num = pp.size();
445 		long kq = gr->AllocPnts(num);
446 #pragma omp parallel for
447 		for(msize i=0;i<num;i++)
448 		{	gr->AddPntQ(kq+i,pp[i].p, gr->GetC(ss,pp[i].p.c));	}
449 		if(mk)	for(size_t i=0;i<num;i+=dx)
450 			if(pp[i].orig)	gr->mark_plot(kq+i, mk);
451 		if(num>1)
452 		{
453 			gr->arrow_plot(kq,kq+1,gr->Arrow1);
454 			gr->arrow_plot(kq+num-1,kq+num-2,gr->Arrow2);
455 		}
456 		gr->curve_plot(num, kq);
457 	}
458 	gr->EndGroup();
459 }
460 //-----------------------------------------------------------------------------
mgl_tens_xy(HMGL gr,HCDT x,HCDT y,HCDT c,const char * pen,const char * opt)461 void MGL_EXPORT mgl_tens_xy(HMGL gr, HCDT x, HCDT y, HCDT c, const char *pen, const char *opt)
462 {
463 	gr->SaveState(opt);
464 	mglDataV z(y->GetNx());	z.Fill(gr->AdjustZMin());
465 	mgl_tens_xyz(gr,x,y,&z,c,pen,0);
466 }
467 //-----------------------------------------------------------------------------
mgl_tens(HMGL gr,HCDT y,HCDT c,const char * pen,const char * opt)468 void MGL_EXPORT mgl_tens(HMGL gr, HCDT y, HCDT c, const char *pen, const char *opt)
469 {
470 	long n=y->GetNx();
471 	if(n<2)	{	gr->SetWarn(mglWarnLow,"Tens");	return;	}
472 	gr->SaveState(opt);
473 	mglDataV x(n), z(n);
474 	x.Fill(gr->Min.x,gr->Max.x);	z.Fill(gr->AdjustZMin());
475 	mgl_tens_xyz(gr,&x,y,&z,c,pen,0);
476 }
477 //-----------------------------------------------------------------------------
mgl_tens_xyz_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,uintptr_t * c,const char * pen,const char * opt,int l,int lo)478 void MGL_EXPORT mgl_tens_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *c, const char *pen, const char *opt,int l,int lo)
479 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
480 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
481 	mgl_tens_xyz(_GR_, _DA_(x),_DA_(y),_DA_(z),_DA_(c),s,o);	delete []o;	delete []s;	}
482 //-----------------------------------------------------------------------------
mgl_tens_xy_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * c,const char * pen,const char * opt,int l,int lo)483 void MGL_EXPORT mgl_tens_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *c, const char *pen, const char *opt,int l,int lo)
484 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
485 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
486 	mgl_tens_xy(_GR_, _DA_(x),_DA_(y),_DA_(c),s,o);	delete []o;	delete []s;	}
487 //-----------------------------------------------------------------------------
mgl_tens_(uintptr_t * gr,uintptr_t * y,uintptr_t * c,const char * pen,const char * opt,int l,int lo)488 void MGL_EXPORT mgl_tens_(uintptr_t *gr, uintptr_t *y, uintptr_t *c, const char *pen, const char *opt,int l,int lo)
489 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
490 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
491 	mgl_tens(_GR_, _DA_(y),_DA_(c),s,o);	delete []o;	delete []s;	}
492 //-----------------------------------------------------------------------------
493 //
494 //	Area series
495 //
496 //-----------------------------------------------------------------------------
mgl_area_xyz(HMGL gr,HCDT x,HCDT y,HCDT z,const char * pen,const char * opt)497 void MGL_EXPORT mgl_area_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt)
498 {
499 	long n=y->GetNx(),m,pal;
500 	if(mgl_check_dim1(gr,x,y,z,0,"Area"))	return;
501 
502 	gr->SaveState(opt);
503 	static int cgid=1;	gr->StartGroup("Area3",cgid++);
504 	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();	m = z->GetNy() > m ? z->GetNy() : m;
505 	bool sh = mglchr(pen,'!'), wire = mglchr(pen,'#'), orig = !mglchr(pen,'a');
506 
507 	double z0=gr->GetOrgZ('x');
508 	gr->SetPenPal(pen,&pal);	gr->SetMask(pen);	gr->Reserve(2*n*m);
509 
510 	for(long j=0;j<m;j++)
511 	{
512 		if(gr->NeedStop())	break;
513 		double c1=gr->NextColor(pal), c2=c1;
514 		if(gr->GetNumPal(pal)==2*m && !sh)	c2 = gr->NextColor(pal);
515 		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0, mz = j<z->GetNy() ? j:0;
516 
517 		mglDataR xx(x,mx), yy(y,my), zz(z,mz);
518 		std::vector<mglPointA> pp = orig ? mgl_pnt_copy(&xx, &yy, &zz, 0) :
519 			mgl_pnt_prepare(gr->Min, gr->Max, &xx, &yy, &zz, 0);
520 		size_t np = pp.size();
521 		mglPoint nn(pp[0].p.y-pp[1].p.y, pp[1].p.x-pp[0].p.x);
522 		long kq = gr->AllocPnts(2*np);
523 #pragma omp parallel for
524 		for(msize i=0;i<np;i++)
525 		{
526 			double cc=gr->NextColor(pal,i);
527 			if(i>0 && i<np-1)	{	nn.x=(pp[i-1].p.y-pp[i+1].p.y)/2;	nn.y=(pp[i+1].p.x-pp[i-1].p.x)/2;	}
528 			else if(i==np-1)	{	nn.x=pp[np-2].p.y-pp[np-1].p.y;	nn.y=pp[np-1].p.x-pp[np-2].p.x;	}
529 			bool r1 = gr->AddPntQ(kq+2*i,pp[i].p, sh?cc:c1,nn,-1,27);	pp[i].p.z = z0;
530 			bool r2 = gr->AddPntQ(kq+2*i+1,pp[i].p, sh?cc:c2,nn,-1,27);
531 			if(!r1 && !r2)	{	gr->DisablePnt(kq+2*i);	gr->DisablePnt(kq+2*i+1);	}
532 		}
533 		for(size_t i=1;i<np;i++)
534 		{
535 			long iq = kq+2*i;
536 			if(gr->SamePnt(iq,iq-2) || gr->SamePnt(iq+1,iq-1))	continue;
537 			if(wire)
538 			{
539 				gr->line_plot(iq,iq+1);	gr->line_plot(iq-1,iq+1);
540 				gr->line_plot(iq,iq-2);	gr->line_plot(iq-1,iq-2);
541 			}
542 			else	gr->quad_plot(iq,iq+1,iq-2,iq-1);
543 		}
544 	}
545 	gr->EndGroup();
546 }
547 //-----------------------------------------------------------------------------
mgl_area_xy(HMGL gr,HCDT x,HCDT y,const char * pen,const char * opt)548 void MGL_EXPORT mgl_area_xy(HMGL gr, HCDT x, HCDT y, const char *pen, const char *opt)
549 {
550 	long n=y->GetNx(),m=y->GetNy(),pal;
551 	if(mgl_check_dim1(gr,x,y,0,0,"Area"))	return;
552 
553 	gr->SaveState(opt);
554 	static int cgid=1;	gr->StartGroup("Curve",cgid++);
555 	double zm = gr->AdjustZMin();
556 	double y0=gr->GetOrgY('x');
557 	mglPoint nn(0,0,1);
558 	bool sh = mglchr(pen,'!'), wire = mglchr(pen,'#'), orig = !mglchr(pen,'a');
559 
560 	gr->SetPenPal(pen,&pal);	gr->SetMask(pen);	gr->Reserve(2*n*m);
561 	for(long j=0;j<m;j++)
562 	{
563 		if(gr->NeedStop())	break;
564 		double c1=gr->NextColor(pal), c2=c1;
565 		if(gr->GetNumPal(pal)==2*m && !sh)	c2=gr->NextColor(pal);
566 		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
567 		double z0 = zm + (m-1-j)*(gr->Max.z-zm)/m;
568 
569 		mglDataR xx(x,mx), yy(y,my);	mglDataV zz(n,1,1,z0);
570 		std::vector<mglPointA> pp = orig ? mgl_pnt_copy(&xx, &yy, &zz, 0) :
571 			mgl_pnt_prepare(gr->Min, gr->Max, &xx, &yy, &zz, 0);
572 		size_t np = pp.size();
573 		long kq = gr->AllocPnts(2*np);
574 #pragma omp parallel for
575 		for(msize i=0;i<np;i++)
576 		{
577 			double cc=gr->NextColor(pal,i);
578 			bool r1 = gr->AddPntQ(kq+2*i,pp[i].p, sh?cc:c1,nn,-1,27);	pp[i].p.y = y0;
579 			bool r2 = gr->AddPntQ(kq+2*i+1,pp[i].p, sh?cc:c2,nn,-1,27);
580 			if(!r1 && !r2)	{	gr->DisablePnt(kq+2*i);	gr->DisablePnt(kq+2*i+1);	}
581 		}
582 		if(wire)	gr->line_plot(kq,kq+1);
583 		for(size_t i=1;i<np;i++)
584 		{
585 			long iq = kq+2*i;
586 			if(gr->SamePnt(iq,iq-2) || gr->SamePnt(iq+1,iq-1))	continue;
587 			if(wire)
588 			{
589 				gr->line_plot(iq,iq+1);	gr->line_plot(iq-1,iq+1);
590 				gr->line_plot(iq,iq-2);
591 			}
592 			else	gr->quad_plot(iq,iq+1,iq-2,iq-1);
593 		}
594 	}
595 	gr->EndGroup();
596 }
597 //-----------------------------------------------------------------------------
mgl_area(HMGL gr,HCDT y,const char * pen,const char * opt)598 void MGL_EXPORT mgl_area(HMGL gr, HCDT y, const char *pen, const char *opt)
599 {
600 	gr->SaveState(opt);
601 	mglDataV x(y->GetNx());	x.Fill(gr->Min.x,gr->Max.x);
602 	mgl_area_xy(gr,&x,y,pen,0);
603 }
604 //-----------------------------------------------------------------------------
mgl_area_xyz_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * pen,const char * opt,int l,int lo)605 void MGL_EXPORT mgl_area_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int l,int lo)
606 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
607 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
608 	mgl_area_xyz(_GR_, _DA_(x),_DA_(y),_DA_(z),s,o);	delete []o;	delete []s;	}
609 //-----------------------------------------------------------------------------
mgl_area_xy_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,const char * pen,const char * opt,int l,int lo)610 void MGL_EXPORT mgl_area_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
611 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
612 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
613 	mgl_area_xy(_GR_, _DA_(x),_DA_(y),s,o);	delete []o;	delete []s;	}
614 //-----------------------------------------------------------------------------
mgl_area_(uintptr_t * gr,uintptr_t * y,const char * pen,const char * opt,int l,int lo)615 void MGL_EXPORT mgl_area_(uintptr_t *gr, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
616 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
617 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
618 	mgl_area(_GR_, _DA_(y),s,o);	delete []o;	delete []s;	}
619 //-----------------------------------------------------------------------------
620 //
621 //	Region series
622 //
623 //-----------------------------------------------------------------------------
624 struct mglPointB {	mglPoint p1, p2;	bool orig;
mglPointBmglPointB625 	mglPointB(const mglPoint &pp1, const mglPoint &pp2, bool o) : p1(pp1), p2(pp2), orig(o) {}	};
mgl_pnt_prepare(const mglPoint & a1,const mglPoint & a2,HCDT xx1,HCDT yy1,HCDT zz1,HCDT xx2,HCDT yy2,HCDT zz2)626 std::vector<mglPointB> static mgl_pnt_prepare(const mglPoint &a1, const mglPoint &a2, HCDT xx1, HCDT yy1, HCDT zz1, HCDT xx2, HCDT yy2, HCDT zz2)
627 {
628 	std::vector<mglPointB> out;
629 	long n = xx1->GetNx();
630 	mglPoint p1(xx1->v(0),yy1->v(0),zz1->v(0)), p2(xx2->v(0),yy2->v(0),zz2->v(0));
631 	if(p1>a1 && p1<a2 && p2>a1 && p2<a2)	out.push_back(mglPointB(p1,p2,true));
632 	else	out.push_back(mglPointB(mglPoint(NAN),mglPoint(NAN),true));
633 	for(long i=1;i<n;i++)
634 	{
635 		mglPoint q1(xx1->v(i),yy1->v(i),zz1->v(i)), q2(xx2->v(i),yy2->v(i),zz2->v(i));
636 		double x1,x2,y1,y2,z1,z2,t;
637 		x1=mgl_d(a1.x, p1.x, q1.x);	x2=mgl_d(a2.x, p1.x, q1.x);	if(x2<x1)	{	t=x1;	x1=x2;	x2=t;	}
638 		y1=mgl_d(a1.y, p1.y, q1.y);	y2=mgl_d(a2.y, p1.y, q1.y);	if(y2<y1)	{	t=y1;	y1=y2;	y2=t;	}
639 		z1=mgl_d(a1.z, p1.z, q1.z);	z2=mgl_d(a2.z, p1.z, q1.z);	if(z2<z1)	{	t=z1;	z1=z2;	z2=t;	}
640 		double d11 = mgl_isnum(x1)?x1:0, d12 = mgl_isnum(x2)?x2:1;
641 		if(y1>d11)	d11=y1;
642 		if(y2<d12)	d12=y2;
643 		if(z1>d11)	d11=z1;
644 		if(z2<d12)	d12=z2;
645 		x1=mgl_d(a1.x, p2.x, q2.x);	x2=mgl_d(a2.x, p2.x, q2.x);	if(x2<x1)	{	t=x1;	x1=x2;	x2=t;	}
646 		y1=mgl_d(a1.y, p2.y, q2.y);	y2=mgl_d(a2.y, p2.y, q2.y);	if(y2<y1)	{	t=y1;	y1=y2;	y2=t;	}
647 		z1=mgl_d(a1.z, p2.z, q2.z);	z2=mgl_d(a2.z, p2.z, q2.z);	if(z2<z1)	{	t=z1;	z1=z2;	z2=t;	}
648 		double d21 = mgl_isnum(x1)?x1:0, d22 = mgl_isnum(x2)?x2:1;
649 		if(y1>d21)	d21=y1;
650 		if(y2<d22)	d22=y2;
651 		if(z1>d21)	d21=z1;
652 		if(z2<d22)	d22=z2;
653 
654 		std::vector<double> dd;
655 		if(d11>0 && d11<1)	dd.push_back(d11);
656 		if(d21>0 && d21<1)	dd.push_back(d21);
657 		if(d12>0 && d12<1)	dd.push_back(d12);
658 		if(d22>0 && d22<1)	dd.push_back(d22);
659 		// now add all intersections to be sure
660 		x1=mgl_d(0, p2.x-p1.x, q2.x-q1.x);	if(x1>0 && x1<1)	dd.push_back(x1);
661 		y1=mgl_d(0, p2.y-p1.y, q2.y-q1.y);	if(y1>0 && y1<1)	dd.push_back(y1);
662 		z1=mgl_d(0, p2.z-p1.z, q2.z-q1.z);	if(z1>0 && z1<1)	dd.push_back(z1);
663 		std::sort(dd.begin(),dd.end());
664 		for(size_t j=0;j<dd.size();j++)
665 			out.push_back(mglPointB(p1+dd[j]*(q1-p1), p2+dd[j]*(q2-p2), false));
666 		if((d11<1 && d12>=1) || (d21<1 && d22>=1))	out.push_back(mglPointB(q1,q2,true));
667 		else if(i==n-1)	out.push_back(mglPointB(mglPoint(NAN),mglPoint(NAN),true));
668 		p1 = q1;	p2 = q2;
669 	}
670 	return out;
671 }
mgl_pnt_copy(HCDT xx1,HCDT yy1,HCDT zz1,HCDT xx2,HCDT yy2,HCDT zz2)672 std::vector<mglPointB> static mgl_pnt_copy(HCDT xx1, HCDT yy1, HCDT zz1, HCDT xx2, HCDT yy2, HCDT zz2)
673 {
674 	std::vector<mglPointB> out;
675 	long n = xx1->GetNx();
676 	for(long i=0;i<n;i++)
677 		out.push_back(mglPointB(mglPoint(xx1->v(i),yy1->v(i),zz1->v(i)), mglPoint(xx2->v(i),yy2->v(i),zz2->v(i)), true));
678 	return out;
679 }
680 //-----------------------------------------------------------------------------
mgl_region_3d(HMGL gr,HCDT x1,HCDT y1,HCDT z1,HCDT x2,HCDT y2,HCDT z2,const char * pen,const char * opt)681 void MGL_EXPORT mgl_region_3d(HMGL gr, HCDT x1, HCDT y1, HCDT z1, HCDT x2, HCDT y2, HCDT z2, const char *pen, const char *opt)
682 {
683 	long n=y1->GetNx(), m, pal;
684 	if(mgl_check_dim1(gr,x1,y1,z1,0,"Region"))	return;
685 	if(mgl_check_dim1(gr,x1,x2,y2,z2,"Region"))	return;
686 	m = x1->GetNy() > y1->GetNy() ? x1->GetNy() : y1->GetNy();
687 	m = (z1 && z1->GetNy() > m) ? z1->GetNy() : m;
688 	bool zhave = z1 && z2;
689 	if(x1->GetNy()!=x2->GetNy() || y1->GetNy()!=y2->GetNy())
690 	{	gr->SetWarn(mglWarnDim,"Region");	return;	}
691 	if(zhave && z1->GetNy()!=z2->GetNy())
692 	{	gr->SetWarn(mglWarnDim,"Region");	return;	}
693 
694 	gr->SaveState(opt);
695 	static int cgid=1;	gr->StartGroup("Region",cgid++);
696 	mglPoint nn(0,0,1);
697 	double zm = gr->AdjustZMin();
698 //	bool inside = (mglchr(pen,'i'));	// NOTE: check if 'i' is free (used here for inside flag)
699 	bool sh = mglchr(pen,'!'), wire = mglchr(pen,'#'), orig = !mglchr(pen,'a');
700 
701 	gr->SetPenPal(pen,&pal);	gr->SetMask(pen);	gr->Reserve(2*n*m);
702 	for(long j=0;j<m;j++)
703 	{
704 		if(gr->NeedStop())	break;
705 		double c1=gr->NextColor(pal), c2=c1;
706 		if(gr->GetNumPal(pal)==2*m && !sh)	c2=gr->NextColor(pal);
707 		long mx = j<x1->GetNy() ? j:0, my = j<y1->GetNy() ? j:0;
708 		long mz = (zhave && j<z1->GetNy()) ? j:0;
709 		double z0 = zm + (m-1-j)*(gr->Max.z-zm)/m;
710 
711 		mglDataR xx1(x1,mx), yy1(y1,my), xx2(x2,mx), yy2(y2,my);
712 		mglDataV zz0(n,1,1,z0);
713 		std::vector<mglPointB> pp;
714 		if(zhave)
715 		{
716 			mglDataR zz1(z1,mz), zz2(z2,mz);
717 			pp = orig ? mgl_pnt_copy(&xx1, &yy1, &zz1, &xx2, &yy2, &zz2) :
718 				mgl_pnt_prepare(gr->Min, gr->Max, &xx1, &yy1, &zz1, &xx2, &yy2, &zz2);
719 		}
720 		else
721 		{
722 			pp = orig ? mgl_pnt_copy(&xx1, &yy1, &zz0, &xx2, &yy2, &zz0) :
723 				mgl_pnt_prepare(gr->Min, gr->Max, &xx1, &yy1, &zz0, &xx2, &yy2, &zz0);
724 		}
725 
726 		size_t np = pp.size();
727 		long kq = gr->AllocPnts(2*np);
728 #pragma omp parallel for
729 		for(msize i=0;i<np;i++)
730 		{
731 			double cc=gr->NextColor(pal,i);
732 			bool r1 = gr->AddPntQ(kq+2*i,pp[i].p1, sh?cc:c1,nn,-1,27);
733 			bool r2 = gr->AddPntQ(kq+2*i+1,pp[i].p2, sh?cc:c2,nn,-1,27);
734 			if(!r1 && !r2)	{	gr->DisablePnt(kq+2*i);	gr->DisablePnt(kq+2*i+1);	}
735 		}
736 		if(wire)	gr->line_plot(kq,kq+1);
737 		for(size_t i=1;i<np;i++)
738 		{
739 			long iq = kq+2*i;
740 			if(gr->SamePnt(iq,iq-2) || gr->SamePnt(iq+1,iq-1))	continue;
741 			if(wire)
742 			{
743 				gr->line_plot(iq,iq+1);	gr->line_plot(iq-1,iq+1);
744 				gr->line_plot(iq,iq-2);
745 			}
746 			else	gr->quad_plot(iq,iq+1,iq-2,iq-1);
747 		}
748 	}
749 	gr->EndGroup();
750 }
751 //-----------------------------------------------------------------------------
mgl_region_xy(HMGL gr,HCDT x,HCDT y1,HCDT y2,const char * pen,const char * opt)752 void MGL_EXPORT mgl_region_xy(HMGL gr, HCDT x, HCDT y1, HCDT y2, const char *pen, const char *opt)
753 {
754 	long n=y1->GetNx(), m=y1->GetNy(), pal;
755 	if(mgl_check_dim1(gr,x,y1,y2,0,"Region"))	return;
756 	if(y2->GetNy()!=m)	{	gr->SetWarn(mglWarnDim,"Region");	return;	}
757 
758 	gr->SaveState(opt);
759 	static int cgid=1;	gr->StartGroup("Region",cgid++);
760 	mglPoint nn(0,0,1);
761 	double zm = gr->AdjustZMin();
762 	bool inside = mglchr(pen,'i');	// NOTE: check if 'i' is free (used here for inside flag)
763 	bool sh = mglchr(pen,'!'), wire = mglchr(pen,'#'), orig = !mglchr(pen,'a');
764 
765 	gr->SetPenPal(pen,&pal);	gr->SetMask(pen);	gr->Reserve(2*n*m);
766 	for(long j=0;j<m;j++)
767 	{
768 		if(gr->NeedStop())	break;
769 		double c1=gr->NextColor(pal), c2=c1;
770 		if(gr->GetNumPal(pal)==2*m && !sh)	c2=gr->NextColor(pal);
771 		long mx = j<x->GetNy() ? j:0;
772 		double z0 = zm + (m-1-j)*(gr->Max.z-zm)/m;
773 
774 		mglDataR xx(x,mx), yy1(y1,j), yy2(y2,j);
775 		mglDataV zz0(n,1,1,z0);
776 		std::vector<mglPointB> pp = orig ? mgl_pnt_copy(&xx, &yy1, &zz0, &xx, &yy2, &zz0) :
777 			mgl_pnt_prepare(gr->Min, gr->Max, &xx, &yy1, &zz0, &xx, &yy2, &zz0);
778 
779 		size_t np = pp.size();
780 		long kq = gr->AllocPnts(2*np);
781 #pragma omp parallel for
782 		for(msize i=0;i<np;i++)
783 		{
784 			double cc=gr->NextColor(pal,i);
785 			bool r1 = gr->AddPntQ(kq+2*i,pp[i].p1, sh?cc:c1,nn,-1,27);
786 			bool r2 = gr->AddPntQ(kq+2*i+1,pp[i].p2, sh?cc:c2,nn,-1,27);
787 			if(!r1 && !r2)	{	gr->DisablePnt(kq+2*i);	gr->DisablePnt(kq+2*i+1);	}
788 		}
789 		if(wire)	gr->line_plot(kq,kq+1);
790 		for(size_t i=1;i<np;i++)
791 		{
792 			long iq = kq+2*i;
793 			if(gr->SamePnt(iq,iq-2) || gr->SamePnt(iq+1,iq-1))	continue;
794 			if(wire)
795 			{
796 				gr->line_plot(iq,iq+1);
797 				gr->line_plot(iq-1,iq+1);
798 				gr->line_plot(iq,iq-2);
799 			}
800 			else if(!inside)	gr->quad_plot(iq,iq+1,iq-2,iq-1);
801 			else
802 			{
803 				const mglPointB &a=pp[i-1], &b=pp[i];
804 				if(a.p1.y<=a.p2.y && b.p1.y<=b.p2.y)
805 					gr->quad_plot(iq,iq+1,iq-2,iq-1);
806 				else if(a.p1.y<=a.p2.y)
807 				{
808 					double cc=gr->NextColor(pal,i);
809 					double dd = (a.p1.y-a.p2.y)/(b.p2.y-b.p1.y-a.p2.y+a.p1.y);
810 					long ns = gr->AddPnt(b.p1*dd+a.p1*(1-dd), sh?cc:c1,nn,-1,27);
811 					gr->trig_plot(iq-2,iq-1,ns);
812 				}
813 				else if(b.p1.y<=b.p2.y)
814 				{
815 					double cc=gr->NextColor(pal,i);
816 					double dd = (a.p1.y-a.p2.y)/(b.p2.y-b.p1.y-a.p2.y+a.p1.y);
817 					long ns = gr->AddPnt(b.p1*dd+a.p1*(1-dd), sh?cc:c1,nn,-1,27);
818 					gr->trig_plot(iq,iq+1,ns);
819 				}
820 			}
821 		}
822 	}
823 	gr->EndGroup();
824 }
825 //-----------------------------------------------------------------------------
mgl_region(HMGL gr,HCDT y1,HCDT y2,const char * pen,const char * opt)826 void MGL_EXPORT mgl_region(HMGL gr, HCDT y1, HCDT y2, const char *pen, const char *opt)
827 {
828 	gr->SaveState(opt);
829 	mglDataV x(y1->GetNx());	x.Fill(gr->Min.x, gr->Max.x);
830 	mgl_region_xy(gr,&x,y1,y2,pen,0);
831 }
832 //-----------------------------------------------------------------------------
mgl_region_3d_(uintptr_t * gr,uintptr_t * x1,uintptr_t * y1,uintptr_t * z1,uintptr_t * x2,uintptr_t * y2,uintptr_t * z2,const char * pen,const char * opt,int l,int lo)833 void MGL_EXPORT mgl_region_3d_(uintptr_t *gr, uintptr_t *x1, uintptr_t *y1, uintptr_t *z1, uintptr_t *x2, uintptr_t *y2, uintptr_t *z2, const char *pen, const char *opt, int l, int lo)
834 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
835 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
836 	mgl_region_3d(_GR_, _DA_(x1),_DA_(y1),_DA_(z1),_DA_(x2),_DA_(y2),_DA_(z2),s,o);	delete []o;	delete []s;	}
837 //-----------------------------------------------------------------------------
mgl_region_xy_(uintptr_t * gr,uintptr_t * x,uintptr_t * y1,uintptr_t * y2,const char * pen,const char * opt,int l,int lo)838 void MGL_EXPORT mgl_region_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt, int l, int lo)
839 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
840 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
841 	mgl_region_xy(_GR_, _DA_(x),_DA_(y1),_DA_(y2),s,o);	delete []o;	delete []s;	}
842 //-----------------------------------------------------------------------------
mgl_region_(uintptr_t * gr,uintptr_t * y1,uintptr_t * y2,const char * pen,const char * opt,int l,int lo)843 void MGL_EXPORT mgl_region_(uintptr_t *gr, uintptr_t *y1, uintptr_t *y2, const char *pen, const char *opt, int l, int lo)
844 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
845 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
846 	mgl_region(_GR_, _DA_(y1),_DA_(y2),s,o);	delete []o;	delete []s;	}
847 //-----------------------------------------------------------------------------
848 //
849 //	Step series
850 //
851 //-----------------------------------------------------------------------------
mgl_step_xyz(HMGL gr,HCDT x,HCDT y,HCDT z,const char * pen,const char * opt)852 void MGL_EXPORT mgl_step_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt)
853 {
854 	long m,n=y->GetNx(), pal;
855 	if(mgl_check_dim1(gr,x,y,z,0,"Step"))	return;
856 
857 	gr->SaveState(opt);
858 	static int cgid=1;	gr->StartGroup("Step3",cgid++);
859 	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();	m = z->GetNy() > m ? z->GetNy() : m;
860 	bool sh = mglchr(pen,'!');
861 
862 	char mk=gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
863 	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n, dx = n>d?n/d:1;
864 	for(long j=0;j<m;j++)
865 	{
866 		if(gr->NeedStop())	break;
867 		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0, mz = j<z->GetNy() ? j:0;
868 		gr->NextColor(pal);
869 		long kq = gr->AllocPnts(2*n);	gr->SetPntOff(kq);
870 		gr->AddPntQ(kq+1,mglPoint(x->v(0,mx), y->v(0,my), z->v(0,mz)));
871 		if(mk)	gr->mark_plot(kq+1,mk);
872 #pragma omp parallel for
873 		for(long i=1;i<n;i++)
874 		{
875 			mglPoint p(x->v(i,mx), y->v(i,my), z->v(i-1,mz));
876 			double c = sh ? gr->NextColor(pal,i):gr->CDef;
877 			gr->AddPntQ(kq+2*i,p,c);
878 			p.z = z->v(i,mz);	gr->AddPntQ(kq+2*i+1,p,c);
879 		}
880 		for(long i=1;i<n;i++)
881 		{
882 			long iq = kq+2*i;
883 			gr->line_plot(iq,iq-1);	gr->line_plot(iq,iq+1);
884 			if(mk && i%dx==0)	gr->mark_plot(iq+1,mk);
885 		}
886 		gr->arrow_plot(kq+1,kq+2,gr->Arrow2);
887 		gr->arrow_plot(kq+2*n-1,kq+2*n-2,gr->Arrow2);
888 	}
889 	gr->EndGroup();
890 }
891 //-----------------------------------------------------------------------------
mgl_step_xy(HMGL gr,HCDT x,HCDT y,const char * pen,const char * opt)892 void MGL_EXPORT mgl_step_xy(HMGL gr, HCDT x, HCDT y, const char *pen, const char *opt)
893 {
894 	long m,n=y->GetNx(), pal;
895 	if(mgl_check_dim1(gr,x,y,0,0,"Step",true))	return;
896 
897 	gr->SaveState(opt);
898 	static int cgid=1;	gr->StartGroup("Step",cgid++);
899 	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
900 	bool sh = mglchr(pen,'!');
901 	bool same = x->GetNx()==n;
902 
903 	double zVal =gr->AdjustZMin();
904 	char mk=gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
905 	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n, dx = n>d?n/d:1;
906 	for(long j=0;j<m;j++)
907 	{
908 		if(gr->NeedStop())	break;
909 		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
910 		gr->NextColor(pal);
911 
912 		long kq = gr->AllocPnts(2*n);	gr->SetPntOff(kq);
913 		gr->AddPntQ(kq+1,mglPoint(x->v(0,mx), y->v(0,my), zVal));
914 		if(same && mk)	gr->mark_plot(kq+1,mk);
915 #pragma omp parallel for
916 		for(long i=1;i<n;i++)
917 		{
918 			mglPoint p(x->v(i,mx), y->v(i-1,my), zVal);
919 			double c = sh ? gr->NextColor(pal,i):gr->CDef;
920 			gr->AddPntQ(kq+2*i,p,c);
921 			p.y = y->v(i,my);	gr->AddPntQ(kq+2*i+1,p,c);
922 		}
923 		for(long i=1;i<n;i++)
924 		{
925 			long iq = kq+2*i;
926 			gr->line_plot(iq,iq-1);	gr->line_plot(iq,iq+1);
927 			if(same && mk && i%dx==0)	gr->mark_plot(iq+1,mk);
928 		}
929 		gr->arrow_plot(kq+1,kq+2,gr->Arrow2);
930 		gr->arrow_plot(kq+2*n-1,kq+2*n-2,gr->Arrow2);
931 		if(!same && mk)
932 		{
933 			kq = gr->AllocPnts(1+(n-1)/dx);
934 #pragma omp parallel for
935 			for(long i=0;i<n;i+=dx)
936 			{
937 				mglPoint p((x->v(i,mx)+x->v(i+1,mx))/2, y->v(i,my), zVal);
938 				double c = sh ? gr->NextColor(pal,i):gr->CDef;
939 				gr->AddPntQ(kq+i,p,c);
940 			}
941 			for(long i=0;i<n;i+=dx)	gr->mark_plot(kq+i,mk);
942 		}
943 	}
944 	gr->EndGroup();
945 }
946 //-----------------------------------------------------------------------------
mgl_step(HMGL gr,HCDT y,const char * pen,const char * opt)947 void MGL_EXPORT mgl_step(HMGL gr, HCDT y,	const char *pen, const char *opt)
948 {
949 	gr->SaveState(opt);
950 	mglDataV x(y->GetNx());	x.Fill(gr->Min.x,gr->Max.x);
951 	mgl_step_xy(gr,&x,y,pen,0);
952 }
953 //-----------------------------------------------------------------------------
mgl_step_xyz_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * pen,const char * opt,int l,int lo)954 void MGL_EXPORT mgl_step_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int l,int lo)
955 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
956 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
957 	mgl_step_xyz(_GR_, _DA_(x),_DA_(y),_DA_(z),s,o);	delete []o;	delete []s;	}
958 //-----------------------------------------------------------------------------
mgl_step_xy_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,const char * pen,const char * opt,int l,int lo)959 void MGL_EXPORT mgl_step_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
960 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
961 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
962 	mgl_step_xy(_GR_, _DA_(x),_DA_(y),s,o);	delete []o;	delete []s;	}
963 //-----------------------------------------------------------------------------
mgl_step_(uintptr_t * gr,uintptr_t * y,const char * pen,const char * opt,int l,int lo)964 void MGL_EXPORT mgl_step_(uintptr_t *gr, uintptr_t *y,	const char *pen, const char *opt,int l,int lo)
965 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
966 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
967 	mgl_step(_GR_, _DA_(y),s,o);	delete []o;	delete []s;	}
968 //-----------------------------------------------------------------------------
969 //
970 //	Stem series
971 //
972 //-----------------------------------------------------------------------------
mgl_lines_xyz(HMGL gr,HCDT x1,HCDT y1,HCDT z1,HCDT x2,HCDT y2,HCDT z2,const char * pen,const char * opt)973 void MGL_EXPORT mgl_lines_xyz(HMGL gr, HCDT x1, HCDT y1, HCDT z1, HCDT x2, HCDT y2, HCDT z2, const char *pen, const char *opt)
974 {
975 	long m,n=y1->GetNx(), pal;
976 	if(mgl_check_dim1(gr,x1,y1,z1,x2,"Lines"))	return;
977 	if(mgl_check_dim1(gr,x2,y2,z2,NULL,"Lines"))	return;
978 	if(x1->GetNy()!=x2->GetNy() || y1->GetNy()!=y2->GetNy() || z1->GetNy()!=z2->GetNy())	return;
979 
980 	gr->SaveState(opt);
981 	static int cgid=1;	gr->StartGroup("Lines",cgid++);
982 	m = x1->GetNy() > y1->GetNy() ? x1->GetNy() : y1->GetNy();	m = z1->GetNy() > m ? z1->GetNy() : m;
983 	bool sh = mglchr(pen,'!');
984 
985 	gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
986 	for(long j=0;j<m;j++)
987 	{
988 		if(gr->NeedStop())	break;
989 		long mx = j<x1->GetNy() ? j:0, my = j<y1->GetNy() ? j:0, mz = j<z1->GetNy() ? j:0;
990 		double c1=gr->NextColor(pal), c2=c1;
991 		if(gr->GetNumPal(pal)==2*m && !sh)	c2=gr->NextColor(pal);
992 		long kq = gr->AllocPnts(2*n);
993 #pragma omp parallel for
994 		for(long i=0;i<n;i++)
995 		{
996 			double cc=gr->NextColor(pal,i);
997 			gr->AddPntQ(kq+2*i,mglPoint(x1->v(i,mx), y1->v(i,my), z1->v(i,mz)),sh?cc:c1);
998 			gr->AddPntQ(kq+2*i+1,mglPoint(x2->v(i,mx), y2->v(i,my), z2->v(i,mz)),sh?cc:c2);
999 		}
1000 		for(long i=0;i<n;i++)
1001 		{
1002 			long iq = kq+2*i;	gr->line_plot(iq,iq+1);
1003 			gr->arrow_plot(iq,iq+1,gr->Arrow2);
1004 			gr->arrow_plot(iq+1,iq,gr->Arrow1);
1005 		}
1006 	}
1007 	gr->EndGroup();
1008 }
1009 //-----------------------------------------------------------------------------
mgl_lines_xy(HMGL gr,HCDT x1,HCDT y1,HCDT x2,HCDT y2,const char * pen,const char * opt)1010 void MGL_EXPORT mgl_lines_xy(HMGL gr, HCDT x1, HCDT y1, HCDT x2, HCDT y2, const char *pen, const char *opt)
1011 {
1012 	gr->SaveState(opt);
1013 	mglDataV z(y1->GetNx());	z.Fill(gr->Min.z,gr->Min.z);
1014 	mgl_lines_xyz(gr,x1,y1,&z,x2,y2,&z,pen,0);
1015 }
1016 //-----------------------------------------------------------------------------
mgl_lines_x(HMGL gr,HCDT x1,HCDT x2,const char * pen,const char * opt)1017 void MGL_EXPORT mgl_lines_x(HMGL gr, HCDT x1, HCDT x2, const char *pen, const char *opt)
1018 {
1019 	gr->SaveState(opt);
1020 	mglDataV y(x1->GetNx()), z(x1->GetNx());
1021 	y.Fill(gr->Min.y,gr->Max.y);
1022 	z.Fill(gr->Min.z,gr->Min.z);
1023 	mgl_lines_xyz(gr,x1,&y,&z,x2,&y,&z,pen,0);
1024 }
1025 //-----------------------------------------------------------------------------
mgl_lines(HMGL gr,HCDT y1,HCDT y2,const char * pen,const char * opt)1026 void MGL_EXPORT mgl_lines(HMGL gr, HCDT y1, HCDT y2, const char *pen, const char *opt)
1027 {
1028 	gr->SaveState(opt);
1029 	mglDataV x(y1->GetNx()), z(y1->GetNx());
1030 	x.Fill(gr->Min.x,gr->Max.x);
1031 	z.Fill(gr->Min.z,gr->Min.z);
1032 	mgl_lines_xyz(gr,&x,y1,&z,&x,y2,&z,pen,0);
1033 }
1034 //-----------------------------------------------------------------------------
mgl_lines_xyz_(uintptr_t * gr,uintptr_t * x1,uintptr_t * y1,uintptr_t * z1,uintptr_t * x2,uintptr_t * y2,uintptr_t * z2,const char * pen,const char * opt,int l,int lo)1035 void MGL_EXPORT mgl_lines_xyz_(uintptr_t *gr, uintptr_t *x1, uintptr_t *y1, uintptr_t *z1, uintptr_t *x2, uintptr_t *y2, uintptr_t *z2, const char *pen, const char *opt,int l,int lo)
1036 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1037 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1038 	mgl_lines_xyz(_GR_,_DA_(x1),_DA_(y1),_DA_(z1),_DA_(x2),_DA_(y2),_DA_(z2),s,o);	delete []o;	delete []s;	}
1039 //-----------------------------------------------------------------------------
mgl_lines_xy_(uintptr_t * gr,uintptr_t * x1,uintptr_t * y1,uintptr_t * x2,uintptr_t * y2,const char * pen,const char * opt,int l,int lo)1040 void MGL_EXPORT mgl_lines_xy_(uintptr_t *gr, uintptr_t *x1, uintptr_t *y1, uintptr_t *x2, uintptr_t *y2, const char *pen, const char *opt,int l,int lo)
1041 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1042 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1043 	mgl_lines_xy(_GR_,_DA_(x1),_DA_(y1),_DA_(x2),_DA_(y2),s,o);	delete []o;	delete []s;	}
1044 //-----------------------------------------------------------------------------
mgl_lines_x_(uintptr_t * gr,uintptr_t * x1,uintptr_t * x2,const char * pen,const char * opt,int l,int lo)1045 void MGL_EXPORT mgl_lines_x_(uintptr_t *gr, uintptr_t *x1,	uintptr_t *x2,	const char *pen, const char *opt,int l,int lo)
1046 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1047 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1048 	mgl_lines_x(_GR_,_DA_(x1),_DA_(x2),s,o);	delete []o;	delete []s;	}
1049 //-----------------------------------------------------------------------------
mgl_lines_(uintptr_t * gr,uintptr_t * y1,uintptr_t * y2,const char * pen,const char * opt,int l,int lo)1050 void MGL_EXPORT mgl_lines_(uintptr_t *gr, uintptr_t *y1,	uintptr_t *y2,	const char *pen, const char *opt,int l,int lo)
1051 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1052 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1053 	mgl_lines(_GR_,_DA_(y1),_DA_(y2),s,o);	delete []o;	delete []s;	}
1054 //-----------------------------------------------------------------------------
1055 //
1056 //	Stem series
1057 //
1058 //-----------------------------------------------------------------------------
mgl_stem_xyz(HMGL gr,HCDT x,HCDT y,HCDT z,const char * pen,const char * opt)1059 void MGL_EXPORT mgl_stem_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt)
1060 {
1061 	long m,n=y->GetNx(), pal;
1062 	if(mgl_check_dim0(gr,x,y,z,0,"Stem"))	return;
1063 
1064 	gr->SaveState(opt);
1065 	static int cgid=1;	gr->StartGroup("Stem3",cgid++);
1066 	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();	m = z->GetNy() > m ? z->GetNy() : m;
1067 	bool sh = mglchr(pen,'!');
1068 
1069 	double z0=gr->GetOrgZ('x');
1070 	char mk=gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
1071 	for(long j=0;j<m;j++)
1072 	{
1073 		if(gr->NeedStop())	break;
1074 		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0, mz = j<z->GetNy() ? j:0;
1075 		gr->NextColor(pal);
1076 		long kq = gr->AllocPnts(2*n);
1077 #pragma omp parallel for
1078 		for(long i=0;i<n;i++)
1079 		{
1080 			double c = sh ? gr->NextColor(pal,i):gr->CDef;
1081 			gr->AddPntQ(kq+2*i,mglPoint(x->v(i,mx), y->v(i,my), z->v(i,mz)),c);
1082 			gr->AddPntQ(kq+2*i+1,mglPoint(x->v(i,mx), y->v(i,my), z0),c);
1083 		}
1084 		for(long i=0;i<n;i++)
1085 		{
1086 			long iq = kq+2*i;	gr->line_plot(iq,iq+1);
1087 			if(mk)	gr->mark_plot(iq,mk);
1088 		}
1089 	}
1090 	gr->EndGroup();
1091 }
1092 //-----------------------------------------------------------------------------
mgl_stem_xy(HMGL gr,HCDT x,HCDT y,const char * pen,const char * opt)1093 void MGL_EXPORT mgl_stem_xy(HMGL gr, HCDT x, HCDT y, const char *pen, const char *opt)
1094 {
1095 	long m,n=y->GetNx(), pal;
1096 	if(mgl_check_dim0(gr,x,y,0,0,"Stem"))	return;
1097 
1098 	gr->SaveState(opt);
1099 	static int cgid=1;	gr->StartGroup("Stem",cgid++);
1100 	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
1101 	bool sh = mglchr(pen,'!');
1102 
1103 	double zVal = gr->AdjustZMin(), y0=gr->GetOrgY('x');
1104 	char mk=gr->SetPenPal(pen,&pal);	gr->Reserve(2*n*m);
1105 	for(long j=0;j<m;j++)
1106 	{
1107 		if(gr->NeedStop())	break;
1108 		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
1109 		gr->NextColor(pal);
1110 		long kq = gr->AllocPnts(2*n);
1111 #pragma omp parallel for
1112 		for(long i=0;i<n;i++)
1113 		{
1114 			double c = sh ? gr->NextColor(pal,i):gr->CDef;
1115 			gr->AddPntQ(kq+2*i,mglPoint(x->v(i,mx), y->v(i,my), zVal),c);
1116 			gr->AddPntQ(kq+2*i+1,mglPoint(x->v(i,mx), y0, zVal),c);
1117 		}
1118 		for(long i=0;i<n;i++)
1119 		{
1120 			long iq = kq+2*i;	gr->line_plot(iq,iq+1);
1121 			if(mk)	gr->mark_plot(iq,mk);
1122 		}
1123 	}
1124 	gr->EndGroup();
1125 }
1126 //-----------------------------------------------------------------------------
mgl_stem(HMGL gr,HCDT y,const char * pen,const char * opt)1127 void MGL_EXPORT mgl_stem(HMGL gr, HCDT y,	const char *pen, const char *opt)
1128 {
1129 	gr->SaveState(opt);
1130 	mglDataV x(y->GetNx());	x.Fill(gr->Min.x,gr->Max.x);
1131 	mgl_stem_xy(gr,&x,y,pen,0);
1132 }
1133 //-----------------------------------------------------------------------------
mgl_stem_xyz_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * pen,const char * opt,int l,int lo)1134 void MGL_EXPORT mgl_stem_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int l,int lo)
1135 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1136 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1137 	mgl_stem_xyz(_GR_,_DA_(x),_DA_(y),_DA_(z),s,o);	delete []o;	delete []s;	}
1138 //-----------------------------------------------------------------------------
mgl_stem_xy_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,const char * pen,const char * opt,int l,int lo)1139 void MGL_EXPORT mgl_stem_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
1140 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1141 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1142 	mgl_stem_xy(_GR_,_DA_(x),_DA_(y),s,o);	delete []o;	delete []s;	}
1143 //-----------------------------------------------------------------------------
mgl_stem_(uintptr_t * gr,uintptr_t * y,const char * pen,const char * opt,int l,int lo)1144 void MGL_EXPORT mgl_stem_(uintptr_t *gr, uintptr_t *y,	const char *pen, const char *opt,int l,int lo)
1145 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1146 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1147 	mgl_stem(_GR_,_DA_(y),s,o);	delete []o;	delete []s;	}
1148 //-----------------------------------------------------------------------------
1149 //
1150 //	Bars series
1151 //
1152 //-----------------------------------------------------------------------------
mgl_bars_xyz(HMGL gr,HCDT x,HCDT y,HCDT z,const char * pen,const char * opt)1153 void MGL_EXPORT mgl_bars_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt)
1154 {
1155 	long m,n=z->GetNx(), pal,nx=x->GetNx(),ny=y->GetNx();
1156 	if(mgl_check_dim1(gr,x,z,y,0,"Bars",true))	return;
1157 
1158 	gr->SaveState(opt);
1159 	static int cgid=1;	gr->StartGroup("Bars3",cgid++);
1160 	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
1161 	m = z->GetNy() > m ? z->GetNy() : m;
1162 	const bool sh = mglchr(pen,'!');
1163 
1164 	bool wire = mglchr(pen,'#'), fixed = mglchr(pen,'F');
1165 	bool above = mglchr(pen,'a'), fall = mglchr(pen,'f');
1166 	if(above)	fall = false;
1167 	double *dd=new double[n], *zp=0, dv=nx>n?1:0;
1168 	if(mglchr(pen,'<'))	dv = 1;
1169 	if(mglchr(pen,'^'))	dv = 0;
1170 	if(mglchr(pen,'>'))	dv = -1;
1171 	memset(dd,0,n*sizeof(double));
1172 	if(fall)	zp = new double[n];
1173 
1174 	double dc=INFINITY;
1175 	if(fixed)	for(long j=0;j<m;j++)
1176 	{
1177 		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
1178 		for(long i=0;i<n-1;i++)
1179 		{
1180 			double cx = hypot(x->v(i+1,mx)-x->v(i,mx), y->v(i+1,my)-y->v(i,my));
1181 			if(cx<dc)	dc=cx;
1182 		}
1183 	}
1184 	if(dc==0)	fixed=false;	// NOTE: disable fixed width if it is zero
1185 
1186 	gr->SetPenPal(pen,&pal);	gr->SetMask(pen);	gr->Reserve(4*n*m);
1187 	for(long j=0;j<m;j++)
1188 	{
1189 		if(gr->NeedStop())	break;
1190 		double c1=gr->NextColor(pal), c2=c1;
1191 		if(gr->GetNumPal(pal)==2*m && !sh)	c2 = gr->NextColor(pal);
1192 		const long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0, mz = j<z->GetNy() ? j:0;
1193 		const double z0 = gr->GetOrgZ('x');
1194 		if(fall)
1195 		{	zp[0]=z0;	for(long i=0;i<n-1;i++)	zp[i+1] = zp[i]+z->v(i,mz);	}
1196 
1197 		const long kq = gr->AllocPnts(4*n);
1198 #pragma omp parallel for
1199 		for(long i=0;i<n;i++)
1200 		{
1201 			double vv = x->v(i,mx), dx = i<nx-1 ? x->v(i+1,mx)-vv : vv-x->v(i-1,mx), dy, zz;
1202 			double x1 = vv + dx/2*(dv-gr->BarWidth), x2 = x1 + gr->BarWidth*dx;
1203 			vv = y->v(i,my);	dy = i<ny-1 ? y->v(i+1,my)-vv : vv-y->v(i-1,my);
1204 			if(fixed)
1205 			{	double ff = dc/hypot(dx,dy);	dx *= ff;	dy *= ff;	}
1206 			double y1 = vv + dy/2*(dv-gr->BarWidth), y2 = y1 + gr->BarWidth*dy;
1207 			vv = zz = z->v(i,mz);
1208 			double zt = z0;
1209 			if(!above)
1210 			{
1211 				x2 = (x2-x1)/m;		x1 += j*x2;		x2 += x1;
1212 				y2 = (y2-y1)/m;		y1 += j*y2;		y2 += y1;
1213 				if(fall)	{	zt = zp[i];	zz += zp[i];	}
1214 			}
1215 			else
1216 			{	zt = gr->GetOrgZ('x') + dd[i];	dd[i] += zz;	zz += zt;	}
1217 
1218 			double c = !sh ? (vv<0 ? c1 : c2) : gr->NextColor(pal,i);
1219 			mglPoint nn(-y->dvx(i,my),x->dvx(i,mx));
1220 			gr->AddPntQ(kq+4*i,mglPoint(x1,y1,zz),c,nn);
1221 			gr->AddPntQ(kq+4*i+1,mglPoint(x1,y1,zt),c,nn);
1222 			gr->AddPntQ(kq+4*i+2,mglPoint(x2,y2,zt),c,nn);
1223 			gr->AddPntQ(kq+4*i+3,mglPoint(x2,y2,zz),c,nn);
1224 		}
1225 		for(long i=0;i<n;i++)
1226 		{
1227 			long iq = kq+4*i;
1228 			if(wire)
1229 			{	gr->line_plot(iq,iq+1);		gr->line_plot(iq,iq+3);
1230 				gr->line_plot(iq+2,iq+1);	gr->line_plot(iq+2,iq+3);	}
1231 			else	gr->quad_plot(iq,iq+1,iq+3,iq+2);
1232 		}
1233 	}
1234 	gr->EndGroup();	delete []dd;	if(fall)	delete []zp;
1235 }
1236 //-----------------------------------------------------------------------------
mgl_bars_xy(HMGL gr,HCDT x,HCDT y,const char * pen,const char * opt)1237 void MGL_EXPORT mgl_bars_xy(HMGL gr, HCDT x, HCDT y, const char *pen, const char *opt)
1238 {
1239 	long m,n=y->GetNx(),nx=x->GetNx(),pal;
1240 	if(mgl_check_dim1(gr,x,y,0,0,"Bars",true))	return;
1241 
1242 	gr->SaveState(opt);
1243 	static int cgid=1;	gr->StartGroup("Bars",cgid++);
1244 	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
1245 	bool sh = mglchr(pen,'!');
1246 
1247 	bool wire = mglchr(pen,'#'), fixed = mglchr(pen,'F');
1248 	bool above = mglchr(pen,'a'), fall = mglchr(pen,'f');
1249 	if(above)	fall = false;
1250 	double *dd=new double[n], dv=nx>n?1:0, *yp=0;
1251 	memset(dd,0,n*sizeof(double));
1252 	if(mglchr(pen,'<'))	dv = 1;
1253 	if(mglchr(pen,'^'))	dv = 0;
1254 	if(mglchr(pen,'>'))	dv = -1;
1255 	const double zm = gr->AdjustZMin();
1256 	if(fall)	yp = new double[n];
1257 
1258 	double dx=INFINITY;
1259 	if(fixed)
1260 	{
1261 		long nn=x->GetNy();
1262 		for(long j=0;j<nn;j++)	for(long i=0;i<n-1;i++)
1263 		{
1264 			double cx = fabs(x->v(i+1,j)-x->v(i,j));
1265 			if(cx<dx)	dx=cx;
1266 		}
1267 	}
1268 	if(dx==0)	fixed=false;	// NOTE: disable fixed width if it is zero
1269 
1270 	gr->SetPenPal(pen,&pal);	gr->SetMask(pen);	gr->Reserve(4*n*m);
1271 	for(long j=0;j<m;j++)
1272 	{
1273 		if(gr->NeedStop())	break;
1274 		double c1=gr->NextColor(pal), c2=c1;
1275 		if(gr->GetNumPal(pal)==2*m && !sh)	c2 = gr->NextColor(pal);
1276 		const long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
1277 		const double y0 = gr->GetOrgY('x');
1278 		if(fall)
1279 		{	yp[0]=y0;	for(long i=0;i<n-1;i++)	yp[i+1] = yp[i]+y->v(i,my);	}
1280 
1281 		const long kq = gr->AllocPnts(4*n);
1282 #pragma omp parallel for
1283 		for(long i=0;i<n;i++)
1284 		{
1285 			double vv = x->v(i,mx), d = i<nx-1 ? x->v(i+1,mx)-vv : vv-x->v(i-1,mx), yy;
1286 			if(fixed)	d = dx;
1287 			double x1 = vv + d/2*(dv-gr->BarWidth), x2 = x1 + gr->BarWidth*d;
1288 			vv = yy = y->v(i,my);
1289 			double yt = y0;
1290 			if(!above)
1291 			{
1292 				x2 = (x2-x1)/m;		x1 += j*x2;		x2 += x1;
1293 				if(fall)	{	yt = yp[i];	yy += yp[i];	}
1294 			}
1295 			else
1296 			{	yt = y0 + dd[i];	dd[i] += yy;	yy += yt;	}
1297 
1298 			double c = !sh ? (vv<0 ? c1 : c2) : gr->NextColor(pal,i);
1299 			gr->AddPntQ(kq+4*i,mglPoint(x1,yy,zm),c);
1300 			gr->AddPntQ(kq+4*i+1,mglPoint(x1,yt,zm),c);
1301 			gr->AddPntQ(kq+4*i+2,mglPoint(x2,yt,zm),c);
1302 			gr->AddPntQ(kq+4*i+3,mglPoint(x2,yy,zm),c);
1303 		}
1304 		for(long i=0;i<n;i++)
1305 		{
1306 			long iq = kq+4*i;
1307 			if(wire)
1308 			{	gr->line_plot(iq,iq+1);		gr->line_plot(iq,iq+3);
1309 				gr->line_plot(iq+2,iq+1);	gr->line_plot(iq+2,iq+3);	}
1310 			else	gr->quad_plot(iq,iq+1,iq+3,iq+2);
1311 		}
1312 	}
1313 	gr->EndGroup();	delete []dd;	if(fall)	delete []yp;
1314 }
1315 //-----------------------------------------------------------------------------
mgl_bars(HMGL gr,HCDT y,const char * pen,const char * opt)1316 void MGL_EXPORT mgl_bars(HMGL gr, HCDT y, const char *pen, const char *opt)
1317 {
1318 	gr->SaveState(opt);
1319 	mglDataV x(y->GetNx()+1);	x.Fill(gr->Min.x,gr->Max.x);
1320 	mgl_bars_xy(gr,&x,y,pen,0);
1321 }
1322 //-----------------------------------------------------------------------------
mgl_bars_xyz_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * pen,const char * opt,int l,int lo)1323 void MGL_EXPORT mgl_bars_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int l,int lo)
1324 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1325 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1326 	mgl_bars_xyz(_GR_,_DA_(x),_DA_(y),_DA_(z),s,o);	delete []o;	delete []s;	}
1327 //-----------------------------------------------------------------------------
mgl_bars_xy_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,const char * pen,const char * opt,int l,int lo)1328 void MGL_EXPORT mgl_bars_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
1329 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1330 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1331 	mgl_bars_xy(_GR_,_DA_(x),_DA_(y),s,o);	delete []o;	delete []s;	}
1332 //-----------------------------------------------------------------------------
mgl_bars_(uintptr_t * gr,uintptr_t * y,const char * pen,const char * opt,int l,int lo)1333 void MGL_EXPORT mgl_bars_(uintptr_t *gr, uintptr_t *y,	const char *pen, const char *opt,int l,int lo)
1334 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1335 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1336 	mgl_bars(_GR_,_DA_(y),s,o);	delete []o;	delete []s;	}
1337 //-----------------------------------------------------------------------------
1338 //
1339 //		Barh series
1340 //
1341 //-----------------------------------------------------------------------------
mgl_barh_yx(HMGL gr,HCDT y,HCDT v,const char * pen,const char * opt)1342 void MGL_EXPORT mgl_barh_yx(HMGL gr, HCDT y, HCDT v, const char *pen, const char *opt)
1343 {
1344 	long m,n=v->GetNx(),ny=y->GetNx(),pal;
1345 	if(mgl_check_dim1(gr,y,v,0,0,"Barh",true))	return;
1346 
1347 	gr->SaveState(opt);
1348 	static int cgid=1;	gr->StartGroup("Barh",cgid++);
1349 	m = y->GetNy() > v->GetNy() ? y->GetNy() : v->GetNy();
1350 	bool sh = mglchr(pen,'!');
1351 
1352 	bool wire = mglchr(pen,'#'), fixed = mglchr(pen,'F');
1353 	bool above = mglchr(pen,'a'), fall = mglchr(pen,'f');
1354 	if(above)	fall = false;
1355 	double *dd=new double[n], *xp=0,dv=ny>n?1:0;
1356 	if(mglchr(pen,'<'))	dv = 1;
1357 	if(mglchr(pen,'^'))	dv = 0;
1358 	if(mglchr(pen,'>'))	dv = -1;
1359 	const double zm = gr->AdjustZMin();
1360 	memset(dd,0,n*sizeof(double));
1361 	if(fall)	xp = new double[n];
1362 
1363 	double dy=INFINITY;
1364 	if(fixed)
1365 	{
1366 		long nn=y->GetNy();
1367 		for(long j=0;j<nn;j++)	for(long i=0;i<n-1;i++)
1368 		{
1369 			double cx = fabs(y->v(i+1,j)-y->v(i,j));
1370 			if(cx<dy)	dy=cx;
1371 		}
1372 	}
1373 	if(dy==0)	fixed=false;	// NOTE: disable fixed width if it is zero
1374 
1375 	gr->SetPenPal(pen,&pal);	gr->SetMask(pen);	gr->Reserve(4*n*m);
1376 	for(long j=0;j<m;j++)
1377 	{
1378 		if(gr->NeedStop())	break;
1379 		double c1=gr->NextColor(pal), c2=c1;
1380 		if(gr->GetNumPal(pal)==2*m && !sh)	c2 = gr->NextColor(pal);
1381 		const long mx = j<v->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
1382 		const double x0 = gr->GetOrgX('y');
1383 		if(fall)
1384 		{	xp[0]=x0;	for(long i=0;i<n-1;i++)	xp[i+1] = xp[i]+v->v(i,mx);	}
1385 
1386 		const long kq = gr->AllocPnts(4*n);
1387 #pragma omp parallel for
1388 		for(long i=0;i<n;i++)
1389 		{
1390 			double vv = y->v(i,my), d = i<ny-1 ? y->v(i+1,my)-vv : vv-y->v(i-1,my), xx;
1391 			if(fixed)	d = dy;
1392 			double y1 = vv + d/2*(dv-gr->BarWidth), y2 = y1 + gr->BarWidth*d;
1393 			vv = xx = v->v(i,mx);
1394 			double xt = x0;
1395 			if(!above)
1396 			{
1397 				y2 = (y2-y1)/m;		y1 += j*y2;		y2 += y1;
1398 				if(fall)	{	xt = xp[i];	xx += xp[i];	}
1399 			}
1400 			else
1401 			{	xt = x0 + dd[i];	dd[i] += xx;	xx += xt;	}
1402 
1403 			double c = !sh ? (vv<0 ? c1 : c2) : gr->NextColor(pal,i);
1404 			gr->AddPntQ(kq+4*i,mglPoint(xx,y1,zm),c);
1405 			gr->AddPntQ(kq+4*i+1,mglPoint(xx,y2,zm),c);
1406 			gr->AddPntQ(kq+4*i+2,mglPoint(xt,y2,zm),c);
1407 			gr->AddPntQ(kq+4*i+3,mglPoint(xt,y1,zm),c);
1408 		}
1409 		for(long i=0;i<n;i++)
1410 		{
1411 			long iq = kq+4*i;
1412 			if(wire)
1413 			{	gr->line_plot(iq,iq+1);		gr->line_plot(iq,iq+3);
1414 				gr->line_plot(iq+2,iq+1);	gr->line_plot(iq+2,iq+3);	}
1415 			else	gr->quad_plot(iq,iq+1,iq+3,iq+2);
1416 		}
1417 	}
1418 	gr->EndGroup();	delete []dd;	if(fall)	delete []xp;
1419 }
1420 //-----------------------------------------------------------------------------
mgl_barh(HMGL gr,HCDT v,const char * pen,const char * opt)1421 void MGL_EXPORT mgl_barh(HMGL gr, HCDT v,	const char *pen, const char *opt)
1422 {
1423 	gr->SaveState(opt);
1424 	mglDataV y(v->GetNx()+1);	y.Fill(gr->Min.y,gr->Max.y);
1425 	mgl_barh_yx(gr,&y,v,pen,0);
1426 }
1427 //-----------------------------------------------------------------------------
mgl_barh_yx_(uintptr_t * gr,uintptr_t * y,uintptr_t * v,const char * pen,const char * opt,int l,int lo)1428 void MGL_EXPORT mgl_barh_yx_(uintptr_t *gr, uintptr_t *y, uintptr_t *v, const char *pen, const char *opt,int l,int lo)
1429 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1430 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1431 	mgl_barh_yx(_GR_,_DA_(y),_DA_(v),s,o);	delete []o;	delete []s;	}
1432 //-----------------------------------------------------------------------------
mgl_barh_(uintptr_t * gr,uintptr_t * v,const char * pen,const char * opt,int l,int lo)1433 void MGL_EXPORT mgl_barh_(uintptr_t *gr, uintptr_t *v,	const char *pen, const char *opt,int l,int lo)
1434 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1435 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1436 	mgl_barh(_GR_,_DA_(v),s,o);	delete []o;	delete []s;	}
1437 //-----------------------------------------------------------------------------
1438 //
1439 //	OHLC series
1440 //
1441 //-----------------------------------------------------------------------------
mgl_ohlc_x(HMGL gr,HCDT x,HCDT open,HCDT high,HCDT low,HCDT close,const char * pen,const char * opt)1442 void MGL_EXPORT mgl_ohlc_x(HMGL gr, HCDT x, HCDT open, HCDT high, HCDT low, HCDT close, const char *pen, const char *opt)
1443 {
1444 	long n=open->GetNx(), nx=x->GetNx(), m=open->GetNy(), mx;
1445 	if(nx<n || n*m!=high->GetNx()*high->GetNy() || n*m!=low->GetNx()*low->GetNy() || n*m!=close->GetNx()*close->GetNy())
1446 	{	gr->SetWarn(mglWarnDim,"OHLC");	return;	}
1447 	gr->SaveState(opt);
1448 	static int cgid=1;	gr->StartGroup("OHLC",cgid++);
1449 	double dv=nx>n?1:0;
1450 	if(mglchr(pen,'<'))	dv = 1;
1451 	if(mglchr(pen,'^'))	dv = 0;
1452 	if(mglchr(pen,'>'))	dv = -1;
1453 	double zVal = gr->AdjustZMin();
1454 	bool sh = mglchr(pen,'!');
1455 
1456 	long pal;
1457 	gr->SetPenPal(pen,&pal);	gr->Reserve(6*n*m);
1458 	for(long j=0;j<m;j++)
1459 	{
1460 		if(gr->NeedStop())	break;
1461 		double c1=gr->NextColor(pal), c2=c1;
1462 		if(gr->GetNumPal(pal)==2*m && !sh)	c2 = gr->NextColor(pal);
1463 		mx = j<x->GetNy() ? j:0;
1464 
1465 		const long kq = gr->AllocPnts(6*n);
1466 #pragma omp parallel for
1467 		for(long i=0;i<n;i++)
1468 		{
1469 			double dd,vv,x1,x2;
1470 			vv = x->v(i,mx);	dd = i<nx-1 ? x->v(i+1)-vv : vv-x->v(i-1);
1471 			x1 = vv + dd/2*(dv-gr->BarWidth);	x2 = x1 + gr->BarWidth*dd;
1472 			x2 = (x2-x1)/m;		x1 += j*x2;		x2 += x1;	vv = (x2+x1)/2;
1473 
1474 			dd = close->v(i,j);
1475 			double c = !sh? ((i==0 || dd>=close->v(i-1,j)) ? c1:c2) : gr->NextColor(pal,i);
1476 			gr->AddPntQ(kq+6*i,mglPoint(vv,dd,zVal),c);
1477 			gr->AddPntQ(kq+6*i+1,mglPoint(x2,dd,zVal),c);
1478 			dd = open->v(i,j);
1479 			gr->AddPntQ(kq+6*i+2,mglPoint(x1,dd,zVal),c);
1480 			gr->AddPntQ(kq+6*i+3,mglPoint(vv,dd,zVal),c);
1481 			gr->AddPntQ(kq+6*i+4,mglPoint(vv,low->v(i,j),zVal),c);
1482 			gr->AddPntQ(kq+6*i+5,mglPoint(vv,high->v(i,j),zVal),c);
1483 		}
1484 		for(long i=0;i<n;i++)
1485 		{
1486 			long iq = kq+6*i;
1487 			gr->line_plot(iq,iq+1);
1488 			gr->line_plot(iq+2,iq+3);
1489 			gr->line_plot(iq+4,iq+5);
1490 		}
1491 	}
1492 	gr->EndGroup();
1493 }
1494 //-----------------------------------------------------------------------------
mgl_ohlc(HMGL gr,HCDT open,HCDT high,HCDT low,HCDT close,const char * pen,const char * opt)1495 void MGL_EXPORT mgl_ohlc(HMGL gr, HCDT open, HCDT high, HCDT low, HCDT close, const char *pen, const char *opt)
1496 {
1497 	gr->SaveState(opt);
1498 	mglDataV x(open->GetNx()+1);	x.Fill(gr->Min.x,gr->Max.x);
1499 	mgl_ohlc_x(gr,&x,open,high,low,close,pen,0);
1500 }
1501 //-----------------------------------------------------------------------------
mgl_ohlc_x_(uintptr_t * gr,uintptr_t * x,uintptr_t * open,uintptr_t * high,uintptr_t * low,uintptr_t * close,const char * pen,const char * opt,int l,int lo)1502 void MGL_EXPORT mgl_ohlc_x_(uintptr_t *gr, uintptr_t *x, uintptr_t *open, uintptr_t *high, uintptr_t *low, uintptr_t *close, const char *pen, const char *opt,int l,int lo)
1503 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1504 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1505 	mgl_ohlc_x(_GR_,_DA_(x),_DA_(open),_DA_(high),_DA_(low),_DA_(close),s,o);	delete []o;	delete []s;	}
1506 //-----------------------------------------------------------------------------
mgl_ohlc_(uintptr_t * gr,uintptr_t * open,uintptr_t * high,uintptr_t * low,uintptr_t * close,const char * pen,const char * opt,int l,int lo)1507 void MGL_EXPORT mgl_ohlc_(uintptr_t *gr, uintptr_t *open, uintptr_t *high, uintptr_t *low, uintptr_t *close, const char *pen, const char *opt,int l,int lo)
1508 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1509 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1510 	mgl_ohlc(_GR_,_DA_(open),_DA_(high),_DA_(low),_DA_(close),s,o);	delete []o;	delete []s;	}
1511 //-----------------------------------------------------------------------------
1512 //
1513 //	BoxPlot series
1514 //
1515 //-----------------------------------------------------------------------------
1516 double sgn(double a);
mgl_cmp_flt(const void * a,const void * b)1517 int static mgl_cmp_flt(const void *a, const void *b)
1518 {
1519 	const double *aa = (const double *)a;
1520 	const double *bb = (const double *)b;
1521 	return int(sgn(*aa-*bb));
1522 }
1523 //-----------------------------------------------------------------------------
mgl_boxplot_xy(HMGL gr,HCDT x,HCDT y,const char * pen,const char * opt)1524 void MGL_EXPORT mgl_boxplot_xy(HMGL gr, HCDT x, HCDT y, const char *pen, const char *opt)
1525 {
1526 	long n=y->GetNx(), m=y->GetNy(), nx=x->GetNx();
1527 	if(nx<n || nx<2 || m<2)	{	gr->SetWarn(mglWarnDim,"BoxPlot");	return;	}
1528 	gr->SaveState(opt);
1529 	static int cgid=1;	gr->StartGroup("BoxPlot",cgid++);
1530 	double *b = new double[5*n], dv=nx>n?1:0;
1531 	if(mglchr(pen,'<'))	dv = 1;
1532 	if(mglchr(pen,'^'))	dv = 0;
1533 	if(mglchr(pen,'>'))	dv = -1;
1534 	double zVal = gr->AdjustZMin();
1535 	bool sh = mglchr(pen,'!');
1536 	double *d = new double[m];
1537 	for(long i=0;i<n;i++)	// find quartiles by itself
1538 	{
1539 		long mm=0,k;
1540 		for(long j=0;j<m;j++)
1541 		{
1542 			double vv = y->v(i,j);
1543 			if(mgl_isnum(vv))	{	d[mm]=vv;	mm++;	}
1544 		}
1545 		qsort(d, mm, sizeof(double), mgl_cmp_flt);
1546 		b[i] = d[0];	b[i+4*n] = d[mm-1];		k = mm/4;
1547 		b[i+n] = (mm%4) ? d[k] : (d[k]+d[k-1])/2.;
1548 		b[i+2*n] = (mm%2) ? d[mm/2] : (d[mm/2]+d[mm/2-1])/2.;
1549 		b[i+3*n] = (mm%4) ? d[mm-k-1] : (d[mm-k-1]+d[mm-k])/2.;
1550 	}
1551 	delete []d;
1552 
1553 	long pal;
1554 	gr->SetPenPal(pen,&pal);	gr->NextColor(pal);
1555 
1556 	const long kq = gr->AllocPnts(18*n);
1557 #pragma omp parallel for
1558 	for(long i=0;i<n;i++)
1559 	{
1560 		const double vv = x->v(i);
1561 		const double dd = i<nx-1 ? x->v(i+1)-vv : vv-x->v(i-1);
1562 		const double x1 = vv + dd/2*(dv-gr->BarWidth);
1563 		const double x2 = x1 + gr->BarWidth*dd;
1564 		const double c = sh ? gr->NextColor(pal,i):gr->CDef;
1565 		const long iq = kq+18*i;
1566 
1567 		gr->AddPntQ(iq,mglPoint(x1,b[i],zVal),c);	// horizontal lines
1568 		gr->AddPntQ(iq+1,mglPoint(x2,b[i],zVal),c);
1569 		gr->AddPntQ(iq+2,mglPoint(x1,b[i+n],zVal),c);
1570 		gr->AddPntQ(iq+3,mglPoint(x2,b[i+n],zVal),c);
1571 		gr->AddPntQ(iq+4,mglPoint(x1,b[i+2*n],zVal),c);
1572 		gr->AddPntQ(iq+5,mglPoint(x2,b[i+2*n],zVal),c);
1573 		gr->AddPntQ(iq+6,mglPoint(x1,b[i+3*n],zVal),c);
1574 		gr->AddPntQ(iq+7,mglPoint(x2,b[i+3*n],zVal),c);
1575 		gr->AddPntQ(iq+8,mglPoint(x1,b[i+4*n],zVal),c);
1576 		gr->AddPntQ(iq+9,mglPoint(x2,b[i+4*n],zVal),c);
1577 
1578 		gr->AddPntQ(iq+10,mglPoint(x1,b[i+n],zVal),c);	//vertical lines
1579 		gr->AddPntQ(iq+11,mglPoint(x1,b[i+3*n],zVal),c);
1580 		gr->AddPntQ(iq+12,mglPoint(x2,b[i+n],zVal),c);
1581 		gr->AddPntQ(iq+13,mglPoint(x2,b[i+3*n],zVal),c);
1582 		gr->AddPntQ(iq+14,mglPoint((x1+x2)/2,b[i],zVal),c);
1583 		gr->AddPntQ(iq+15,mglPoint((x1+x2)/2,b[i+n],zVal),c);
1584 		gr->AddPntQ(iq+16,mglPoint((x1+x2)/2,b[i+3*n],zVal),c);
1585 		gr->AddPntQ(iq+17,mglPoint((x1+x2)/2,b[i+4*n],zVal),c);
1586 	}
1587 	for(long i=0;i<n;i++)	for(long j=0;j<9;j++)
1588 		gr->line_plot(kq+18*i+2*j, kq+18*i+2*j+1);
1589 	delete []b;	gr->EndGroup();
1590 }
1591 //-----------------------------------------------------------------------------
mgl_boxplot(HMGL gr,HCDT y,const char * pen,const char * opt)1592 void MGL_EXPORT mgl_boxplot(HMGL gr, HCDT y, const char *pen, const char *opt)
1593 {
1594 	gr->SaveState(opt);
1595 	mglDataV x(y->GetNx()+1);	x.Fill(gr->Min.x,gr->Max.x);
1596 	mgl_boxplot_xy(gr,&x,y,pen,0);
1597 }
1598 //-----------------------------------------------------------------------------
mgl_boxplot_xy_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,const char * pen,const char * opt,int l,int lo)1599 void MGL_EXPORT mgl_boxplot_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
1600 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1601 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1602 	mgl_boxplot_xy(_GR_,_DA_(x),_DA_(y),s,o);	delete []o;	delete []s;	}
1603 //-----------------------------------------------------------------------------
mgl_boxplot_(uintptr_t * gr,uintptr_t * y,const char * pen,const char * opt,int l,int lo)1604 void MGL_EXPORT mgl_boxplot_(uintptr_t *gr, uintptr_t *y,	const char *pen, const char *opt,int l,int lo)
1605 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1606 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1607 	mgl_boxplot(_GR_,_DA_(y),s,o);	delete []o;	delete []s;	}
1608 //-----------------------------------------------------------------------------
1609 //
1610 //		Error series
1611 //
1612 //-----------------------------------------------------------------------------
mgl_error_exy(HMGL gr,HCDT x,HCDT y,HCDT ex,HCDT ey,const char * pen,const char * opt)1613 void MGL_EXPORT mgl_error_exy(HMGL gr, HCDT x, HCDT y, HCDT ex, HCDT ey, const char *pen, const char *opt)
1614 {
1615 	long m,n=ey->GetNx(),pal;
1616 	if(mgl_check_dim0(gr,x,y,ey,ex,"Error"))	return;
1617 
1618 	gr->SaveState(opt);
1619 	static int cgid=1;	gr->StartGroup("Error",cgid++);
1620 	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
1621 	m = ex->GetNy() > m ? ex->GetNy() : m;
1622 	m = ey->GetNy() > m ? ey->GetNy() : m;
1623 	bool sh = mglchr(pen,'!');
1624 
1625 	bool ma = mglchr(pen,'@');
1626 	char mk = gr->SetPenPal(pen,&pal);
1627 	double zVal=gr->AdjustZMin();
1628 	gr->Reserve(5*n*m);
1629 	if(ma && (mk==0 || !strchr("PXsSdD+xoOC",mk) ))	mk = 'S';
1630 	gr->ResetMask();
1631 	mglPoint q(NAN,NAN);
1632 	for(long j=0;j<m;j++)
1633 	{
1634 		if(gr->NeedStop())	break;
1635 		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
1636 		long m1 = j<ex->GetNy() ? j:0,m2 = j<ey->GetNy() ? j:0;
1637 		gr->NextColor(pal);
1638 		if(ma)
1639 		{
1640 			if(strchr("PXsS",mk))	// boundary of square
1641 			{
1642 				const long kq = gr->AllocPnts(4*n);
1643 #pragma omp parallel for
1644 				for(long i=0;i<n;i++)
1645 				{
1646 					double vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
1647 					double c = sh ? gr->NextColor(pal,i):gr->CDef;
1648 					gr->AddPntQ(kq+4*i,mglPoint(vx-ve, vy+vf, zVal),c,q,-1,27);
1649 					gr->AddPntQ(kq+4*i+1,mglPoint(vx-ve, vy-vf, zVal),c,q,-1,27);
1650 					gr->AddPntQ(kq+4*i+2,mglPoint(vx+ve, vy+vf, zVal),c,q,-1,27);
1651 					gr->AddPntQ(kq+4*i+3,mglPoint(vx+ve, vy-vf, zVal),c,q,-1,27);
1652 				}
1653 				for(long i=0;i<n;i++)
1654 				{
1655 					long iq = kq+4*i;
1656 					gr->line_plot(iq,iq+1);		gr->line_plot(iq,iq+2);
1657 					gr->line_plot(iq+3,iq+1);	gr->line_plot(iq+3,iq+2);
1658 				}
1659 			}
1660 			if(strchr("dD",mk))
1661 			{
1662 				const long kq = gr->AllocPnts(4*n);
1663 #pragma omp parallel for
1664 				for(long i=0;i<n;i++)	// boundary of rhomb
1665 				{
1666 					double vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
1667 					double c = sh ? gr->NextColor(pal,i):gr->CDef;
1668 					gr->AddPntQ(kq+4*i,mglPoint(vx, vy+vf, zVal),c,q,-1,27);
1669 					gr->AddPntQ(kq+4*i+1,mglPoint(vx-ve, vy, zVal),c,q,-1,27);
1670 					gr->AddPntQ(kq+4*i+2,mglPoint(vx, vy-vf, zVal),c,q,-1,27);
1671 					gr->AddPntQ(kq+4*i+3,mglPoint(vx+ve, vy, zVal),c,q,-1,27);
1672 				}
1673 				for(long i=0;i<n;i++)
1674 				{
1675 					long iq = kq+4*i;
1676 					gr->line_plot(iq,iq+1);		gr->line_plot(iq+1,iq+2);
1677 					gr->line_plot(iq+2,iq+3);	gr->line_plot(iq+3,iq);
1678 				}
1679 			}
1680 			if(strchr("oOC",mk))
1681 			{
1682 				const long kq = gr->AllocPnts(40*n);
1683 #pragma omp parallel for
1684 				for(long i=0;i<n;i++)	// circle
1685 				{
1686 					double vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
1687 					double c = sh ? gr->NextColor(pal,i):gr->CDef;
1688 					for(long k=0;k<40;k++)
1689 						gr->AddPntQ(kq+40*i+k,mglPoint(vx+ve*mgl_cos[(18*k)%360],
1690 								vy+vf*mgl_cos[(270+18*k)%360], zVal),c,q,-1,27);
1691 				}
1692 				for(long i=0;i<n;i++)	// circle
1693 				{
1694 					long iq = kq+40*i;	gr->line_plot(iq+39,iq);
1695 					for(long k=1;k<40;k++)	gr->line_plot(iq+k-1,iq+k);
1696 				}
1697 			}
1698 			long kq;
1699 			switch(mk)
1700 			{
1701 			case 'P':	case '+':
1702 				kq = gr->AllocPnts(4*n);
1703 #pragma omp parallel for
1704 				for(long i=0;i<n;i++)
1705 				{
1706 					double vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
1707 					double c = sh ? gr->NextColor(pal,i):gr->CDef;
1708 					gr->AddPntQ(kq+4*i,mglPoint(vx, vy+vf, zVal),c,q,-1,27);
1709 					gr->AddPntQ(kq+4*i+1,mglPoint(vx-ve, vy, zVal),c,q,-1,27);
1710 					gr->AddPntQ(kq+4*i+2,mglPoint(vx, vy-vf, zVal),c,q,-1,27);
1711 					gr->AddPntQ(kq+4*i+3,mglPoint(vx+ve, vy, zVal),c,q,-1,27);
1712 				}
1713 				for(long i=0;i<n;i++)
1714 				{	long iq = kq+4*i;
1715 					gr->line_plot(iq,iq+2);	gr->line_plot(iq+1,iq+3);
1716 				}	break;
1717 			case 'X':	case 'x':
1718 				kq = gr->AllocPnts(4*n);
1719 #pragma omp parallel for
1720 				for(long i=0;i<n;i++)
1721 				{
1722 					double vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
1723 					double c = sh ? gr->NextColor(pal,i):gr->CDef;
1724 					gr->AddPntQ(kq+4*i,mglPoint(vx-ve, vy+vf, zVal),c,q,-1,27);
1725 					gr->AddPntQ(kq+4*i+1,mglPoint(vx-ve, vy-vf, zVal),c,q,-1,27);
1726 					gr->AddPntQ(kq+4*i+2,mglPoint(vx+ve, vy+vf, zVal),c,q,-1,27);
1727 					gr->AddPntQ(kq+4*i+3,mglPoint(vx+ve, vy-vf, zVal),c,q,-1,27);
1728 				}
1729 				for(long i=0;i<n;i++)
1730 				{	long iq = kq+4*i;
1731 					gr->line_plot(iq,iq+3);	gr->line_plot(iq+1,iq+2);
1732 				}	break;
1733 			case 'S':
1734 				kq = gr->AllocPnts(4*n);
1735 #pragma omp parallel for
1736 				for(long i=0;i<n;i++)
1737 				{
1738 					double vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
1739 					double c = sh ? gr->NextColor(pal,i):gr->CDef;
1740 					gr->AddPntQ(kq+4*i,mglPoint(vx-ve, vy+vf, zVal),c,q,-1,27);
1741 					gr->AddPntQ(kq+4*i+1,mglPoint(vx-ve, vy-vf, zVal),c,q,-1,27);
1742 					gr->AddPntQ(kq+4*i+2,mglPoint(vx+ve, vy+vf, zVal),c,q,-1,27);
1743 					gr->AddPntQ(kq+4*i+3,mglPoint(vx+ve, vy-vf, zVal),c,q,-1,27);
1744 				}
1745 				for(long i=0;i<n;i++)
1746 				{	long iq = kq+4*i;	gr->quad_plot(iq,iq+1,iq+2,iq+3);	}
1747 				break;
1748 			case 'D':
1749 				kq = gr->AllocPnts(4*n);
1750 #pragma omp parallel for
1751 				for(long i=0;i<n;i++)
1752 				{
1753 					double vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
1754 					double c = sh ? gr->NextColor(pal,i):gr->CDef;
1755 					gr->AddPntQ(kq+4*i,mglPoint(vx, vy+vf, zVal),c,q,-1,27);
1756 					gr->AddPntQ(kq+4*i+1,mglPoint(vx-ve, vy, zVal),c,q,-1,27);
1757 					gr->AddPntQ(kq+4*i+2,mglPoint(vx, vy-vf, zVal),c,q,-1,27);
1758 					gr->AddPntQ(kq+4*i+3,mglPoint(vx+ve, vy, zVal),c,q,-1,27);
1759 				}
1760 				for(long i=0;i<n;i++)
1761 				{	long iq = kq+4*i;	gr->quad_plot(iq,iq+3,iq+1,iq+2);	}
1762 				break;
1763 			case 'O':
1764 				kq = gr->AllocPnts(41*n);
1765 #pragma omp parallel for
1766 				for(long i=0;i<n;i++)	// circle
1767 				{
1768 					double vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
1769 					double c = sh ? gr->NextColor(pal,i):gr->CDef;
1770 					long iq = kq+41*i+1;
1771 					gr->AddPntQ(iq-1,mglPoint(vx,vy,zVal),c);
1772 					for(long k=0;k<40;k++)
1773 						gr->AddPntQ(iq+k,mglPoint(vx+ve*mgl_cos[(18*k)%360],
1774 								vy+vf*mgl_cos[(270+18*k)%360], zVal),c,q,-1,27);
1775 				}
1776 				for(long i=0;i<n;i++)	// circle
1777 				{
1778 					long iq = kq+41*i+1;	gr->trig_plot(iq-1,iq+39,iq);
1779 					for(long k=1;k<40;k++)	gr->trig_plot(iq-1,iq+k-1,iq+k);
1780 				}	break;
1781 			case 'C':
1782 				for(long i=0;i<n;i++)
1783 				{
1784 					gr->mark_plot(gr->AddPnt(mglPoint(x->v(i,mx),y->v(i,my),zVal),-1,q,-1,3), '.');
1785 					if(sh)	gr->NextColor(pal);
1786 				}
1787 			}
1788 		}
1789 		else
1790 		{
1791 			const long nq = mk?5:4, kq = gr->AllocPnts(nq*n);
1792 #pragma omp parallel for
1793 			for(long i=0;i<n;i++)
1794 			{
1795 				double vx=x->v(i,mx), ve=ex->v(i,m1), vy=y->v(i,my), vf=ey->v(i,m2);
1796 				double c = sh ? gr->NextColor(pal,i):gr->CDef;
1797 				long iq = kq + nq*i;
1798 				gr->AddPntQ(iq,mglPoint(vx, vy+vf, zVal),c,q,-1,27);
1799 				gr->AddPntQ(iq+1,mglPoint(vx, vy-vf, zVal),c,q,-1,27);
1800 				gr->AddPntQ(iq+2,mglPoint(vx+ve, vy, zVal),-1,q,c,27);
1801 				gr->AddPntQ(iq+3,mglPoint(vx-ve, vy, zVal),-1,q,c,27);
1802 				if(mk)	gr->AddPntQ(iq+4,mglPoint(vx,vy,zVal),c);
1803 			}
1804 			for(long i=0;i<n;i++)
1805 			{
1806 				long iq = kq + nq*i;
1807 				if(mk)	gr->mark_plot(iq+4, mk);
1808 				gr->line_plot(iq,iq+1);			gr->line_plot(iq+2,iq+3);
1809 				gr->arrow_plot(iq,iq+1,'I');	gr->arrow_plot(iq+1,iq,'I');
1810 				gr->arrow_plot(iq+2,iq+3,'I');	gr->arrow_plot(iq+3,iq+2,'I');
1811 			}
1812 		}
1813 	}
1814 	gr->EndGroup();
1815 }
1816 //-----------------------------------------------------------------------------
mgl_error_xy(HMGL gr,HCDT x,HCDT y,HCDT ey,const char * pen,const char * opt)1817 void MGL_EXPORT mgl_error_xy(HMGL gr, HCDT x, HCDT y, HCDT ey, const char *pen, const char *opt)
1818 {
1819 	gr->SaveState(opt);
1820 	mglDataV ex(y->GetNx());	ex.Fill(NAN);
1821 	mgl_error_exy(gr,x,y,&ex,ey,pen,0);
1822 }
1823 //-----------------------------------------------------------------------------
mgl_error(HMGL gr,HCDT y,HCDT ey,const char * pen,const char * opt)1824 void MGL_EXPORT mgl_error(HMGL gr, HCDT y, HCDT ey, const char *pen, const char *opt)
1825 {
1826 	gr->SaveState(opt);
1827 	mglDataV x(y->GetNx()), ex(y->GetNx());
1828 	x.Fill(gr->Min.x,gr->Max.x);	ex.Fill(NAN);
1829 	mgl_error_exy(gr,&x,y,&ex,ey,pen,0);
1830 }
1831 //-----------------------------------------------------------------------------
mgl_error_(uintptr_t * gr,uintptr_t * y,uintptr_t * ey,const char * pen,const char * opt,int l,int lo)1832 void MGL_EXPORT mgl_error_(uintptr_t *gr, uintptr_t *y, uintptr_t *ey, const char *pen, const char *opt,int l,int lo)
1833 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1834 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1835 	mgl_error(_GR_,_DA_(y),_DA_(ey),s,o);	delete []o;	delete []s;	}
1836 //-----------------------------------------------------------------------------
mgl_error_xy_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * ey,const char * pen,const char * opt,int l,int lo)1837 void MGL_EXPORT mgl_error_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ey, const char *pen, const char *opt,int l,int lo)
1838 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1839 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1840 	mgl_error_xy(_GR_,_DA_(x),_DA_(y),_DA_(ey),s,o);	delete []o;	delete []s;	}
1841 //-----------------------------------------------------------------------------
mgl_error_exy_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * ex,uintptr_t * ey,const char * pen,const char * opt,int l,int lo)1842 void MGL_EXPORT mgl_error_exy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *ex, uintptr_t *ey, const char *pen, const char *opt,int l,int lo)
1843 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1844 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1845 	mgl_error_exy(_GR_,_DA_(x),_DA_(y),_DA_(ex),_DA_(ey),s,o);
1846 	delete []o;	delete []s;	}
1847 //-----------------------------------------------------------------------------
1848 //
1849 //		Chart series
1850 //
1851 //-----------------------------------------------------------------------------
face_plot(mglBase * gr,const mglPoint & o,mglPoint d1,mglPoint d2,double c,bool wire)1852 void face_plot(mglBase *gr, const mglPoint &o, mglPoint d1, mglPoint d2, double c, bool wire)
1853 {
1854 	const int num=10;
1855 	mglPoint nn=d1^d2;
1856 	d1 = d1/num;	d2 = d2/num;
1857 	const long n=num+1, kq = gr->AllocPnts(n*n);
1858 #pragma omp parallel for
1859 	for(long j=0;j<n;j++)	for(long i=0;i<n;i++)
1860 		gr->AddPntQ(kq+i+n*j,o+d1*i+d2*j,c,nn);
1861 	for(long j=0;j<num;j++)	for(long i=0;i<num;i++)
1862 	{	long ii = kq+i+n*j;	gr->quad_plot(ii,ii+1,ii+n,ii+n+1);	}
1863 	if(wire)
1864 	{
1865 		gr->SetPenPal("k-");
1866 		const long jq = gr->AllocPnts(4*n);
1867 #pragma omp parallel for
1868 		for(long i=0;i<n;i++)
1869 		{
1870 			gr->CopyNtoC(jq+4*i,kq+i,gr->CDef);
1871 			gr->CopyNtoC(jq+4*i+1,kq+n*i,gr->CDef);
1872 			gr->CopyNtoC(jq+4*i+2,kq+n*n-1-i,gr->CDef);
1873 			gr->CopyNtoC(jq+4*i+3,kq+n*n-1-n*i,gr->CDef);
1874 		}
1875 		for(long i=0;i<num;i++)
1876 		{
1877 			long jj = jq+4*i;
1878 			gr->line_plot(jj+4,jj);
1879 			gr->line_plot(jj+5,jj+1);
1880 			gr->line_plot(jj+6,jj+2);
1881 			gr->line_plot(jj+7,jj+3);
1882 		}
1883 	}
1884 }
1885 //-----------------------------------------------------------------------------
mgl_chart(HMGL gr,HCDT a,const char * cols,const char * opt)1886 void MGL_EXPORT mgl_chart(HMGL gr, HCDT a, const char *cols, const char *opt)
1887 {
1888 	if(a->Minimal()<0)	{	gr->SetWarn(mglWarnNeg,"Chart");	return;	}
1889 	gr->SaveState(opt);
1890 	static int cgid=1;	gr->StartGroup("Chart",cgid++);
1891 	bool wire = mglchr(cols,'#');	// draw edges
1892 	long n=a->GetNx(),i,j=0,len=cols?long(strlen(cols)):0;
1893 	if(cols)	for(i=0;i<len;i++)
1894 		if(strchr(MGL_COLORS,cols[i]) || cols[i]==' ')	j++;
1895 	if(j==0)	{	cols = MGL_DEF_PAL;	len=long(strlen(cols));	}
1896 	double *c = new double[len+1],cc;
1897 	long nc=0;			// number of colors
1898 	for(i=0;i<len;i++)
1899 		if(strchr(MGL_COLORS,cols[i]) || cols[i]==' ')
1900 		{	c[nc]=gr->AddTexture(cols[i]);	nc++;	}
1901 	// NOTE: nc>0 since j>0 or MGL_DEF_PAL is not empty
1902 
1903 	double dy = (gr->Max.y-gr->Min.y)/a->GetNy(), dx, ss, cs, x1, y1, dz=gr->Max.z-gr->Min.z, vv;
1904 	mglPoint d1,d2,o;
1905 	gr->SetMask(cols);
1906 
1907 	for(j=0;j<a->GetNy();j++)
1908 	{
1909 		if(gr->NeedStop())	break;
1910 		y1 = gr->Min.y + dy*j;
1911 		for(i=0,ss=0;i<n;i++)	ss += a->v(i,j);
1912 		if(ss==0)	continue;
1913 		for(cs=0,i=0;i<n;i++)
1914 		{
1915 			vv = a->v(i,j);	dx = vv/ss;	cc = c[i%nc];
1916 			if(dx==0)	continue;
1917 			x1 = gr->Min.x + (gr->Max.x-gr->Min.x)*cs/ss;	dx *= (gr->Max.x-gr->Min.x);
1918 			if(cc>=0)
1919 			{
1920 				face_plot(gr,mglPoint(x1,y1,gr->Min.z),mglPoint(dx,0,0),mglPoint(0,0,dz),cc,wire);
1921 				face_plot(gr,mglPoint(x1,y1,gr->Min.z),mglPoint(dx,0,0),mglPoint(0,dy,0),cc,wire);
1922 				face_plot(gr,mglPoint(x1,y1,gr->Min.z),mglPoint(0,dy,0),mglPoint(0,0,dz),cc,wire);
1923 
1924 				face_plot(gr,mglPoint(x1+dx,y1+dy,gr->Max.z),mglPoint(-dx,0,0),mglPoint(0,0,-dz),cc,wire);
1925 				face_plot(gr,mglPoint(x1+dx,y1+dy,gr->Max.z),mglPoint(-dx,0,0),mglPoint(0,-dy,0),cc,wire);
1926 				face_plot(gr,mglPoint(x1+dx,y1+dy,gr->Max.z),mglPoint(0,-dy,0),mglPoint(0,0,-dz),cc,wire);
1927 			}
1928 			cs += vv;
1929 		}
1930 	}
1931 	gr->EndGroup();	delete []c;
1932 }
1933 //-----------------------------------------------------------------------------
mgl_chart_(uintptr_t * gr,uintptr_t * a,const char * col,const char * opt,int l,int lo)1934 void MGL_EXPORT mgl_chart_(uintptr_t *gr, uintptr_t *a, const char *col, const char *opt,int l,int lo)
1935 {	char *s=new char[l+1];	memcpy(s,col,l);	s[l]=0;
1936 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1937 	mgl_chart(_GR_, _DA_(a), s,o);	delete []o;	delete []s;	}
1938 //-----------------------------------------------------------------------------
1939 //
1940 //	Mark series
1941 //
1942 //-----------------------------------------------------------------------------
mgl_mark_xyz(HMGL gr,HCDT x,HCDT y,HCDT z,HCDT r,const char * pen,const char * opt)1943 void MGL_EXPORT mgl_mark_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT r, const char *pen, const char *opt)
1944 {
1945 	long m,n=y->GetNx(),pal;
1946 	if(mgl_check_dim0(gr,x,y,z,r,"Mark"))	return;
1947 
1948 	gr->SaveState(opt);
1949 	static int cgid=1;	gr->StartGroup("Mark",cgid++);
1950 	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
1951 	m = z->GetNy() > m ? z->GetNy() : m;
1952 	char mk=gr->SetPenPal(pen,&pal);	gr->Reserve(n*m);
1953 	if(mk==0)	mk='.';
1954 	bool sh = mglchr(pen,'!');
1955 
1956 	int d = gr->MeshNum>0 ? gr->MeshNum+1 : n, dx = n>d?n/d:1;
1957 	for(long j=0;j<m;j++)
1958 	{
1959 		if(gr->NeedStop())	break;
1960 		gr->NextColor(pal);
1961 		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
1962 		long mz = j<z->GetNy() ? j:0, mr = j<r->GetNy() ? j:0;
1963 		const long kq = gr->AllocPnts(n);
1964 #pragma omp parallel for
1965 		for(long i=0;i<n;i+=dx)
1966 		{
1967 			double c = sh ? gr->NextColor(pal,i):gr->CDef;
1968 			gr->AddPntQ(kq+i,mglPoint(x->v(i,mx),y->v(i,my),z->v(i,mz)),c);
1969 		}
1970 		for(long i=0;i<n;i+=dx)		gr->mark_plot(kq+i, mk, fabs(r->v(i,mr)));
1971 	}
1972 	gr->EndGroup();
1973 }
1974 //-----------------------------------------------------------------------------
mgl_mark_xy(HMGL gr,HCDT x,HCDT y,HCDT r,const char * pen,const char * opt)1975 void MGL_EXPORT mgl_mark_xy(HMGL gr, HCDT x, HCDT y, HCDT r, const char *pen, const char *opt)
1976 {
1977 	gr->SaveState(opt);
1978 	mglDataV z(y->GetNx());	z.Fill(gr->AdjustZMin());
1979 	mgl_mark_xyz(gr,x,y,&z,r,pen,0);
1980 }
1981 //-----------------------------------------------------------------------------
mgl_mark_y(HMGL gr,HCDT y,HCDT r,const char * pen,const char * opt)1982 void MGL_EXPORT mgl_mark_y(HMGL gr, HCDT y, HCDT r, const char *pen, const char *opt)
1983 {
1984 	long n=y->GetNx();
1985 	gr->SaveState(opt);
1986 	mglDataV x(n), z(n);
1987 	x.Fill(gr->Min.x,gr->Max.x);	z.Fill(gr->AdjustZMin());
1988 	mgl_mark_xyz(gr,&x,y,&z,r,pen,0);
1989 }
1990 //-----------------------------------------------------------------------------
mgl_mark_xyz_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,uintptr_t * r,const char * pen,const char * opt,int l,int lo)1991 void MGL_EXPORT mgl_mark_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
1992 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1993 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
1994 	mgl_mark_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(r),s,o);
1995 	delete []o;	delete []s;	}
1996 //-----------------------------------------------------------------------------
mgl_mark_xy_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * r,const char * pen,const char * opt,int l,int lo)1997 void MGL_EXPORT mgl_mark_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
1998 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
1999 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
2000 	mgl_mark_xy(_GR_, _DA_(x), _DA_(y), _DA_(r),s,o);	delete []o;	delete []s;	}
2001 //-----------------------------------------------------------------------------
mgl_mark_y_(uintptr_t * gr,uintptr_t * y,uintptr_t * r,const char * pen,const char * opt,int l,int lo)2002 void MGL_EXPORT mgl_mark_y_(uintptr_t *gr, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
2003 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
2004 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
2005 	mgl_mark_y(_GR_,_DA_(y),_DA_(r),s,o);	delete []o;	delete []s;	}
2006 //-----------------------------------------------------------------------------
2007 //
2008 //	Tube series
2009 //
2010 //-----------------------------------------------------------------------------
mgl_tube_xyzr(HMGL gr,HCDT x,HCDT y,HCDT z,HCDT r,const char * pen,const char * opt)2011 void MGL_EXPORT mgl_tube_xyzr(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT r, const char *pen, const char *opt)
2012 {
2013 	long m,n=y->GetNx(),pal;
2014 	if(mgl_check_dim1(gr,x,y,z,r,"Tube"))	return;
2015 
2016 	mreal rnum = gr->SaveState(opt);
2017 	static int cgid=1;	gr->StartGroup("Tube",cgid++);
2018 	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
2019 	m = z->GetNy() > m ? z->GetNy() : m;
2020 	m = r->GetNy() > m ? r->GetNy() : m;
2021 	bool sh = mglchr(pen,'!');
2022 	bool wire = mglchr(pen,'#');
2023 
2024 	int num = rnum>2?rnum:!(gr->GetQuality()&3)?13:25;
2025 	gr->SetPenPal(pen,&pal);	gr->Reserve(n*m*num);
2026 	for(long j=0;j<m;j++)
2027 	{
2028 		if(gr->NeedStop())	break;
2029 		gr->NextColor(pal);
2030 		const long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
2031 		const long mz = j<z->GetNy() ? j:0, mr = j<r->GetNy() ? j:0;
2032 		const long kq = gr->AllocPnts(n*num);
2033 #pragma omp parallel for collapse(2)
2034 		for(long i=0;i<n;i++)	for(long k=0;k<num;k++)
2035 		{
2036 			const mglPoint l(x->dvx(i,mx),y->dvx(i,my),z->dvx(i,mz));
2037 			mglPoint t(!l);		t.Normalize();
2038 			mglPoint u(t^l);	u.Normalize();
2039 			const mglPoint q(x->v(i,mx),y->v(i,my),z->v(i,mz));
2040 			const double rr=r->v(i,mr), dr=r->dvx(i,mr);
2041 			const double c = sh ? gr->NextColor(pal,i):gr->CDef;
2042 
2043 			const int kk = k*360/(num-1);
2044 			const float  co = mgl_cos[kk%360], si = mgl_cos[(270+kk)%360];
2045 			const mglPoint p(q + t*(rr*co) + u*(rr*si));
2046 			const mglPoint d((t*si - u*co)^(l + t*(dr*co) + u*(dr*si)));
2047 			gr->AddPntQ(kq+num*i+k, p,c,wire?mglPoint(NAN,NAN):d,-1,3);
2048 		}
2049 		if(!wire)	for(long i=1;i<n;i++)	for(long k=1;k<num;k++)
2050 		{	long jj=kq+num*i+k;	gr->quad_plot(jj,jj-1,jj-num,jj-num-1);	}
2051 		if(wire)
2052 		{
2053 			for(long i=1;i<n;i++)	for(long k=0;k<num;k+=4)
2054 			{	long jj=kq+num*i+k;	gr->line_plot(jj,jj-num);	}
2055 			for(long i=0;i<n;i++)	for(long k=1;k<num;k++)
2056 			{	long jj=kq+num*i+k;	gr->line_plot(jj,jj-1);		}
2057 		}
2058 	}
2059 	gr->EndGroup();
2060 }
2061 //-----------------------------------------------------------------------------
mgl_tube_xyr(HMGL gr,HCDT x,HCDT y,HCDT r,const char * pen,const char * opt)2062 void MGL_EXPORT mgl_tube_xyr(HMGL gr, HCDT x, HCDT y, HCDT r, const char *pen, const char *opt)
2063 {
2064 	gr->SaveState(opt);
2065 	mglDataV z(y->GetNx());	z.Fill(gr->AdjustZMin());
2066 	mgl_tube_xyzr(gr,x,y,&z,r,pen,0);
2067 }
2068 //-----------------------------------------------------------------------------
mgl_tube_r(HMGL gr,HCDT y,HCDT r,const char * pen,const char * opt)2069 void MGL_EXPORT mgl_tube_r(HMGL gr, HCDT y, HCDT r, const char *pen, const char *opt)
2070 {
2071 	long n=y->GetNx();
2072 	if(n<2)	{	gr->SetWarn(mglWarnLow,"Tube");	return;	}
2073 	gr->SaveState(opt);
2074 	mglDataV x(n), z(n);
2075 	x.Fill(gr->Min.x,gr->Max.x);	z.Fill(gr->AdjustZMin());
2076 	mgl_tube_xyzr(gr,&x,y,&z,r,pen,0);
2077 }
2078 //-----------------------------------------------------------------------------
mgl_tube(HMGL gr,HCDT y,double rr,const char * pen,const char * opt)2079 void MGL_EXPORT mgl_tube(HMGL gr, HCDT y, double rr, const char *pen, const char *opt)
2080 {
2081 	long n=y->GetNx();
2082 	if(n<2)	{	gr->SetWarn(mglWarnLow,"Tube");	return;	}
2083 	gr->SaveState(opt);
2084 	mglDataV x(n), r(n), z(n);
2085 	x.Fill(gr->Min.x,gr->Max.x);
2086 	r.Fill(rr);	z.Fill(gr->AdjustZMin());
2087 	mgl_tube_xyzr(gr,&x,y,&z,&r,pen,0);
2088 }
2089 //-----------------------------------------------------------------------------
mgl_tube_xy(HMGL gr,HCDT x,HCDT y,double rr,const char * pen,const char * opt)2090 void MGL_EXPORT mgl_tube_xy(HMGL gr, HCDT x, HCDT y, double rr, const char *pen, const char *opt)
2091 {
2092 	long n=y->GetNx();
2093 	if(n<2)	{	gr->SetWarn(mglWarnLow,"Tube");	return;	}
2094 	gr->SaveState(opt);
2095 	mglDataV r(n), z(n);
2096 	r.Fill(rr);	z.Fill(gr->AdjustZMin());
2097 	mgl_tube_xyzr(gr,x,y,&z,&r,pen,0);
2098 }
2099 //-----------------------------------------------------------------------------
mgl_tube_xyz(HMGL gr,HCDT x,HCDT y,HCDT z,double rr,const char * pen,const char * opt)2100 void MGL_EXPORT mgl_tube_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, double rr, const char *pen, const char *opt)
2101 {
2102 	gr->SaveState(opt);
2103 	mglDataV r(y->GetNx());	r.Fill(rr);
2104 	mgl_tube_xyzr(gr,x,y,z,&r,pen,0);
2105 }
2106 //-----------------------------------------------------------------------------
mgl_tube_xyzr_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,uintptr_t * r,const char * pen,const char * opt,int l,int lo)2107 void MGL_EXPORT mgl_tube_xyzr_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
2108 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
2109 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
2110 	mgl_tube_xyzr(_GR_,_DA_(x),_DA_(y),_DA_(z), _DA_(r),s,o);
2111 	delete []o;	delete []s;	}
2112 //-----------------------------------------------------------------------------
mgl_tube_xyr_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * r,const char * pen,const char * opt,int l,int lo)2113 void MGL_EXPORT mgl_tube_xyr_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
2114 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
2115 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
2116 	mgl_tube_xyr(_GR_,_DA_(x),_DA_(y),_DA_(r),s,o);	delete []o;	delete []s;	}
2117 //-----------------------------------------------------------------------------
mgl_tube_r_(uintptr_t * gr,uintptr_t * y,uintptr_t * r,const char * pen,const char * opt,int l,int lo)2118 void MGL_EXPORT mgl_tube_r_(uintptr_t *gr, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
2119 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
2120 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
2121 	mgl_tube_r(_GR_,_DA_(y),_DA_(r),s,o);	delete []s;	delete []o;	}
2122 //-----------------------------------------------------------------------------
mgl_tube_xyz_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,mreal * r,const char * pen,const char * opt,int l,int lo)2123 void MGL_EXPORT mgl_tube_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, mreal *r, const char *pen, const char *opt,int l,int lo)
2124 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
2125 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
2126 	mgl_tube_xyz(_GR_,_DA_(x),_DA_(y),_DA_(z),*r,s,o);	delete []o;	delete []s;	}
2127 //-----------------------------------------------------------------------------
mgl_tube_xy_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,mreal * r,const char * pen,const char * opt,int l,int lo)2128 void MGL_EXPORT mgl_tube_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, mreal *r, const char *pen, const char *opt,int l,int lo)
2129 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
2130 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
2131 	mgl_tube_xy(_GR_,_DA_(x),_DA_(y),*r,s,o);	delete []s;	delete []o;	}
2132 //-----------------------------------------------------------------------------
mgl_tube_(uintptr_t * gr,uintptr_t * y,mreal * r,const char * pen,const char * opt,int l,int lo)2133 void MGL_EXPORT mgl_tube_(uintptr_t *gr, uintptr_t *y, mreal *r, const char *pen, const char *opt,int l,int lo)
2134 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
2135 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
2136 	mgl_tube(_GR_,_DA_(y),*r,s,o);
2137 	delete []s;	delete []o;	}
2138 //-----------------------------------------------------------------------------
2139 //
2140 //	Tape series
2141 //
2142 //-----------------------------------------------------------------------------
mgl_tape_xyz(HMGL gr,HCDT x,HCDT y,HCDT z,const char * pen,const char * opt)2143 void MGL_EXPORT mgl_tape_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, const char *pen, const char *opt)
2144 {
2145 	long m,n=y->GetNx(),pal;
2146 	if(mgl_check_dim1(gr,x,y,z,0,"Tape"))	return;
2147 
2148 	static int cgid=1;	gr->StartGroup("Tape",cgid++);
2149 	double rr = gr->SaveState(opt);
2150 	if(rr==0 || mgl_isnan(rr))	rr = mgl_norm(gr->Max-gr->Min)*gr->BarWidth/25;
2151 	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();	m = z->GetNy() > m ? z->GetNy() : m;
2152 	gr->SetPenPal(pen,&pal);	gr->SetMask(pen);	gr->Reserve(4*n*m);
2153 	mglPoint qn(NAN,NAN);
2154 	bool sh = mglchr(pen,'!'), xo = mglchr(pen,'x'), zo = mglchr(pen,'z'), wire = mglchr(pen,'#');
2155 	if(!xo && !zo)	xo = zo = true;
2156 	int nv = xo && zo ? 4:2;
2157 
2158 	for(long j=0;j<m;j++)
2159 	{
2160 		if(gr->NeedStop())	break;
2161 		double c1=gr->NextColor(pal), c2=c1;
2162 		if(gr->GetNumPal(pal)==2*m && !sh)	c2 = gr->NextColor(pal);
2163 		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0, mz = j<z->GetNy() ? j:0;
2164 		const long kq = gr->AllocPnts(nv*n);
2165 // TODO: use AddPntQ() -- problem is vector q1
2166 		// initial values for normales
2167 		mglPoint p2(x->v(0,mx), y->v(0,my), z->v(0,mz));
2168 		mglPoint l(x->v(1,mx)-p2.x, y->v(1,my)-p2.y, z->v(1,mz)-p2.z);	l /= mgl_norm(l);
2169 		mglPoint q1(-l.y,l.x,0);
2170 		double ll = mgl_norm(q1);
2171 		if(ll)	q1 /= ll;	else	q1.Set(0,1,0);
2172 		mglPoint q2(q1^l);
2173 		if(xo&&zo)
2174 		{
2175 			gr->AddPntQ(kq,p2,c1,q2,-1,3);		gr->AddPntQ(kq+1,p2+rr*q1,c1,q2,-1,3);
2176 			gr->AddPntQ(kq+2,p2,c2,q1,-1,3);	gr->AddPntQ(kq+3,p2+rr*q2,c2,q1,-1,3);
2177 		}
2178 		else if(xo)	{	gr->AddPntQ(kq,p2,c1,q2,-1,3);	gr->AddPntQ(kq+1,p2+rr*q1,c1,q2,-1,3);	}
2179 		else		{	gr->AddPntQ(kq,p2,c2,q1,-1,3);	gr->AddPntQ(kq+1,p2+rr*q2,c2,q1,-1,3);	}
2180 		for(long i=1;i<n;i++)
2181 		{
2182 			mglPoint p1 = p2;
2183 			p2.Set(x->v(i,mx), y->v(i,my), z->v(i,mz));
2184 			l = p2-p1;		l /= mgl_norm(l);
2185 			q1 -= l*(l*q1);	q1/= mgl_norm(q1);
2186 			q2 = (q1^l);	// NOTE: not thread safe!!!
2187 
2188 			if(sh)	c2=c1=gr->NextColor(pal,i);	// NOTE: not thread safe
2189 			long iq = kq+nv*i;
2190 			if(xo&&zo)
2191 			{
2192 				gr->AddPntQ(iq,p2,c1,q2,-1,3);		gr->AddPntQ(iq+1,p2+rr*q1,c1,q2,-1,3);
2193 				gr->AddPntQ(iq+2,p2,c2,q1,-1,3);	gr->AddPntQ(iq+3,p2+rr*q2,c2,q1,-1,3);
2194 			}
2195 			else if(xo)	{	gr->AddPntQ(iq,p2,c1,q2,-1,3);	gr->AddPntQ(iq+1,p2+rr*q1,c1,q2,-1,3);	}
2196 			else		{	gr->AddPntQ(iq,p2,c2,q1,-1,3);	gr->AddPntQ(iq+1,p2+rr*q2,c2,q1,-1,3);	}
2197 		}
2198 		if(wire)
2199 		{
2200 			if(xo&&zo)	for(long i=1;i<n;i++)
2201 			{	long iq = kq+nv*i+1;	gr->line_plot(iq-nv,iq);	gr->line_plot(iq-nv+2,iq+2);	}
2202 			else	for(long i=1;i<n;i++)
2203 			{	long iq = kq+nv*i+1;	gr->line_plot(iq-nv,iq);	}
2204 		}
2205 		else
2206 		{
2207 			if(xo&&zo)	for(long i=1;i<n;i++)
2208 			{	long iq = kq+nv*i;
2209 				gr->quad_plot(iq,iq+1,iq-nv,iq-nv+1);	gr->quad_plot(iq+2,iq+3,iq-nv+2,iq-nv+3);	}
2210 			else	for(long i=1;i<n;i++)
2211 			{	long iq = kq+nv*i;	gr->quad_plot(iq,iq+1,iq-nv,iq-nv+1);	}
2212 		}
2213 	}
2214 	gr->EndGroup();
2215 }
2216 //-----------------------------------------------------------------------------
mgl_tape_xy(HMGL gr,HCDT x,HCDT y,const char * pen,const char * opt)2217 void MGL_EXPORT mgl_tape_xy(HMGL gr, HCDT x, HCDT y, const char *pen, const char *opt)
2218 {
2219 	gr->SaveState(opt);
2220 	mglDataV z(y->GetNx());	z.Fill(gr->AdjustZMin());
2221 	mgl_tape_xyz(gr,x,y,&z,pen,0);
2222 }
2223 //-----------------------------------------------------------------------------
mgl_tape(HMGL gr,HCDT y,const char * pen,const char * opt)2224 void MGL_EXPORT mgl_tape(HMGL gr, HCDT y, const char *pen, const char *opt)
2225 {
2226 	long n=y->GetNx();
2227 	if(n<2)	{	gr->SetWarn(mglWarnLow,"Plot");	return;	}
2228 	gr->SaveState(opt);
2229 	mglDataV x(n), z(n);
2230 	x.Fill(gr->Min.x,gr->Max.x);	z.Fill(gr->AdjustZMin());
2231 	mgl_tape_xyz(gr,&x,y,&z,pen,0);
2232 }
2233 //-----------------------------------------------------------------------------
mgl_tape_xyz_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,const char * pen,const char * opt,int l,int lo)2234 void MGL_EXPORT mgl_tape_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, const char *pen, const char *opt,int l,int lo)
2235 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
2236 	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
2237 	mgl_tape_xyz(_GR_, _DA_(x),_DA_(y),_DA_(z),s,o);	delete []s;	delete []o;	}
2238 //-----------------------------------------------------------------------------
mgl_tape_xy_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,const char * pen,const char * opt,int l,int lo)2239 void MGL_EXPORT mgl_tape_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, const char *pen, const char *opt,int l,int lo)
2240 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
2241 	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
2242 	mgl_tape_xy(_GR_, _DA_(x),_DA_(y),s,o);	delete []s;	delete []o;	}
2243 //-----------------------------------------------------------------------------
mgl_tape_(uintptr_t * gr,uintptr_t * y,const char * pen,const char * opt,int l,int lo)2244 void MGL_EXPORT mgl_tape_(uintptr_t *gr, uintptr_t *y,	const char *pen, const char *opt,int l,int lo)
2245 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
2246 	char *o=new char[lo+1];		memcpy(o,opt,lo);	o[lo]=0;
2247 	mgl_tape(_GR_, _DA_(y),s,o);	delete []s;	delete []o;	}
2248 //-----------------------------------------------------------------------------
2249 //
2250 //	Pmap series
2251 //
2252 //-----------------------------------------------------------------------------
mgl_pmap_xyz(HMGL gr,HCDT x,HCDT y,HCDT z,HCDT r,const char * pen,const char * opt)2253 void MGL_EXPORT mgl_pmap_xyz(HMGL gr, HCDT x, HCDT y, HCDT z, HCDT r, const char *pen, const char *opt)
2254 {
2255 	long m,n=y->GetNx(),pal;
2256 	if(mgl_check_dim0(gr,x,y,z,r,"Mark"))	return;
2257 
2258 	gr->SaveState(opt);
2259 	static int cgid=1;	gr->StartGroup("Mark",cgid++);
2260 	m = x->GetNy() > y->GetNy() ? x->GetNy() : y->GetNy();
2261 	m = z->GetNy() > m ? z->GetNy() : m;
2262 	char mk=gr->SetPenPal(pen,&pal);	gr->Reserve(n*m);
2263 	if(mk==0)	mk='.';
2264 
2265 	for(long j=0;j<m;j++)
2266 	{
2267 		if(gr->NeedStop())	break;
2268 		gr->NextColor(pal);
2269 		long mx = j<x->GetNy() ? j:0, my = j<y->GetNy() ? j:0;
2270 		long mz = j<z->GetNy() ? j:0, mr = j<r->GetNy() ? j:0;
2271 		for(long i=0;i<n-1;i++)	// NOTE: AddPntQ() is useless due to rare points
2272 		{
2273 			double r1=r->v(i,mr), r2 = r->v(i+1,mr);
2274 			if(r1==0)	gr->mark_plot(gr->AddPnt(mglPoint(x->v(i,mx),y->v(i,my),z->v(i,mz))), mk);
2275 			if(r1*r2<0)
2276 			{
2277 				double d = r1/(r1-r2);
2278 				mglPoint p(x->v(i,mx)*(1-d)+x->v(i+1,mx)*d, y->v(i,my)*(1-d)+y->v(i+1,my)*d, z->v(i,mz)*(1-d)+d*z->v(i+1,mz));
2279 				gr->mark_plot(gr->AddPnt(p), mk);
2280 			}
2281 		}
2282 	}
2283 	gr->EndGroup();
2284 }
2285 //-----------------------------------------------------------------------------
mgl_pmap_xy(HMGL gr,HCDT x,HCDT y,HCDT r,const char * pen,const char * opt)2286 void MGL_EXPORT mgl_pmap_xy(HMGL gr, HCDT x, HCDT y, HCDT r, const char *pen, const char *opt)
2287 {
2288 	gr->SaveState(opt);
2289 	mglDataV z(y->GetNx());	z.Fill(gr->AdjustZMin());
2290 	mgl_pmap_xyz(gr,x,y,&z,r,pen,0);
2291 }
2292 //-----------------------------------------------------------------------------
mgl_pmap(HMGL gr,HCDT y,HCDT r,const char * pen,const char * opt)2293 void MGL_EXPORT mgl_pmap(HMGL gr, HCDT y, HCDT r, const char *pen, const char *opt)
2294 {
2295 	long n=y->GetNx();
2296 	gr->SaveState(opt);
2297 	mglDataV x(n), z(n);
2298 	x.Fill(gr->Min.x,gr->Max.x);	z.Fill(gr->AdjustZMin());
2299 	mgl_pmap_xyz(gr,&x,y,&z,r,pen,0);
2300 }
2301 //-----------------------------------------------------------------------------
mgl_pmap_xyz_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * z,uintptr_t * r,const char * pen,const char * opt,int l,int lo)2302 void MGL_EXPORT mgl_pmap_xyz_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *z, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
2303 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
2304 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
2305 	mgl_pmap_xyz(_GR_, _DA_(x), _DA_(y), _DA_(z), _DA_(r),s,o);
2306 	delete []o;	delete []s;	}
2307 //-----------------------------------------------------------------------------
mgl_pmap_xy_(uintptr_t * gr,uintptr_t * x,uintptr_t * y,uintptr_t * r,const char * pen,const char * opt,int l,int lo)2308 void MGL_EXPORT mgl_pmap_xy_(uintptr_t *gr, uintptr_t *x, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
2309 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
2310 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
2311 	mgl_pmap_xy(_GR_, _DA_(x), _DA_(y), _DA_(r),s,o);	delete []o;	delete []s;	}
2312 //-----------------------------------------------------------------------------
mgl_pmap_(uintptr_t * gr,uintptr_t * y,uintptr_t * r,const char * pen,const char * opt,int l,int lo)2313 void MGL_EXPORT mgl_pmap_(uintptr_t *gr, uintptr_t *y, uintptr_t *r, const char *pen, const char *opt,int l,int lo)
2314 {	char *s=new char[l+1];	memcpy(s,pen,l);	s[l]=0;
2315 	char *o=new char[lo+1];	memcpy(o,opt,lo);	o[lo]=0;
2316 	mgl_pmap(_GR_,_DA_(y),_DA_(r),s,o);	delete []o;	delete []s;	}
2317 //-----------------------------------------------------------------------------
2318