void ArchesModel::InitModel() { int NumArches=parm1; int SegmentsPerArch=parm2; arc = wxAtoi(ModelXml->GetAttribute("arc", "180")); SetBufferSize(NumArches,SegmentsPerArch); if (SingleNode) { SetNodeCount(NumArches * SegmentsPerArch, parm3,rgbOrder); } else { SetNodeCount(NumArches, SegmentsPerArch, rgbOrder); if (parm3 > 1) { for (int x = 0; x < Nodes.size(); x++) { Nodes[x]->Coords.resize(parm3); } } } screenLocation.SetRenderSize(SegmentsPerArch, NumArches); for (int y=0; y < NumArches; y++) { for(int x=0; x<SegmentsPerArch; x++) { int idx = y * SegmentsPerArch + x; Nodes[idx]->ActChan = stringStartChan[y] + x*GetNodeChannelCount(StringType); Nodes[idx]->StringNum=y; for(size_t c=0; c < GetCoordCount(idx); c++) { Nodes[idx]->Coords[c].bufX=IsLtoR ? x : SegmentsPerArch-x-1; Nodes[idx]->Coords[c].bufY=isBotToTop ? y : NumArches-y-1; } } } SetArchCoord(); }
// initialize buffer coordinates // parm1=Number of Strings/Arches // parm2=Pixels Per String/Arch void ModelClass::InitLine() { SetNodeCount(parm1,parm2); SetBufferSize(1,parm2); int LastStringNum=-1; int chan,idx; int ChanIncr=SingleChannel ? 1 : 3; size_t NodeCount=GetNodeCount(); for(size_t n=0; n<NodeCount; n++) { if (Nodes[n]->StringNum != LastStringNum) { LastStringNum=Nodes[n]->StringNum; chan=stringStartChan[LastStringNum]; idx=0; } Nodes[n]->ActChan=chan; chan+=ChanIncr; size_t CoordCount=GetCoordCount(n); for(size_t c=0; c < CoordCount; c++) { Nodes[n]->Coords[c].bufX=IsLtoR ? idx : parm2-idx-1; Nodes[n]->Coords[c].bufY=0; idx++; } } }
// parm3 is number of points // top left=top ccw, top right=top cw, bottom left=bottom cw, bottom right=bottom ccw void ModelClass::InitStar() { if (parm3 < 2) parm3=2; // need at least 2 arms SetNodeCount(parm1,parm2); int numlights=parm1*parm2; SetBufferSize(numlights+1,numlights+1); int LastStringNum=-1; int chan,cursegment,nextsegment,x,y; int offset=numlights/2; int numsegments=parm3*2; double segstart_x,segstart_y,segend_x,segend_y,segstart_pct,segend_pct,r,segpct,dseg; double dpct=1.0/(double)numsegments; double OuterRadius=offset; double InnerRadius=OuterRadius/2.618034; // divide by golden ratio squared double pct=isBotToTop ? 0.5 : 0.0; // % of circle, 0=top double pctIncr=1.0 / (double)numlights; // this is cw if (IsLtoR != isBotToTop) pctIncr*=-1.0; // adjust to ccw int ChanIncr=SingleChannel ? 1 : 3; size_t NodeCount=GetNodeCount(); for(size_t n=0; n<NodeCount; n++) { if (Nodes[n]->StringNum != LastStringNum) { LastStringNum=Nodes[n]->StringNum; chan=stringStartChan[LastStringNum]; } Nodes[n]->ActChan=chan; chan+=ChanIncr; size_t CoordCount=GetCoordCount(n); for(size_t c=0; c < CoordCount; c++) { cursegment=(int)((double)numsegments*pct) % numsegments; nextsegment=(cursegment+1) % numsegments; segstart_pct=(double)cursegment / numsegments; segend_pct=(double)nextsegment / numsegments; dseg=pct - segstart_pct; segpct=dseg / dpct; r=cursegment%2==0 ? OuterRadius : InnerRadius; segstart_x=r*sin(segstart_pct*2.0*M_PI); segstart_y=r*cos(segstart_pct*2.0*M_PI); r=nextsegment%2==0 ? OuterRadius : InnerRadius; segend_x=r*sin(segend_pct*2.0*M_PI); segend_y=r*cos(segend_pct*2.0*M_PI); // now interpolate between segstart and segend x=(segend_x - segstart_x)*segpct + segstart_x + offset + 0.5; y=(segend_y - segstart_y)*segpct + segstart_y + offset + 0.5; Nodes[n]->Coords[c].bufX=x; Nodes[n]->Coords[c].bufY=y; pct+=pctIncr; if (pct >= 1.0) pct-=1.0; if (pct < 0.0) pct+=1.0; } } }
// initialize buffer coordinates // parm1=NumStrings // parm2=PixelsPerString // parm3=StrandsPerString void ModelClass::InitHMatrix() { int y,x,idx,stringnum,segmentnum,xincr; int NumStrands=parm1*parm3; int PixelsPerStrand=parm2/parm3; int PixelsPerString=PixelsPerStrand*parm3; SetBufferSize(NumStrands,PixelsPerStrand); SetNodeCount(parm1,PixelsPerString); SetRenderSize(NumStrands,PixelsPerStrand); // create output mapping if (SingleNode) { y=0; for (size_t n=0; n<Nodes.size(); n++) { Nodes[n]->ActChan = stringStartChan[n]; x=0; xincr=1; for (size_t c=0; c<PixelsPerString; c++) { Nodes[n]->Coords[c].bufX=x; Nodes[n]->Coords[c].bufY=isBotToTop ? y :NumStrands-y-1; x+=xincr; if (x < 0 || x >= PixelsPerStrand) { xincr=-xincr; x+=xincr; y++; } } } } else { for (y=0; y < NumStrands; y++) { stringnum=y / parm3; segmentnum=y % parm3; for(x=0; x<PixelsPerStrand; x++) { idx=stringnum * PixelsPerString + segmentnum * PixelsPerStrand + x; Nodes[idx]->ActChan = stringStartChan[stringnum] + segmentnum * PixelsPerStrand*3 + x*3; Nodes[idx]->Coords[0].bufX=IsLtoR != (segmentnum % 2 == 0) ? PixelsPerStrand-x-1 : x; Nodes[idx]->Coords[0].bufY= isBotToTop ? y :NumStrands-y-1; Nodes[idx]->StringNum=stringnum; } } } }
// initialize buffer coordinates // parm1=NumStrings // parm2=PixelsPerString // parm3=StrandsPerString void ModelClass::InitVMatrix() { int y,x,idx,stringnum,segmentnum,yincr; int NumStrands=parm1*parm3; int PixelsPerStrand=parm2/parm3; int PixelsPerString=PixelsPerStrand*parm3; SetBufferSize(PixelsPerStrand,NumStrands); SetNodeCount(parm1,PixelsPerString); SetRenderSize(PixelsPerStrand,NumStrands); // create output mapping if (SingleNode) { x=0; for (size_t n=0; n<Nodes.size(); n++) { Nodes[n]->ActChan = stringStartChan[n]; y=0; yincr=1; for (size_t c=0; c<PixelsPerString; c++) { Nodes[n]->Coords[c].bufX=IsLtoR ? x : NumStrands-x-1; Nodes[n]->Coords[c].bufY=y; y+=yincr; if (y < 0 || y >= PixelsPerStrand) { yincr=-yincr; y+=yincr; x++; } } } } else { for (x=0; x < NumStrands; x++) { stringnum=x / parm3; segmentnum=x % parm3; for(y=0; y < PixelsPerStrand; y++) { idx=stringnum * PixelsPerString + segmentnum * PixelsPerStrand + y; Nodes[idx]->ActChan = stringStartChan[stringnum] + segmentnum * PixelsPerStrand*3 + y*3; Nodes[idx]->Coords[0].bufX=IsLtoR ? x : NumStrands-x-1; Nodes[idx]->Coords[0].bufY= isBotToTop == (segmentnum % 2 == 0) ? y:PixelsPerStrand-y-1; Nodes[idx]->StringNum=stringnum; } } } }
void ModelClass::InitCustomMatrix(const wxString& customModel) { wxString value; wxArrayString cols; long idx; int width=1; std::vector<int> nodemap; wxArrayString rows=wxSplit(customModel,';'); int height=rows.size(); int cpn = ChannelsPerNode(); for(size_t row=0; row < rows.size(); row++) { cols=wxSplit(rows[row],','); if (cols.size() > width) width=cols.size(); for(size_t col=0; col < cols.size(); col++) { value=cols[col]; if (!value.IsEmpty() && value != "0") { value.ToLong(&idx); // increase nodemap size if necessary if (idx > nodemap.size()) { nodemap.resize(idx, -1); } idx--; // adjust to 0-based // is node already defined in map? if (nodemap[idx] < 0) { // unmapped - so add a node nodemap[idx]=Nodes.size(); SetNodeCount(1,0); // this creates a node of the correct class Nodes.back()->StringNum= SingleNode ? idx : 0; Nodes.back()->ActChan=stringStartChan[0] + idx * cpn; Nodes.back()->AddBufCoord(col,height - row - 1); } else { // mapped - so add a coord to existing node Nodes[nodemap[idx]]->AddBufCoord(col,height - row - 1); } } } } SetBufferSize(height,width); }
// top left=top ccw, top right=top cw, bottom left=bottom cw, bottom right=bottom ccw void ModelClass::InitWreath() { SetNodeCount(parm1,parm2); int numlights=parm1*parm2; SetBufferSize(numlights+1,numlights+1); int LastStringNum=-1; int offset=numlights/2; double r=offset; int chan,x,y; double pct=isBotToTop ? 0.5 : 0.0; // % of circle, 0=top double pctIncr=1.0 / (double)numlights; // this is cw if (IsLtoR != isBotToTop) pctIncr*=-1.0; // adjust to ccw int ChanIncr=SingleChannel ? 1 : 3; size_t NodeCount=GetNodeCount(); for(size_t n=0; n<NodeCount; n++) { if (Nodes[n]->StringNum != LastStringNum) { LastStringNum=Nodes[n]->StringNum; chan=stringStartChan[LastStringNum]; } Nodes[n]->ActChan=chan; chan+=ChanIncr; size_t CoordCount=GetCoordCount(n); for(size_t c=0; c < CoordCount; c++) { x=r*sin(pct*2.0*M_PI) + offset + 0.5; y=r*cos(pct*2.0*M_PI) + offset + 0.5; Nodes[n]->Coords[c].bufX=x; Nodes[n]->Coords[c].bufY=y; pct+=pctIncr; if (pct >= 1.0) pct-=1.0; if (pct < 0.0) pct+=1.0; } } }
// initialize buffer coordinates // parm1=Nodes on Top // parm2=Nodes left and right // parm3=Nodes on Bottom void ModelClass::InitFrame() { int x,y,newx,newy; SetNodeCount(1,parm1+2*parm2+parm3); int FrameWidth=std::max(parm1,parm3)+2; SetBufferSize(parm2,FrameWidth); // treat as outside of matrix //SetBufferSize(1,Nodes.size()); // treat as single string SetRenderSize(parm2,FrameWidth); int chan=stringStartChan[0]; int ChanIncr=SingleChannel ? 1 : 3; int xincr[4]= {0,1,0,-1}; // indexed by side int yincr[4]= {1,0,-1,0}; x=IsLtoR ? 0 : FrameWidth-1; y=isBotToTop ? 0 : parm2-1; int dir=1; // 1=clockwise int side=x>0 ? 2 : 0; // 0=left, 1=top, 2=right, 3=bottom int SideIncr=1; // 1=clockwise if ((parm1 > parm3 && x>0) || (parm3 > parm1 && x==0)) { // counter-clockwise dir=-1; SideIncr=3; } // determine starting position if (parm1 > parm3) { // more nodes on top, must start at bottom y=0; } else if (parm3 > parm1) { // more nodes on bottom, must start at top y=parm2-1; } else { // equal top and bottom, can start in any corner // assume clockwise numbering if (x>0 && y==0) { // starting in lower right side=3; } else if (x==0 && y>0) { // starting in upper left side=1; } } size_t NodeCount=GetNodeCount(); for(size_t n=0; n<NodeCount; n++) { Nodes[n]->ActChan=chan; chan+=ChanIncr; size_t CoordCount=GetCoordCount(n); for(size_t c=0; c < CoordCount; c++) { Nodes[n]->Coords[c].bufX=x; Nodes[n]->Coords[c].bufY=y; newx=x+xincr[side]*dir; newy=y+yincr[side]*dir; if (newx < 0 || newx >= FrameWidth || newy < 0 || newy >= parm2) { // move to the next side side=(side+SideIncr) % 4; newx=x+xincr[side]*dir; newy=y+yincr[side]*dir; } x=newx; y=newy; } } }