void WarpPerspectiveBilinear::keyDown( KeyEvent &event ) { if( !isEditModeEnabled() ) return; if( mSelected >= mPoints.size() ) return; switch( event.getCode() ) { case KeyEvent::KEY_UP: case KeyEvent::KEY_DOWN: case KeyEvent::KEY_LEFT: case KeyEvent::KEY_RIGHT: // make sure cursor keys are handled by 1 warp only if( !isCorner( mSelected ) ) mWarp->keyDown( event ); if( !event.isHandled() ) WarpBilinear::keyDown( event ); break; case KeyEvent::KEY_F9: case KeyEvent::KEY_F10: // let only the Perspective warp handle rotating mWarp->keyDown( event ); break; case KeyEvent::KEY_F11: case KeyEvent::KEY_F12: // let only the Bilinear warp handle flipping WarpBilinear::keyDown( event ); break; default: // let both warps handle the other keyDown events mWarp->keyDown( event ); WarpBilinear::keyDown( event ); break; } }
void FieldWall::init() { mType=FieldType::FIELD_WALL; if(isCorner()) { static int howManyCorners = 0; mFieldSprite.setTexture(ResourceManager::getTexture(ResourceManager::FIELD_WALL_CORNER)); sf::IntRect subTexture(0, 0, gi::FIELD_WIDTH, gi::FIELD_HEIGHT); // always 4 corners subTexture.top = gi::FIELD_HEIGHT * howManyCorners++; mFieldSprite.setTextureRect(subTexture); } else if(getPosition().x == 0 || getPosition().x == gi::WINDOW_WIDTH - gi::FIELD_WIDTH) //vertical walls { mFieldSprite.setTexture(ResourceManager::getTexture(ResourceManager::FIELD_WALL_VERTICAL)); mFieldSprite.setTextureRect(sf::IntRect(0, getPosition().x == 0 ? 0 : gi::FIELD_HEIGHT, gi::FIELD_WIDTH, gi::FIELD_HEIGHT)); } else if(getPosition().y == 0 || getPosition().y == gi::WINDOW_HEIGHT - gi::FIELD_HEIGHT) //horizontal walls { mFieldSprite.setTexture(ResourceManager::getTexture(ResourceManager::FIELD_WALL_HORIZONTAL)); mFieldSprite.setTextureRect(sf::IntRect(0, getPosition().y == 0 ? 0 : gi::FIELD_HEIGHT, gi::FIELD_WIDTH, gi::FIELD_HEIGHT)); } else //wall in the middle { mFieldSprite.setTexture(ResourceManager::getTexture(ResourceManager::FIELD_WALL_MIDDLE)); } }
bool WarpPerspectiveBilinear::keyDown(KeyEvent event) { if( ! isEditModeEnabled() ) return false; if(mSelected >= mPoints.size()) return false; switch( event.getCode() ) { case KeyEvent::KEY_UP: case KeyEvent::KEY_DOWN: case KeyEvent::KEY_LEFT: case KeyEvent::KEY_RIGHT: { // make sure cursor keys are handled by 1 warp only if(!isCorner( mSelected ) || !mWarp->keyDown(event)) return WarpBilinear::keyDown( event ); return true; } break; case KeyEvent::KEY_F9: case KeyEvent::KEY_F10: // let only the Perspective warp handle rotating return mWarp->keyDown(event); case KeyEvent::KEY_F11: case KeyEvent::KEY_F12: // let only the Bilinear warp handle flipping return WarpBilinear::keyDown( event ); default: { // let both warps handle the other keyDown events bool handled = mWarp->keyDown(event); return (WarpBilinear::keyDown( event ) || handled); } break; } }
void WarpPerspectiveBilinear::selectControlPoint(unsigned index) { // depending on index, select perspective or bilinear control point if( isCorner( index ) ) { mWarp->selectControlPoint( convertIndex( index ) ); } else { mWarp->deselectControlPoint(); } // always select bilinear control point, which we use to keep track of editing Warp::selectControlPoint( index ); }
void WarpPerspectiveBilinear::moveControlPoint(unsigned index, const Vec2f &shift) { // depending on index, move perspective or bilinear control point if( isCorner( index ) ) { // perspective: simply move the control point mWarp->moveControlPoint( convertIndex( index ), shift ); } else { // bilinear: transform control point from normalized screen space to warped space Vec2f pt = getControlPoint(index); setControlPoint(index, pt + shift); } }
bool WarpPerspectiveBilinear::mouseDrag( MouseEvent event ) { if( !isEditModeEnabled() ) return false; if(mSelected >= mPoints.size()) return false; // depending on selected control point, let perspective or bilinear warp handle it if( isCorner( mSelected ) ) { return mWarp->mouseDrag( event ); } else { return Warp::mouseDrag( event ); } }
Vec2f WarpPerspectiveBilinear::getControlPoint(unsigned index) const { // depending on index, return perspective or bilinear control point if( isCorner( index ) ) { // perspective: simply return one of the corners return mWarp->getControlPoint( convertIndex( index ) ); } else { // bilinear: transform control point from warped space to normalized screen space Vec2f p = Warp::getControlPoint(index) * Vec2f( mWarp->getSize() ); Vec3f pt = mWarp->getTransform().transformPoint( Vec3f(p.x, p.y, 0.0f) ); return Vec2f(pt.x, pt.y) / mWindowSize; } }
void WarpPerspectiveBilinear::mouseDown( MouseEvent &event ) { if( !isEditModeEnabled() ) return; if( mSelected >= mPoints.size() ) return; // depending on selected control point, let perspective or bilinear warp handle it if( isCorner( mSelected ) ) { mWarp->mouseDown( event ); } else { Warp::mouseDown( event ); } }
void WarpPerspectiveBilinear::setControlPoint(unsigned index, const Vec2f &pos) { // depending on index, set perspective or bilinear control point if( isCorner( index ) ) { // perspective: simply set the control point mWarp->setControlPoint( convertIndex( index ), pos ); } else { // bilinear:: transform control point from normalized screen space to warped space Vec2f p = pos * mWindowSize; Vec3f pt = mWarp->getInvertedTransform().transformPoint( Vec3f(p.x, p.y, 0.0f) ); Vec2f size( mWarp->getSize() ); Warp::setControlPoint( index, Vec2f(pt.x, pt.y) / size ); } }
NeighborBitset update(float dTime) { NeighborBitset neighbors; neighbors.reserve(mHeight); std::vector<CA::State> bitLine; bitLine.reserve(mWidth); for(int i = 0; i < mHeight; i++){ bitLine.clear(); for(int j = 0; j < mWidth; j++){ if(mCells[i+j*mWidth].get() == mCenter.get() || isCorner(i, j)){ bitLine.push_back(CA::State::OFF); } else{ bitLine.push_back(mCells[i+j*mWidth]->getState() == true ? CA::State::ON : CA::State::OFF); } } neighbors.push_back(bitLine); } return neighbors; /* NeighborBitset neighbors; neighbors.reserve(mHeight); std::vector<CA::State> bitLine; bitLine.reserve(mWidth); for(int i = 0; i < mHeight; i++){ bitLine.clear(); for(int j = 0; j < mWidth; j++){ if(mCells[i+j*mHeight].get() == mCenter.get() || isCorner(i, j)){ bitLine.push_back(CA::State::OFF); } else{ bitLine.push_back(mCells[i+j*mHeight]->getState() == true ? CA::State::ON : CA::State::OFF); } } neighbors.push_back(bitLine); } return neighbors; */ }
vec2 WarpPerspectiveBilinear::getControlPoint( unsigned index ) const { // depending on index, return perspective or bilinear control point if( isCorner( index ) ) { // perspective: simply return one of the corners return mWarp->getControlPoint( convertIndex( index ) ); } else { // bilinear: transform control point from warped space to normalized screen space vec2 p = Warp::getControlPoint( index ) * vec2( mWarp->getSize() ); vec4 pt = mWarp->getTransform() * vec4( p.x, p.y, 0, 1 ); if( pt.w != 0 ) pt.w = 1 / pt.w; pt *= pt.w; return vec2( pt.x, pt.y ) / mWindowSize; } }
void WarpPerspectiveBilinear::setControlPoint( unsigned index, const vec2 &pos ) { // depending on index, set perspective or bilinear control point if( isCorner( index ) ) { // perspective: simply set the control point mWarp->setControlPoint( convertIndex( index ), pos ); } else { // bilinear:: transform control point from normalized screen space to warped space vec2 p = pos * mWindowSize; vec4 pt = mWarp->getInvertedTransform() * vec4( p.x, p.y, 0, 1 ); if( pt.w != 0 ) pt.w = 1 / pt.w; pt *= pt.w; vec2 size( mWarp->getSize() ); Warp::setControlPoint( index, vec2( pt.x, pt.y ) / size ); } }
void compute_splines() { // get point tangents first std::cout << "HermiteSpline2D: compute_splines(): Getting tangents of boundary points." << std::endl; for(int ipoin = 0; ipoin < m->gnbpoin(); ipoin++) { // in 2D, bpoints is not an array of stl std::vectors - we know there are only two faces surrounding each boundary point // if edge is bounded by (x1,y1) and (x2,y2), tangent to edge is (x2-x1)i + (y2-y1)j // first check if this point belongs to a face that needs to be reconstructed if(toRec(m->gbpoints(ipoin,1))==1 || toRec(m->gbpoints(ipoin,2))==1) { std::vector<int> en(2); // get intfac faces containing this point en[0] = m->gbpoints(ipoin,1); en[1] = m->gbpoints(ipoin,2); //std::cout << en[0] << " " << en[1] << std::endl; double xt, yt, dotx = 1, doty = 1, mag; // iterate over the two faces containing ipoin for(int i = 0; i < 2; i++) { xt = m->gcoords(m->gintfac(en[i],3),0) - m->gcoords(m->gintfac(en[i],2),0); yt = m->gcoords(m->gintfac(en[i],3),1) - m->gcoords(m->gintfac(en[i],2),1); mag = sqrt(xt*xt + yt*yt); ptangents(m->gbpoints(ipoin,0),0) += xt; ptangents(m->gbpoints(ipoin,0),1) += yt; dotx *= xt/mag; doty *= yt/mag; } ptangents(m->gbpoints(ipoin,0),0) /= 2.0; ptangents(m->gbpoints(ipoin,0),1) /= 2.0; // now normalize the averaged tangent std::vector mag = sqrt(ptangents(m->gbpoints(ipoin,0),0)*ptangents(m->gbpoints(ipoin,0),0) + ptangents(m->gbpoints(ipoin,0),1)*ptangents(m->gbpoints(ipoin,0),1)); ptangents(m->gbpoints(ipoin,0),0) /= mag; ptangents(m->gbpoints(ipoin,0),1) /= mag; // check if this is a corner point double dotp = dotx+doty; // dot product of tangents of the two faces if(dotp < cos(angle_threshold)) { isCorner(m->gbpoints(ipoin,0)) = 1; // set isCorner for global point number corresponding to boundary point ipoin std::cout << "Boundary point " << m->gbpoints(ipoin,0) << " is a corner point!" << std::endl; } } } // iterate over boundary faces of the mesh std::cout << "HermiteSpline2D: compute_splines(): Iterating over boundary faces to get tangents." << std::endl; std::vector<int> pnts(m->gnnofa()); // to store point numbers of points making up iface for(int iface = 0; iface < m->gnbface(); iface++) { if(toRec(iface) == 1) { // get tangent for this face for(int inofa = 0; inofa < m->gnnofa(); inofa++) pnts[inofa] = m->gintfac(iface,inofa+2); // magnitude of tangent (x2-x1)i + (y2-y1)j double mag = sqrt((m->gcoords(pnts[1],0)-m->gcoords(pnts[0],0))*(m->gcoords(pnts[1],0)-m->gcoords(pnts[0],0)) + (m->gcoords(pnts[1],1)-m->gcoords(pnts[0],1))*(m->gcoords(pnts[1],1)-m->gcoords(pnts[0],1))); for(int inofa = 0; inofa < m->gnnofa(); inofa++) { if(isCorner(pnts[inofa]) == 0) // if not a corner { gallfa(iface,2*inofa) = ptangents(pnts[inofa],0); gallfa(iface,2*inofa+1) = ptangents(pnts[inofa],1); } else // if pnts[inofa] is a corner, use this face's tangent at that point { gallfa(iface,2*inofa) = (m->gcoords(pnts[1],0) - m->gcoords(pnts[0],0))/mag; gallfa(iface,2*inofa+1) = (m->gcoords(pnts[1],1) - m->gcoords(pnts[0],1))/mag; } } /* Note that gallfa(*,0) contains x-component of tangent at point 1, gallfa(*,1) contains y-component of tangent at point 1, gallfa(*,2) contains x-component of tangent at point 2, and gallfa(*,3) contains y-component of tangent at points 2. */ } } // iterate over boundary faces of mesh again to calculate geometric spline coeffs from gallfa and intfac std::cout << "HermiteSpline2d: compute_splines(): Iterating over boundary faces again to compute geometric coefficients of the splines" << std::endl; for(int iface = 0; iface < m->gnbface(); iface++) if(toRec(iface) == 1) { for(int idim = 0; idim < m->gndim(); idim++) { cf[idim](iface,0) = m->gcoords(m->gintfac(iface,2),idim); cf[idim](iface,1) = m->gcoords(m->gintfac(iface,3),idim); cf[idim](iface,2) = gallfa(iface,idim); cf[idim](iface,3) = gallfa(iface,idim+2); } } }
void edgeColoringSimple(Shape &shape, double angleThreshold, unsigned long long seed) { double crossThreshold = sin(angleThreshold); std::vector<int> corners; for (std::vector<Contour>::iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour) { // Identify corners corners.clear(); if (!contour->edges.empty()) { Vector2 prevDirection = (*(contour->edges.end()-1))->direction(1); int index = 0; for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge, ++index) { if (isCorner(prevDirection.normalize(), (*edge)->direction(0).normalize(), crossThreshold)) corners.push_back(index); prevDirection = (*edge)->direction(1); } } // Smooth contour if (corners.empty()) for (std::vector<EdgeHolder>::iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) (*edge)->color = WHITE; // "Teardrop" case else if (corners.size() == 1) { EdgeColor colors[3] = { WHITE, WHITE }; switchColor(colors[0], seed); switchColor(colors[2] = colors[0], seed); int corner = corners[0]; if (contour->edges.size() >= 3) { int m = contour->edges.size(); for (int i = 0; i < m; ++i) contour->edges[(corner+i)%m]->color = (colors+1)[int(3+2.875*i/(m-1)-1.4375+.5)-3]; } else if (contour->edges.size() >= 1) { // Less than three edge segments for three colors => edges must be split EdgeSegment *parts[7] = { }; contour->edges[0]->splitInThirds(parts[0+3*corner], parts[1+3*corner], parts[2+3*corner]); if (contour->edges.size() >= 2) { contour->edges[1]->splitInThirds(parts[3-3*corner], parts[4-3*corner], parts[5-3*corner]); parts[0]->color = parts[1]->color = colors[0]; parts[2]->color = parts[3]->color = colors[1]; parts[4]->color = parts[5]->color = colors[2]; } else { parts[0]->color = colors[0]; parts[1]->color = colors[1]; parts[2]->color = colors[2]; } contour->edges.clear(); for (int i = 0; parts[i]; ++i) contour->edges.push_back(EdgeHolder(parts[i])); } } // Multiple corners else { int cornerCount = corners.size(); int spline = 0; int start = corners[0]; int m = contour->edges.size(); EdgeColor color = WHITE; switchColor(color, seed); EdgeColor initialColor = color; for (int i = 0; i < m; ++i) { int index = (start+i)%m; if (spline+1 < cornerCount && corners[spline+1] == index) { ++spline; switchColor(color, seed, EdgeColor((spline == cornerCount-1)*initialColor)); } contour->edges[index]->color = color; } } } }