Example #1
0
void VolumeSample::demonstrate(const int width, const int height, const Crystal::Graphics::ICamera<float>& camera)
{
	glEnable(GL_DEPTH_TEST);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	LegacyRenderer renderer;
	PointBuffer buffer;
	buffer.add(*volume);
	renderer.render(camera, buffer);

	LineBuffer lineBuffer;
	lineBuffer.add(*polygon, ColorRGBA<float>(1.0, 0.0, 0.0, 1.0));
	renderer.render(camera, lineBuffer);
}
void SE_PositioningAlgorithms::PathLabels(SE_ApplyContext* applyCtx,
                                          SE_RenderStyle*  rstyle)
{
    SE_Renderer* se_renderer = applyCtx->renderer;
    LineBuffer* geometry = applyCtx->geometry;

    // path labeling only applies to linestring feature geometry
    switch (geometry->geom_type())
    {
        case GeometryType_LineString:
        case GeometryType_MultiLineString:
        case GeometryType_CurveString:
        case GeometryType_MultiCurveString:
            break;

        default:
            return;
    }

    // in the case of a point style, just use the default placement algorithm
    if (rstyle->type == SE_RenderStyle_Point)
        return SE_PositioningAlgorithms::Default(applyCtx, rstyle);

    // path labeling using an area style is not supported
    if (rstyle->type == SE_RenderStyle_Area)
        return;

    // the style needs to contain at least one primitive
    SE_RenderPrimitiveList& prims = rstyle->symbol;
    if (prims.size() == 0)
        return;

    // If the symbol contains just a single text element then add the
    // text as a regular path label (non-symbol).  Use 0.5 as the
    // default value for the scale limit.
    if (prims.size() == 1 && prims[0]->type == SE_RenderPrimitive_Text)
    {
        SE_RenderText* rt = (SE_RenderText*)prims[0];

        RS_LabelInfo info(0.0, 0.0, 0.0, 0.0, RS_Units_Device, rt->tdef);
        RS_OverpostType overpostType = rstyle->checkExclusionRegion? RS_OverpostType_AllFit : RS_OverpostType_All;
        return se_renderer->ProcessLabelGroup(&info, 1, rt->content, overpostType, rstyle->addToExclusionRegion, geometry, 0.5);
    }

    se_renderer->ProcessLineLabels(geometry, (SE_RenderLineStyle*)rstyle);
}
 void clear()
 {
     for (PointBufferMap::iterator it = pointmap.begin(); it != pointmap.end(); ++it)
         it->second.clear();
     
     lines.clear();
     lineIndices.clear();
 }
Example #4
0
void Shell::executeCommand(const LineBuffer& line){
  _out << '\n';
  _modules.commandExecute(line.line(), *this);
  const auto executionResult = handleExecuteCommand(line);
  _modules.commandExecuted(executionResult, line.line(), *this);
  switch (executionResult.status()) {
    case Status::NoMatch:
      _out << "Command not found [" << line.firstWord() << "]\n";
    case Status::Ok:
      prompt();
      break;
    case Status::Incomplete:
      _function.parse(":prompt_feed", _out, true);
      _column = _cursor.position().x;
      break;
  }
}
Example #5
0
    explicit ContigPair(LineBuffer &source)
    : count(0)
    {
        auto const line = source.get();
        if (line.first == nullptr) return;

        auto n = 0;
        for (auto i = line.first, end = i; ; ++end) {
            if (end == line.second || *end == '\t') {
                switch (n) {
                    case 0:
                        first.ref = unsigned(references[std::string(i, end)]);
                        break;
                    case 1:
                        if (!string_to_i(first.start, i, end)) goto CONVERSION_ERROR;
                        break;
                    case 2:
                        if (!string_to_i(first.end, i, end)) goto CONVERSION_ERROR;
                        break;
                    case 3:
                        second.ref = unsigned(references[std::string(i, end)]);
                        break;
                    case 4:
                        if (!string_to_i(second.start, i, end)) goto CONVERSION_ERROR;
                        break;
                    case 5:
                        if (!string_to_i(second.end, i, end)) goto CONVERSION_ERROR;
                        break;
                    case 6:
                        group = unsigned(groups[std::string(i, end)]);
                        break;
                    case 7:
                        std::cerr << "extra data in record: " << std::string(line.first, line.second) << std::endl;
                        return;
                }
                ++n;
                if (end == line.second)
                    break;
                i = end + 1;
            }
        }
        if (n < 6) {
            std::cerr << "truncated record: " << std::string(line.first, line.second) << std::endl;
            return;
        }
        if (n < 7)
            group = groups[""];

        count = 1;
        return;
        
    CONVERSION_ERROR:
        std::cerr << "error parsing record: " << std::string(line.first, line.second) << std::endl;
        return;
    }
