/// /// DrawingCanvas::useWhiteInk() /// /// /// bool DrawingCanvas::useWhiteInk(Individual *pIndividual){ // // How many sections are there? // unsigned sections = pIndividual->getDataTable()->getIconColumnCount(); if(!sections){ return false; }else{ const DataTable * pDT = pIndividual->getDataTable(); // // Well, we are only going to look at the first section of the pie // even if there are multiple sections ... // DataColumn * pDC = pDT->getColumn( pDT->getIconColumnIndex(0) ); const UniqueList * pUL = pDC->getUniqueList(); // // Only process if there are some non-missing levels present: // if(!pUL->getLevels()){ return false; }else{ // // What is the level and label in the UniqueList corresponding to the data value // for this individual? // unsigned level; std::string label; pUL->getOrdinalAndLabelForKey( pDC->getDataAtIndex( pIndividual->getRowIndex() ),label,level ); // // UniqueList ordinals are 1-offset, so we should only get zero back // if the key was not found, which should never happen: // if(level==0) throw Exception("DrawingCanvas::useWhiteInk()","UniqueList returned ordinal 0."); // // Level is 1-offset, so subtract: // level--; // // Get the color series corresponding to this icon column: // ColorSeries *pCS; if(DrawingMetrics::getColor()){ pCS = pDT->getColorSeriesFromStack(0); }else{ pCS = pDT->getBlackAndWhiteSeriesFromStack(0); } if(pCS->useBlackInkAtLevel(level)){ return false; }else{ return true; } } } }
/// /// iconPie(): Draws a pie with a given color on the individual icon. Each pie corresponds to one /// categorical variable. The color corresponds to the level in that variable. /// void DrawingCanvas::iconPie( double x, double y, Individual *pIndividual ){ // // Handle virtual individuals: // if(pIndividual->isVirtual()){ //_body << "<circle cx=\"" << x << "\" cy=\"" << y << "\" r=\"" << 0.5*DrawingMetrics::getScalingFactor() << "\""; //_body << " class=\"thinLine\""; //_body << "/>\n"; return; } // // Get here if non-virtual: // // // How many sections are there? // unsigned sections = pIndividual->getDataTable()->getIconColumnCount(); if(!sections){ // // No affected fields : Draw a small circle in the middle: // (Nice for debugging -- otherwise comment out ) // //_body << "<circle cx=\"" << x << "\" cy=\"" << y << "\" r=\"" << 0.5*DrawingMetrics::getScalingFactor() << "\""; //_body << " class=\"thinLine\""; //_body << "/>\n"; return; } // // Setup clipping Id, if needed: // std::string clipId = pIndividual->getId().get() + "_clipPath"; double radius=DrawingMetrics::getIconRadius(); bool isMale = false; if( pIndividual->getGender().getEnum()==Gender::MALE ){ setClipPath(x,y,clipId); // // Increase radius for clipping: // radius*=Number::SQRT_TWO; isMale = true; _body << "<g clip-path=\"url(#" << clipId << ")\">\n"; }else{ // // Empty g with no clipping for female: // _body << "<g>\n"; } // // Iterate over _iconColumns: // const DataTable *pDT = pIndividual->getDataTable(); double arcAngle = 2.0*Number::PI/sections; double startAngle = 0.5*Number::PI - arcAngle; double endAngle = startAngle+arcAngle; for(unsigned i=0;i<sections;i++){ // // Get the data column of the ith icon column: // DataColumn * pDC = pDT->getColumn( pDT->getIconColumnIndex(i) ); // // Get the UniqueList for this column: // const UniqueList * pUL = pDC->getUniqueList(); // // Only process if there are some non-missing levels // present: // if(!pUL->getLevels()) continue; // // What is the level and label in the UniqueList corresponding to the data value // for this individual? // unsigned level; std::string label; pUL->getOrdinalAndLabelForKey( pDC->getDataAtIndex( pIndividual->getRowIndex() ),label,level ); // // UniqueList ordinals are 1-offset, so we should only get zero back // if the key was not found, which should never happen: // if(level==0) throw Exception("DrawingCanvas::iconPie()","UniqueList returned ordinal 0."); // // Level is 1-offset, so subtract: // level--; // // Get the color series corresponding to this icon column: // // NOTA BENE: (1) IF there is only one section, we use the // blackAndWhite series // UNLESS there is a color override. // // (2) OTHERWISE if there are more than one section, // we use the color series // UNLESS there is a black-and-white override. // ColorSeries *pCS; if(sections==1){ if(DrawingMetrics::getColor()) pCS = pDT->getColorSeriesFromStack(i); else pCS = pDT->getBlackAndWhiteSeriesFromStack(i); }else{ if(DrawingMetrics::getBlackAndWhite()) pCS = pDT->getBlackAndWhiteSeriesFromStack(i); else pCS = pDT->getColorSeriesFromStack(i); } // // Assume reversed for now: // bool reversed=true; std::string arcClass="blackInkLetter"; if(!pCS->reversedSeriesUseBlackInkAtLevel(level)) arcClass="whiteInkLetter"; // // If the number of sections is small, use a larger font size // if(sections == 1) arcClass += "_1"; else if(sections == 2) arcClass += "_2"; else if(sections == 3) arcClass += "_3"; arc(x,y,radius,startAngle,endAngle,(reversed?pCS->reversedSeriesGetColorAtLevel(level):pCS->getColorAtLevel(level)),label,arcClass,isMale); startAngle+=arcAngle; endAngle+=arcAngle; // For the first time draw the icon legend too: if(!_iconLegendFlag){ _iconLegendFlag = true; _iconLegend.setPedigreeTable(pDT); } } _body << "</g>\n"; return; }
/// /// iconQuadrantFill(): Shade quadrants of the icon to indicate specific levels. /// This method has a limit of 16 distinct levels. /// void DrawingCanvas::iconQuadrantFill( double x, double y, Individual *pIndividual ){ // // Handle virtual individuals: // if(pIndividual->isVirtual()){ return; } // // Get here if non-virtual: // // // How many sections are there? // unsigned sections = pIndividual->getDataTable()->getIconColumnCount(); if(!sections){ // // No affected fields : Draw a small circle in the middle: // (Nice for debugging -- otherwise comment out ) // //_body << "<circle cx=\"" << x << "\" cy=\"" << y << "\" r=\"" << 0.5*DrawingMetrics::getScalingFactor() << "\""; //_body << " class=\"thinLine\""; //_body << "/>\n"; return; } // // Setup clipping Id, if needed: // double radius=DrawingMetrics::getIconRadius(); bool isMale = false; if( pIndividual->getGender().getEnum()==Gender::MALE ){ std::string clipId = pIndividual->getId().get() + "_clipPath"; setClipPath(x,y,clipId); // // Increase radius for clipping: // radius*=Number::SQRT_TWO; isMale = true; _body << "<g clip-path=\"url(#" << clipId << ")\">\n"; }else{ // // Empty g with no clipping for female: // _body << "<g>\n"; } // // NOTA BENE: The quadrant fill method looks only at the // FIRST iconColumn and ignores any additional icon columns: // const DataTable *pDT = pIndividual->getDataTable(); // // Get the data column of the first icon column: // DataColumn * pDC = pDT->getColumn( pDT->getIconColumnIndex(0) ); // // Get the UniqueList for this column: // const UniqueList * pUL = pDC->getUniqueList(); // // Only process if there are some non-missing levels // present: // if(!pUL->getLevels()){ _body << "</g>\n"; return; } // // What is the level and label in the UniqueList corresponding to the data value // for this individual? // //unsigned level; //std::string label; //pUL->getOrdinalAndLabelForKey( pDC->getDataAtIndex( pIndividual->getRowIndex() ),label,level ); // Data* data = pDC->getDataAtIndex( pIndividual->getRowIndex()); // // Draw a dot for missing values: // if(data->isMissing()){ drawText(x,y,".","blackInkLetter_1"); _body << "</g>\n"; return; } std::string label; std::string svalue = data->get(); std::istringstream i(svalue); int level; bool converted = (i>>level); if(!converted || level<0 || level>15 ){ // // (1) Unable to convert data string to integer, or // (2) integer value is out of range // double lineSpacing,xAdvance,yMinimum,yMaximum; _lasiWrapper.getDimensions(svalue,&lineSpacing,&xAdvance,&yMinimum,&yMaximum); y+= 0.5*(yMaximum-yMinimum); drawIconText(x,y,svalue,"blackInkLetter_1"); _body << "</g>\n"; return; } // // Fill arc for each quadrant based on level: // Note: Madeline's "arc()" method doesn't use the standard counter-clockwise quadrants // starting at 0, so the order of the 4 "if" statements below may appear mixed up but // this actually results in shading of the quadrants according to standard notation: // if(level & 0x02 ){ arc(x,y,radius,0,0.5*Number::PI,"#000",label,"whiteInkLetter",isMale); } if(level & 0x01 ){ arc(x,y,radius,0.5*Number::PI,Number::PI,"#000",label,"whiteInkLetter",isMale); } if(level & 0x08 ){ arc(x,y,radius,Number::PI,1.5*Number::PI,"#000",label,"whiteInkLetter",isMale); } if(level & 0x04 ){ arc(x,y,radius,1.5*Number::PI,2.0*Number::PI,"#000",label,"whiteInkLetter",isMale); } // // For the first time draw the icon legend too: // //if(!_iconLegendFlag){ // _iconLegendFlag = true; // _iconLegend.setPedigreeTable(pDT); //} _body << "</g>\n"; return; }