vector<Formula*>& SubSupParser::rec_findSubSup(vector<Formula*>& allSymbols, vector<Formula*>& mainSymbols, vector<Formula*>& otherSymbols, unsigned int currentMainIndex, double formulaMidline) { unsigned int& i = currentMainIndex; if (i >= mainSymbols.size()) { return *(new vector<Formula*>()); } Formula* currentMain = mainSymbols.at(i); Formula* subscript = NULL; Formula* superscript = NULL; bool subformulaFound = true; while (subformulaFound && !otherSymbols.empty()) { Formula* currentOther = otherSymbols.at(0); //se alcuni simboli vengono classificati come apice/pedice, vengono rimossi dal vettore. Per questo motivo il simbolo "corrente" è sempre il primo int currentLeftLimit = currentMain->left(); int currentRightLimit = (i == mainSymbols.size() - 1) ? maxRightLimit : mainSymbols.at(i + 1)->left() - 1; bool currentOtherBetweenLimits = (currentLeftLimit <= currentOther->left() && currentOther->right() <= currentRightLimit); /* è possibile che il simbolo corrente sia un apice/pedice SE è completamente contenuto nell'intervallo (orizzontale) definito * dall'estremo sinistro del simbolo corrente fino all'estremo sinistro (escluso) del prossimo simbolo. Si prende l'estremo sinistro * e non il destro perché in questo modo si è sicuri che non ci sono "buchi" in cui * si può trovare un simbolo non principale: in alcuni casi, e.g. il simbolo di integrale, è necessario che il limite sia quello sinistro. */ double currentMainMidline = currentMain->center().getY(); bool aboveMidline = currentOther->center().getY() <= currentMainMidline; bool belowMidline = currentOther->center().getY() >= currentMainMidline; bool crossedByMidline = !aboveMidline && !belowMidline; if (currentOtherBetweenLimits) { if (!crossedByMidline && !Blacklist::inSubSupBlacklist(currentMain)) { if (belowMidline) { //pedice findSubSup(&subscript, currentOther, allSymbols, mainSymbols, otherSymbols, i, false); } else if (aboveMidline) { //apice findSubSup(&superscript, currentOther, allSymbols, mainSymbols, otherSymbols, i, true); } subformulaFound = true; } else { mainSymbols.insert(mainSymbols.begin() + i + 1, currentOther); otherSymbols.erase(otherSymbols.begin()); subformulaFound = false; } } else { subformulaFound = false; } } SubSup* newSubformula = new SubSup(currentMain, subscript, superscript); vector<Formula*>& tmpFormula = rec_findSubSup(allSymbols, mainSymbols, otherSymbols, i + 1, formulaMidline); tmpFormula.insert(tmpFormula.begin(), newSubformula); return tmpFormula; }
void IteratorOpParser::findSubformulaeSymbols(vector<Formula*>& mainSymbols, vector<Formula*>& otherSymbols, unsigned int currentMainIndex, vector<Formula*>& underscriptSymbols, vector<Formula*>& overscriptSymbols, long currentRightLimit, long currentLeftLimit) { unsigned int& k = currentMainIndex; Formula* currentMainSymbol = mainSymbols.at(k); if (underscriptSymbols.empty() && overscriptSymbols.empty()) { // caso in cui non ci sono underscript e overscript ma (forse) apici e pedici long currentMainMidline = currentMainSymbol->center().getY(); unsigned int j = 0; bool beforeCurrentRightLimit = true; while (j < otherSymbols.size() && beforeCurrentRightLimit) { if (otherSymbols.at(j)->left() >= currentRightLimit) { beforeCurrentRightLimit = false; } else { Formula* oth = otherSymbols.at(j); bool crossedByMidline = oth->top() < currentMainMidline && currentMainMidline < oth->bottom(); if (crossedByMidline) { mainSymbols.insert(mainSymbols.begin() + k + 1, oth); otherSymbols.erase(otherSymbols.begin() + j); currentRightLimit = oth->left(); } j++; } } currentLeftLimit = currentMainSymbol->right(); underscriptSymbols = FormulaParserUtils::extractSymbolsWithinRange(otherSymbols, currentRightLimit, currentLeftLimit, maxBottomLimit, currentMainMidline, true); overscriptSymbols = FormulaParserUtils::extractSymbolsWithinRange(otherSymbols, currentRightLimit, currentLeftLimit, currentMainMidline, maxTopLimit, true); } else { // l'underscript e l'overscript, che al momento contengono solo simboli allineati verticalmente col main, vengono estesi underscriptSymbols = FormulaParserUtils::extractSymbolsWithinRange(otherSymbols, currentRightLimit, currentLeftLimit, maxBottomLimit, currentMainSymbol->bottom() + 1, true); overscriptSymbols = FormulaParserUtils::extractSymbolsWithinRange(otherSymbols, currentRightLimit, currentLeftLimit, currentMainSymbol->top() - 1, maxTopLimit, true); } }
void SubSupParser::findSubSup(Formula** subformulaToSet, Formula* currentOther, vector<Formula*>& allSymbols, vector<Formula*>& mainSymbols, vector<Formula*>& otherSymbols, unsigned int currentMainIndex, bool sup_notSub) { using namespace FormulaParserUtils; unsigned int& i = currentMainIndex; Formula* currentMain = mainSymbols.at(currentMainIndex); long mainVBar = currentMain->center().getY(); int currentLeftLimit = currentMain->left(); int currentRightLimit = (i == mainSymbols.size() - 1) ? maxRightLimit : mainSymbols.at(i + 1)->left() - 1; bool subformulaCondition; long subsup_bottomLimit, subsup_topLimit, context_bottomLimit, context_topLimit; if (sup_notSub) { //apice bool higherTop = currentOther->top() + currentOther->height() * SUP_MIN_FRACTION_ABOVE_MAIN < currentMain->top(); bool higherBar = getWeightedVBar(currentOther) < getWeightedVBar(currentMain) && currentOther->area() <= currentMain->area() * LOW_SUP_MAX_AREA; subformulaCondition = higherTop || higherBar; // /* un apice deve: // * - avere un bordo superiore "sufficientemente" più in alto del mainSymbol corrente, OPPURE // * - avere un baricentro più alto ed essere "sufficientemente" più piccolo del simbolo principale // * */ subsup_bottomLimit = mainVBar; subsup_topLimit = maxTopLimit; context_bottomLimit = maxBottomLimit; context_topLimit = mainVBar; } else { //pedice subformulaCondition = (currentOther->bottom() - currentOther->height() * SUB_MIN_FRACTION_BELOW_MAIN) > currentMain->bottom(); // // un pedice deve trovarsi "sufficientemente" più in basso del mainSymbol corrente subsup_bottomLimit = maxBottomLimit; subsup_topLimit = mainVBar; context_bottomLimit = mainVBar; context_topLimit = maxTopLimit; } if (!subformulaCondition) { /* Non vengono rispettate le condizioni date: l'apice/pedice è stato mal classificato. Viene allora aggiunto ai simboli principali ed eliminato * da quelli secondari. */ mainSymbols.insert(mainSymbols.begin() + i + 1, currentOther); otherSymbols.erase(otherSymbols.begin()); } else { otherSymbols.erase(otherSymbols.begin()); vector<Formula*> subsup = extractSymbolsInRange(otherSymbols, currentRightLimit, currentLeftLimit, subsup_bottomLimit, subsup_topLimit); subsup.insert(subsup.begin(), currentOther); /* Viene passato allSymbols e non otherSymbols perché gli elementi di otherSymbols vengono cancellati una volta classificati (quindi se classifico, * ad esempio, un pedice poi quei simboli non saranno più in otherSymbols e non verrebbero più trovati dalla funzione di estrazione, che quindi non * fornirebbe il contesto appropriato) */ vector<Formula*> context = extractSymbolsInRange(allSymbols, currentRightLimit, currentLeftLimit, context_bottomLimit, context_topLimit, false); fixBadClassification(mainSymbols, otherSymbols, subsup, context, i); *subformulaToSet = _parse(subsup, allSymbols); } }