Example #6
0
void LegacyRenderer::render(const Matrix4d<float>& projectionMatrix, const Matrix4d<float>& modelviewMatrix, const LineBuffer& buffer, const GLfloat width)
{
	const auto& positions = buffer.getPosition().get();// buffers[0].get();
	const auto& colors = buffer.getColor().get();
	const auto& indices = buffer.getIds();

	if (positions.empty()) {
		return;
	}

	glLineWidth(width);
	glEnable(GL_DEPTH_TEST);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glLoadMatrixf(projectionMatrix.toArray().data());

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glLoadMatrixf(modelviewMatrix.toArray().data());

	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_FLOAT, 0, positions.data());

	glEnableClientState(GL_COLOR_ARRAY);
	glColorPointer(4, GL_FLOAT, 0, colors.data());
	assert(glGetError() == GL_NO_ERROR);

	//glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(positions.size()) / 3);
	glDrawElements(GL_LINES, static_cast<GLsizei>(indices.size()), GL_UNSIGNED_INT, indices.data());

	glDisableClientState(GL_COLOR_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisable(GL_DEPTH_TEST);

	glLineWidth(1);
}
Example #7
0
ParseResult Shell::handleExecuteCommand(const LineBuffer& line){
  _buffer += line.line();

  const ParseResult executionResult {
    _commands.parse(_buffer, _out, true)};

  switch (executionResult.status()) {
    case Status::Incomplete:
      _buffer += '\n';
      break;
    default:
      _buffer.clear();
      break;
  }
  return executionResult;
}
void SE_Renderer::DrawSymbol(SE_RenderPrimitiveList& symbol,
                             const SE_Matrix& xform,
                             double angleRad,
                             bool excludeRegion)
{
    RS_Bounds extents(DBL_MAX, DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX, -DBL_MAX);
    unsigned int nprims = symbol.size();

    for (unsigned int i=0; i<nprims; ++i)
    {
        SE_RenderPrimitive* primitive = symbol[i];

        if (primitive->type == SE_RenderPrimitive_Polygon || primitive->type == SE_RenderPrimitive_Polyline)
        {
            SE_RenderPolyline* rp = (SE_RenderPolyline*)primitive;

            LineBuffer* lb = rp->geometry->xf_buffer();

            // update the extents with this primitive
            RS_Bounds lbnds;
            lb->ComputeBounds(lbnds);
            extents.add_bounds(lbnds);

            if (m_bSelectionMode)
            {
                if (primitive->type == SE_RenderPrimitive_Polygon)
                    DrawScreenPolygon(lb, &xform, m_selFillColor);

                m_selLineStroke.cap        = rp->lineStroke.cap;
                m_selLineStroke.join       = rp->lineStroke.join;
                m_selLineStroke.miterLimit = rp->lineStroke.miterLimit;
                DrawScreenPolyline(lb, &xform, m_selLineStroke);
            }
            else
            {
                if (primitive->type == SE_RenderPrimitive_Polygon)
                    DrawScreenPolygon(lb, &xform, ((SE_RenderPolygon*)primitive)->fill);

                DrawScreenPolyline(lb, &xform, rp->lineStroke);
            }
        }
        else if (primitive->type == SE_RenderPrimitive_Text)
        {
            SE_RenderText* tp = (SE_RenderText*)primitive;

            // update the extents with this primitive's bounds
            for (int j=0; j<4; ++j)
                extents.add_point(primitive->bounds[j]);

            // get position and angle to use
            double x, y;
            xform.transform(tp->position[0], tp->position[1], x, y);
            RS_TextDef tdef = tp->tdef;
            tdef.rotation() += angleRad * M_180PI;

            if (m_bSelectionMode)
            {
                tdef.textcolor()   = m_textForeColor;
                tdef.ghostcolor()  = m_textBackColor;
//              tdef.framecolor()  = m_textBackColor;
//              tdef.opaquecolor() = m_textBackColor;
            }

            // Here we cannot use the cached RS_TextMetrics in the SE_RenderText object.
            // We must recalculate the text metrics with the new tdef before we can call DrawScreenText.
            RS_TextMetrics tm;
            if (this->GetRSFontEngine()->GetTextMetrics(tp->content, tdef, tm, false))
                DrawScreenText(tm, tdef, x, y, NULL, 0, 0.0);
        }
        else if (primitive->type == SE_RenderPrimitive_Raster)
        {
            SE_RenderRaster* rp = (SE_RenderRaster*)primitive;

            if (m_bSelectionMode)
            {
                // if the raster symbol is selected, then draw the mask selection polygon only
                LineBuffer *lb = LineBufferPool::NewLineBuffer(m_pPool, 5);
                std::auto_ptr<LineBuffer> spLB(lb);

                lb->MoveTo(rp->bounds[3].x, rp->bounds[3].y);
                for (int i = 0; i < 4; ++i)
                {
                    lb->LineTo(rp->bounds[i].x, rp->bounds[i].y);
                }
                
                DrawScreenPolygon(lb, &xform, m_selFillColor);
                DrawScreenPolyline(lb, &xform, m_selLineStroke);

                LineBufferPool::FreeLineBuffer(m_pPool, spLB.release());
            }
            else 
            {
                ImageData& imgData = rp->imageData;
                if (imgData.data != NULL)
                {
                    // update the extents with this primitive's bounds
                    for (int j=0; j<4; ++j)
                        extents.add_point(primitive->bounds[j]);

                    // get position and angle to use
                    double x, y;
                    xform.transform(rp->position[0], rp->position[1], x, y);
                    double angleDeg = (rp->angleRad + angleRad) * M_180PI;

                    DrawScreenRaster(imgData.data, imgData.size, imgData.format, imgData.width, imgData.height, x, y, rp->extent[0], rp->extent[1], angleDeg, rp->opacity);
                }
            }
        }
    }

    if (nprims > 0)
    {
        // always compute the last symbol extent
        xform.transform(extents.minx, extents.miny, m_lastSymbolExtent[0].x, m_lastSymbolExtent[0].y);
        xform.transform(extents.maxx, extents.miny, m_lastSymbolExtent[1].x, m_lastSymbolExtent[1].y);
        xform.transform(extents.maxx, extents.maxy, m_lastSymbolExtent[2].x, m_lastSymbolExtent[2].y);
        xform.transform(extents.minx, extents.maxy, m_lastSymbolExtent[3].x, m_lastSymbolExtent[3].y);

        if (excludeRegion)
            AddExclusionRegion(m_lastSymbolExtent, 4);
    }
    else
    {
        // symbol contains no primitives - update last symbol extent assuming
        // zero symbol extent, but don't add any exclusion region
        xform.transform(0.0, 0.0, m_lastSymbolExtent[0].x, m_lastSymbolExtent[0].y);
        m_lastSymbolExtent[1].x = m_lastSymbolExtent[2].x = m_lastSymbolExtent[3].x = m_lastSymbolExtent[0].x;
        m_lastSymbolExtent[1].y = m_lastSymbolExtent[2].y = m_lastSymbolExtent[3].y = m_lastSymbolExtent[0].y;
    }
}
///////////////////////////////////////////////////////////////////////////////
// Called when applying a line style on a feature geometry.  Line styles can
// only be applied to linestring and polygon feature geometry types.
void SE_Renderer::ProcessLine(SE_ApplyContext* ctx, SE_RenderLineStyle* style)
{
    // the feature geometry we're applying the style on...
    LineBuffer* featGeom = ctx->geometry;

    // can't apply a line style to point geometry types
    switch (featGeom->geom_type())
    {
        case GeometryType_Point:
        case GeometryType_MultiPoint:
            return;
    }

    //--------------------------------------------------------------
    // special code to handle simple straight solid line styles
    //--------------------------------------------------------------

    if (style->solidLine)
    {
        // just draw it and bail out of the layout function
        SE_RenderPolyline* rp = (SE_RenderPolyline*)style->symbol[0];

        SE_Matrix w2s;
        GetWorldToScreenTransform(w2s);
        if (m_bSelectionMode)
        {
            m_selLineStroke.cap        = rp->lineStroke.cap;
            m_selLineStroke.join       = rp->lineStroke.join;
            m_selLineStroke.miterLimit = rp->lineStroke.miterLimit;
            DrawScreenPolyline(featGeom, &w2s, m_selLineStroke);
        }
        else
            DrawScreenPolyline(featGeom, &w2s, rp->lineStroke);
        return;
    }

    //--------------------------------------------------------------
    // handle the case repeat <= 0 - here we ignore vertex control
    //--------------------------------------------------------------

    if (style->repeat <= 0.0)
    {
        // this can be handled using the overlap direct algorithm with:
        // - repeat set to larger than each contour length
        // - vertex angle limit set to >180 degrees
        double old_val = style->vertexAngleLimit;
        double old_rep = style->repeat;
        style->vertexAngleLimit = M_PI + 1.0;   // any value greater than M_PI
        style->repeat = DBL_MAX;

        ProcessLineOverlapDirect(featGeom, style);

        style->vertexAngleLimit = old_val;
        style->repeat = old_rep;
        return;
    }

    //--------------------------------------------------------------
    // check the vertex control type and call the appropriate helper
    //--------------------------------------------------------------

    if (style->vertexControl == SE_VertexControl_OverlapNone)
        ProcessLineOverlapNone(featGeom, style);
    else if (style->vertexControl == SE_VertexControl_OverlapDirect)
        ProcessLineOverlapDirect(featGeom, style);
    else
        ProcessLineOverlapWrap(featGeom, style);
}
///////////////////////////////////////////////////////////////////////////////
// Called when applying an area style on a feature geometry.  Area styles can
// can only be applied to polygon feature geometry types.
void SE_Renderer::ProcessArea(SE_ApplyContext* ctx, SE_RenderAreaStyle* style)
{
    // the feature geometry we're applying the style on...
    LineBuffer* featGeom = ctx->geometry;

    // can't apply an area style to point and linestring geometry types
    switch (featGeom->geom_type())
    {
        case GeometryType_Point:
        case GeometryType_MultiPoint:
        case GeometryType_LineString:
        case GeometryType_MultiLineString:
        case GeometryType_CurveString:
        case GeometryType_MultiCurveString:
            return;
    }

    SE_Matrix w2s;
    GetWorldToScreenTransform(w2s);

    //--------------------------------------------------------------
    // special code to handle simple solid fill styles
    //--------------------------------------------------------------

    if (style->solidFill)
    {
        // just draw it and bail out of the layout function
        SE_RenderPolygon* rp = (SE_RenderPolygon*)style->symbol[0];

        if (m_bSelectionMode)
            DrawScreenPolygon(featGeom, &w2s, m_selFillColor);
        else
            DrawScreenPolygon(featGeom, &w2s, rp->fill);
        return;
    }

    // transform the feature geometry to rendering space
    LineBuffer* xfgeom = LineBufferPool::NewLineBuffer(m_pPool, featGeom->point_count());
    std::auto_ptr<LineBuffer> spLB(xfgeom);
    *xfgeom = *featGeom;

    int size = featGeom->point_count();
    for (int i=0; i<size; ++i)
        w2s.transform(xfgeom->x_coord(i), xfgeom->y_coord(i));

    // recompute the bounds
    RS_Bounds& bounds = const_cast<RS_Bounds&>(xfgeom->bounds());
    bounds.minx = bounds.miny = bounds.minz = +DBL_MAX;
    bounds.maxx = bounds.maxy = bounds.maxz = -DBL_MAX;
    xfgeom->ComputeBounds(bounds);

    // account for any viewport rotation
    SE_AreaPositioning ap(xfgeom, style, GetWorldToScreenRotation());
    double baserot = ap.PatternRotation();

    SE_Matrix xform;
    SE_Matrix xformbase = *ctx->xform;
    xformbase.rotate(baserot);

    for (const Point2D* pos = ap.NextLocation(); pos != NULL; pos = ap.NextLocation())
    {
        xform = xformbase;
        xform.translate(pos->x, pos->y);
        DrawSymbol(style->symbol, xform, baserot, style->addToExclusionRegion);
    }

    LineBufferPool::FreeLineBuffer(m_pPool, spLB.release());
}
void PointAdapter::Stylize(Renderer*                   renderer,
                           RS_FeatureReader*           features,
                           bool                        initialPass,
                           SE_Evaluator*               eval,
                           LineBuffer*                 geometry,
                           MdfModel::FeatureTypeStyle* style,
                           const MdfModel::MdfString*  tooltip,
                           const MdfModel::MdfString*  url,
                           RS_ElevationSettings*       elevSettings,
                           CSysTransformer*            /*layer2mapxformer*/)
{
    m_eval = eval;

    // no need to do anything if the style is not a point style, so quit
    if (FeatureTypeStyleVisitor::DetermineFeatureTypeStyle(style) != FeatureTypeStyleVisitor::ftsPoint)
        return;

    //-------------------------------------------------------
    // determine the rule for the feature
    //-------------------------------------------------------

    MdfModel::RuleCollection* prc = style->GetRules();
    MdfModel::PointRule* rule = NULL;

    for (int i=0; i<prc->GetCount(); ++i)
    {
        rule = static_cast<MdfModel::PointRule*>(prc->GetAt(i));

        // apply any filter on the rule - if it fails move to the next rule
        if (!ExecFilter(&rule->GetFilter()))
        {
            // don't stylize with failed rule
            rule = NULL;
            continue;
        }

        break;
    }

    if (!rule)
        return;

    MdfModel::PointSymbolization2D* psym = rule->GetSymbolization();

    MdfModel::PointTypeStyle* pfs = (MdfModel::PointTypeStyle*)style;

    //-------------------------------------------------------
    // prepare the geometry on which to apply the style
    //-------------------------------------------------------

    // NOTE: clipping of geometry for rendering (the RequiresClipping
    //       option) does not need to be done for points.  Points
    //       outside the map extents already get clipped away as part
    //       of the FDO query.

    LineBuffer* lb = geometry;
    std::auto_ptr<LineBuffer> spClipLB;

    if (renderer->RequiresClipping())
    {
        // clip geometry to given extents
        // NOTE: point styles do not require a clip offset
        LineBuffer* lbc = lb->Clip(renderer->GetBounds(), LineBuffer::ctAGF, m_lbPool);
        if (lbc != lb)
        {
            // if the clipped buffer is NULL (completely clipped) just move on to
            // the next feature
            if (!lbc)
                return;

            // otherwise continue processing with the clipped buffer
            lb = lbc;
            if (lb != geometry)
                spClipLB.reset(lb);
        }
    }

    //-------------------------------------------------------
    // do the StartFeature notification
    //-------------------------------------------------------

    RS_String tip; //TODO: this should be quick since we are not assigning
    RS_String eurl;
    const RS_String &theme = rule->GetLegendLabel();

    if (tooltip && !tooltip->empty())
        EvalString(*tooltip, tip);
    if (url && !url->empty())
        EvalString(*url, eurl);

    // elevation settings
    RS_ElevationType elevType = RS_ElevationType_RelativeToGround;
    double zOffset = 0.0;
    double zExtrusion = 0.0;
    GetElevationParams(elevSettings, zOffset, zExtrusion, elevType);

    renderer->StartFeature(features, initialPass,
                           tip.empty()? NULL : &tip,
                           eurl.empty()? NULL : &eurl,
                           theme.empty()? NULL : &theme,
                           zOffset, zExtrusion, elevType);

    //-------------------------------------------------------
    // apply the style to the geometry using the renderer
    //-------------------------------------------------------

    // Process point symbol, if any.  If there is no point symbol, there may
    // be a label which we will use as a symbol instead.  This one does not
    // obey overposting, it is always there.  The marker specified in the rule
    // is the one that does overposting.

    double mdefW = 0.01;
    double mdefH = 0.01;
    RS_Units mdefU = RS_Units_Device;
    double mdefRot = 0.0;

    // the actual position used for the marker by the renderer
    // may be returned in this structure to help place labels better
    RS_Bounds bounds = RS_Bounds(1.0, 1.0, 0.0, 0.0); // init invalid

    if (psym && psym->GetSymbol())
    {
        // quick check if style is already cached
        RS_MarkerDef* cachedStyle = m_hPointSymCache[psym];
        if (cachedStyle)
        {
            mdefW = cachedStyle->width();
            mdefH = cachedStyle->height();
            mdefU = cachedStyle->units();
            mdefRot = cachedStyle->rotation();
            renderer->ProcessMarker(lb, *cachedStyle, pfs->IsAllowOverpost(), &bounds);
        }
        else
        {
            RS_MarkerDef mdef;
            ObtainStyle(psym, mdef);

            mdefW = mdef.width();
            mdefH = mdef.height();
            mdefU = mdef.units();
            mdefRot = mdef.rotation();

            renderer->ProcessMarker(lb, mdef, pfs->IsAllowOverpost(), &bounds);
        }
    }

    //-------------------------------------------------------
    // do labeling if needed
    //-------------------------------------------------------

    MdfModel::Label* label = rule->GetLabel();
    if (label && label->GetSymbol())
    {
        // NOTE: clipping of geometry for labeling (the RequiresLabelClipping
        //       option) does not need to be done for points.

        // TODO: compute label position
        double cx = std::numeric_limits<double>::quiet_NaN();
        double cy = std::numeric_limits<double>::quiet_NaN();
        double dummy;

        // multi should work for simple polygons also
        lb->Centroid(LineBuffer::ctPoint, &cx, &cy, &dummy);

        if (!_isnan(cx) && !_isnan(cy))
        {
            // if there was no point symbol, the label is the symbol,
            // so we send without overposting and at the center point
            if (!psym || !psym->GetSymbol() || pfs->IsDisplayAsText())
            {
                AddLabel(cx, cy, 0.0, false, label, RS_OverpostType_All, !pfs->IsAllowOverpost(), renderer, lb);
            }
            else
            {
                MdfModel::TextSymbol* text = label->GetSymbol();

                RS_String txt;
                EvalString(text->GetText(), txt);

                if (!txt.empty())
                {
                    RS_TextDef def;
                    ConvertTextDef(text, def);

                    // if there's a symbol there are 8 possible positions to place the label
                    // around the symbol

                    // NOTE: at this point we know that mdef has been initialized with
                    //       whatever was in psym->GetSymbol() and that expressions have
                    //       been evaluated

                    double op_pts[16];

                    // offset the label from the symbol's edge
                    double offset = 0.001 * POINT_LABEL_OFFSET_MM;  // in meters
                    if (def.rotation() != 0.0)
                    {
                        // if the text label has rotation put the text at least half the font height
                        // away, so that it doesn't intersect with the marker at the worst-case (45
                        // degree) rotation.
                        offset += 0.5*def.font().height();
                    }

                    // in case of mapping space we need to scale by map scale
                    if (mdefU != RS_Units_Device)
                        offset *= renderer->GetMapScale();

                    // compute how far label needs to be offset from center point of symbol
                    double w = 0.5 * mdefW;
                    double h = 0.5 * mdefH;
                    double ch = 0;      // vertical center point
                    double cw = 0;      // horizontal center point

                    w += offset;
                    h += offset;

                    bool useBounds = bounds.IsValid();
                    if (useBounds)
                    {
                        bounds.maxx += offset;    bounds.maxy += offset;
                        bounds.minx -= offset;    bounds.miny -= offset;
                        ch = 0.5*(bounds.maxy + bounds.miny);
                        cw = 0.5*(bounds.maxx + bounds.minx);
                    }

                    // take into account rotation of the symbol
                    // find increased extents of the symbol bounds due to the rotation
                    if (mdefRot != 0.0)
                    {
                        double rotRad = mdefRot * M_PI180;
                        double cs = cos(rotRad);
                        double sn = sin(rotRad);

                        double wcs, nwcs, wsn, nwsn, hsn, nhsn, hcs, nhcs, cwsn, cwcs, chsn, chcs;
                        // check to see if the bounds have been set
                        if (useBounds)
                        {
                            wcs = bounds.maxx * cs;   nwcs = bounds.minx * cs;
                            wsn = bounds.maxx * sn;   nwsn = bounds.minx * sn;
                            hsn = bounds.maxy * sn;   nhsn = bounds.miny * sn;
                            hcs = bounds.maxy * cs;   nhcs = bounds.miny * cs;
                        }
                        else
                        {
                            wcs = w * cs;   nwcs = -wcs;
                            wsn = w * sn;   nwsn = -wsn;
                            hsn = h * sn;   nhsn = -hsn;
                            hcs = h * cs;   nhcs = -hcs;
                        }

                        cwsn = cw * sn;     chsn = ch * sn;
                        cwcs = cw * cs;     chcs = ch * cs;

                        // find the octant that the marker is rotated into, and shift the points accordingly.
                        // this way, the overpost points are still within 22.5 degrees of an axis-aligned box.
                        // (position 0 will always be the closest to Center-Right)
                        double nangle = fmod(mdefRot, 360.0);
                        if (nangle < 0.0)
                            nangle += 360.0;
                        int i = (((int)((nangle/45.0) + 0.5)) << 1) & 0x0000000f; // i is 2 * the octant
                        op_pts[i++] =  wcs - chsn;  op_pts[i++] =  wsn + chcs;  i &= 0x0000000f; // & 15 does (mod 16)
                        op_pts[i++] =  wcs -  hsn;  op_pts[i++] =  wsn +  hcs;  i &= 0x0000000f;
                        op_pts[i++] = cwcs -  hsn;  op_pts[i++] = cwsn +  hcs;  i &= 0x0000000f;
                        op_pts[i++] = nwcs -  hsn;  op_pts[i++] = nwsn +  hcs;  i &= 0x0000000f;
                        op_pts[i++] = nwcs - chsn;  op_pts[i++] = nwsn + chcs;  i &= 0x0000000f;
                        op_pts[i++] = nwcs - nhsn;  op_pts[i++] = nwsn + nhcs;  i &= 0x0000000f;
                        op_pts[i++] = cwcs - nhsn;  op_pts[i++] = cwsn + nhcs;  i &= 0x0000000f;
                        op_pts[i++] =  wcs - nhsn;  op_pts[i]   =  wsn + nhcs;
                    }
                    else
                    {
                        if (!useBounds)
                        {
                            bounds.maxx = w;    bounds.minx = -w;
                            bounds.maxy = h;    bounds.miny = -h;
                        }
                        op_pts[ 0] = bounds.maxx;   op_pts[ 1] = ch;
                        op_pts[ 2] = bounds.maxx;   op_pts[ 3] = bounds.maxy;
                        op_pts[ 4] = cw;            op_pts[ 5] = bounds.maxy;
                        op_pts[ 6] = bounds.minx;   op_pts[ 7] = bounds.maxy;
                        op_pts[ 8] = bounds.minx;   op_pts[ 9] = ch;
                        op_pts[10] = bounds.minx;   op_pts[11] = bounds.miny;
                        op_pts[12] = cw;            op_pts[13] = bounds.miny;
                        op_pts[14] = bounds.maxx;   op_pts[15] = bounds.miny;
                    }

                    RS_LabelInfo candidates[8];

                    def.halign() = RS_HAlignment_Left;
                    def.valign() = RS_VAlignment_Half;
                    candidates[0] = RS_LabelInfo(cx, cy, op_pts[0], op_pts[1], mdefU, def);

                    def.valign() = RS_VAlignment_Descent;
                    candidates[1] = RS_LabelInfo(cx, cy, op_pts[2], op_pts[3], mdefU, def);

                    def.halign() = RS_HAlignment_Center;
                    candidates[2] = RS_LabelInfo(cx, cy, op_pts[4], op_pts[5], mdefU, def);

                    def.halign() = RS_HAlignment_Right;
                    candidates[3] = RS_LabelInfo(cx, cy, op_pts[6], op_pts[7], mdefU, def);

                    def.valign() = RS_VAlignment_Half;
                    candidates[4] = RS_LabelInfo(cx, cy, op_pts[8], op_pts[9], mdefU, def);

                    def.valign() = RS_VAlignment_Ascent;
                    candidates[5] = RS_LabelInfo(cx, cy, op_pts[10], op_pts[11], mdefU, def);

                    def.halign() = RS_HAlignment_Center;
                    candidates[6] = RS_LabelInfo(cx, cy, op_pts[12], op_pts[13], mdefU, def);

                    def.halign() = RS_HAlignment_Left;
                    candidates[7] = RS_LabelInfo(cx, cy, op_pts[14], op_pts[15], mdefU, def);

                    renderer->ProcessLabelGroup(candidates, 8, txt, RS_OverpostType_FirstFit, true, lb, text->GetScaleLimit());
                }
            }
        }
    }

    // free clipped line buffer if the geometry was clipped
    if (spClipLB.get())
        LineBufferPool::FreeLineBuffer(m_lbPool, spClipLB.release());
}
///////////////////////////////////////////////////////////////////////////////
// Called when applying a point style on a feature geometry.  Point styles can
// be applied to all feature geometry types.
void SE_Renderer::ProcessPoint(SE_ApplyContext* ctx, SE_RenderPointStyle* style, RS_Bounds* bounds)
{
    // the feature geometry we're applying the style on...
    LineBuffer* featGeom = ctx->geometry;

    double angleRad = 0.0;
    if (style->angleControl == SE_AngleControl_FromGeometry)
    {
        switch (featGeom->geom_type())
        {
            case GeometryType_LineString:
            case GeometryType_MultiLineString:
            case GeometryType_Polygon:
            case GeometryType_MultiPolygon:
            {
                double x0, y0;
                featGeom->Centroid(LineBuffer::ctLine, &x0, &y0, &angleRad);
                break;
            }
        }
    }

    angleRad += style->angleRad;

    // also account for any viewport rotation
    angleRad += GetWorldToScreenRotation();

    SE_Matrix xform;
    bool yUp = YPointsUp();

    // see StylizationEngine::Stylize for a detailed explanation of these transforms
    SE_Matrix xformbase;
    xformbase.translate(style->offset[0], style->offset[1]);
    xformbase.rotate(yUp? angleRad : -angleRad);
    xformbase.premultiply(*ctx->xform);

    // render the points
    for (int i=0; i<featGeom->point_count(); ++i)
    {
        double x, y;
        featGeom->get_point(i, x, y);

        // transform to screen space - feature geometry is in [the original] mapping space
        WorldToScreenPoint(x, y, x, y);

        xform = xformbase;
        xform.translate(x, y);

        if (style->drawLast)
            AddLabel(featGeom, style, xform, angleRad);
        else
            DrawSymbol(style->symbol, xform, angleRad, style->addToExclusionRegion);
    }

    if (bounds)
    {
        // get the symbol bounds after applying the transforms
        bounds->minx = bounds->miny = +DBL_MAX;
        bounds->maxx = bounds->maxy = -DBL_MAX;
        for (int i=0; i<4; ++i)
        {
            RS_F_Point xfpt;
            xformbase.transform(style->bounds[i].x, style->bounds[i].y, xfpt.x, xfpt.y);
            bounds->add_point(xfpt);
        }
    }
}
Example #13
0
void	
OutputFile::writePixels (int numScanLines)
{
    try
    {
        Lock lock (*_data);

	if (_data->slices.size() == 0)
	    throw Iex::ArgExc ("No frame buffer specified "
			       "as pixel data source.");

        //
        // Maintain two iterators:
        //     nextWriteBuffer: next linebuffer to be written to the file
        //     nextCompressBuffer: next linebuffer to compress
        //

        int first = (_data->currentScanLine - _data->minY) /
                         _data->linesInBuffer;

        int nextWriteBuffer = first;
        int nextCompressBuffer;
        int stop;
        int step;
        int scanLineMin;
        int scanLineMax;

        {
            //
            // Create a task group for all line buffer tasks. When the
            // taskgroup goes out of scope, the destructor waits until
	    // all tasks are complete.
            //
            
            TaskGroup taskGroup;
            
            //
            // Determine the range of lineBuffers that intersect the scan
	    // line range.  Then add the initial compression tasks to the
	    // thread pool.  We always add in at least one task but the
	    // individual task might not do anything if numScanLines == 0.
            //
    
            if (_data->lineOrder == INCREASING_Y)
            {
                int last = (_data->currentScanLine + (numScanLines - 1) -
                            _data->minY) / _data->linesInBuffer;
    
                scanLineMin = _data->currentScanLine;
                scanLineMax = _data->currentScanLine + numScanLines - 1;
    
                int numTasks = max (min ((int)_data->lineBuffers.size(),
                                         last - first + 1),
				    1);

                for (int i = 0; i < numTasks; i++)
		{
                    ThreadPool::addGlobalTask
                        (new LineBufferTask (&taskGroup, _data, first + i,
                                             scanLineMin, scanLineMax));
		}
    
                nextCompressBuffer = first + numTasks;
                stop = last + 1;
                step = 1;
            }
            else
            {
                int last = (_data->currentScanLine - (numScanLines - 1) -
                            _data->minY) / _data->linesInBuffer;
    
                scanLineMax = _data->currentScanLine;
                scanLineMin = _data->currentScanLine - numScanLines + 1;
    
                int numTasks = max (min ((int)_data->lineBuffers.size(),
                                         first - last + 1),
				    1);

                for (int i = 0; i < numTasks; i++)
		{
                    ThreadPool::addGlobalTask
                        (new LineBufferTask (&taskGroup, _data, first - i,
                                             scanLineMin, scanLineMax));
		}
    
                nextCompressBuffer = first - numTasks;
                stop = last - 1;
                step = -1;
            }
            
            while (true)
            {
                if (_data->missingScanLines <= 0)
                {
                    throw Iex::ArgExc ("Tried to write more scan lines "
                                       "than specified by the data window.");
                }
    
		//
                // Wait until the next line buffer is ready to be written
		//

                LineBuffer *writeBuffer =
		    _data->getLineBuffer (nextWriteBuffer);

                writeBuffer->wait();
                
                int numLines = writeBuffer->scanLineMax - 
                               writeBuffer->scanLineMin + 1;

                _data->missingScanLines -= numLines;
    
		//
                // If the line buffer is only partially full, then it is
		// not complete and we cannot write it to disk yet.
		//

                if (writeBuffer->partiallyFull)
                {
                    _data->currentScanLine = _data->currentScanLine +
                                             step * numLines;
                    writeBuffer->post();
    
                    return;
                }
    
		//
                // Write the line buffer
		//

                writePixelData (_data, writeBuffer);
                nextWriteBuffer += step;

                _data->currentScanLine = _data->currentScanLine +
                                         step * numLines;
    
                #ifdef DEBUG
    
                    assert (_data->currentScanLine ==
                            ((_data->lineOrder == INCREASING_Y) ?
                             writeBuffer->scanLineMax + 1:
                             writeBuffer->scanLineMin - 1));
    
                #endif
                
		//
                // Release the lock on the line buffer
		//

                writeBuffer->post();
                
		//
                // If this was the last line buffer in the scanline range
		//

                if (nextWriteBuffer == stop)
                    break;
    
		//
                // If there are no more line buffers to compress,
                // then only continue to write out remaining lineBuffers
		//

                if (nextCompressBuffer == stop)
                    continue;
    
		//
                // Add nextCompressBuffer as a compression task
		//

                ThreadPool::addGlobalTask
                    (new LineBufferTask (&taskGroup, _data, nextCompressBuffer,
                                         scanLineMin, scanLineMax));
                
		//
                // Update the next line buffer we need to compress
		//

                nextCompressBuffer += step;
            }
        
	    //
            // Finish all tasks
	    //
        }
        
	//
	// Exeption handling:
	//
	// LineBufferTask::execute() may have encountered exceptions, but
	// those exceptions occurred in another thread, not in the thread
	// that is executing this call to OutputFile::writePixels().
	// LineBufferTask::execute() has caught all exceptions and stored
	// the exceptions' what() strings in the line buffers.
	// Now we check if any line buffer contains a stored exception; if
	// this is the case then we re-throw the exception in this thread.
	// (It is possible that multiple line buffers contain stored
	// exceptions.  We re-throw the first exception we find and
	// ignore all others.)
	//

	const string *exception = 0;

        for (int i = 0; i < _data->lineBuffers.size(); ++i)
	{
            LineBuffer *lineBuffer = _data->lineBuffers[i];

	    if (lineBuffer->hasException && !exception)
		exception = &lineBuffer->exception;

	    lineBuffer->hasException = false;
	}

	if (exception)
	    throw Iex::IoExc (*exception);
    }
    catch (Iex::BaseExc &e)
    {
	REPLACE_EXC (e, "Failed to write pixel data to image "
		        "file \"" << fileName() << "\". " << e);
	throw;
    }
}
void PolygonAdapter::Stylize(Renderer*                   renderer,
                             RS_FeatureReader*           features,
                             bool                        initialPass,
                             SE_Evaluator*               eval,
                             LineBuffer*                 geometry,
                             MdfModel::FeatureTypeStyle* style,
                             const MdfModel::MdfString*  tooltip,
                             const MdfModel::MdfString*  url,
                             RS_ElevationSettings*       elevSettings,
                             CSysTransformer*            /*layer2mapxformer*/)
{
    m_eval = eval;

    // no need to do anything if the style is not an area style, so quit
    if (FeatureTypeStyleVisitor::DetermineFeatureTypeStyle(style) != FeatureTypeStyleVisitor::ftsArea)
        return;

    //-------------------------------------------------------
    // determine the rule for the feature
    //-------------------------------------------------------

    MdfModel::RuleCollection* arc = style->GetRules();
    MdfModel::AreaRule* rule = NULL;

    for (int i=0; i<arc->GetCount(); ++i)
    {
        rule = static_cast<MdfModel::AreaRule*>(arc->GetAt(i));

        // apply any filter on the rule - if it fails move to the next rule
        if (!ExecFilter(&rule->GetFilter()))
        {
            // don't stylize with failed rule
            rule = NULL;
            continue;
        }

        break;
    }

    if (!rule)
        return;

    MdfModel::AreaSymbolization2D* asym = rule->GetSymbolization();
    if (asym == NULL)
        return;

    //-------------------------------------------------------
    // evaluate the style to use
    //-------------------------------------------------------

    // quick check if style is already cached
    RS_FillStyle* fillStyle = m_hAreaSymCache[asym];
    if (!fillStyle)
    {
        // if not, then we need to either cache or evaluate it
        fillStyle = &m_fillStyle;
        ObtainStyle(asym, *fillStyle);
    }

    //-------------------------------------------------------
    // compute the clip offset from the styles
    //-------------------------------------------------------

    double clipOffsetWU = 0.0;  // in mapping units

    bool bClip      = renderer->RequiresClipping();
    bool bLabelClip = renderer->RequiresLabelClipping();

    if (bClip || bLabelClip)
    {
        double mapScale = renderer->GetMapScale();

        // in meters in device units
        double clipOffsetMeters = GetClipOffset(fillStyle->outline(), mapScale);

        // add one pixel's worth to handle any roundoff
        clipOffsetMeters += METERS_PER_INCH / renderer->GetDpi();

        // limit the offset to something reasonable
        if (clipOffsetMeters > MAX_CLIPOFFSET_IN_METERS)
            clipOffsetMeters = MAX_CLIPOFFSET_IN_METERS;

        // convert to mapping units
        clipOffsetWU = clipOffsetMeters * mapScale / renderer->GetMetersPerUnit();
    }

    //-------------------------------------------------------
    // prepare the geometry on which to apply the style
    //-------------------------------------------------------

    LineBuffer* lb = geometry;
    std::auto_ptr<LineBuffer> spClipLB;

    if (bClip)
    {
        // the clip region is the map request extents expanded by the offset
        RS_Bounds clip = renderer->GetBounds();
        clip.minx -= clipOffsetWU;
        clip.miny -= clipOffsetWU;
        clip.maxx += clipOffsetWU;
        clip.maxy += clipOffsetWU;

        // clip geometry to given extents
        LineBuffer* lbc = lb->Clip(clip, LineBuffer::ctAGF, m_lbPool);
        if (lbc != lb)
        {
            // if the clipped buffer is NULL (completely clipped) just move on to
            // the next feature
            if (!lbc)
                return;

            // otherwise continue processing with the clipped buffer
            lb = lbc;
            if (lb != geometry)
                spClipLB.reset(lb);
        }
    }

    //-------------------------------------------------------
    // do the StartFeature notification
    //-------------------------------------------------------

    RS_String tip; //TODO: this should be quick since we are not assigning
    RS_String eurl;
    const RS_String &theme = rule->GetLegendLabel();

    if (tooltip && !tooltip->empty())
        EvalString(*tooltip, tip);
    if (url && !url->empty())
        EvalString(*url, eurl);

    // elevation settings
    RS_ElevationType elevType = RS_ElevationType_RelativeToGround;
    double zOffset = 0.0;
    double zExtrusion = 0.0;
    GetElevationParams(elevSettings, zOffset, zExtrusion, elevType);

    renderer->StartFeature(features, initialPass,
                           tip.empty()? NULL : &tip,
                           eurl.empty()? NULL : &eurl,
                           theme.empty()? NULL : &theme,
                           zOffset, zExtrusion, elevType);

    //-------------------------------------------------------
    // apply the style to the geometry using the renderer
    //-------------------------------------------------------

    renderer->ProcessPolygon(lb, *fillStyle);

    //-------------------------------------------------------
    // do labeling if needed
    //-------------------------------------------------------

    MdfModel::Label* label = rule->GetLabel();
    if (label && label->GetSymbol())
    {
        // Make sure the geometry is clipped if label clipping is specified.
        // If bClip is true then the geometry is already clipped.
        if (!bClip && bLabelClip)
        {
            // the clip region is the map request extents expanded by the offset
            RS_Bounds clip = renderer->GetBounds();
            clip.minx -= clipOffsetWU;
            clip.miny -= clipOffsetWU;
            clip.maxx += clipOffsetWU;
            clip.maxy += clipOffsetWU;

            LineBuffer* lbc = lb->Clip(clip, LineBuffer::ctAGF, m_lbPool);
            if (lbc != lb)
            {
                // if the clipped buffer is NULL (completely clipped) just move on to
                // the next feature
                if (!lbc)
                    return;

                // otherwise continue processing with the clipped buffer
                lb = lbc;
                if (lb != geometry)
                    spClipLB.reset(lb);
            }
        }

        double cx = std::numeric_limits<double>::quiet_NaN();
        double cy = std::numeric_limits<double>::quiet_NaN();
        double dummy;

        // multi should work for simple polygons too
        lb->Centroid(LineBuffer::ctArea, &cx, &cy, &dummy);

        if (!_isnan(cx) && !_isnan(cy))
            AddLabel(cx, cy, 0.0, false, label, RS_OverpostType_AllFit, true, renderer, lb);
    }

    // free clipped line buffer if the geometry was clipped
    if (spClipLB.get())
        LineBufferPool::FreeLineBuffer(m_lbPool, spClipLB.release());
}
void SE_PositioningAlgorithms::EightSurrounding(SE_ApplyContext* applyCtx,
                                                SE_RenderStyle*  rstyle,
                                                double           mm2su)
{
    SE_Renderer* se_renderer = applyCtx->renderer;
    LineBuffer* geometry = applyCtx->geometry;

    // eight surrounding labeling only applies to point feature geometry
    switch (geometry->geom_type())
    {
        case GeometryType_Point:
        case GeometryType_MultiPoint:
            break;

        default:
            return;
    }

    // eight surrounding labeling only works with point styles
    if (rstyle->type != SE_RenderStyle_Point)
        return;

    // the style needs to contain at least one primitive
    SE_RenderPrimitiveList& prims = rstyle->symbol;
    if (prims.size() == 0)
        return;

    SE_RenderPointStyle* rpstyle = (SE_RenderPointStyle*)rstyle;

    // get actual feature point and transform to screen space
    // TODO: in the case of a multi-point feature we get the average of all the points;
    //       generating candidate labels around this point doesn't make a whole lot of
    //       sense
    double cx = 0.0;
    double cy = 0.0;
    geometry->Centroid(LineBuffer::ctPoint, &cx, &cy, NULL);

    // don't add a label if we can't compute the centroid
    if (_isnan(cx) || _isnan(cy))
        return;

    se_renderer->WorldToScreenPoint(cx, cy, cx, cy);

    // Get the extent of the last drawn point symbol so that we know how much to offset
    // the label.  This call assumes the symbol draws right before the label.
    // TODO: remove this assumption
    const RS_F_Point* cfpts = se_renderer->GetLastSymbolExtent();
    RS_F_Point fpts[4];
    if(cfpts[0].x == 0 && cfpts[0].y == 0 &&
        cfpts[1].x == 0 && cfpts[1].y == 0 &&
        cfpts[2].x == 0 && cfpts[2].y == 0 &&
        cfpts[3].x == 0 && cfpts[3].y == 0)
    {
        for (int i=0; i<4; ++i)
        {
            fpts[i].x = cx;
            fpts[i].y = cy;
        }
    }
    else
        memcpy(fpts, cfpts, 4*sizeof(RS_F_Point));

    double dx = fpts[1].x - fpts[0].x;
    double dy = fpts[1].y - fpts[0].y;
    double symbol_rot_rad = atan2(dy, dx);

    // factor out position and rotation
    SE_Matrix ixform;
    ixform.translate(-cx, -cy);     // factor out point position
    ixform.rotate(-symbol_rot_rad); // factor out rotation
    for (int i=0; i<4; ++i)
        ixform.transform(fpts[i].x, fpts[i].y);

    bool yUp = se_renderer->YPointsUp();
    if (!yUp)
        symbol_rot_rad = -symbol_rot_rad;

    // unrotated bounds
    RS_Bounds symbol_bounds(fpts[0].x, fpts[0].y, fpts[2].x, fpts[2].y);
    double symbol_width  = symbol_bounds.width();   // symbol width in screen units
    double symbol_height = symbol_bounds.height();  // symbol height in screen units

    // offset the label from the symbol's edge
    double offset = POINT_LABEL_OFFSET_MM * mm2su;  // offset in screen units

    // make sure we have at least one pixel's worth of offset
    double screenUnitsPerPixel = MILLIMETERS_PER_INCH * se_renderer->GetScreenUnitsPerMillimeterDevice() / se_renderer->GetDpi();
    if (offset < screenUnitsPerPixel)
        offset = screenUnitsPerPixel;

    // compute how far label needs to be offset from center point of symbol
    double w2 = 0.5 * symbol_width;
    double h2 = 0.5 * symbol_height;
    double ch = 0.0;    // vertical center point
    double cw = 0.0;    // horizontal center point

    w2 += offset;
    h2 += offset;

    bool useBounds = symbol_bounds.IsValid();
    if (useBounds)
    {
        symbol_bounds.maxx += offset;    symbol_bounds.maxy += offset;
        symbol_bounds.minx -= offset;    symbol_bounds.miny -= offset;
        ch = 0.5*(symbol_bounds.maxy + symbol_bounds.miny);
        cw = 0.5*(symbol_bounds.maxx + symbol_bounds.minx);
    }

    // get the viewport rotation
    double w2sAngleRad = se_renderer->GetWorldToScreenRotation();

    // take into account rotation of the symbol - find increased extents
    // of the symbol bounds due to the rotation
    double op_pts[16];
    if (symbol_rot_rad != 0.0)
    {
        double cs = cos(symbol_rot_rad);
        double sn = sin(symbol_rot_rad);

        // check to see if the bounds have been set
        double wcs, nwcs, wsn, nwsn, hsn, nhsn, hcs, nhcs, cwsn, cwcs, chsn, chcs;
        if (useBounds)
        {
            wcs = symbol_bounds.maxx * cs;   nwcs = symbol_bounds.minx * cs;
            wsn = symbol_bounds.maxx * sn;   nwsn = symbol_bounds.minx * sn;
            hsn = symbol_bounds.maxy * sn;   nhsn = symbol_bounds.miny * sn;
            hcs = symbol_bounds.maxy * cs;   nhcs = symbol_bounds.miny * cs;
        }
        else
        {
            wcs = w2 * cs;   nwcs = -wcs;
            wsn = w2 * sn;   nwsn = -wsn;
            hsn = h2 * sn;   nhsn = -hsn;
            hcs = h2 * cs;   nhcs = -hcs;
        }

        cwsn = cw * sn;     chsn = ch * sn;
        cwcs = cw * cs;     chcs = ch * cs;

        // Find the octant that the symbol is rotated into, and shift the points accordingly.
        // This way the overpost points are still within 22.5 degrees of an axis-aligned box
        // (position 0 will always be the closest to Center-Right).
        // NOTE: The symbol rotation includes the viewport rotation.  We want to use the
        //       relative angle between these to compute the quadrant (it's the angle of
        //       the symbol relative to the viewport which matters).
        double relativeAngle = symbol_rot_rad - w2sAngleRad;
        double nangle = fmod(relativeAngle * M_180PI, 360.0);
        if (nangle < 0.0)
            nangle += 360.0;
        int i = (((int)((nangle/45.0) + 0.5)) << 1) & 0x0000000f; // i is 2 * the octant
        op_pts[i++] =  wcs - chsn;  op_pts[i++] =  wsn + chcs;  i &= 0x0000000f; // & 15 does (mod 16)
        op_pts[i++] =  wcs -  hsn;  op_pts[i++] =  wsn +  hcs;  i &= 0x0000000f;
        op_pts[i++] = cwcs -  hsn;  op_pts[i++] = cwsn +  hcs;  i &= 0x0000000f;
        op_pts[i++] = nwcs -  hsn;  op_pts[i++] = nwsn +  hcs;  i &= 0x0000000f;
        op_pts[i++] = nwcs - chsn;  op_pts[i++] = nwsn + chcs;  i &= 0x0000000f;
        op_pts[i++] = nwcs - nhsn;  op_pts[i++] = nwsn + nhcs;  i &= 0x0000000f;
        op_pts[i++] = cwcs - nhsn;  op_pts[i++] = cwsn + nhcs;  i &= 0x0000000f;
        op_pts[i++] =  wcs - nhsn;  op_pts[i  ] =  wsn + nhcs;
    }
    else
    {
        if (!useBounds)
        {
            symbol_bounds.maxx = w2; symbol_bounds.minx = -w2;
            symbol_bounds.maxy = h2; symbol_bounds.miny = -h2;
        }
        op_pts[0 ] = symbol_bounds.maxx; op_pts[1 ] = ch;
        op_pts[2 ] = symbol_bounds.maxx; op_pts[3 ] = symbol_bounds.maxy;
        op_pts[4 ] = cw;                 op_pts[5 ] = symbol_bounds.maxy;
        op_pts[6 ] = symbol_bounds.minx; op_pts[7 ] = symbol_bounds.maxy;
        op_pts[8 ] = symbol_bounds.minx; op_pts[9 ] = ch;
        op_pts[10] = symbol_bounds.minx; op_pts[11] = symbol_bounds.miny;
        op_pts[12] = cw;                 op_pts[13] = symbol_bounds.miny;
        op_pts[14] = symbol_bounds.maxx; op_pts[15] = symbol_bounds.miny;
    }

    // check if the incoming point style contains just a single text element
    bool foundSingleText = false;
    if (prims.size() == 1)
    {
        if (prims[0]->type == SE_RenderPrimitive_Text)
            foundSingleText = true;
    }

    // OK, who says I can't write bad code? Behold:
    SE_LabelInfo candidates[8];
    double yScale = yUp? 1.0 : -1.0; // which way does y go in the renderer?

    double angleRad = rpstyle->angleRad;

    // also account for the viewport rotation
    angleRad += w2sAngleRad;

    if (foundSingleText)
    {
        // In this case we set the appropriate alignments for the single text element
        // in each candidate label.  This allows us to draw the symbol directly at the
        // candidate points surrounding the feature point.

        SE_RenderStyle* st0 = se_renderer->CloneRenderStyle(rpstyle);
        ((SE_RenderText*)st0->symbol[0])->tdef.halign() = RS_HAlignment_Left;
        ((SE_RenderText*)st0->symbol[0])->tdef.valign() = RS_VAlignment_Half;
        UpdateStyleBounds(st0, se_renderer);
        candidates[0].Set(cx + op_pts[ 0], cy + op_pts[ 1]*yScale, RS_Units_Device, angleRad, st0);

        SE_RenderStyle* st1 = se_renderer->CloneRenderStyle(st0);
        ((SE_RenderText*)st1->symbol[0])->tdef.valign() = RS_VAlignment_Descent;
        UpdateStyleBounds(st1, se_renderer);
        candidates[1].Set(cx + op_pts[ 2], cy + op_pts[ 3]*yScale, RS_Units_Device, angleRad, st1);

        SE_RenderStyle* st2 = se_renderer->CloneRenderStyle(st1);
        ((SE_RenderText*)st2->symbol[0])->tdef.halign() = RS_HAlignment_Center;
        UpdateStyleBounds(st2, se_renderer);
        candidates[2].Set(cx + op_pts[ 4], cy + op_pts[ 5]*yScale, RS_Units_Device, angleRad, st2);

        SE_RenderStyle* st3 = se_renderer->CloneRenderStyle(st2);
        ((SE_RenderText*)st3->symbol[0])->tdef.halign() = RS_HAlignment_Right;
        UpdateStyleBounds(st3, se_renderer);
        candidates[3].Set(cx + op_pts[ 6], cy + op_pts[ 7]*yScale, RS_Units_Device, angleRad, st3);

        SE_RenderStyle* st4 = se_renderer->CloneRenderStyle(st3);
        ((SE_RenderText*)st4->symbol[0])->tdef.valign() = RS_VAlignment_Half;
        UpdateStyleBounds(st4, se_renderer);
        candidates[4].Set(cx + op_pts[ 8], cy + op_pts[ 9]*yScale, RS_Units_Device, angleRad, st4);

        SE_RenderStyle* st5 = se_renderer->CloneRenderStyle(st4);
        ((SE_RenderText*)st5->symbol[0])->tdef.valign() = RS_VAlignment_Ascent;
        UpdateStyleBounds(st5, se_renderer);
        candidates[5].Set(cx + op_pts[10], cy + op_pts[11]*yScale, RS_Units_Device, angleRad, st5);

        SE_RenderStyle* st6 = se_renderer->CloneRenderStyle(st5);
        ((SE_RenderText*)st6->symbol[0])->tdef.halign() = RS_HAlignment_Center;
        UpdateStyleBounds(st6, se_renderer);
        candidates[6].Set(cx + op_pts[12], cy + op_pts[13]*yScale, RS_Units_Device, angleRad, st6);

        SE_RenderStyle* st7 = se_renderer->CloneRenderStyle(st6);
        ((SE_RenderText*)st7->symbol[0])->tdef.halign() = RS_HAlignment_Left;
        UpdateStyleBounds(st7, se_renderer);
        candidates[7].Set(cx + op_pts[14], cy + op_pts[15]*yScale, RS_Units_Device, angleRad, st7);
    }
    else
    {
        // In the general case we have to account for the label symbol's extents when we
        // position each candidate.  For example, for candidate 1 (top right) we adjust the
        // position so that the bottom left corner of the label symbol's extent ends up at
        // the top right candidate point.

        double labelMinX = rpstyle->bounds[0].x;
        double labelMinY = rpstyle->bounds[0].y;
        double labelMaxX = rpstyle->bounds[2].x;
        double labelMaxY = rpstyle->bounds[2].y;
        double labelCtrX = 0.5*(labelMinX + labelMaxX);
        double labelCtrY = 0.5*(labelMinY + labelMaxY);

        SE_RenderStyle* st0 = se_renderer->CloneRenderStyle(rpstyle);
        candidates[0].Set(cx + op_pts[ 0] - labelMinX, cy + (op_pts[ 1] - labelCtrY)*yScale, RS_Units_Device, angleRad, st0);

        SE_RenderStyle* st1 = se_renderer->CloneRenderStyle(st0);
        candidates[1].Set(cx + op_pts[ 2] - labelMinX, cy + (op_pts[ 3] - labelMinY)*yScale, RS_Units_Device, angleRad, st1);

        SE_RenderStyle* st2 = se_renderer->CloneRenderStyle(st1);
        candidates[2].Set(cx + op_pts[ 4] - labelCtrX, cy + (op_pts[ 5] - labelMinY)*yScale, RS_Units_Device, angleRad, st2);

        SE_RenderStyle* st3 = se_renderer->CloneRenderStyle(st2);
        candidates[3].Set(cx + op_pts[ 6] - labelMaxX, cy + (op_pts[ 7] - labelMinY)*yScale, RS_Units_Device, angleRad, st3);

        SE_RenderStyle* st4 = se_renderer->CloneRenderStyle(st3);
        candidates[4].Set(cx + op_pts[ 8] - labelMaxX, cy + (op_pts[ 9] - labelCtrY)*yScale, RS_Units_Device, angleRad, st4);

        SE_RenderStyle* st5 = se_renderer->CloneRenderStyle(st4);
        candidates[5].Set(cx + op_pts[10] - labelMaxX, cy + (op_pts[11] - labelMaxY)*yScale, RS_Units_Device, angleRad, st5);

        SE_RenderStyle* st6 = se_renderer->CloneRenderStyle(st5);
        candidates[6].Set(cx + op_pts[12] - labelCtrX, cy + (op_pts[13] - labelMaxY)*yScale, RS_Units_Device, angleRad, st6);

        SE_RenderStyle* st7 = se_renderer->CloneRenderStyle(st6);
        candidates[7].Set(cx + op_pts[14] - labelMinX, cy + (op_pts[15] - labelMaxY)*yScale, RS_Units_Device, angleRad, st7);
    }

    se_renderer->ProcessSELabelGroup(candidates, 8, RS_OverpostType_FirstFit, true, NULL);
}
Example #16
0
	static DWORD WINAPI StdErrReaderThread(LPVOID lpParameter)
	{
		CDownloader* pObj = ((PipeThreadParm*)lpParameter)->pObj;
		char Line[4096+1]; // When output is redirected, RAW ASCII is used
		const DWORD dwToRead = countof(Line)-1;
		DWORD dwRead, nValue, nErrCode;
		BOOL bSuccess;

		CEStr szLine;
		const wchar_t *ptr;
		const wchar_t sProgressMark[]    = L" " CEDLOG_MARK_PROGR;
		const wchar_t sInformationMark[] = L" " CEDLOG_MARK_INFO;
		const wchar_t sErrorMark[]       = L" " CEDLOG_MARK_ERROR;

		LineBuffer buffer = {};
		bool bExit = false;

		while (!bExit)
		{
			bSuccess = ReadFile(pObj->mh_PipeErrRead, Line, dwToRead, &dwRead, NULL);
			if (!bSuccess || dwRead == 0)
			{
				nErrCode = GetLastError();
				break;
			}
			_ASSERTE(dwRead < countof(Line));
			Line[dwRead] = 0; // Ensure it is ASCIIZ
			// Append to the line-buffer
			buffer.AddBlock(Line, dwRead);

			// Parse read line
			while (buffer.GetLine(szLine))
			{
				bool bProgress = false;
				if ((ptr = wcsstr(szLine, sProgressMark)) != NULL)
				{
					bProgress = true;
					if (pObj->mfn_Callback[dc_ProgressCallback])
					{
						// 09:01:20.811{1234} Progr: Bytes downloaded 1656
						wchar_t* ptrEnd = NULL;
						LPCWSTR pszFrom = wcspbrk(ptr+wcslen(sProgressMark), L"0123456789");
						nValue = pszFrom ? wcstoul(pszFrom, &ptrEnd, 10) : 0;

						if (nValue)
						{
							CEDownloadInfo progrInfo = {
								sizeof(progrInfo),
								pObj->m_CallbackLParam[dc_ProgressCallback]
							};
							progrInfo.argCount = 1;
							progrInfo.Args[0].argType = at_Uint;
							progrInfo.Args[0].uintArg = nValue;

							pObj->mfn_Callback[dc_ProgressCallback](&progrInfo);
						}
					}
				}

				// For logging purposes
				if (!bProgress && ((ptr = wcsstr(szLine, sErrorMark)) != NULL))
				{
					if (pObj->mfn_Callback[dc_ErrCallback])
					{
						CEDownloadInfo Error = {
							sizeof(Error),
							pObj->m_CallbackLParam[dc_ErrCallback],
							szLine.ms_Val
						};
						pObj->mfn_Callback[dc_ErrCallback](&Error);
					}
				}
				else //if (bProgress || ((ptr = wcsstr(szLine, sInformationMark)) != NULL))
				{
					if (pObj->mfn_Callback[dc_LogCallback])
					{
						CEDownloadInfo Info = {
							sizeof(Info),
							pObj->m_CallbackLParam[dc_LogCallback],
							szLine.ms_Val
						};
						pObj->mfn_Callback[dc_LogCallback](&Info);
					}
					// Exit?
					ptr = wcsstr(szLine, sInformationMark);
					if (ptr)
					{
						ptr += wcslen(sInformationMark);
						if (wcsncmp(ptr, L"Exit", 4) == 0)
						{
							bExit = true;
							break;
						}
					}
				}
			}
		}

		return 0;
	};
