void CAView::updateTransform() { // Recursively iterate over children if(m_pobImage && isDirty() ) { // If it is not visible, or one of its ancestors is not visible, then do nothing: if( !m_bVisible || ( m_pSuperview && m_pSuperview != m_pobBatchView && m_pSuperview->m_bShouldBeHidden) ) { m_sQuad.br.vertices = m_sQuad.tl.vertices = m_sQuad.tr.vertices = m_sQuad.bl.vertices = vertex3(0,0,0); m_bShouldBeHidden = true; } else { m_bShouldBeHidden = false; if( !m_pSuperview || m_pSuperview == m_pobBatchView) { m_transformToBatch = nodeToParentTransform(); } else { m_transformToBatch = CATransformationConcat( nodeToParentTransform() , m_pSuperview->m_transformToBatch ); } DSize size = m_obContentSize; float x1 = 0; float y1 = 0; float x = m_transformToBatch.tx; float y = m_transformToBatch.ty; float cr = m_transformToBatch.a; float sr = m_transformToBatch.b; float cr2 = m_transformToBatch.d; float sr2 = -m_transformToBatch.c; x1 = x1 * cr - y1 * sr2 + x; y1 = x1 * sr + y1 * cr2 + y; x1 = RENDER_IN_SUBPIXEL(x1); y1 = RENDER_IN_SUBPIXEL(y1); float x2 = x1 + size.width; float y2 = y1 + size.height; m_sQuad.bl.vertices = vertex3( x1, y1, m_fVertexZ ); m_sQuad.br.vertices = vertex3( x2, y1, m_fVertexZ ); m_sQuad.tl.vertices = vertex3( x1, y2, m_fVertexZ ); m_sQuad.tr.vertices = vertex3( x2, y2, m_fVertexZ ); } if (m_pobImageAtlas) { m_pobImageAtlas->updateQuad(&m_sQuad, m_uAtlasIndex); } m_bRecursiveDirty = false; setDirty(false); } if (!m_obSubviews.empty()) { CAVector<CAView*>::iterator itr; for (itr=m_obSubviews.begin(); itr!=m_obSubviews.end(); itr++) (*itr)->updateTransform(); } #if CC_SPRITE_DEBUG_DRAW // draw bounding box DPoint vertices[4] = { DPoint( m_sQuad.bl.vertices.x, m_sQuad.bl.vertices.y ), DPoint( m_sQuad.br.vertices.x, m_sQuad.br.vertices.y ), DPoint( m_sQuad.tr.vertices.x, m_sQuad.tr.vertices.y ), DPoint( m_sQuad.tl.vertices.x, m_sQuad.tl.vertices.y ), }; ccDrawPoly(vertices, 4, true); #endif }
double LayoutStatistics::angularResolution( const GraphAttributes &ga, double *pMaxAngle, double *pAvgAngle, double *pStdDeviation, bool considerBends) { const Graph &G = ga.constGraph(); double minAngle = 2*Math::pi, maxAngle = 0, sumAngles = 0; int numAngles = 0; ListPure<double> allAngles; for (node v : G.nodes) { double vx = ga.x(v), vy = ga.y(v); List<double> angles; for (adjEntry adj : v->adjEntries) { const DPolyline &dpl = ga.bends(adj->theEdge()); double ex, ey; if (dpl.empty()) { ex = ga.x(adj->twinNode()); ey = ga.y(adj->twinNode()); } else { ex = dpl.front().m_x; ey = dpl.front().m_y; } angles.pushBack(atan2(ex-vx, ey-vy)); } if (angles.size() < 2) continue; numAngles += angles.size(); angles.quicksort(); double lastAngle = angles.back(); for (double psi : angles) { double alpha = psi - lastAngle; if (pStdDeviation) allAngles.pushBack(alpha); sumAngles += alpha; minAngle = min(minAngle, alpha); maxAngle = max(maxAngle, alpha); lastAngle = psi; } } if (considerBends) { for (edge e : G.edges) { DPolyline dpl = ga.bends(e); dpl.pushFront( DPoint(ga.x(e->source()), ga.y(e->source())) ); dpl.pushBack ( DPoint(ga.x(e->target()), ga.y(e->target())) ); dpl.normalize(); if (dpl.size() < 3) continue; for (ListConstIterator<DPoint> it = dpl.begin().succ(); it != dpl.rbegin(); ++it) { double bx = (*it).m_x, by = (*it).m_y; const DPoint &p1 = *it.pred(); double psi1 = atan2(p1.m_x-bx, p1.m_y-by); const DPoint &p2 = *it.succ(); double psi2 = atan2(p2.m_x - bx, p2.m_y - by); double alpha = fabs(psi1 - psi2); if (alpha > Math::pi) alpha -= Math::pi; sumAngles += 2 * Math::pi; minAngle = min(minAngle, alpha); maxAngle = max(maxAngle, alpha + Math::pi); if (pStdDeviation) { numAngles += 2; allAngles.pushBack(alpha); allAngles.pushBack(alpha*Math::pi); } } } } double avgAngle = sumAngles / numAngles; if (pAvgAngle) *pAvgAngle = avgAngle; if (pMaxAngle) *pMaxAngle = maxAngle; if (pStdDeviation) { double sum = 0; for (double alpha : allAngles) { double d = alpha - avgAngle; sum += d*d; } *pStdDeviation = sqrt(sum / numAngles); } return minAngle; }
void CAView::visit() { CC_RETURN_IF(!m_bVisible); kmGLPushMatrix(); this->transform(); bool isScissor = (bool)glIsEnabled(GL_SCISSOR_TEST); DRect restoreScissorRect = DRectZero; if (isScissor) { GLfloat params[4]; glGetFloatv(GL_SCISSOR_BOX, params); restoreScissorRect = DRect(params[0], params[1], params[2], params[3]); } if (!m_bDisplayRange) { kmMat4 modelview; kmGLGetMatrix(KM_GL_MODELVIEW, &modelview); kmMat4 tm; kmMat4Identity(&tm); tm.mat[12] = m_obContentSize.width; tm.mat[13] = m_obContentSize.height; kmMat4 tm2; kmMat4Multiply(&tm2, &modelview, &tm); DPoint point = DPoint(modelview.mat[12], modelview.mat[13]); static CAApplication* application = CAApplication::getApplication(); if (application->getProjection() == CAApplication::P3D) { point = ccpAdd(point, application->getWinSize() / 2); } DSize size = DSize(tm2.mat[12] - modelview.mat[12], tm2.mat[13] - modelview.mat[13]); DRect frame = DRect(point.x, point.y, size.width, size.height); if (isScissor) { float x1 = MAX(s_dip_to_px(frame.getMinX()), restoreScissorRect.getMinX()); float y1 = MAX(s_dip_to_px(frame.getMinY()), restoreScissorRect.getMinY()); float x2 = MIN(s_dip_to_px(frame.getMaxX()) + 0.5f, restoreScissorRect.getMaxX()); float y2 = MIN(s_dip_to_px(frame.getMaxY()) + 0.5f, restoreScissorRect.getMaxY()); float width = MAX(x2-x1, 0); float height = MAX(y2-y1, 0); glScissor(x1, y1, width, height); } else { glEnable(GL_SCISSOR_TEST); glScissor(s_dip_to_px(frame.origin.x), s_dip_to_px(frame.origin.y), s_dip_to_px(frame.size.width) + 0.5f, s_dip_to_px(frame.size.height) + 0.5f); } } this->sortAllSubviews(); CAVector<CAView*>::iterator itr=m_obSubviews.begin(); while (itr!=m_obSubviews.end()) { CC_BREAK_IF((*itr)->m_nZOrder >= 0); (*itr)->visit(); itr++; } this->draw(); while (itr!=m_obSubviews.end()) { (*itr)->visit(); itr++; } //m_uOrderOfArrival = 0; if (!m_bDisplayRange) { if (isScissor) { glScissor(restoreScissorRect.origin.x, restoreScissorRect.origin.y , restoreScissorRect.size.width, restoreScissorRect.size.height); } else { glDisable(GL_SCISSOR_TEST); } } kmGLPopMatrix(); }
CATransformation CAView::nodeToParentTransform(void) { if (m_bTransformDirty) { // Translate values float height = 0; if (this->getSuperview()) { height= this->getSuperview()->getBounds().size.height; } else { height= CAApplication::getApplication()->getWinSize().height; } float x = m_obPoint.x; float y = height - m_obPoint.y; // Rotation values // Change rotation code to handle X and Y // If we skew with the exact same value for both x and y then we're simply just rotating float cx = 1, sx = 0, cy = 1, sy = 0; if (m_fRotationX || m_fRotationY) { float radiansX = -CC_DEGREES_TO_RADIANS(m_fRotationX); float radiansY = -CC_DEGREES_TO_RADIANS(m_fRotationY); cx = cosf(radiansX); sx = sinf(radiansX); cy = cosf(radiansY); sy = sinf(radiansY); } bool needsSkewMatrix = ( m_fSkewX || m_fSkewY ); // optimization: // inline anchor point calculation if skew is not needed // Adjusted transform calculation for rotational skew DPoint anchorPointInPoints = DPoint(m_obAnchorPointInPoints.x, m_obContentSize.height - m_obAnchorPointInPoints.y); if (! needsSkewMatrix && !anchorPointInPoints.equals(DPointZero)) { x += cy * -anchorPointInPoints.x * m_fScaleX + -sx * -anchorPointInPoints.y * m_fScaleY; y += sy * -anchorPointInPoints.x * m_fScaleX + cx * -anchorPointInPoints.y * m_fScaleY; } // Build Transform Matrix // Adjusted transform calculation for rotational skew m_sTransform = CATransformationMake(cy * m_fScaleX, sy * m_fScaleX, -sx * m_fScaleY, cx * m_fScaleY, x, y ); // XXX: Try to inline skew // If skew is needed, apply skew and then anchor point if (needsSkewMatrix) { CATransformation skewMatrix = CATransformationMake(1.0f, tanf(CC_DEGREES_TO_RADIANS(m_fSkewY)), tanf(CC_DEGREES_TO_RADIANS(m_fSkewX)), 1.0f, 0.0f, 0.0f ); m_sTransform = CATransformationConcat(skewMatrix, m_sTransform); // adjust anchor point DPoint anchorPointInPoints = DPoint(m_obAnchorPointInPoints.x, m_obContentSize.height - m_obAnchorPointInPoints.y); if (!anchorPointInPoints.equals(DPointZero)) { m_sTransform = CATransformationTranslate(m_sTransform, -anchorPointInPoints.x, -anchorPointInPoints.y); } } m_bTransformDirty = false; } return m_sTransform; }
void GEMLayout::call(GraphAttributes &AG) { const Graph &G = AG.constGraph(); if(G.empty()) return; // all edges straight-line AG.clearAllBends(); GraphCopy GC; GC.createEmpty(G); // compute connected component of G NodeArray<int> component(G); int numCC = connectedComponents(G,component); // intialize the array of lists of nodes contained in a CC Array<List<node> > nodesInCC(numCC); for(node v : G.nodes) nodesInCC[component[v]].pushBack(v); EdgeArray<edge> auxCopy(G); Array<DPoint> boundingBox(numCC); int i; for(i = 0; i < numCC; ++i) { GC.initByNodes(nodesInCC[i],auxCopy); GraphCopyAttributes AGC(GC,AG); for(node vCopy : GC.nodes) { node vOrig = GC.original(vCopy); AGC.x(vCopy) = AG.x(vOrig); AGC.y(vCopy) = AG.y(vOrig); } SList<node> permutation; // initialize node data m_impulseX.init(GC,0); m_impulseY.init(GC,0); m_skewGauge.init(GC,0); m_localTemperature.init(GC,m_initialTemperature); // initialize other data m_globalTemperature = m_initialTemperature; m_barycenterX = 0; m_barycenterY = 0; for(node v : GC.nodes) { m_barycenterX += weight(v) * AGC.x(v); m_barycenterY += weight(v) * AGC.y(v); } m_cos = cos(m_oscillationAngle / 2.0); m_sin = sin(Math::pi / 2 + m_rotationAngle / 2.0); // main loop int counter = m_numberOfRounds; while(OGDF_GEOM_ET.greater(m_globalTemperature,m_minimalTemperature) && counter--) { // choose nodes by random permutations if(permutation.empty()) { for(node v : GC.nodes) permutation.pushBack(v); permutation.permute(m_rng); } node v = permutation.popFrontRet(); // compute the impulse of node v computeImpulse(GC,AGC,v); // update node v updateNode(GC,AGC,v); } node vFirst = GC.firstNode(); double minX = AGC.x(vFirst), maxX = AGC.x(vFirst), minY = AGC.y(vFirst), maxY = AGC.y(vFirst); for(node vCopy : GC.nodes) { node v = GC.original(vCopy); AG.x(v) = AGC.x(vCopy); AG.y(v) = AGC.y(vCopy); if(AG.x(v)-AG.width (v)/2 < minX) minX = AG.x(v)-AG.width(v) /2; if(AG.x(v)+AG.width (v)/2 > maxX) maxX = AG.x(v)+AG.width(v) /2; if(AG.y(v)-AG.height(v)/2 < minY) minY = AG.y(v)-AG.height(v)/2; if(AG.y(v)+AG.height(v)/2 > maxY) maxY = AG.y(v)+AG.height(v)/2; } minX -= m_minDistCC; minY -= m_minDistCC; for(node vCopy : GC.nodes) { node v = GC.original(vCopy); AG.x(v) -= minX; AG.y(v) -= minY; } boundingBox[i] = DPoint(maxX - minX, maxY - minY); } Array<DPoint> offset(numCC); TileToRowsCCPacker packer; packer.call(boundingBox,offset,m_pageRatio); // The arrangement is given by offset to the origin of the coordinate // system. We still have to shift each node and edge by the offset // of its connected component. for(i = 0; i < numCC; ++i) { const List<node> &nodes = nodesInCC[i]; const double dx = offset[i].m_x; const double dy = offset[i].m_y; // iterate over all nodes in ith CC ListConstIterator<node> it; for(node v : nodes) { AG.x(v) += dx; AG.y(v) += dy; } } // free node data m_impulseX.init(); m_impulseY.init(); m_skewGauge.init(); m_localTemperature.init(); }
void CAView::draw() { m_uZLevel = CAApplication::getApplication()->getCurrentNumberOfDraws(); CC_RETURN_IF(m_pobImage == NULL); CC_RETURN_IF(m_pShaderProgram == NULL); CC_NODE_DRAW_SETUP(); ccGLBlendFunc(m_sBlendFunc.src, m_sBlendFunc.dst); ccGLBindTexture2D(m_pobImage->getName()); ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex); #define kQuadSize sizeof(m_sQuad.bl) #ifdef EMSCRIPTEN long offset = 0; setGLBufferData(&m_sQuad, 4 * kQuadSize, 0); #else long offset = (long)&m_sQuad; #endif // vertex int diff = offsetof( ccV3F_C4B_T2F, vertices); glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff)); // texCoods diff = offsetof( ccV3F_C4B_T2F, texCoords); glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff)); // color diff = offsetof( ccV3F_C4B_T2F, colors); glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff)); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); #if CC_SPRITE_DEBUG_DRAW // draw bounding box DPoint vertices[4]= { DPoint(m_sQuad.tl.vertices.x, m_sQuad.tl.vertices.y), DPoint(m_sQuad.bl.vertices.x, m_sQuad.bl.vertices.y), DPoint(m_sQuad.br.vertices.x, m_sQuad.br.vertices.y), DPoint(m_sQuad.tr.vertices.x, m_sQuad.tr.vertices.y), }; ccDrawPoly(vertices, 4, true); #endif // CC_SPRITE_DEBUG_DRAW CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "CAView - draw"); }
DPoint DPoint::operator*(float a) const { return DPoint(this->x * a, this->y * a); }
// subtracts p from *this DPoint DPoint::operator-(const DPoint &p) const { return DPoint(m_x - p.m_x, m_y - p.m_y); }
DPoint DPoint::operator-(const DPoint& right) const { return DPoint(this->x - right.x, this->y - right.y); }
DPoint DPoint::operator-() const { return DPoint(-x, -y); }
DPoint DPoint::operator+(const DPoint& right) const { return DPoint(this->x + right.x, this->y + right.y); }
void CAScrollView::ccTouchMoved(CATouch *pTouch, CAEvent *pEvent) { CC_RETURN_IF(m_bPCMode); CC_RETURN_IF(m_vTouches.contains(pTouch) == false); DPoint p_container = m_pContainer->getFrameOrigin(); DPoint p_off = DPointZero; if (m_vTouches.size() == 1) { p_off = ccpSub(this->convertToNodeSpace(pTouch->getLocation()), this->convertToNodeSpace(pTouch->getPreviousLocation())); DPoint off = p_off; if (off.getLength() <= 5) { off = DPointZero; } m_tPointOffset.push_back(off); } else if (m_vTouches.size() == 2) { CATouch* touch0 = dynamic_cast<CATouch*>(m_vTouches.at(0)); CATouch* touch1 = dynamic_cast<CATouch*>(m_vTouches.at(1)); DPoint mid_point = ccpMidpoint(this->convertToNodeSpace(touch0->getLocation()), this->convertToNodeSpace(touch1->getLocation())); p_off = ccpSub(mid_point, ccpAdd(p_container, m_pContainer->getAnchorPointInPoints() * m_fZoomScale)); if (m_fMinimumZoomScale < m_fMaximumZoomScale) { float touch_lenght = ccpDistance(this->convertToNodeSpace(touch0->getLocation()) , this->convertToNodeSpace(touch1->getLocation())); float scale_off = _dip(touch_lenght - m_fTouchLength) * 0.0020f; m_fZoomScale = m_pContainer->getScale(); m_fZoomScale += m_fZoomScale * scale_off; m_fZoomScale = MIN(m_fZoomScale, m_fMaximumZoomScale); m_fZoomScale = MAX(m_fZoomScale, m_fMinimumZoomScale); m_pContainer->setScale(m_fZoomScale); m_fTouchLength = touch_lenght; } } if (m_bBounces) { DSize size = this->getBounds().size; DPoint curr_point = m_pContainer->getFrameOrigin(); DPoint relust_point = curr_point; this->getScrollWindowNotOutPoint(relust_point); float lenght_x = fabsf(curr_point.x - relust_point.x); float lenght_y = fabsf(curr_point.y - relust_point.y); DPoint scale = DPoint(1.0f, 1.0f); if (!(lenght_x < FLT_EPSILON)) { scale.x = (0.5f - MIN(lenght_x / size.width, 0.5f)); p_off.x *= scale.x; } if (!(lenght_y < FLT_EPSILON)) { scale.y = (0.5f - MIN(lenght_y / size.height, 0.5f)); p_off.y *= scale.y; } } p_container = ccpAdd(p_container, p_off); if (m_bBounces == false) { this->getScrollWindowNotOutPoint(p_container); } else { if (m_bBounceHorizontal == false) { p_container.x = this->getScrollWindowNotOutHorizontal(p_container.x); } if (m_bBounceVertical == false) { p_container.y = this->getScrollWindowNotOutVertical(p_container.y); } } if (p_container.equals(m_pContainer->getFrameOrigin()) == false) { this->setContainerFrame(p_container); this->showIndicator(); if (m_bTracking == false) { if (m_pScrollViewDelegate) { m_pScrollViewDelegate->scrollViewWillBeginDragging(this); } m_bTracking = true; } if (m_pScrollViewDelegate) { m_pScrollViewDelegate->scrollViewDidScroll(this); m_pScrollViewDelegate->scrollViewDragging(this); m_pScrollViewDelegate->scrollViewDidMoved(this); } } this->changedFromPullToRefreshView(); }
void CAScrollView::startPullToHeaderRefreshView() { this->setContentOffset(DPoint(0, -128.0f), true); }
void SpringEmbedderFRExact::call(GraphAttributes &AG) { const Graph &G = AG.constGraph(); if(G.empty()) return; // all edges straight-line AG.clearAllBends(); ArrayGraph component(AG); component.m_useNodeWeight = m_useNodeWeight; EdgeArray<edge> auxCopy(G); Array<DPoint> boundingBox(component.numberOfCCs()); int i; for(i = 0; i < component.numberOfCCs(); ++i) { component.initCC(i); if (component.numberOfNodes() >= 2) { initialize(component); #ifdef OGDF_SSE3_EXTENSIONS if(System::cpuSupports(cpufSSE3)) mainStep_sse3(component); else #endif mainStep(component); } double minX, maxX, minY, maxY; minX = maxX = component.m_x[0]; minY = maxY = component.m_y[0]; for(int vCopy = 0; vCopy < component.numberOfNodes(); ++vCopy) { node v = component.original(vCopy); AG.x(v) = component.m_x[vCopy]; AG.y(v) = component.m_y[vCopy]; if(AG.x(v)-AG.width (v)/2 < minX) minX = AG.x(v)-AG.width(v) /2; if(AG.x(v)+AG.width (v)/2 > maxX) maxX = AG.x(v)+AG.width(v) /2; if(AG.y(v)-AG.height(v)/2 < minY) minY = AG.y(v)-AG.height(v)/2; if(AG.y(v)+AG.height(v)/2 > maxY) maxY = AG.y(v)+AG.height(v)/2; } minX -= m_minDistCC; minY -= m_minDistCC; for(int vCopy = 0; vCopy < component.numberOfNodes(); ++vCopy) { node v = component.original(vCopy); AG.x(v) -= minX; AG.y(v) -= minY; } boundingBox[i] = DPoint(maxX - minX, maxY - minY); } Array<DPoint> offset(component.numberOfCCs()); TileToRowsCCPacker packer; packer.call(boundingBox,offset,m_pageRatio); // The arrangement is given by offset to the origin of the coordinate // system. We still have to shift each node and edge by the offset // of its connected component. for(i = 0; i < component.numberOfCCs(); ++i) { const SList<node> &nodes = component.nodesInCC(i); const double dx = offset[i].m_x; const double dy = offset[i].m_y; // iterate over all nodes in ith CC for(node v : nodes) { AG.x(v) += dx; AG.y(v) += dy; } } }
DPoint DPoint::operator/(float a) const { CCAssert(a, "DPoint division by 0."); return DPoint(this->x / a, this->y / a); }
void CirclePlacer::placeOneLevel(MultilevelGraph &MLG) { int level = MLG.getLevel(); DPoint center(0.0, 0.0); float radius = 0.0; std::map<node, bool> oldNodes; Graph &G = MLG.getGraph(); double n = G.numberOfNodes(); if (n > 0) { node v; forall_nodes(v, G) { oldNodes[v] = true; center = center + DPoint( MLG.x(v), MLG.y(v) ); } center = DPoint(center.m_x / n, center.m_y / n); forall_nodes(v, G) { float r = sqrt( MLG.x(v) * MLG.x(v) + MLG.y(v) * MLG.y(v) ); if (r > radius) radius = r; } radius += m_circleSize; } else { radius = 0.0f + m_circleSize; } BarycenterPlacer BP; BP.placeOneLevel(MLG); node v; forall_nodes(v, G) { if (!m_fixedRadius) {
// adds p to *this DPoint DPoint::operator+(const DPoint &p) const { return DPoint(m_x + p.m_x, m_y + p.m_y); }