void CurveNode::calcBoundingBoxes() { m_AABBs.clear(); // Lowest level: Generate from curve points. m_AABBs.push_back(CurveAABBVectorPtr(new CurveAABBVector())); CurveAABBVectorPtr pCurAABBs = m_AABBs.back(); pCurAABBs->reserve(m_CenterCurve.size()/8); glm::vec2 stroke(getStrokeWidth()/2, getStrokeWidth()/2); for (unsigned i=0; i<=m_CenterCurve.size()/8; ++i) { int startIdx = i*8; int endIdx = min(i*8+7, unsigned(m_CenterCurve.size()-1)); const glm::vec2& curPt = m_CenterCurve[startIdx]; pCurAABBs->push_back(CurveAABB(curPt, startIdx, endIdx)); CurveAABB& curAABB = pCurAABBs->back(); for (int j=startIdx; j<=endIdx; j+=2) { curAABB.expand(m_CenterCurve[j]); } curAABB.tl -= stroke; curAABB.br += stroke; } // Higher levels: combine AABBs of lower levels. unsigned numSections = pCurAABBs->size(); unsigned level = 0; while (numSections > 1) { numSections = int(ceil(float(numSections)/2)); m_AABBs.push_back(CurveAABBVectorPtr(new CurveAABBVector())); CurveAABBVectorPtr pLastAABBs = m_AABBs[level]; pCurAABBs = m_AABBs.back(); pCurAABBs->reserve(numSections); for (unsigned i=0; i<numSections; ++i) { pCurAABBs->push_back(CurveAABB((*pLastAABBs)[i*2])); CurveAABB& curAABB = pCurAABBs->back(); if (i*2+1 < pLastAABBs->size()) { curAABB.expand((*pLastAABBs)[i*2+1]); } } level++; } /* for (unsigned i=0; i<m_AABBs.size(); ++i) { cerr << "Level: " << i << " (size: " << m_AABBs[i]->size() << ")" << endl; for (unsigned j=0; j<m_AABBs[i]->size(); ++j) { cerr << (*m_AABBs[i])[j] << " "; } cerr << endl; } */ }
const char *Circle::toXmlElement() { char *element = new char[MAX_SHAPE_LEN]; element[0] = '\0'; strcat(element, "<"); strcat(element, Circle::simpleClassName); strcat(element, " "); /* Write properties */ strcat(element, toPropertyValue("radius=\"", radius)); strcat(element, " "); strcat(element, toPropertyValue("cx=\"", cx)); strcat(element, " "); strcat(element, toPropertyValue("cy=\"", cy)); strcat(element, " "); strcat(element, toPropertyValue("stroke-width=\"", getStrokeWidth())); strcat(element, " "); strcat(element, toPropertyValue("stroke=\"", getStroke())); strcat(element, " "); strcat(element, toPropertyValue("fill=\"", getFill())); strcat(element, "/>"); return element; }
void CurveNode::addLRCurvePoint(const glm::vec2& pos, const glm::vec2& deriv) { glm::vec2 m = glm::normalize(deriv); glm::vec2 w = glm::vec2(m.y, -m.x)*float(getStrokeWidth()/2); m_LeftCurve.push_back(pos-w); m_RightCurve.push_back(pos+w); }
bool CurveNode::isInsideBB(const glm::vec2& pos, unsigned level, unsigned i) { if ((*m_AABBs[level])[i].contains(pos)) { if (level == 0) { // Check individual points const CurveAABB& aabb = (*m_AABBs[level])[i]; for (int i=aabb.m_StartIdx; i<=aabb.m_EndIdx; ++i) { if (glm::distance(m_CenterCurve[i], pos) < getStrokeWidth()/2) { return true; } } return false; } else { // Recurse to smaller bounding boxes. if (i*2+1 < m_AABBs[level-1]->size()) { return isInsideBB(pos, level-1, i*2) || isInsideBB(pos, level-1, i*2+1); } else { return isInsideBB(pos, level-1, i*2); } } } else { return false; } }
std::string CQIllustratorShape:: getSVGStroke() const { std::string str = "style=\""; const CQIllustratorShapeStroke &stroke = getStroke(); const CRGBA &scolor = stroke.getColor(); double sopacity = stroke.getOpacity(); double width = getStrokeWidth(); const CLineDash &dash = stroke.getLineDash(); CLineCapType cap = stroke.getLineCap(); CLineJoinType join = stroke.getLineJoin(); if (sopacity > 0.0) { str += CStrUtil::strprintf("stroke: rgb(%d,%d,%d);", scolor.getRedI(), scolor.getGreenI(), scolor.getBlueI()); if (sopacity < 1.0) str += CStrUtil::strprintf(" stroke-opacity: %g;", sopacity); } else str += "stroke: none;"; if (width != 1.0) str += CStrUtil::strprintf(" stroke-width: %g;", width); if (! dash.isSolid()) str += CStrUtil::strprintf("stroke-dasharray: %s", dash.toString().c_str()); if (cap == LINE_CAP_TYPE_ROUND) str += CStrUtil::strprintf(" stroke-linecap: round;"); else if (cap == LINE_CAP_TYPE_SQUARE) str += CStrUtil::strprintf(" stroke-linecap: square;"); if (join == LINE_JOIN_TYPE_ROUND) str += CStrUtil::strprintf(" stroke-linejoin: round;"); else if (join == LINE_JOIN_TYPE_BEVEL) str += CStrUtil::strprintf(" stroke-linejoin: bevel;"); const CQIllustratorShapeFill &fill = getFill(); if (fill.hasGradient()) { // TODO } else { const CRGBA &fcolor = fill.getColor(); double fopacity = fill.getOpacity(); if (fopacity > 0.0) { str += CStrUtil::strprintf(" fill: rgb(%d,%d,%d);", fcolor.getRedI(), fcolor.getGreenI(), fcolor.getBlueI()); if (fopacity < 1.0) str += CStrUtil::strprintf(" fill-opacity: %g;", fopacity); } else str += "fill: none;"; } str += "\""; return str; }
void Circle::print() { std::cout << "circle " << cx << " " << cy << " " << getFill() << " " << getStroke() << " " << getStrokeWidth() << '\n'; }
void LineNode::calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color) { pVertexData->addLineData(color, m_P1, m_P2, getStrokeWidth(), m_TC1, m_TC2); }