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