void SE_PositioningAlgorithms::MultipleHighwaysShields(SE_ApplyContext*  applyCtx,
                                                       SE_RenderStyle*   rstyle,
                                                       double            mm2su,
                                                       RS_FeatureReader* featureReader,
                                                       SE_SymbolManager* symbolManager)
{
    if (featureReader == NULL)
        return;

    SE_Renderer* se_renderer = applyCtx->renderer;
    LineBuffer* geometry = applyCtx->geometry;

    // this placement algorithm only applies to line styles
    if (rstyle->type != SE_RenderStyle_Line)
        return;

    SE_RenderLineStyle* rlStyle = (SE_RenderLineStyle*)rstyle;

    // ... and the units control must be absolute
    if (rlStyle->unitsControl != SE_UnitsControl_Absolute)
        return;

    // highway info format:  countryCode|type1|num1|type2|num2|type3|num3|...
    // example:              US|2|101|3|1
    StringOfTokens highwayInfo(featureReader->GetString(L"Url"), L"|");

    int shieldCount = (highwayInfo.getTokenCount() - 1) / 2;
    if (shieldCount < 1)
        return;

    double startOffset = rlStyle->startOffset;
    double increment = rlStyle->repeat;

    // the endOffset is used in this context as the increment between multiple shields in one group
//  double incrementS = 10.0 * mm2su;
    double incrementS = rlStyle->endOffset;

    // calc the overall length of this geometry
    double totalLen = 0.0;
    for (int i=0; i<geometry->cntr_count(); ++i)
    {
        int pt = geometry->contour_start_point(i);
        int last = geometry->contour_end_point(i);
        while (pt < last)
        {
            // transform the point to screen space
            double  cx1, cy1, cx2, cy2;
            se_renderer->WorldToScreenPoint(geometry->x_coord(pt), geometry->y_coord(pt), cx1, cy1);
            pt++;
            se_renderer->WorldToScreenPoint(geometry->x_coord(pt), geometry->y_coord(pt), cx2, cy2);

            // calc length
            double dx = cx2 - cx1;
            double dy = cy2 - cy1;
            totalLen += sqrt(dx*dx + dy*dy);
        }
    }

    if (startOffset >= 0.0)
    {
        // calc optimal start offset (with rlStyle->startOffset taken as a minimum)
        // to co-locate shield groups placed on two-line highways where the two
        // parallel lines are processed from opposit ends.
        // this avoids a problem with perceived irregular placement when overposting
        // removes just some of the duplicate shields

        double shieldGroupLen = (shieldCount - 1) * incrementS;

        // length in excess of the required length to place one group with startOffset on each side
        double availLen = totalLen - (shieldGroupLen + 2.0 * startOffset);

        if (availLen < 0.0)
        {
            // there is no room to 'properly' place even one group, nothing to do but cry about it
            return;
        }

        int numAdditionalGroups = (int) (availLen / (shieldGroupLen + increment));

        double additionalOffset = (availLen - numAdditionalGroups * (shieldGroupLen + increment)) / 2;

        startOffset += additionalOffset;
    }
    else
    {
        // negative startOffset value disables the optimization
        // use absolute value as the offset
        startOffset = -startOffset;
    }

    SE_RenderPrimitiveList* symbolVectors = new SE_RenderPrimitiveList[shieldCount];

    std::wstring countryCode = highwayInfo.getFirstToken();

    int shieldIndex;
    for (shieldIndex=0; shieldIndex<shieldCount; ++shieldIndex)
    {
        std::wstring shieldType = highwayInfo.getNextToken();
        std::wstring highwayNum = highwayInfo.getNextToken();

        // first the shield graphic

        SE_RenderRaster* rr = new SE_RenderRaster();

        std::wstring imgName = HIGWAY_SHIELD_SYMBOLS_PREFIX + countryCode + L"_" + shieldType + L".png";

        symbolManager->GetImageData(HIGWAY_SHIELD_SYMBOLS_RESOURCE.c_str(), imgName.c_str(), rr->imageData);

        if (rr->imageData.size == 0)
        {
            // could not find the image or resource

            // we could fall back and try to pick up the image from a disk file like this:
            //  std::wstring imgPathName = HIGWAY_SHIELD_SYMBOLS_LOCATION + imgName;
            //  rr->pngPtr = symbolManager->GetImageData(L"", imgPathName.c_str(), rr->pngSize);
            // but let's not do that unless really necessary

            // cannot just leave this shield empty, that causes exceptions later, so bail out
            // TODO: find a better way to handle this condition
            return;
        }

        rr->position[0] = 0.0;
        rr->position[1] = 0.0;
        rr->extent[0] = 20.0;
        rr->extent[1] = 20.0;
        rr->angleRad = 0.0;

        if (highwayNum.length() == 1)
            rr->extent[0] = ((shieldType == L"3")? 25.0 : 20.0);
        else if (highwayNum.length() == 2)
            rr->extent[0] = 25.0;
        else
            rr->extent[0] = 30.0;

        double w = 0.5 * rr->extent[0];
        double h = 0.5 * rr->extent[1];

        rr->bounds[0].x = -w;
        rr->bounds[0].y = -h;
        rr->bounds[1].x =  w;
        rr->bounds[1].y = -h;
        rr->bounds[2].x =  w;
        rr->bounds[2].y =  h;
        rr->bounds[3].x = -w;
        rr->bounds[3].y =  h;

        // the shield graphic is ready
        symbolVectors[shieldIndex].push_back(rr);

        // now symbol for the highway number
        SE_RenderText* rt = new SE_RenderText();

        rt->content = highwayNum;
        rt->position[0] = 0.0;
        rt->position[1] = 0.0;
        rt->tdef.font().name() = L"Arial";
        rt->tdef.font().height() = 10.0*0.001 / mm2su; // convert mm to meters
        rt->tdef.rotation() = 0.0;

        rt->tdef.halign() = RS_HAlignment_Center;
        rt->tdef.valign() = RS_VAlignment_Half;

        if (shieldType == L"1")
        {
            rt->tdef.textcolor() = RS_Color(255, 255, 255, 255);
        }
        else
        {
            rt->tdef.textcolor() = RS_Color(0, 0, 0, 255);
        }

        rt->tdef.textbg() = RS_TextBackground_None;
        rt->tdef.font().style() = RS_FontStyle_Bold;

        // the number graphic is ready
        symbolVectors[shieldIndex].push_back(rt);
    }

    SE_Matrix symxf;
    shieldIndex = 0;

    // account for any viewport rotation
    double angleRad = se_renderer->GetWorldToScreenRotation();

    // init position along the whole geometry to the start offset
    double drawpos = startOffset;

    for (int j=0; j<geometry->cntr_count(); ++j)
    {
        // current polyline
        int pt = geometry->contour_start_point(j);
        int last = geometry->contour_end_point(j);

        while (pt < last)
        {
            symxf.setIdentity();
            symxf.rotate(angleRad);

            // current line segment

            // transform the point to screen space
            double  cx1, cy1, cx2, cy2;
            se_renderer->WorldToScreenPoint(geometry->x_coord(pt), geometry->y_coord(pt), cx1, cy1);
            pt++;
            se_renderer->WorldToScreenPoint(geometry->x_coord(pt), geometry->y_coord(pt), cx2, cy2);

            // calc length
            double dx = cx2 - cx1;
            double dy = cy2 - cy1;
            double len = sqrt(dx*dx + dy*dy);

            // check if completely skipping current segment since it is smaller than the increment
            if (drawpos < len)
            {
                double invlen = 1.0 / len;
                double dx_fact = dx * invlen;
                double dy_fact = dy * invlen;

                double tx = cx1 + dx_fact * drawpos;
                double ty = cy1 + dy_fact * drawpos;
                symxf.translate(tx, ty);

                double dx_incr = dx_fact * increment;      // x/y incr between groups of shields
                double dy_incr = dy_fact * increment;

                double dx_incS = dx_fact * incrementS;     // x/y incr between shields in a group
                double dy_incS = dy_fact * incrementS;

                // follow the segment and place the shield symbols alternated via shieldIndex
                while (drawpos < len)
                {
                    if (rlStyle->drawLast)
                    {
                        rlStyle->symbol = symbolVectors[shieldIndex];
                        memcpy(rlStyle->bounds, symbolVectors[shieldIndex].front()->bounds, sizeof(rlStyle->bounds));
                        SE_RenderStyle* clonedStyle = se_renderer->CloneRenderStyle(rlStyle);

                        SE_LabelInfo info(symxf.x2, symxf.y2, RS_Units_Device, angleRad, clonedStyle);
                        RS_OverpostType overpostType = rlStyle->checkExclusionRegion? RS_OverpostType_AllFit : RS_OverpostType_All;
                        se_renderer->ProcessSELabelGroup(&info, 1, overpostType, rlStyle->addToExclusionRegion, geometry);
                    }
                    else
                    {
                        se_renderer->DrawSymbol(symbolVectors[shieldIndex], symxf, angleRad);

                        // TODO: if this is ever needed ...
//                      if (rlStyle->addToExclusionRegion)
//                          se_renderer->AddExclusionRegion(style, symxf, 0.0);
                    }

                    // move on to the next shield, if beyond the last one go back to the first
                    shieldIndex++;
                    if (shieldIndex < shieldCount)
                    {
                        symxf.translate(dx_incS, dy_incS);
                        drawpos += incrementS;
                    }
                    else
                    {
                        // finished with one group
                        // go back to the first symbol and advance using the full increment

                        shieldIndex = 0;
                        symxf.translate(dx_incr, dy_incr);
                        drawpos += increment;
                    }
                }
            }

            drawpos -= len;
        }
    }

    // cleanup time

    // the rlStyle->symbol has been assigned various values from the 'symbolVectors',
    // 'un-assign' it, so that we can clean them up
    rlStyle->symbol.clear();

    for (shieldIndex=0; shieldIndex<shieldCount; ++shieldIndex)
    {
        for (SE_RenderPrimitiveList::iterator iter = symbolVectors[shieldIndex].begin();
             iter != symbolVectors[shieldIndex].end(); ++iter)
        {
            // necessary since destructor of SE_RenderPrimitive is not virtual
            switch ((*iter)->type)
            {
                case SE_RenderPrimitive_Polyline:
                    delete (SE_RenderPolyline*)(*iter);
                    break;

                case SE_RenderPrimitive_Polygon:
                    delete (SE_RenderPolygon*)(*iter);
                    break;

                case SE_RenderPrimitive_Raster:
                    delete (SE_RenderRaster*)(*iter);
                    break;

                case SE_RenderPrimitive_Text:
                    delete (SE_RenderText*)(*iter);
                    break;

                default:
                    throw; // means there is a bug
            }
        }
    }

    delete [] symbolVectors;
}
Example #18
0
static int process(VDB::Writer const &out, LineBuffer &ifs)
{
    auto active = std::vector<ContigPair>();
    
    auto ref = decltype(active.front().first.ref)(0); ///< the active reference (first read)
    auto end = decltype(active.front().first.end)(0); ///< the largest ending position (first read) seen so far; the is the end of the active window

    unsigned long long in_count = 0;
    unsigned long long out_count = 0;
    unsigned long long gapless_count = 0;
    auto time0 = time(nullptr);
    auto freq = 0.1;
    auto report = freq;

    for ( ; ; ) {
        auto pair = ContigPair(ifs);
        auto const isEOF = pair.count == 0;
        
        if ((!active.empty() && (pair.first.ref != ref || pair.first.start >= end)) || isEOF) {
            // new pair is outside the active window (or EOF);
            // output the active contig pairs and empty the window
            
            for (auto && i : active) {
                if (i.first.ref == i.second.ref && i.second.start < i.first.end) {
                    // the region is gapless, i.e. the mate-pair gap has been filled in
                    i.first.end = i.second.start = 0;
                }
            }
            for (auto i = decltype(active.size())(0); i < active.size(); ++i) {
                if (active[i].first.end != 0 || active[i].second.end != 0) continue;
                // active[i] is gapless

                auto const group = active[i].group;
                auto start = active[i].first.start;
                auto end = active[i].second.end;
            AGAIN:
                for (auto j = decltype(i)(0); j < active.size(); ++j) {
                    if (j == i) continue;
                    auto const &J = active[j];
                    if (J.group != group || J.second.ref != ref || J.first.start >= end || J.second.end <= start) continue;
                    
                    // active[j] overlaps active[i]
                    if ((J.first.end == 0 && J.second.start == 0) ///< active[j] is also gapless
                        || (start < J.first.end && J.second.start < end)) ///< or active[i] covers active[j]'s gap
                    {
                        start = std::min(start, J.first.start);
                        end = std::max(end, J.second.end);
                        active[i].first.start = start;
                        active[i].second.end = end;
                        active[i].count += J.count;
                        if (j < i)
                            --i;
                        active.erase(active.begin() + j);
                        goto AGAIN;
                    }
                }
            }
            std::sort(active.begin(), active.end(), ///< want order to be canonical; should be mostly in-order already
                      [](ContigPair const &a, ContigPair const &b) {
                          if (a.first.start < b.first.start) return true;
                          if (a.first.start > b.first.start) return false;
                          if (a.first.end == 0 && a.second.start == 0) {
                              if (b.first.end == 0 && b.second.start == 0) {
                                  if (a.second.end < b.second.end) return false; ///< longer one goes first
                                  if (a.second.end > b.second.end) return true;
                              }
                              else if (a.second.ref == b.second.ref) {
                                  return true; ///< gapless one goes first
                              }
                              else {
                                  return a.second.ref < b.second.ref;
                              }
                          }
                          else if (b.first.end == 0 && b.second.start == 0) {
                              if (a.second.ref == b.second.ref) {
                                  return false; ///< gapless one goes first
                              }
                              else {
                                  return a.second.ref < b.second.ref;
                              }
                          }
                          else {
                              // both have a gap
                              if (a.first.end < b.first.end) return true;
                              if (a.first.end > b.first.end) return false;
                              if (a.second.ref < b.second.ref) return true;
                              if (a.second.ref > b.second.ref) return false;
                              if (a.second.start < b.second.start) return true;
                              if (a.second.start > b.second.start) return false;
                              if (a.second.end < b.second.end) return true;
                              if (a.second.end > b.second.end) return false;
                          }
                          return a.group < b.group;
                      });
            for (auto && i : active) {
                if (i.second.start == 0 && i.first.end == 0)
                    ++gapless_count;
                i.write(out);
                ++out_count;
            }
            active.clear();
            if (isEOF) goto REPORT;
        }
        if (active.empty()) {
            ref = pair.first.ref;
            end = pair.first.end;
            active.emplace_back(pair);
        }
        else {
            for ( ; ; ) {
                unsigned maxOverlap = 0;
                auto merge = active.size(); ///< index of an existing contig pair into which the new pair should be merged
                
                for (auto i = active.size(); i != 0; ) {  ///< the best overlap is probably near the end of the list, so start at the back
                    --i;                            ///< and loop backwards
                    auto const &j = active[i];
                    if (j.group == pair.group && j.second.ref == pair.second.ref) {
                        if (j == pair) {
                            /// found an exact match, and since the list is unique, we're done
                            merge = i;
                            break;
                        }
                        
                        auto const start1 = std::max(pair.first.start, j.first.start);
                        auto const start2 = std::max(pair.second.start, j.second.start);
                        auto const end1 = std::min(pair.first.end, j.first.end);
                        auto const end2 = std::min(pair.second.end, j.second.end);
                        
                        /// the regions of overlap are [start1 - end1), [start2 - end2)
                        /// if either are empty (start >= end) then we aren't interested in the contig pair
                        if (start1 < end1 && start2 < end2) {
                            unsigned const overlap = (end1 - start1) + (end2 - start2);
                            if (maxOverlap < overlap) {
                                maxOverlap = overlap;
                                merge = i;
                            }
                        }
                    }
                }
                if (merge == active.size()) {
                    end = std::max(end, pair.first.end);
                    active.emplace_back(pair);
                    break;
                }
                auto const mergedPair = active[merge] + pair;
                if (active[merge] == mergedPair) {
                    active[merge] = mergedPair;
                    break;
                }
                pair = mergedPair;
                active.erase(active.begin() + merge);
            }
        }

        ++in_count;
        if (ifs.position() >= report) {
            report += freq;
        REPORT:
            auto elapsed = double(time(nullptr) - time0);
            if (elapsed > 0)
                std::cerr << "prog: " << unsigned(ifs.position() * 100.0) << "%; " << in_count << " alignments processed (" << in_count / elapsed << " per sec); (" << gapless_count << " gapless) " << out_count << " contig pairs generated (" << out_count / elapsed << " per sec); ratio: " << double(in_count) / out_count << std::endl;
            else
                std::cerr << "prog: " << unsigned(ifs.position() * 100.0) << "%; " << in_count << " alignments processed; (" << gapless_count << " gapless) " << out_count << " contig pairs generated; ratio: " << double(in_count) / out_count << std::endl;
            if (isEOF)
                return 0;
        }
    }
}
Example #19
0
void Shell::displayLine(const LineBuffer& line){
  _cursor.column(_column);
  auto matched = _commands.parse(line.line(), _out, false);
  _modules.lineUpdated(matched, line, *this);
  _cursor.column(line.pos() + _column);
}
Example #20
0
void PolylineAdapter::Stylize(Renderer*                   renderer,
                              RS_FeatureReader*           features,
                              bool                        initialPass,
                              FdoExpressionEngine*        exec,
                              LineBuffer*                 geometry,
                              MdfModel::FeatureTypeStyle* style,
                              const MdfModel::MdfString*  tooltip,
                              const MdfModel::MdfString*  url,
                              RS_ElevationSettings*       elevSettings,
                              CSysTransformer*            /*layer2mapxformer*/)
{
    m_exec = exec;

    // no need to do anything if the style is not a line style, so quit
    if (FeatureTypeStyleVisitor::DetermineFeatureTypeStyle(style) != FeatureTypeStyleVisitor::ftsLine)
        return;

    //-------------------------------------------------------
    // determine the rule for the feature
    //-------------------------------------------------------

    MdfModel::RuleCollection* lrc = style->GetRules();
    MdfModel::LineRule* rule = NULL;

    for (int i=0; i<lrc->GetCount(); ++i)
    {
        rule = static_cast<MdfModel::LineRule*>(lrc->GetAt(i));

        // apply any filter on the rule - if it fails move to the next rule
        if (!ExecFdoFilter(&rule->GetFilter()))
        {
            // don't stylize with failed rule
            rule = NULL;
            continue;
        }

        break;
    }

    if (!rule)
        return;

    MdfModel::LineSymbolizationCollection* lsymc = rule->GetSymbolizations();
    if (lsymc == NULL)
        return;

    int nSyms = lsymc->GetCount();

    //-------------------------------------------------------
    // evaluate all the styles once
    //-------------------------------------------------------

    // temporary array used to store pointers to each evaluated style
    RS_LineStroke** ppStrokes = (RS_LineStroke**)alloca(nSyms * sizeof(RS_LineStroke*));
    if (!ppStrokes)
        return;

    size_t tempIndex = 0;
    for (int i=0; i<nSyms; ++i)
    {
        MdfModel::LineSymbolization2D* lsym = lsymc->GetAt(i);

        // don't render if there's no symbolization
        if (lsym == NULL)
        {
            ppStrokes[i] = NULL;
            continue;
        }

        // quick check if style is already cached
        RS_LineStroke* cachedStyle = m_hLineSymCache[lsym];
        if (cachedStyle)
        {
            ppStrokes[i] = cachedStyle;
        }
        else
        {
            // if not, then we need to either cache or evaluate it

            // make sure the vector has a style in the slot we need
            if (tempIndex >= m_lineSyms.size())
            {
                _ASSERT(tempIndex == m_lineSyms.size());

                // allocate a new style and add it to the vector
                m_lineSyms.push_back(new RS_LineStroke());
            }

            // use the existing style in the vector
            ppStrokes[i] = m_lineSyms[tempIndex];
            ObtainStyle(lsym, *ppStrokes[i]);

            ++tempIndex;
        }
    }

    //-------------------------------------------------------
    // compute the clip offset from the styles
    //-------------------------------------------------------

    double clipOffsetWU = 0.0;  // in mapping units

    bool bClip      = renderer->RequiresClipping();
    bool bLabelClip = renderer->RequiresLabelClipping();

    if (bClip || bLabelClip)
    {
        double mapScale = renderer->GetMapScale();

        double clipOffsetMeters = 0.0;  // in device units
        for (int i=0; i<nSyms; ++i)
        {
            if (ppStrokes[i])
            {
                double styleClipOffset = GetClipOffset(*ppStrokes[i], mapScale);
                clipOffsetMeters = rs_max(styleClipOffset, clipOffsetMeters);
            }
        }

        // add one pixel's worth to handle any roundoff
        clipOffsetMeters += METERS_PER_INCH / renderer->GetDpi();

        // limit the offset to something reasonable
        if (clipOffsetMeters > MAX_CLIPOFFSET_IN_METERS)
            clipOffsetMeters = MAX_CLIPOFFSET_IN_METERS;

        // convert to mapping units
        clipOffsetWU = clipOffsetMeters * mapScale / renderer->GetMetersPerUnit();
    }

    //-------------------------------------------------------
    // prepare the geometry on which to apply the style
    //-------------------------------------------------------

    LineBuffer* lb = geometry;
    std::auto_ptr<LineBuffer> spClipLB;

    if (bClip)
    {
        // the clip region is the map request extents expanded by the offset
        RS_Bounds clip = renderer->GetBounds();
        clip.minx -= clipOffsetWU;
        clip.miny -= clipOffsetWU;
        clip.maxx += clipOffsetWU;
        clip.maxy += clipOffsetWU;

        // clip geometry to given extents
        LineBuffer* lbc = lb->Clip(clip, LineBuffer::ctAGF, m_lbPool);
        if (lbc != lb)
        {
            // if the clipped buffer is NULL (completely clipped) just move on to
            // the next feature
            if (!lbc)
                return;

            // otherwise continue processing with the clipped buffer
            lb = lbc;
            if (lb != geometry)
                spClipLB.reset(lb);
        }
    }

    //-------------------------------------------------------
    // do the StartFeature notification
    //-------------------------------------------------------

    RS_String tip; //TODO: this should be quick since we are not assigning
    RS_String eurl;
    const RS_String &theme = rule->GetLegendLabel();

    if (tooltip && !tooltip->empty())
        EvalString(*tooltip, tip);
    if (url && !url->empty())
        EvalString(*url, eurl);

    // elevation settings
    RS_ElevationType elevType = RS_ElevationType_RelativeToGround;
    double zOffset = 0.0;
    double zExtrusion = 0.0;
    GetElevationParams(elevSettings, zOffset, zExtrusion, elevType);

    renderer->StartFeature(features, initialPass,
                           tip.empty()? NULL : &tip,
                           eurl.empty()? NULL : &eurl,
                           theme.empty()? NULL : &theme,
                           zOffset, zExtrusion, elevType);

    //-------------------------------------------------------
    // apply the style to the geometry using the renderer
    //-------------------------------------------------------

    for (int i=0; i<nSyms; ++i)
    {
        if (ppStrokes[i])
            renderer->ProcessPolyline(lb, *ppStrokes[i]);
    }

    //-------------------------------------------------------
    // do labeling if needed
    //-------------------------------------------------------

    MdfModel::Label* label = rule->GetLabel();
    if (label && label->GetSymbol())
    {
        // Make sure the geometry is clipped if label clipping is specified.
        // If bClip is true then the geometry is already clipped.
        if (!bClip && bLabelClip)
        {
            // the clip region is the map request extents expanded by the offset
            RS_Bounds clip = renderer->GetBounds();
            clip.minx -= clipOffsetWU;
            clip.miny -= clipOffsetWU;
            clip.maxx += clipOffsetWU;
            clip.maxy += clipOffsetWU;

            LineBuffer* lbc = lb->Clip(clip, LineBuffer::ctAGF, m_lbPool);
            if (lbc != lb)
            {
                // if the clipped buffer is NULL (completely clipped) just move on to
                // the next feature
                if (!lbc)
                    return;

                // otherwise continue processing with the clipped buffer
                lb = lbc;
                if (lb != geometry)
                    spClipLB.reset(lb);
            }
        }

        double cx = std::numeric_limits<double>::quiet_NaN();
        double cy = std::numeric_limits<double>::quiet_NaN();
        double slope_rad = 0.0;

        // multi should work for simple polylines too
        lb->Centroid(LineBuffer::ctLine, &cx, &cy, &slope_rad);

        if (!_isnan(cx) && !_isnan(cy))
            AddLabel(cx, cy, slope_rad, true, label, RS_OverpostType_AllFit, true, renderer, label->GetSymbol()->IsAdvancedPlacement()? lb : NULL);
    }

    // free clipped line buffer if the geometry was clipped
    if (spClipLB.get())
        LineBufferPool::FreeLineBuffer(m_lbPool, spClipLB.release());
}
void SE_PositioningAlgorithms::Default(SE_ApplyContext* applyCtx,
                                       SE_RenderStyle*  rstyle)
{
    // the style needs to contain at least one primitive
    SE_RenderPrimitiveList& prims = rstyle->symbol;
    if (prims.size() == 0)
        return;

    SE_Renderer* se_renderer = applyCtx->renderer;
    LineBuffer* geometry = applyCtx->geometry;
    SE_Matrix& xform = *applyCtx->xform;

    double cx = 0.0;
    double cy = 0.0;
    double offsetX = 0.0;
    double offsetY = 0.0;
    double angleRad = 0.0;

    switch (rstyle->type)
    {
        case SE_RenderStyle_Point:
        {
            SE_RenderPointStyle* rpStyle = (SE_RenderPointStyle*)rstyle;

            // get the feature centroid (no angle for point centroids)
            geometry->Centroid(LineBuffer::ctPoint, &cx, &cy, NULL);

            // account for the point usage angle control and offset
            angleRad = rpStyle->angleRad;
            offsetX  = rpStyle->offset[0];
            offsetY  = rpStyle->offset[1];

            break;
        }

        case SE_RenderStyle_Line:
        {
            SE_RenderLineStyle* rlStyle = (SE_RenderLineStyle*)rstyle;

            // get the feature centroid and angle
            double fAngleRad;
            geometry->Centroid(LineBuffer::ctLine, &cx, &cy, &fAngleRad);

            // account for the angle control
            angleRad = rlStyle->angleRad;
            if (rlStyle->angleControl == SE_AngleControl_FromGeometry)
                angleRad += fAngleRad;

            break;
        }

        case SE_RenderStyle_Area:
        {
            SE_RenderAreaStyle* raStyle = (SE_RenderAreaStyle*)rstyle;

            // get the feature centroid (no angle for area centroids)
            geometry->Centroid(LineBuffer::ctArea, &cx, &cy, NULL);

            // account for the angle control
            angleRad = raStyle->angleRad;

            break;
        }
    }

    // don't add a label if we can't compute the centroid
    if (_isnan(cx) || _isnan(cy))
        return;

    // need to convert centroid to screen units
    se_renderer->WorldToScreenPoint(cx, cy, cx, cy);

    // also account for any viewport rotation
    angleRad += se_renderer->GetWorldToScreenRotation();

    // see StylizationEngine::Stylize for a detailed explanation of these transforms
    bool yUp = se_renderer->YPointsUp();
    SE_Matrix xformLabel;
    xformLabel.translate(offsetX, offsetY);
    xformLabel.rotate(yUp? angleRad : -angleRad);
    xformLabel.premultiply(xform);
    xformLabel.translate(cx, cy);

    se_renderer->AddLabel(geometry, rstyle, xformLabel, angleRad);
}