bool isCloseToSegment(const TPointD &point, const TSegment &segment, double distance) { TPointD a = segment.getP0(); TPointD b = segment.getP1(); double length2 = tdistance2(a, b); if (length2 < tdistance2(a, point) || length2 < tdistance2(point, b)) return false; if (a.x == b.x) return fabs(point.x - a.x) <= distance; if (a.y == b.y) return fabs(point.y - a.y) <= distance; // y=mx+q double m = (a.y - b.y) / (a.x - b.x); double q = a.y - (m * a.x); double d2 = pow(fabs(point.y - (m * point.x) - q), 2) / (1 + (m * m)); return d2 <= distance * distance; }
int intersectCloseControlPoints(const TQuadratic &c0, const TQuadratic &c1, std::vector<DoublePair> &intersections) { int ret = -2; double dist1 = tdistance2(c0.getP0(), c0.getP1()); if (dist1 == 0) dist1 = 1e-20; double dist2 = tdistance2(c0.getP1(), c0.getP2()); if (dist2 == 0) dist2 = 1e-20; double val0 = std::max(dist1, dist2) / std::min(dist1, dist2); double dist3 = tdistance2(c1.getP0(), c1.getP1()); if (dist3 == 0) dist3 = 1e-20; double dist4 = tdistance2(c1.getP1(), c1.getP2()); if (dist4 == 0) dist4 = 1e-20; double val1 = std::max(dist3, dist4) / std::min(dist3, dist4); if (val0 > 1000000 && val1 > 1000000) // both c0 and c1 approximated by segments { TSegment s0 = TSegment(c0.getP0(), c0.getP2()); TSegment s1 = TSegment(c1.getP0(), c1.getP2()); ret = intersect(s0, s1, intersections); for (UINT i = intersections.size() - ret; i < (int)intersections.size(); i++) { intersections[i].first = (dist1 < dist2) ? sqrt(intersections[i].first) : 1 - sqrt(1 - intersections[i].first); intersections[i].second = (dist3 < dist4) ? sqrt(intersections[i].second) : 1 - sqrt(1 - intersections[i].second); } // return ret; } else if (val0 > 1000000) // c0 only approximated segment { TSegment s0 = TSegment(c0.getP0(), c0.getP2()); ret = intersect(s0, c1, intersections); for (UINT i = intersections.size() - ret; i < (int)intersections.size(); i++) intersections[i].first = (dist1 < dist2) ? sqrt(intersections[i].first) : 1 - sqrt(1 - intersections[i].first); // return ret; } else if (val1 > 1000000) // only c1 approximated segment { TSegment s1 = TSegment(c1.getP0(), c1.getP2()); ret = intersect(c0, s1, intersections); for (UINT i = intersections.size() - ret; i < (int)intersections.size(); i++) intersections[i].second = (dist3 < dist4) ? sqrt(intersections[i].second) : 1 - sqrt(1 - intersections[i].second); // return ret; } /* if (ret!=-2) { std::vector<DoublePair> intersections1; int ret1 = intersect(c0, c1, intersections1, false); if (ret1>ret) { intersections = intersections1; return ret1; } } */ return ret; }
void subCompute(TRasterFxPort &m_input, TTile &tile, double frame, const TRenderSettings &ri, TPointD p00, TPointD p01, TPointD p11, TPointD p10, int details, bool wireframe, TDimension m_offScreenSize, bool isCast) { TPixel32 bgColor; TRectD outBBox, inBBox; outBBox = inBBox = TRectD(tile.m_pos, TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy())); m_input->getBBox(frame, inBBox, ri); if (inBBox == TConsts::infiniteRectD) // e' uno zerario inBBox = outBBox; int inBBoxLx = (int)inBBox.getLx() / ri.m_shrinkX; int inBBoxLy = (int)inBBox.getLy() / ri.m_shrinkY; if (inBBox.isEmpty()) return; if (p00 == p01 && p00 == p10 && p00 == p11 && !isCast) // significa che non c'e' deformazione { m_input->compute(tile, frame, ri); return; } TRaster32P rasIn; TPointD rasInPos; if (!wireframe) { if (ri.m_bpp == 64 || ri.m_bpp == 48) { TRaster64P aux = TRaster64P(inBBoxLx, inBBoxLy); rasInPos = TPointD(inBBox.x0 / ri.m_shrinkX, inBBox.y0 / ri.m_shrinkY); TTile tmp(aux, rasInPos); m_input->compute(tmp, frame, ri); rasIn = TRaster32P(inBBoxLx, inBBoxLy); TRop::convert(rasIn, aux); } else { rasInPos = TPointD(inBBox.x0 / ri.m_shrinkX, inBBox.y0 / ri.m_shrinkY); TTile tmp(TRaster32P(inBBoxLx, inBBoxLy), rasInPos); m_input->allocateAndCompute(tmp, rasInPos, TDimension(inBBoxLx, inBBoxLy), TRaster32P(), frame, ri); rasIn = tmp.getRaster(); } } unsigned int texWidth = 2; unsigned int texHeight = 2; while (texWidth < (unsigned int)inBBoxLx) texWidth = texWidth << 1; while (texHeight < (unsigned int)inBBoxLy) texHeight = texHeight << 1; while (texWidth > 1024 || texHeight > 1024) // avevo usato la costante // GL_MAX_TEXTURE_SIZE invece di // 1024, ma non funzionava! { inBBoxLx = inBBoxLx >> 1; inBBoxLy = inBBoxLy >> 1; texWidth = texWidth >> 1; texHeight = texHeight >> 1; } if (rasIn->getLx() != inBBoxLx || rasIn->getLy() != inBBoxLy) { TRaster32P rasOut = TRaster32P(inBBoxLx, inBBoxLy); TRop::resample(rasOut, rasIn, TScale((double)rasOut->getLx() / rasIn->getLx(), (double)rasOut->getLy() / rasIn->getLy())); rasIn = rasOut; } int rasterWidth = tile.getRaster()->getLx() + 2; int rasterHeight = tile.getRaster()->getLy() + 2; assert(rasterWidth > 0); assert(rasterHeight > 0); TRectD clippingRect = TRectD(tile.m_pos, TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy())); #if CREATE_GL_CONTEXT_ONE_TIME int ret = wglMakeCurrent(m_offScreenGL.m_offDC, m_offScreenGL.m_hglRC); assert(ret == TRUE); #else TOfflineGL offScreenRendering(TDimension(rasterWidth, rasterHeight)); //#ifdef _WIN32 offScreenRendering.makeCurrent(); //#else //#if defined(LINUX) || defined(MACOSX) // offScreenRendering.m_offlineGL->makeCurrent(); //#endif #endif checkErrorsByGL // disabilito quello che non mi serve per le texture glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glDisable(GL_DITHER); glDisable(GL_DEPTH_TEST); glCullFace(GL_FRONT); glDisable(GL_STENCIL_TEST); glDisable(GL_LOGIC_OP); // creo la texture in base all'immagine originale glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); checkErrorsByGL #if !CREATE_GL_CONTEXT_ONE_TIME TRaster32P rasaux; if (!wireframe) { TRaster32P texture(texWidth, texHeight); texture->clear(); rasaux = texture; rasaux->lock(); texture->copy(rasIn); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexImage2D(GL_TEXTURE_2D, 0, 4, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture->getRawData()); } #else unsigned int texWidth = 1024; unsigned int texHeight = 1024; rasaux = rasIn; rasaux->lock(); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rasIn->getLx(), rasIn->getLy(), GL_RGBA, GL_UNSIGNED_BYTE, rasIn->getRawData()); #endif checkErrorsByGL glEnable(GL_TEXTURE_2D); // cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-rasterWidth * 0.5, rasterWidth * 0.5, -rasterHeight * 0.5, rasterHeight * 0.5, -1, 1); glViewport(0, 0, rasterWidth, rasterHeight); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); // do OpenGL draw double lwTex = (double)(inBBoxLx - 1) / (double)(texWidth - 1); double lhTex = (double)(inBBoxLy - 1) / (double)(texHeight - 1); TPointD tex00 = TPointD(0.0, 0.0); TPointD tex10 = TPointD(lwTex, 0.0); TPointD tex11 = TPointD(lwTex, lhTex); TPointD tex01 = TPointD(0.0, lhTex); GLenum polygonStyle; if (wireframe) { polygonStyle = GL_LINE; glDisable(GL_TEXTURE_2D); } else polygonStyle = GL_FILL; checkErrorsByGL p00.x /= ri.m_shrinkX; p00.y /= ri.m_shrinkY; p10.x /= ri.m_shrinkX; p10.y /= ri.m_shrinkY; p11.x /= ri.m_shrinkX; p11.y /= ri.m_shrinkY; p01.x /= ri.m_shrinkX; p01.y /= ri.m_shrinkY; TPointD translate = TPointD(tile.m_pos.x + tile.getRaster()->getLx() * 0.5, tile.m_pos.y + tile.getRaster()->getLy() * 0.5); glTranslated(-translate.x, -translate.y, 0.0); // disegno il poligono double dist_p00_p01 = tdistance2(p00, p01); double dist_p10_p11 = tdistance2(p10, p11); double dist_p01_p11 = tdistance2(p01, p11); double dist_p00_p10 = tdistance2(p00, p10); bool vertical = (dist_p00_p01 == dist_p10_p11); bool horizontal = (dist_p00_p10 == dist_p01_p11); if (vertical && horizontal) details = 1; glPolygonMode(GL_FRONT_AND_BACK, polygonStyle); subdivision(p00, p10, p11, p01, tex00, tex10, tex11, tex01, clippingRect, details); if (!wireframe) { // abilito l'antialiasing delle linee glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // disegno il bordo del poligono glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glBegin(GL_QUADS); glTexCoord2d(tex00.x, tex00.y); tglVertex(p00); glTexCoord2d(tex10.x, tex10.y); tglVertex(p10); glTexCoord2d(tex11.x, tex11.y); tglVertex(p11); glTexCoord2d(tex01.x, tex01.y); tglVertex(p01); glEnd(); // disabilito l'antialiasing per le linee glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); } // force to finish glFlush(); // rimetto il disegno dei poligoni a GL_FILL glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // metto il frame buffer nel raster del tile glPixelStorei(GL_UNPACK_ROW_LENGTH, rasterWidth); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); TRaster32P newRas(tile.getRaster()->getLx(), tile.getRaster()->getLy()); newRas->lock(); glReadPixels(1, 1, newRas->getLx(), newRas->getLy(), GL_RGBA, GL_UNSIGNED_BYTE, (void *)newRas->getRawData()); newRas->unlock(); checkErrorsByGL rasaux->unlock(); tile.getRaster()->copy(newRas); }