void StrokeSelection::changeColorStyle(int styleIndex) { TTool *tool = TTool::getApplication()->getCurrentTool()->getTool(); if (!tool) return; TVectorImageP img(tool->getImage(true)); if (!img) return; TPalette *palette = img->getPalette(); TColorStyle *cs = palette->getStyle(styleIndex); if (!cs->isStrokeStyle()) return; if (m_indexes.empty()) return; UndoSetStrokeStyle *undo = new UndoSetStrokeStyle(img, styleIndex); std::set<int>::iterator it; for (it = m_indexes.begin(); it != m_indexes.end(); ++it) { int index = *it; assert(0 <= index && index < (int)img->getStrokeCount()); TStroke *stroke = img->getStroke(index); undo->addStroke(stroke); stroke->setStyle(styleIndex); } tool->notifyImageChanged(); TUndoManager::manager()->add(undo); }
void ControlPointEditorStroke::setLinearSpeedOut(int index, bool linear, bool updatePoints) { TStroke *stroke = getStroke(); if (!stroke || m_controlPoints.size() == 1) return; int cpCount = stroke->getControlPointCount(); int pointIndex = m_controlPoints[index].m_pointIndex; if (pointIndex == cpCount - 1) { if (isSelfLoop()) pointIndex = 0; else return; } int nextIndex = (index == m_controlPoints.size() - 1 && isSelfLoop()) ? 0 : index + 1; TThickPoint point = stroke->getControlPoint(pointIndex); TThickPoint nextPoint = (pointIndex < cpCount - 3) ? stroke->getControlPoint(pointIndex + 3) : TThickPoint(); if (linear) { TThickPoint p(nextPoint - point); double n = norm(p); TThickPoint speedOut = (n != 0.0) ? (0.01 / n) * p : TThickPoint(0.001, 0.001, 0.0); m_controlPoints[index].m_speedOut = speedOut; } else { TThickPoint newNext2 = (nextPoint + point) * 0.5; TThickPoint speedOut = (newNext2 - point) * 0.5; m_controlPoints[index].m_speedOut = speedOut; } if (updatePoints) updateDependentPoint(index); }
void ControlPointEditorStroke::setLinearSpeedIn(int index, bool linear, bool updatePoints) { TStroke *stroke = getStroke(); if (!stroke || m_controlPoints.size() == 1) return; int pointIndex = m_controlPoints[index].m_pointIndex; if (pointIndex == 0) { if (isSelfLoop()) pointIndex = stroke->getControlPointCount() - 1; else return; } int precIndex = (index == 0 && isSelfLoop()) ? m_controlPoints.size() - 1 : index - 1; TThickPoint point = stroke->getControlPoint(pointIndex); TThickPoint precPoint = (pointIndex > 2) ? stroke->getControlPoint(pointIndex - 3) : TThickPoint(); if (linear) { TThickPoint p(point - precPoint); double n = norm(p); TThickPoint speedIn = (n != 0.0) ? (0.01 / n) * p : TThickPoint(0.001, 0.001, 0.0); m_controlPoints[index].m_speedIn = speedIn; } else { TThickPoint newPrec2 = (precPoint + point) * 0.5; TThickPoint speedIn = (point - newPrec2) * 0.5; m_controlPoints[index].m_speedIn = speedIn; } if (updatePoints) updateDependentPoint(index); }
TThickPoint ControlPointEditorStroke::getSpeedOutPoint(int index) const { TStroke *stroke = getStroke(); assert(stroke && 0 <= index && index < (int)m_controlPoints.size()); ControlPoint cp = m_controlPoints[index]; return stroke->getControlPoint(cp.m_pointIndex) + cp.m_speedOut; }
void ControlPointEditorStroke::updatePoints() { TStroke *stroke = getStroke(); if (!stroke) return; bool selfLoop = isSelfLoop(); // Se e' rimasto un unico punto non ha senso che la stroke sia selfloop if (selfLoop && m_controlPoints.size() == 1) { stroke->setSelfLoop(false); selfLoop = false; } // Se e' self loop devo aggiungere un punto in piu' al cpCount std::vector<TThickPoint> points; int cpCount = selfLoop ? m_controlPoints.size() + 1 : m_controlPoints.size(); if (cpCount == 1) // Single point case points.resize(3, getControlPoint(0)); else { std::vector<std::pair<int, TThickPoint>> dependentPoints; points.push_back(getControlPoint(0)); points.push_back(getSpeedOutPoint(0)); int i, pointIndex, currPointIndex = m_controlPoints[0].m_pointIndex + 1; for (i = 1; i < cpCount; ++i) { bool isLastSelfLoopPoint = (selfLoop && i == cpCount - 1); int index = isLastSelfLoopPoint ? 0 : i; TThickPoint p = getControlPoint(index); pointIndex = isLastSelfLoopPoint ? getStroke()->getControlPointCount() : m_controlPoints[index].m_pointIndex; dependentPoints.clear(); getDependentPoints(index, dependentPoints); int j; for (j = 0; j < (int)dependentPoints.size() && dependentPoints[j].first < pointIndex; j++) { if (currPointIndex < dependentPoints[j].first) { currPointIndex = dependentPoints[j].first; points.push_back(dependentPoints[j].second); } } points.push_back(p); for (; j < (int)dependentPoints.size(); j++) { if (currPointIndex < dependentPoints[j].first) { currPointIndex = dependentPoints[j].first; points.push_back(dependentPoints[j].second); } } } } stroke->reshape(&points[0], points.size()); m_vi->notifyChangedStrokes(m_strokeIndex); }
/*-- (StylePickerTool内で)LineとAreaを切り替えてPickできる。mode: 0=Area, 1=Line, 2=Line&Areas(default) --*/ int StylePicker::pickStyleId(const TPointD &pos, double radius2, int mode) const { int styleId = 0; if (TToonzImageP ti = m_image) { TRasterCM32P ras = ti->getRaster(); TPoint point = getRasterPoint(pos); if (!ras->getBounds().contains(point)) return -1; TPixelCM32 col = ras->pixels(point.y)[point.x]; switch (mode) { case 0: //AREAS styleId = col.getPaint(); break; case 1: //LINES styleId = col.getInk(); break; case 2: //ALL (Line & Area) default: styleId = col.isPurePaint() ? col.getPaint() : col.getInk(); break; } } else if (TRasterImageP ri = m_image) { const TPalette *palette = m_palette.getPointer(); if (!palette) return -1; TRaster32P ras = ri->getRaster(); if (!ras) return -1; TPoint point = getRasterPoint(pos); if (!ras->getBounds().contains(point)) return -1; TPixel32 col = ras->pixels(point.y)[point.x]; styleId = palette->getClosestStyle(col); } else if (TVectorImageP vi = m_image) { // prima cerca lo stile della regione piu' vicina TRegion *r = vi->getRegion(pos); if (r) styleId = r->getStyle(); // poi cerca quello della stroke, ma se prima aveva trovato una regione, richiede che // il click sia proprio sopra la stroke, altrimenti cerca la stroke piu' vicina (max circa 10 pixel) const double maxDist2 = (styleId == 0) ? 100.0 * radius2 : 0; bool strokeFound; double dist2, w, thick; UINT index; //!funzionerebbe ancora meglio con un getNearestStroke che considera //la thickness, cioe' la min distance dalla outline e non dalla centerLine strokeFound = vi->getNearestStroke(pos, w, index, dist2); if (strokeFound) { TStroke *stroke = vi->getStroke(index); thick = stroke->getThickPoint(w).thick; if (dist2 - thick * thick < maxDist2) { assert(stroke); styleId = stroke->getStyle(); } } } return styleId; }
bool TRegion::Imp::contains(const TStroke &s, bool mayIntersect) const { if (!getBBox().contains(s.getBBox())) return false; if (mayIntersect && thereAreintersections(s)) return false; return contains(s.getThickPoint(0.5)); }
double TStrokeBenderDeformation::getDelta(const TStroke &s, double w) const { double totalLenght = s.getLength(); if (totalLenght != 0) { double val = s.getLength(w) / totalLenght * (M_PI * 10.0); return sin(val); } return 0; }
bool PinchTool::moveCursor(const TPointD &pos) { double w = 0.0; TStroke *stroke = getClosestStroke(pos, w); if (!stroke) return false; m_cursor = stroke->getThickPoint(w); return true; }
TRect TRasterImageUtils::addStroke(const TRasterImageP &ri, TStroke *stroke, TRectD clip, double opacity, bool doAntialiasing) { TStroke *s = new TStroke(*stroke); TPoint riCenter = ri->getRaster()->getCenter(); s->transform(TTranslation(riCenter.x, riCenter.y)); TRect rect = fastAddInkStroke(ri, s, clip, opacity, doAntialiasing); rect -= riCenter; delete s; return rect; }
void ControlPointEditorStroke::moveSegment(int beforeIndex, int nextIndex, const TPointD &delta, const TPointD &pos) { TStroke *stroke = getStroke(); if (!stroke) return; int cpCount = getControlPointCount(); // Verifiche per il caso in cui lo stroke e' selfLoop if (isSelfLoop() && beforeIndex == 0 && nextIndex == cpCount - 1) std::swap(beforeIndex, nextIndex); int beforePointIndex = m_controlPoints[beforeIndex].m_pointIndex; int nextPointIndex = (isSelfLoop() && nextIndex == 0) ? stroke->getControlPointCount() - 1 : m_controlPoints[nextIndex].m_pointIndex; double w = stroke->getW(pos); double w0 = stroke->getParameterAtControlPoint(beforePointIndex); double w4 = stroke->getParameterAtControlPoint(nextPointIndex); if (w0 > w) return; assert(w0 <= w && w <= w4); double t = 1; double s = 1; if (isSpeedOutLinear(beforeIndex)) { m_controlPoints[beforeIndex].m_speedOut = (stroke->getControlPoint(nextPointIndex) - stroke->getControlPoint(beforePointIndex)) * 0.3; if (!isSpeedInLinear(beforeIndex)) m_controlPoints[beforeIndex].m_isCusp = true; } else if (!isSpeedOutLinear(beforeIndex) && !isSpeedInLinear(beforeIndex) && !isCusp(beforeIndex)) { t = 1 - fabs(w - w0) / fabs(w4 - w0); moveSingleControlPoint(beforeIndex, t * delta); t = 1 - t; } if (isSpeedInLinear(nextIndex)) { m_controlPoints[nextIndex].m_speedIn = (stroke->getControlPoint(nextPointIndex) - stroke->getControlPoint(beforePointIndex)) * 0.3; if (!isSpeedOutLinear(nextIndex)) m_controlPoints[nextIndex].m_isCusp = true; } else if (!isSpeedInLinear(nextIndex) && !isSpeedOutLinear(nextIndex) && !isCusp(nextIndex)) { s = 1 - fabs(w4 - w) / fabs(w4 - w0); moveSingleControlPoint(nextIndex, s * delta); s = 1 - s; } moveSpeedOut(beforeIndex, delta * s, 0); // updateDependentPoint(beforeIndex); moveSpeedIn(nextIndex, delta * t, 0); // updateDependentPoint(nextIndex); updatePoints(); }
bool PinchTool::keyDown(int key, TUINT32 flags, const TPoint &pos) { m_deformation->reset(); #if 0 char c = (char)key; if(c == 'p' || c == 'P' ) { TVectorImageP vimage(getImage()); if(!vimage) return false; char fileName[] = {"c:\\toonz_input.sdd"}; ofstream out_file(fileName); if(!out_file) { cerr<<"Error on opening: "<<fileName<<endl; return false; } out_file<<"# VImage info\n"; out_file<<"# Number of stroke:\n"; const int max_number_of_strokes = vimage->getStrokeCount(); out_file<<max_number_of_strokes<<endl; int number_of_strokes = 0; const int cp_for_row=3; while( number_of_strokes<max_number_of_strokes) { TStroke* ref = vimage->getStroke(number_of_strokes); out_file<<endl; out_file<<"# Number of control points for stroke:\n"; const int max_number_of_cp = ref->getControlPointCount(); out_file<<max_number_of_cp <<endl; out_file<<"# Control Points:\n"; int number_of_cp=0; while( number_of_cp<max_number_of_cp ) { out_file<<ref->getControlPoint(number_of_cp)<<" "; if(!((number_of_cp+1)%cp_for_row)) // add a new line after ten points out_file<<endl; number_of_cp++; } out_file<<endl; number_of_strokes++; } } #endif return true; }
void ControlPointEditorStroke::updateDependentPoint(int index) { TStroke *stroke = getStroke(); if (!stroke) return; std::vector<std::pair<int, TThickPoint>> points; getDependentPoints(index, points); int i; for (i = 0; i < (int)points.size(); i++) stroke->setControlPoint(points[i].first, points[i].second); m_vi->notifyChangedStrokes(m_strokeIndex); }
double TStrokePointDeformation::getDelta(const TStroke &stroke, double w) const { // reference to a thickpoint TThickPoint thickPnt = m_imp->m_vect ? stroke.getControlPointAtParameter(w) : stroke.getThickPoint(w); assert(thickPnt != TConsts::natp); TPointD pntOfStroke = convert(thickPnt); double d = tdistance(pntOfStroke, m_imp->m_circleCenter); return m_imp->m_potential->gradient(d); }
TThickPoint TStrokeThicknessDeformation::getDisplacement(const TStroke &stroke, double w) const { // potenziale exp^(-x^2) limitato tra // [-c_maxLenghtOfGaussian,c_maxLenghtOfGaussian] double diff = stroke.getLength(w); diff = diff - m_startParameter; if (fabs(diff) <= m_lengthOfDeformation) { // modulo il vettore spostamento in funzione del potenziale // il termine (1.0/m_lengthOfDeformation) * 3 scala // il punto in diff su un sistema di coordinate // normalizzato, associato con la curva exp^(-x^2) diff *= (1.0 / m_lengthOfDeformation) * c_maxLenghtOfGaussian; if (m_vect) return gaussianPotential(diff) * TThickPoint(*m_vect, 0); else { double outVal = gaussianPotential(diff); return TThickPoint(0, 0, outVal); } } return TThickPoint(); }
//----------------------------------------------------------------------------- TThickPoint TStrokeThicknessDeformation::getDisplacementForControlPoint( const TStroke &stroke, UINT n) const { // potenziale exp^(-x^2) limitato tra // [-c_maxLenghtOfGaussian,c_maxLenghtOfGaussian] double diff = stroke.getLengthAtControlPoint(n); diff = diff - m_startParameter; if (fabs(diff) <= m_lengthOfDeformation) { // modulo il vettore spostamento in funzione del potenziale // il termine (1.0/m_lengthOfDeformation) * 3 scala // il punto in diff su un sistema di coordinate // normalizzato, associato con la curva exp^(-x^2) diff *= (1.0 / m_lengthOfDeformation) * c_maxLenghtOfGaussian; TThickPoint delta; if (m_vect) { // tsign(m_vect->y) * 0.1 delta = TThickPoint(0, 0, m_versus * norm(*m_vect) * gaussianPotential(diff)); } else { double outVal = gaussianPotential(diff); delta = TThickPoint(0, 0, outVal); } // TThickPoint cp = stroke.getControlPoint(n); // if(cp.thick + delta.thick<0.001) delta.thick = 0.001-cp.thick; return delta; } return TThickPoint(); }
void ControlPointEditorStroke::setStroke(const TVectorImageP &vi, int strokeIndex) { m_strokeIndex = strokeIndex; m_vi = vi; if (!vi || strokeIndex == -1) { m_controlPoints.clear(); return; } TStroke *stroke = getStroke(); const TThickQuadratic *chunk = stroke->getChunk(0); if (stroke->getControlPointCount() == 3 && chunk->getP0() == chunk->getP1() && chunk->getP0() == chunk->getP2()) { resetControlPoints(); return; } adjustChunkParity(); resetControlPoints(); }
bool SelfLoopDeformation::check(Context *dragger, DraggerStatus *status) { assert(status && dragger && "Not dragger or status available"); assert(!"SelfLoopDeformation::check not yet implemented!"); // lengthOfAction_ = status->lengthOfAction_; // deformerSensibility_ = status->deformerSensibility_; // stroke2move_ = status->stroke2change_; TStroke *s = stroke2move_; // double &w = status->w_; if (s->isSelfLoop()) { // dragger->changeDeformation(SelfLoopDeformation::instance()); // SelfLoopDeformation::instance()->activate(dragger, // status); return true; } return false; }
void ControlPointEditorStroke::getDependentPoints( int index, std::vector<std::pair<int, TThickPoint>> &points) const { TStroke *stroke = getStroke(); if (!stroke) return; int cpCount = m_controlPoints.size(); if (index == cpCount && isSelfLoop()) // strange, but was treated... index = 0; if (index == 0 && cpCount == 1) { // Single point case TStroke *stroke = getStroke(); TThickPoint pos(stroke->getControlPoint(m_controlPoints[0].m_pointIndex)); points.push_back(std::make_pair(1, pos)); points.push_back(std::make_pair(2, pos)); return; } int prev = prevIndex(index); if (prev >= 0) { int prevPointIndex = m_controlPoints[prev].m_pointIndex; if (isSpeedOutLinear(prev)) points.push_back( std::make_pair(prevPointIndex + 1, getSpeedOutPoint(prev))); points.push_back( std::make_pair(prevPointIndex + 2, getPureDependentPoint(prev))); points.push_back( std::make_pair(prevPointIndex + 3, getSpeedInPoint(index))); } int next = nextIndex(index); if (next >= 0) { int pointIndex = m_controlPoints[index].m_pointIndex; points.push_back(std::make_pair(pointIndex + 1, getSpeedOutPoint(index))); points.push_back( std::make_pair(pointIndex + 2, getPureDependentPoint(index))); if (isSpeedInLinear(next)) points.push_back(std::make_pair(pointIndex + 3, getSpeedInPoint(next))); } }
double ToonzExt::StrokeParametricDeformer::getDelta(const TStroke &stroke, double w) const { #if 0 double w0 = w; if(w0 == 1.0) return norm( stroke.getSpeed(1.0)); double tmp = stroke.getLength(w0); tmp+=1.0; double w1 = stroke.getParameterAtLength(tmp); /* double w1 = w + 0.01; if(w1>1.0) { w0 = 1.0 - 0.01; w1 = 1.0; } */ const double dx = 1.0; //stroke.getLength(w0,w1); TThickPoint pnt = this->getDisplacement(stroke,w1) - this->getDisplacement(stroke,w0); double dy = sqrt( sq(pnt.x) + sq(pnt.y) + sq(pnt.thick) ); assert(dx!=0.0); return dy/dx; /* // the increaser is wrong than this value need to be the deformation // value // is norm TThickPoint pnt = this->getDisplacement(stroke, w); return sqrt( sq(pnt.x) + sq(pnt.y) + sq(pnt.thick) ); //return pot_->gradient(w); */ #endif return this->getDisplacement(stroke, w).y; }
TThickPoint TStrokePointDeformation::getDisplacement(const TStroke &stroke, double w) const { // riferimento ad un punto ciccione della stroke TThickPoint thickPnt = m_imp->m_vect ? stroke.getControlPointAtParameter(w) : stroke.getThickPoint(w); assert(thickPnt != TConsts::natp); TPointD pntOfStroke(convert(thickPnt)); double d = tdistance(pntOfStroke, m_imp->m_circleCenter); if (m_imp->m_vect) return m_imp->m_potential->value(d) * TThickPoint(*m_imp->m_vect, 0); else { double outVal = m_imp->m_potential->value(d); return TThickPoint(outVal, outVal, 0); } }
void renormalizeImage(TVectorImage *vi) { int i, j; int n = vi->getStrokeCount(); std::vector<ControlPoint> points; points.reserve(n * 2); for (i = 0; i < n; i++) { TStroke *stroke = vi->getStroke(i); int m = stroke->getControlPointCount(); if (m > 0) { if (m == 1) points.push_back(ControlPoint(stroke, 0)); else { points.push_back(ControlPoint(stroke, 0)); points.push_back(ControlPoint(stroke, m - 1)); } } } int count = points.size(); for (i = 0; i < count; i++) { ControlPoint &pi = points[i]; TPointD posi = pi.getPoint(); TPointD center = posi; std::vector<int> neighbours; neighbours.push_back(i); for (j = i + 1; j < count; j++) { TPointD posj = points[j].getPoint(); double d = tdistance(posj, posi); if (d < 0.01) { neighbours.push_back(j); center += posj; } } int m = neighbours.size(); if (m == 1) continue; center = center * (1.0 / m); for (j = 0; j < m; j++) points[neighbours[j]].setPoint(center); } }
TThickPoint TStrokeTwirlDeformation::getDisplacement(const TStroke &stroke, double s) const { double outVal = 0; double distance2 = tdistance2(convert(stroke.getControlPointAtParameter(s)), m_center); if (distance2 <= m_innerRadius2) outVal = wyvillPotential(distance2, m_innerRadius2); return TThickPoint(m_vectorOfMovement * outVal, 0); }
TThickPoint ControlPointEditorStroke::getPureDependentPoint(int index) const { TStroke *stroke = getStroke(); if (!stroke) return TThickPoint(); bool selfLoop = isSelfLoop(); int cpCount = selfLoop ? m_controlPoints.size() + 1 : m_controlPoints.size(); int nextIndex = (selfLoop && index == cpCount - 2) ? 0 : index + 1; int pointIndex = m_controlPoints[index].m_pointIndex; TThickPoint oldP(stroke->getControlPoint(pointIndex + 2)); TPointD oldSpeedOutP = stroke->getControlPoint(pointIndex + 1); TPointD oldSpeedInP = stroke->getControlPoint(pointIndex + 3); double dist = tdistance(oldSpeedOutP, oldSpeedInP); double t = (dist > 1e-4) ? tdistance(oldSpeedInP, convert(oldP)) / dist : 0.5; TPointD speedOutPoint(getSpeedOutPoint(index)); TPointD nextSpeedInPoint(getSpeedInPoint(nextIndex)); return TThickPoint((1 - t) * nextSpeedInPoint + t * speedOutPoint, oldP.thick); // return TThickPoint(0.5 * (speedOutPoint + nextSpeedInPoint), oldThick); }
TThickPoint TStrokePointDeformation::getDisplacementForControlPoint( const TStroke &stroke, UINT n) const { // riferimento ad un punto ciccione della stroke TPointD pntOfStroke(convert(stroke.getControlPoint(n))); double d = tdistance(pntOfStroke, m_imp->m_circleCenter); if (m_imp->m_vect) return m_imp->m_potential->value(d) * TThickPoint(*m_imp->m_vect, 0); else { double outVal = m_imp->m_potential->value(d); return TThickPoint(outVal, outVal, 0); } }
void TColorStyle::drawStroke(TFlash &flash, const TStroke *s) const { bool isCenterline = false; double minThickness, maxThickness = 0; std::wstring quality = flash.getLineQuality(); double thickness = computeAverageThickness(s, minThickness, maxThickness); if (minThickness == maxThickness && minThickness == 0) return; if (quality == TFlash::ConstantLines) isCenterline = true; else if (quality == TFlash::MixedLines && (maxThickness == 0 || minThickness / maxThickness > 0.5)) isCenterline = true; else if (quality == TFlash::VariableLines && maxThickness - minThickness < 0.16) // Quando si salva il pli, si approssima al thick. // L'errore di approx e' sempre 0.1568... isCenterline = true; // else assert(false); flash.setFillColor(getAverageColor()); // flash.setFillColor(TPixel::Red); TStroke *saux = const_cast<TStroke *>(s); if (isCenterline) { saux->setAverageThickness(thickness); flash.setThickness(s->getAverageThickness()); flash.setLineColor(getAverageColor()); flash.drawCenterline(s, false); } else { saux->setAverageThickness(0); if (!flash.drawOutline(saux)) { flash.setThickness(thickness); flash.setLineColor(getAverageColor()); flash.drawCenterline(s, false); } } }
void ControlPointEditorStroke::deleteControlPoint(int index) { TStroke *stroke = getStroke(); if (!stroke) return; assert(stroke && 0 <= index && index < (int)getControlPointCount()); // E' un unico chunk e in questo caso rappresenta un punto if (stroke->getControlPointCount() <= 3 || (isSelfLoop() && stroke->getControlPointCount() <= 5)) { m_controlPoints.clear(); m_vi->deleteStroke(m_strokeIndex); return; } QList<int> newPointsIndex; int i; for (i = 0; i < (int)getControlPointCount() - 1; i++) newPointsIndex.push_back(m_controlPoints[i].m_pointIndex); m_controlPoints.removeAt(index); updatePoints(); // Aggiorno gli indici dei punti nella stroke assert((int)newPointsIndex.size() == (int)getControlPointCount()); for (i = 0; i < (int)getControlPointCount(); i++) m_controlPoints[i].m_pointIndex = newPointsIndex.at(i); int prev = prevIndex(index); if (prev >= 0 && isSpeedOutLinear(prev)) { setLinearSpeedOut(prev); updateDependentPoint(prev); } if (index < (int)m_controlPoints.size() && isSpeedInLinear(index)) { setLinearSpeedIn(index); updateDependentPoint(index); } }
double TStrokeParamDeformation::getDelta(const TStroke &stroke, double w) const { // potenziale exp^(-x^2) limitato tra // [-c_maxLenghtOfGaussian,c_maxLenghtOfGaussian] double diff = stroke.getLength(w); diff = diff - m_startParameter; if (fabs(diff) <= m_lengthOfDeformation) { // modulo il vettore spostamento in funzione del potenziale // il termine (1.0/m_lengthOfDeformation) * 3 scala // il punto in diff su un sistema di coordinate // normalizzato, associato con la curva exp^(-x^2) diff *= (1.0 / m_lengthOfDeformation) * c_maxLenghtOfGaussian; return derivateOfGaussianPotential(diff); } return 0; }
void ControlPointEditorStroke::adjustChunkParity() { TStroke *stroke = getStroke(); if (!stroke) return; int firstChunk; int secondChunk = stroke->getChunkCount(); int i; for (i = stroke->getChunkCount() - 1; i > 0; i--) { if (tdistance(stroke->getChunk(i - 1)->getP0(), stroke->getChunk(i)->getP2()) < 0.5) continue; TPointD p0 = stroke->getChunk(i - 1)->getP1(); TPointD p1 = stroke->getChunk(i - 1)->getP2(); TPointD p2 = stroke->getChunk(i)->getP1(); if (isCuspPoint(p0, p1, p2) || isLinearPoint(p0, p1, p2)) { firstChunk = i; insertPoint(stroke, firstChunk, secondChunk); secondChunk = firstChunk; } } insertPoint(stroke, 0, secondChunk); }
void ControlPointEditorStroke::resetControlPoints() { TStroke *stroke = getStroke(); if (!stroke) return; m_controlPoints.clear(); int i; int cpCount = stroke->getControlPointCount(); if (cpCount == 3) { const TThickQuadratic *chunk = stroke->getChunk(0); if (chunk->getP0() == chunk->getP1() && chunk->getP0() == chunk->getP2()) // E' un punto { m_controlPoints.push_back( ControlPoint(0, TPointD(0.0, 0.0), TPointD(0.0, 0.0), true)); return; } } for (i = 0; i < cpCount; i = i + 4) { TThickPoint speedIn, speedOut; bool isPickOut = false; TThickPoint p = stroke->getControlPoint(i); TThickPoint precP = stroke->getControlPoint(i - 1); TThickPoint nextP = stroke->getControlPoint(i + 1); if (0 < i && i < cpCount - 1) // calcola speedIn e speedOut { speedIn = p - precP; speedOut = nextP - p; } if (i == 0) // calcola solo lo speedOut { speedOut = nextP - p; if (isSelfLoop()) speedIn = p - stroke->getControlPoint(cpCount - 2); } if (i == cpCount - 1) // calcola solo lo speedIn speedIn = p - precP; if (i == cpCount - 1 && isSelfLoop()) break; // Se lo stroke e' selfLoop inserisco solo il primo dei due punti // coincidenti bool isCusp = ((i != 0 && i != cpCount - 1) || (isSelfLoop() && i == 0)) ? isCuspPoint(precP, p, nextP) : true; m_controlPoints.push_back(ControlPoint(i, speedIn, speedOut, isCusp)); } }