void mglCanvas::line_plot(long p1, long p2) { if(PDef==0) return; if(p1<0 || p2<0 || mgl_isnan(Pnt[p1].x) || mgl_isnan(Pnt[p2].x)) return; if(p1>p2) { long kk=p1; p1=p2; p2=kk; } // rearrange start/end for proper dashing long pp1=p1,pp2=p2; mreal pw = fabs(PenWidth)*sqrt(font_factor/400); if(TernAxis&12) for(int i=0;i<4;i++) { p1 = ProjScale(i, pp1); p2 = ProjScale(i, pp2); MGL_LINE_PLOT } else { MGL_LINE_PLOT }
void mglCanvas::mark_plot(long p, char type, mreal size) { if(p<0 || mgl_isnan(Pnt[p].x) || mgl_isnan(size)) return; long pp=p; mreal pw = 0.15/sqrt(font_factor); size = size?fabs(size):1; size *= MarkSize*0.35*font_factor; if(type=='.') size = fabs(PenWidth)*sqrt(font_factor/400); if(TernAxis&12) for(int i=0;i<4;i++) { p = ProjScale(i, pp); MGL_MARK_PLOT } else { MGL_MARK_PLOT }
//----------------------------------------------------------------------------- void MGL_EXPORT mgl_cont_z_val(HMGL gr, HCDT v, HCDT a, const char *sch, double sv, const char *opt) { long n=a->GetNx(),m=a->GetNy(); if(n<2 || m<2) { gr->SetWarn(mglWarnLow,"ContZ"); return; } gr->SaveState(opt); if(mgl_isnan(sv)) sv = gr->GetOrgZ('z'); if(sv<gr->Min.z || sv>gr->Max.z) { gr->SetWarn(mglWarnSlc,"ContZ"); gr->LoadState(); return; } static int cgid=1; gr->StartGroup("ContZ",cgid++); mglDataV xx,yy,zz; mglData aa; int text=0; if(mglchr(sch,'t')) text=1; if(mglchr(sch,'T')) text=2; long ss=gr->AddTexture(sch); gr->SetPenPal(sch); a = fill_slice_z(gr,sv,a,xx,yy,zz,aa); #pragma omp parallel for for(long i=0;i<v->GetNx();i++) { mreal v0 = v->v(i); mgl_cont_gen(gr,v0,a,&xx,&yy,&zz,gr->GetC(ss,v0),text,0); } gr->EndGroup(); }
//----------------------------------------------------------------------------- void mglCanvasGL::AddLight(int n,mglPoint r,mglPoint d,char cc, mreal br,mreal /*ap*/) { mglColor c(cc); mglColor AmbLight = mglColor(AmbBr,AmbBr,AmbBr); mglColor DifLight = mglColor(br,br,br); GLenum lght[8] = {GL_LIGHT0,GL_LIGHT1,GL_LIGHT2,GL_LIGHT3,GL_LIGHT4, GL_LIGHT5,GL_LIGHT6,GL_LIGHT7}; float amb[4], pos[4],dif[4],dir[4]; bool inf = mgl_isnan(r.x); if(n<0 || n>7) { SetWarn(mglWarnLId,"AddLight"); return; } if(c.Valid()) { DifLight = c*br; AmbLight = c*AmbBr; } dif[0] = DifLight.r; dif[1] = DifLight.g; dif[2] = DifLight.b; dif[3] = 1.; amb[0] = AmbLight.r; amb[1] = AmbLight.g; amb[2] = AmbLight.b; amb[3] = 1.; if(inf) { pos[0] = d.x; pos[1] = d.y; pos[2] = d.z; pos[3] = 0; } else { pos[0] = r.x; pos[1] = r.y; pos[2] = r.z; pos[3] = 1; } dir[0] = d.x; dir[1] = d.y; dir[2] = d.z; glShadeModel(GL_SMOOTH); //glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 5.0); //glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, pos); glLightfv(lght[n], GL_AMBIENT, amb); glLightfv(lght[n], GL_DIFFUSE, dif); //glLightfv(lght[n], GL_SPECULAR, spc); glLightfv(lght[n], GL_POSITION, pos); if(!inf) glLightfv(lght[n], GL_SPOT_DIRECTION, dir); glEnable(lght[n]); }
//----------------------------------------------------------------------------- void MGL_EXPORT mgl_contf_z(HMGL gr, HCDT a, const char *sch, double sv, const char *opt) { mreal r = gr->SaveState(opt); long Num = (mgl_isnan(r) || r<=0) ? 7:long(r+0.5); mglData v(Num); v.Fill(gr->Min.c, gr->Max.c); mgl_contf_z_val(gr,&v,a,sch,sv,0); }
//----------------------------------------------------------------------------- void mglCanvas::glyph_pix(long i, long j, const mglPrim &P, mglDrawReg *d) { float phi = GetGlyphPhi(Pnt[P.n2],P.w); if(mgl_isnan(phi)) return; if(d) { d->PDef = MGL_SOLID_MASK; d->angle = 0; d->PenWidth=1; } mglPnt p=Pnt[P.n1]; mreal pf=sqrt((Bp.b[0]*Bp.b[0]+Bp.b[1]*Bp.b[1]+Bp.b[3]*Bp.b[3]+Bp.b[4]*Bp.b[4])/2), f = P.p*pf; mglMatrix M; M.b[0] = M.b[4] = M.b[8] = P.s; M.RotateN(phi,0,0,1); M.x=p.x; M.y=p.y; M.z=p.z; M.pf = 1; p.u *= pf; p.v *= pf; const mglGlyph &g = Glf[P.n4]; if(P.n3&8) { if(!(P.n3&4)) glyph_lpix(i,j,&M,p,f,true, d); glyph_lpix(i,j,&M,p,f,false, d); } else { if(!(P.n3&4)) glyph_fpix(i,j,&M,p,f,g, d); glyph_wpix(i,j,&M,p,f,g, d); } }
//----------------------------------------------------------------------------- void MGL_EXPORT mgl_tricontv_xyzc(HMGL gr, HCDT nums, HCDT x, HCDT y, HCDT z, HCDT a, const char *sch, const char *opt) { mreal r = gr->SaveState(opt); long n = (mgl_isnan(r) || r<=0) ? 7:long(r+0.5); mglData v(n); for(long i=0;i<n;i++) v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(n+1); mgl_tricontv_xyzcv(gr,&v,nums,x,y,z,a,sch,0); }
//----------------------------------------------------------------------------- void MGL_EXPORT mgl_cont_z(HMGL gr, HCDT a, const char *sch, double sv, const char *opt) { mreal r = gr->SaveState(opt); long Num = (mgl_isnan(r) || r<=0) ? 7:long(r+0.5); mglData v(Num); for(long i=0;i<Num;i++) v.a[i] = gr->Min.c + (gr->Max.c-gr->Min.c)*mreal(i+1)/(Num+1); mgl_cont_z_val(gr,&v,a,sch,sv,0); }
//----------------------------------------------------------------------------- void MGL_EXPORT mgl_dens_z(HMGL gr, HCDT a, const char *sch, double sv, const char *opt) { long n=a->GetNx(),m=a->GetNy(); if(n<2 || m<2) { gr->SetWarn(mglWarnLow,"DensZ"); return; } gr->SaveState(opt); if(mgl_isnan(sv)) sv = gr->GetOrgZ('z'); if(sv<gr->Min.z || sv>gr->Max.z) { gr->SetWarn(mglWarnSlc,"DensZ"); gr->LoadState(); return; } mglDataV xx,yy,zz; mglData aa; a = fill_slice_z(gr,sv,a,xx,yy,zz,aa); mgl_surf_gen(gr, &xx,&yy,&zz,a, 0, sch); }
void MGL_EXPORT mgl_datac_fill(HADT d, dual x1,dual x2,char dir) { if(mgl_isnan(x2)) x2=x1; if(dir<'x' || dir>'z') dir='x'; long par[2]={d->nx,d->ny}; dual b[2]={x1,x2-x1}; if(dir=='x') b[1] *= d->nx>1 ? 1./(d->nx-1):0; if(dir=='y') b[1] *= d->ny>1 ? 1./(d->ny-1):0; if(dir=='z') b[1] *= d->nz>1 ? 1./(d->nz-1):0; mglStartThreadC(mgl_cfill_x,0,d->nx*d->ny*d->nz,d->a,b,0,par,0,0,0,&dir); }
//----------------------------------------------------------------------------- mreal mglCanvas::GetOrgY(char dir, bool inv) const { mreal res = Org.y; if(mgl_isnan(res)) { if(strchr("xyz",dir)) res = FindOptOrg(dir,1); else if(dir=='t') res = Min.y; else res = B.b[7]>0 ? Max.y:Min.y; if(inv) res = Min.y+Max.y-res; } return res; }
//----------------------------------------------------------------------------- mreal mglCanvas::GetOrgZ(char dir, bool inv) const { mreal res = Org.z; if(mgl_isnan(res)) { if(strchr("xyz",dir)) res = FindOptOrg(dir,2); else if(dir=='t') res = Min.z; else res = B.b[8]>0 ? Max.z:Min.z; if(inv) res = Min.z+Max.z-res; } return res; }
//----------------------------------------------------------------------------- mreal mglCanvas::GetOrgX(char dir, bool inv) const { mreal res = Org.x; if(mgl_isnan(res)) { if(strchr("xyz",dir)) res = FindOptOrg(dir,0); else if(dir=='t') res = Min.x; else res = B.b[6]>0 ? Max.x:Min.x; if(inv) res = Min.x+Max.x-res; } return res; }
//----------------------------------------------------------------------------- void DatPanel::putValue(int r, int c) { if(!var || r<0 || c<0 || r>=ny || c>=nx || !ready) return; QString s = tab->item(r,c)->text().toLower(); mreal f; dual g; if(s=="nan") f=NAN; else if(s=="inf") f=INFINITY; else if(s=="-inf") f=-INFINITY; else g = mgl_str2dual(s.toLocal8Bit().constData()); //f = s.toDouble(); f = real(g); mglDataC *cc = dynamic_cast<mglDataC*>(var); if(cc) { if(g!=cc->a[c+nx*(r+ny*kz)]) { if(mgl_isnan(g)) s="nan"; else if(mgl_isbad(g)) s="inf"; else if(imag(g)>0) s.sprintf("%g+%gi",real(g),imag(g)); else if(imag(g)<0) s.sprintf("%g-%gi",real(g),-imag(g)); else s.sprintf("%g",real(g)); tab->item(r,c)->setText(s); } cc->a[c+nx*(r+ny*kz)] = g; } else { if(f!=var->v(c,r,kz)) { if(mgl_isnan(f)) s="nan"; else if(mgl_isbad(f)) s=f>0?"inf":"-inf"; else s.sprintf("%g", f); tab->item(r,c)->setText(s); } var->set_v(f,c,r,kz); } infoDlg->refresh(); }
//----------------------------------------------------------------------------- void mglCanvas::trig_pix(long i, long j, const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, bool anorm, const mglDrawReg *d) { if(!visible(i,j,d->m, d->PenWidth,d->angle)) return; mglPnt d1(p2-p1), d2(p3-p1); float dd = d2.x*d1.y - d1.x*d2.y; if(fabs(dd)<1e-5) return; // points lies on the same line float dyv =-d1.x/dd, dxv = d1.y/dd, dyu = d2.x/dd, dxu =-d2.y/dd; float xx = (i-p1.x), yy = (j-p1.y); float u = dxu*xx+dyu*yy, v = dxv*xx+dyv*yy; if(u<0 || v<0 || u+v>1) return; mglPnt p(p1+d1*u+d2*v); if(mgl_isnan(p.u) && mgl_isnum(p.v) && anorm) { mglPoint nr(mglPoint(p2.x-p1.x,p2.y-p1.y,p2.z-p1.z)^mglPoint(p3.x-p1.x,p3.y-p1.y,p3.z-p1.z)); p.u = nr.x; p.v = nr.y; p.w = nr.z; } unsigned char r[4]; if(r[3]) pnt_plot(i,j,p.z,col2int(p,r,d->ObjId),d->ObjId); }
//----------------------------------------------------------------------------- void mglCanvas::quad_pix(long i, long j, const mglPnt &p1, const mglPnt &p2, const mglPnt &p3, const mglPnt &p4, const mglDrawReg *d) { if(!visible(i,j,d->m, d->PenWidth,d->angle)) return; mglPnt d1(p2-p1), d2(p3-p1), d3(p4+p1-p2-p3); float dd = d1.x*d2.y-d1.y*d2.x; float dsx =-4*(d2.y*d3.x - d2.x*d3.y)*d1.y; float dsy = 4*(d2.y*d3.x - d2.x*d3.y)*d1.x; float xx = (i-p1.x), yy = (j-p1.y), s; s = dsx*xx + dsy*yy + (dd+d3.y*xx-d3.x*yy)*(dd+d3.y*xx-d3.x*yy); if(s<0) return; // no solution s = sqrt(s); float qu = d3.x*yy - d3.y*xx + dd + s, u=-1; float qv = d3.y*xx - d3.x*yy + dd + s, v=-1; if(qu && qv) { u = 2.f*(d2.y*xx - d2.x*yy)/qu; v = 2.f*(d1.x*yy - d1.y*xx)/qv; } if(u*(1.f-u)<0.f || v*(1.f-v)<0.f) // first root bad { qu = d3.x*yy - d3.y*xx + dd - s; qv = d3.y*xx - d3.x*yy + dd - s; u = v = -1.f; if(qu && qv) { u = 2.f*(d2.y*xx - d2.x*yy)/qu; v = 2.f*(d1.x*yy - d1.y*xx)/qv; } if(u*(1.f-u)<0.f || v*(1.f-v)<0.f) return; // second root bad } mglPnt p(p1+d1*u+d2*v+d3*(u*v)); if(mgl_isnan(p.u) && mgl_isnum(p.v)) { mglPoint n1(mglPoint(p2.x-p1.x,p2.y-p1.y,p2.z-p1.z)^mglPoint(p3.x-p1.x,p3.y-p1.y,p3.z-p1.z)); mglPoint n2(mglPoint(p2.x-p4.x,p2.y-p4.y,p2.z-p4.z)^mglPoint(p3.x-p4.x,p3.y-p4.y,p3.z-p4.z)); p.u = (n1.x+n2.x)*0.5; p.v = (n1.y+n2.y)*0.5; p.w = (n1.z+n2.z)*0.5; } unsigned char r[4]; col2int(p,r,d->ObjId); if(r[3]) pnt_plot(i,j,p.z,r,d->ObjId); }
//----------------------------------------------------------------------------- void MGL_EXPORT mgl_contf_y_val(HMGL gr, HCDT v, HCDT a, const char *sch, double sv, const char *opt) { long n=a->GetNx(),m=a->GetNy(); if(n<2 || m<2) { gr->SetWarn(mglWarnLow,"ContFY"); return; } gr->SaveState(opt); if(mgl_isnan(sv)) sv = gr->GetOrgY('y'); if(sv<gr->Min.y || sv>gr->Max.y) { gr->SetWarn(mglWarnSlc,"ContFY"); gr->LoadState(); return; } static int cgid=1; gr->StartGroup("ContFY",cgid++); mglDataV xx,yy,zz; mglData aa; long ss=gr->AddTexture(sch); a = fill_slice_y(gr,sv,a,xx,yy,zz,aa); #pragma omp parallel for for(long i=0;i<v->GetNx()-1;i++) { mreal v0 = v->v(i); mgl_contf_gen(gr,v0,v->v(i+1),a,&xx,&yy,&zz,gr->GetC(ss,v0),0); } gr->EndGroup(); }
//----------------------------------------------------------------------------- void mglCanvasGL::AddLight(int n,mglPoint r,mglPoint d,char cc, mreal br,mreal ap) { mglColor c(cc); float amb[4],dif[4],spc[4], pos[4],dir[4]; bool inf = mgl_isnan(r.x); if(n<0 || n>7) { SetWarn(mglWarnLId,"AddLight"); return; } if(c.Valid()) { spc[0] = br*c.r; spc[1] = br*c.g; spc[2] = br*c.b; amb[0] = AmbBr*c.r; amb[1] = AmbBr*c.g; amb[2] = AmbBr*c.b; } else { spc[0] = spc[1] = spc[2] = br; amb[0] = amb[1] = amb[2] = AmbBr; } ap = 90-180*atan(fabs(ap))/M_PI; dif[0] = dif[1] = dif[2] = DifBr; dif[3] = amb[3] = spc[3] = 1.; if(inf) { pos[0] = d.x; pos[1] = d.y; pos[2] = d.z; pos[3] = 0; } else { pos[0] = r.x; pos[1] = r.y; pos[2] = r.z; pos[3] = 1; } dir[0] = d.x; dir[1] = d.y; dir[2] = d.z; dir[3] = 0; glShadeModel(GL_SMOOTH); glLightfv(GL_LIGHT0+n, GL_AMBIENT, amb); glLightfv(GL_LIGHT0+n, GL_DIFFUSE, dif); glLightfv(GL_LIGHT0+n, GL_SPECULAR, spc); glLightfv(GL_LIGHT0+n, GL_POSITION, pos); if(!inf) { glLightfv(GL_LIGHT0+n, GL_SPOT_DIRECTION, dir); glLightf(GL_LIGHT0+n, GL_SPOT_CUTOFF, ap); } glEnable(GL_LIGHT0+n); }
//----------------------------------------------------------------------------- void DatPanel::refresh() { bool rc = false; if(!var) return; infoDlg->allowRefresh=false; if(nx!=var->GetNx()) { nx = var->GetNx(); tab->setColumnCount(nx); rc=true; } if(ny!=var->GetNy()) { ny = var->GetNy(); tab->setRowCount(ny); rc=true; } if(kz>=var->GetNz()) { kz = 0; emit sliceChanged(0); } if(nz!=var->GetNz()) { nz = var->GetNz(); emit nzChanged(nz); } const mglData *dd = dynamic_cast<const mglData *>(var); if(dd) id = QString(dd->id.c_str()); const mglDataC *dc = dynamic_cast<const mglDataC *>(var); if(dc) id = QString(dc->id.c_str()); if(nz==1 && ny>1 && !id.isEmpty()) { QStringList head; QString s; for(int i=0;i<ny;i++) { s = QString("%1").arg(i); if(id[i]>='a' && id[i]<='z') s=s+" ("+id[i]+")"; head<<s; } tab->setHorizontalHeaderLabels(head); } long m=var->s.length(); QString s,d; if(rc) { QStringList sh,sv; for(long i=0;i<nx;i++) sh<<QString::number(i); tab->setHorizontalHeaderLabels(sh); for(long i=0;i<ny;i++) sv<<QString::number(i); tab->setVerticalHeaderLabels(sv); for(long i=0;i<nx;i++) for(long j=0;j<ny;j++) tab->setItem(j,i,new QTableWidgetItem); } mglDataC *cc = dynamic_cast<mglDataC*>(var); if(cc) for(long i=0;i<nx;i++) for(long j=0;j<ny;j++) { dual f = cc->a[i+nx*(j+ny*kz)]; if(mgl_isnan(f)) s = "nan"; else if(mgl_isbad(f)) s="inf"; else if(imag(f)>0) s.sprintf("%.15g+%.15gi",real(f),imag(f)); else if(imag(f)<0) s.sprintf("%.15g-%.15gi",real(f),-imag(f)); else s.sprintf("%15g",real(f)); tab->item(j,i)->setText(s); } else for(long i=0;i<nx;i++) for(long j=0;j<ny;j++) { double f = var->v(i,j,kz); if(mgl_isnan(f)) s = "nan"; else if(mgl_isbad(f)) s=f>0?"inf":"-inf"; else s.sprintf("%.15g",f); tab->item(j,i)->setText(s); } infoDlg->allowRefresh=true; infoDlg->refresh(); QChar *ss = new QChar[m+1]; for(long i=0;i<m;i++) ss[i] = var->s[i]; s = QString(ss, m); delete []ss; d.sprintf("%d * %d * %d", nx, ny, nz); ready = true; }