<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2016 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                              SOFA :: Framework                              *
*                                                                             *
* Authors: The SOFA Team (see Authors.txt)                                    *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/

#include <SofaOpenglVisual/OglColorMap.h>

#include <sofa/core/ObjectFactory.h>
#include <sofa/core/visual/VisualParams.h>

#ifdef SOFA_HAVE_GLEW
#include <sofa/helper/gl/GLSLShader.h>
#endif // SOFA_HAVE_GLEW

#include <string>
#include <iostream>

namespace sofa
{

namespace component
{

namespace visualmodel
{

SOFA_DECL_CLASS(OglColorMap)

int OglColorMapClass = core::RegisterObject("Provides color palette and support for conversion of numbers to colors.")
        .add< OglColorMap >()
        .addAlias("ColorMap")
        ;

OglColorMap::OglColorMap()
: f_paletteSize(initData(&f_paletteSize, (unsigned int)256, "paletteSize", "How many colors to use"))
, f_colorScheme(initData(&f_colorScheme, "colorScheme", "Color scheme to use"))
, f_showLegend(initData(&f_showLegend, false, "showLegend", "Activate rendering of color scale legend on the side"))
, f_legendOffset(initData(&f_legendOffset, defaulttype::Vec2f(10.0f,5.0f),"legendOffset", "Draw the legend on screen with an x,y offset"))
, f_legendTitle(initData(&f_legendTitle,"legendTitle", "Add a title to the legend"))
, d_min(initData(&d_min,0.0f,"min","min value for drawing the legend without the need to actually use the range with getEvaluator method wich sets the min"))
, d_max(initData(&d_max,0.0f,"max","max value for drawing the legend without the need to actually use the range with getEvaluator method wich sets the max"))
, d_legendRangeScale(initData(&d_legendRangeScale,1.f,"legendRangeScale","to change the unit of the min/max value of the legend"))
, texture(0)
{
   f_colorScheme.beginEdit()->setNames(19,
        "Red to Blue",  // HSV space
        "Blue to Red",  // HSV space
        "HSV",          // HSV space
        "Red",          // RGB space
        "Green",        // RGB space
        "Blue",         // RGB space
		"Yellow to Cyan",// HSV space
		"Cyan to Yellow",// HSV space
		"Red to Yellow",// RGB space
		"Yellow to Red",// RGB space
		"Yellow to Green",// RGB space
		"Green to Yellow",// RGB space
		"Green to Cyan",// RGB space
		"Cyan to Green",// RGB space
		"Cyan to Blue",// RGB space
		"Blue to Cyan",// RGB space
		"BlueInv",// HSV space
		"GreenInv",// HSV space
		"RedInv",// HSV space
        "Custom"// TODO: Custom colors
        );
    f_colorScheme.beginEdit()->setSelectedItem("HSV");
    f_colorScheme.endEdit();

}

OglColorMap::~OglColorMap() {
    // Some components may use OglColorMap internally, in which case an OpenGL
    // context might not exist.  That's why this 'if' is here, to avoid calling
    // an OpenGL function in a destructor unless strictly necessary.
    if (texture != 0)
        glDeleteTextures(1, &texture);
}

// For backward compatibility only
// TODO: remove this later
//void OglColorMap::initOld(const std::string &data)
//{
//    if (data == "") {
//        entries.insert(entries.end(), DefaultOglColorMapEntries, DefaultOglColorMapEntries+NDefaultOglColorMapEntries);
//        return;
//    }
//
//    std::istringstream is(data);
//    is >> *this;
//
//    return;
//}

void OglColorMap::init()
{
    reinit();
}

void OglColorMap::reinit()
{
    m_colorMap.setPaletteSize(f_paletteSize.getValue());
    m_colorMap.setColorScheme(f_colorScheme.getValue().getSelectedItem());
    m_colorMap.reinit();
    }

OglColorMap* OglColorMap::getDefault()
{
    static OglColorMap::SPtr defaultOglColorMap;
    if (defaultOglColorMap == NULL) {
        defaultOglColorMap = sofa::core::objectmodel::New< OglColorMap >();
        std::string tmp("");
        //defaultOglColorMap->initOld(tmp); // TODO: replace initOld() with init()
        defaultOglColorMap->init();
    }
    return defaultOglColorMap.get();
}

void OglColorMap::drawVisual(const core::visual::VisualParams* vparams)
{
    if( !vparams->displayFlags().getShowVisual() ) return;

    if (!f_showLegend.getValue()) return;

    // Prepare texture for legend
    // crashes on mac in batch mode (no GL context)
    if (vparams->isSupported(core::visual::API_OpenGL)
        && !texture)
    {
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_1D, texture);
        //glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

        int width = getNbColors();
        unsigned char *data = new unsigned char[ width * 3 ];

        for (int i=0; i<width; i++) {
            Color c = getColor(i);
            data[i*3+0] = (unsigned char)(c[0]*255);
            data[i*3+1] = (unsigned char)(c[1]*255);
            data[i*3+2] = (unsigned char)(c[2]*255);
        }

        glBindTexture(GL_TEXTURE_1D, texture);

        glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, width, 0, GL_RGB, GL_UNSIGNED_BYTE,
            data);

        delete[] data;
    }

    //
    // Draw legend
    //
    // TODO: move the code to DrawTool

    const std::string& legendTitle = f_legendTitle.getValue();
    int yoffset = legendTitle.empty() ? 0 : 25;

    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT,viewport);
    const int vWidth = viewport[2];
    const int vHeight = viewport[3];

    glPushAttrib(GL_ENABLE_BIT);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);
    glDisable(GL_BLEND);

    // disable clipping planes
	for(int i = 0; i < GL_MAX_CLIP_PLANES; ++i)
		glDisable(GL_CLIP_PLANE0+i);

    // Setup orthogonal projection
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glOrtho(0.0, vWidth, vHeight, 0.0, -1.0, 1.0);

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();

#ifdef SOFA_HAVE_GLEW
    for(int i = 0; i < 8; ++i)
    {
        glActiveTexture(GL_TEXTURE0 + i);
        glDisable(GL_TEXTURE_2D);
    }

    glActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_1D);
    glBindTexture(GL_TEXTURE_1D, texture);

    //glBlendFunc(GL_ONE, GL_ONE);
    glColor3f(1.0f, 1.0f, 1.0f);

    GLhandleARB currentShader = sofa::helper::gl::GLSLShader::GetActiveShaderProgram();
    sofa::helper::gl::GLSLShader::SetActiveShaderProgram(0);
#endif // SOFA_HAVE_GLEW

    glBegin(GL_QUADS);

    glTexCoord1f(1.0);
    glVertex3f(20.0f+f_legendOffset.getValue().x(), yoffset+20.0f+f_legendOffset.getValue().y(), 0.0f);

    glTexCoord1f(1.0);
    glVertex3f(10.0f+f_legendOffset.getValue().x(), yoffset+20.0f+f_legendOffset.getValue().y(), 0.0f);

    glTexCoord1f(0.0);
    glVertex3f(10.0f+f_legendOffset.getValue().x(), yoffset+120.0f+f_legendOffset.getValue().y(), 0.0f);

    glTexCoord1f(0.0);
    glVertex3f(20.0f+f_legendOffset.getValue().x(), yoffset+120.0f+f_legendOffset.getValue().y(), 0.0f);

    glEnd();

    glDisable(GL_TEXTURE_1D);

    // Restore projection matrix
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    // Restore model view matrix
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();

    // Maximum & minimum
    std::ostringstream smin, smax;
    smin << d_min.getValue() * d_legendRangeScale.getValue();
    smax << d_max.getValue() * d_legendRangeScale.getValue();

    // Adjust the text color according to the background luminance
    GLfloat bgcol[4];
    glGetFloatv(GL_COLOR_CLEAR_VALUE,bgcol);

    Color textcolor(1.0f, 1.0f, 1.0f, 1.0f);
    sofa::defaulttype::Vec3f luminanceMatrix(0.212f, 0.715f, 0.072f);
    float backgroundLuminance = sofa::defaulttype::Vec3f(bgcol[0], bgcol[1], bgcol[2]) * luminanceMatrix;
    if(backgroundLuminance > 0.5f)
        textcolor = Color(0.0f, 0.0f, 0.0f, 1.0f);

    if( !legendTitle.empty() )
    {
        vparams->drawTool()->writeOverlayText((int)f_legendOffset.getValue().x(), // x
                                              (int)f_legendOffset.getValue().y(), // y
                                              11u, // size
                                              textcolor,
                                              legendTitle.c_str());
    }

    vparams->drawTool()->writeOverlayText((int)f_legendOffset.getValue().x(), // x
                                          yoffset + (int)f_legendOffset.getValue().y(), // y
                                          12u, // size
                                          textcolor,
                                          smax.str().c_str());

    vparams->drawTool()->writeOverlayText((int)f_legendOffset.getValue().x(), // x
                                          yoffset + 120 + (int)f_legendOffset.getValue().y(), // y
                                          12u, // size
                                          textcolor,
                                          smin.str().c_str());

#ifdef SOFA_HAVE_GLEW
    sofa::helper::gl::GLSLShader::SetActiveShaderProgram(currentShader);
#endif // SOFA_HAVE_GLEW

    // Restore state
    glPopAttrib();
}

} // namespace visualmodel

} // namespace component

} // namespace sofa
<commit_msg>[SofaOpenglVisual] fixing OglColorMap<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2016 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                              SOFA :: Framework                              *
*                                                                             *
* Authors: The SOFA Team (see Authors.txt)                                    *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/

#include <SofaOpenglVisual/OglColorMap.h>

#include <sofa/core/ObjectFactory.h>
#include <sofa/core/visual/VisualParams.h>

#ifdef SOFA_HAVE_GLEW
#include <sofa/helper/gl/GLSLShader.h>
#endif // SOFA_HAVE_GLEW

#include <string>
#include <iostream>

namespace sofa
{

namespace component
{

namespace visualmodel
{

SOFA_DECL_CLASS(OglColorMap)

int OglColorMapClass = core::RegisterObject("Provides color palette and support for conversion of numbers to colors.")
        .add< OglColorMap >()
        .addAlias("ColorMap")
        ;

OglColorMap::OglColorMap()
: f_paletteSize(initData(&f_paletteSize, (unsigned int)256, "paletteSize", "How many colors to use"))
, f_colorScheme(initData(&f_colorScheme, "colorScheme", "Color scheme to use"))
, f_showLegend(initData(&f_showLegend, false, "showLegend", "Activate rendering of color scale legend on the side"))
, f_legendOffset(initData(&f_legendOffset, defaulttype::Vec2f(10.0f,5.0f),"legendOffset", "Draw the legend on screen with an x,y offset"))
, f_legendTitle(initData(&f_legendTitle,"legendTitle", "Add a title to the legend"))
, d_min(initData(&d_min,0.0f,"min","min value for drawing the legend without the need to actually use the range with getEvaluator method wich sets the min"))
, d_max(initData(&d_max,0.0f,"max","max value for drawing the legend without the need to actually use the range with getEvaluator method wich sets the max"))
, d_legendRangeScale(initData(&d_legendRangeScale,1.f,"legendRangeScale","to change the unit of the min/max value of the legend"))
, texture(0)
{
   f_colorScheme.beginEdit()->setNames(19,
        "Red to Blue",  // HSV space
        "Blue to Red",  // HSV space
        "HSV",          // HSV space
        "Red",          // RGB space
        "Green",        // RGB space
        "Blue",         // RGB space
		"Yellow to Cyan",// HSV space
		"Cyan to Yellow",// HSV space
		"Red to Yellow",// RGB space
		"Yellow to Red",// RGB space
		"Yellow to Green",// RGB space
		"Green to Yellow",// RGB space
		"Green to Cyan",// RGB space
		"Cyan to Green",// RGB space
		"Cyan to Blue",// RGB space
		"Blue to Cyan",// RGB space
		"BlueInv",// HSV space
		"GreenInv",// HSV space
		"RedInv",// HSV space
        "Custom"// TODO: Custom colors
        );
    f_colorScheme.beginEdit()->setSelectedItem("HSV");
    f_colorScheme.endEdit();

}

OglColorMap::~OglColorMap() {
    // Some components may use OglColorMap internally, in which case an OpenGL
    // context might not exist.  That's why this 'if' is here, to avoid calling
    // an OpenGL function in a destructor unless strictly necessary.
    if (texture != 0)
        glDeleteTextures(1, &texture);
}

// For backward compatibility only
// TODO: remove this later
//void OglColorMap::initOld(const std::string &data)
//{
//    if (data == "") {
//        entries.insert(entries.end(), DefaultOglColorMapEntries, DefaultOglColorMapEntries+NDefaultOglColorMapEntries);
//        return;
//    }
//
//    std::istringstream is(data);
//    is >> *this;
//
//    return;
//}

void OglColorMap::init()
{
    reinit();
}

void OglColorMap::reinit()
{
    m_colorMap.setPaletteSize(f_paletteSize.getValue());
    m_colorMap.setColorScheme(f_colorScheme.getValue().getSelectedItem());
    m_colorMap.reinit();
    }

OglColorMap* OglColorMap::getDefault()
{
    static OglColorMap::SPtr defaultOglColorMap;
    if (defaultOglColorMap == NULL) {
        defaultOglColorMap = sofa::core::objectmodel::New< OglColorMap >();
        std::string tmp("");
        //defaultOglColorMap->initOld(tmp); // TODO: replace initOld() with init()
        defaultOglColorMap->init();
    }
    return defaultOglColorMap.get();
}

void OglColorMap::drawVisual(const core::visual::VisualParams* vparams)
{
    if( !vparams->displayFlags().getShowVisual() ) return;

    if (!f_showLegend.getValue()) return;

    // Prepare texture for legend
    // crashes on mac in batch mode (no GL context)
    if (vparams->isSupported(core::visual::API_OpenGL)
        && !texture)
    {
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_1D, texture);
        //glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

        int width = getNbColors();
        unsigned char *data = new unsigned char[ width * 3 ];

        for (int i=0; i<width; i++) {
            Color c = getColor(i);
            data[i*3+0] = (unsigned char)(c[0]*255);
            data[i*3+1] = (unsigned char)(c[1]*255);
            data[i*3+2] = (unsigned char)(c[2]*255);
        }

        glBindTexture(GL_TEXTURE_1D, texture);

        glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, width, 0, GL_RGB, GL_UNSIGNED_BYTE,
            data);

        delete[] data;
    }

    //
    // Draw legend
    //
    // TODO: move the code to DrawTool

    const std::string& legendTitle = f_legendTitle.getValue();
    int yoffset = legendTitle.empty() ? 0 : 25;

    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT,viewport);
    const int vWidth = viewport[2];
    const int vHeight = viewport[3];

    glPushAttrib(GL_ENABLE_BIT);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);
    glDisable(GL_BLEND);

    // disable clipping planes
	for(int i = 0; i < GL_MAX_CLIP_PLANES; ++i)
		glDisable(GL_CLIP_PLANE0+i);

    // Setup orthogonal projection
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glOrtho(0.0, vWidth, vHeight, 0.0, -1.0, 1.0);

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();

#ifdef SOFA_HAVE_GLEW
    for(int i = 0; i < 8; ++i)
    {
        glActiveTexture(GL_TEXTURE0 + i);
        glDisable(GL_TEXTURE_2D);
    }

    glActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_1D);
    glBindTexture(GL_TEXTURE_1D, texture);

    //glBlendFunc(GL_ONE, GL_ONE);
    glColor3f(1.0f, 1.0f, 1.0f);

    GLhandleARB currentShader = sofa::helper::gl::GLSLShader::GetActiveShaderProgram();
    sofa::helper::gl::GLSLShader::SetActiveShaderProgram(0);
#endif // SOFA_HAVE_GLEW

    glBegin(GL_QUADS);

    glTexCoord1f(1.0);
    glVertex3f(20.0f+f_legendOffset.getValue().x(), yoffset+20.0f+f_legendOffset.getValue().y(), 0.0f);

    glTexCoord1f(1.0);
    glVertex3f(10.0f+f_legendOffset.getValue().x(), yoffset+20.0f+f_legendOffset.getValue().y(), 0.0f);

    glTexCoord1f(0.0);
    glVertex3f(10.0f+f_legendOffset.getValue().x(), yoffset+120.0f+f_legendOffset.getValue().y(), 0.0f);

    glTexCoord1f(0.0);
    glVertex3f(20.0f+f_legendOffset.getValue().x(), yoffset+120.0f+f_legendOffset.getValue().y(), 0.0f);

    glEnd();

    glDisable(GL_TEXTURE_1D);

    // Restore model view matrix
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();

    // Restore projection matrix
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    // Maximum & minimum
    std::ostringstream smin, smax;
    smin << d_min.getValue() * d_legendRangeScale.getValue();
    smax << d_max.getValue() * d_legendRangeScale.getValue();

    // Adjust the text color according to the background luminance
    GLfloat bgcol[4];
    glGetFloatv(GL_COLOR_CLEAR_VALUE,bgcol);

    Color textcolor(1.0f, 1.0f, 1.0f, 1.0f);
    sofa::defaulttype::Vec3f luminanceMatrix(0.212f, 0.715f, 0.072f);
    float backgroundLuminance = sofa::defaulttype::Vec3f(bgcol[0], bgcol[1], bgcol[2]) * luminanceMatrix;
    if(backgroundLuminance > 0.5f)
        textcolor = Color(0.0f, 0.0f, 0.0f, 1.0f);

    if( !legendTitle.empty() )
    {
        vparams->drawTool()->writeOverlayText((int)f_legendOffset.getValue().x(), // x
                                              (int)f_legendOffset.getValue().y(), // y
                                              11u, // size
                                              textcolor,
                                              legendTitle.c_str());
    }

    vparams->drawTool()->writeOverlayText((int)f_legendOffset.getValue().x(), // x
                                          yoffset + (int)f_legendOffset.getValue().y(), // y
                                          12u, // size
                                          textcolor,
                                          smax.str().c_str());

    vparams->drawTool()->writeOverlayText((int)f_legendOffset.getValue().x(), // x
                                          yoffset + 120 + (int)f_legendOffset.getValue().y(), // y
                                          12u, // size
                                          textcolor,
                                          smin.str().c_str());

#ifdef SOFA_HAVE_GLEW
    sofa::helper::gl::GLSLShader::SetActiveShaderProgram(currentShader);
#endif // SOFA_HAVE_GLEW

    // Restore state
    glPopAttrib();
}

} // namespace visualmodel

} // namespace component

} // namespace sofa
<|endoftext|>


<commit_before>//! Copyright (c) 2013 ASMlover. All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//!  * Redistributions of source code must retain the above copyright
//!    notice, this list ofconditions and the following disclaimer.
//!
//!  * Redistributions in binary form must reproduce the above copyright
//!    notice, this list of conditions and the following disclaimer in
//!    the documentation and/or other materialsprovided with the
//!    distribution.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//! COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//! POSSIBILITY OF SUCH DAMAGE.
#include <stdio.h>

int
main(int argc, char* argv[])
{
  return 0;
}
<commit_msg>add test for AppendFile in windows platform<commit_after>//! Copyright (c) 2013 ASMlover. All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//!  * Redistributions of source code must retain the above copyright
//!    notice, this list ofconditions and the following disclaimer.
//!
//!  * Redistributions in binary form must reproduce the above copyright
//!    notice, this list of conditions and the following disclaimer in
//!    the documentation and/or other materialsprovided with the
//!    distribution.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//! COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//! POSSIBILITY OF SUCH DAMAGE.
#include <stdio.h>
#include <string.h>
#include "append_file.h"

#define LOOP_TIMES  (100000)

int
main(int argc, char* argv[])
{
  char* s = "Hello, world! This is AppendFile testing ...\n";
  size_t n = strlen(s);
  DWORD beg, end;
  int counter;

  FILE* fp = fopen("test1.txt", "a+");
  counter = 0;
  beg = GetTickCount();
  while (counter++ < LOOP_TIMES)
    _fwrite_nolock(s, sizeof(char), n, fp);
  end = GetTickCount();
  fprintf(stdout, "stream io used: %lu\n", end - beg);
  fclose(fp);

  AppendFile f;
  f.Open("test2.txt");
  counter = 0;
  beg = GetTickCount();
  while (counter++ < LOOP_TIMES)
    f.Write(s, n);
  end = GetTickCount();
  fprintf(stdout, "AppendFile used: %lu\n", end - beg);
  f.Close();

  return 0;
}
<|endoftext|>


<commit_before><commit_msg>rework to begin supporting #else and #elif<commit_after><|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "test_precomp.hpp"
#include "npy_blob.hpp"
#include <opencv2/dnn/shape_utils.hpp>

namespace opencv_test
{

using namespace std;
using namespace testing;
using namespace cv;
using namespace cv::dnn;

template<typename TStr>
static std::string _tf(TStr filename, bool inTorchDir = true)
{
    String path = "dnn/";
    if (inTorchDir)
        path += "torch/";
    path += filename;
    return findDataFile(path, false);
}

TEST(Torch_Importer, simple_read)
{
    Net net;
    ASSERT_NO_THROW(net = readNetFromTorch(_tf("net_simple_net.txt"), false));
    ASSERT_FALSE(net.empty());
}

static void runTorchNet(String prefix, int targetId = DNN_TARGET_CPU, String outLayerName = "",
                        bool check2ndBlob = false, bool isBinary = false)
{
    String suffix = (isBinary) ? ".dat" : ".txt";

    Net net = readNetFromTorch(_tf(prefix + "_net" + suffix), isBinary);
    ASSERT_FALSE(net.empty());

    net.setPreferableBackend(DNN_BACKEND_DEFAULT);
    net.setPreferableTarget(targetId);

    Mat inp, outRef;
    ASSERT_NO_THROW( inp = readTorchBlob(_tf(prefix + "_input" + suffix), isBinary) );
    ASSERT_NO_THROW( outRef = readTorchBlob(_tf(prefix + "_output" + suffix), isBinary) );

    if (outLayerName.empty())
        outLayerName = net.getLayerNames().back();

    net.setInput(inp, "0");
    std::vector<Mat> outBlobs;
    net.forward(outBlobs, outLayerName);
    normAssert(outRef, outBlobs[0]);

    if (check2ndBlob)
    {
        Mat out2 = outBlobs[1];
        Mat ref2 = readTorchBlob(_tf(prefix + "_output_2" + suffix), isBinary);
        normAssert(out2, ref2);
    }
}

typedef testing::TestWithParam<DNNTarget> Test_Torch_layers;

TEST_P(Test_Torch_layers, run_convolution)
{
    runTorchNet("net_conv", GetParam());
}

TEST_P(Test_Torch_layers, run_pool_max)
{
    runTorchNet("net_pool_max", GetParam(), "", true);
}

TEST_P(Test_Torch_layers, run_pool_ave)
{
    runTorchNet("net_pool_ave", GetParam());
}

TEST_P(Test_Torch_layers, run_reshape)
{
    int targetId = GetParam();
    runTorchNet("net_reshape", targetId);
    runTorchNet("net_reshape_batch", targetId);
    runTorchNet("net_reshape_single_sample", targetId);
    runTorchNet("net_reshape_channels", targetId, "", false, true);
}

TEST_P(Test_Torch_layers, run_linear)
{
    runTorchNet("net_linear_2d", GetParam());
}

TEST_P(Test_Torch_layers, run_concat)
{
    int targetId = GetParam();
    runTorchNet("net_concat", targetId, "l5_torchMerge");
    runTorchNet("net_depth_concat", targetId, "", false, true);
}

TEST_P(Test_Torch_layers, run_deconv)
{
    runTorchNet("net_deconv", GetParam());
}

TEST_P(Test_Torch_layers, run_batch_norm)
{
    runTorchNet("net_batch_norm", GetParam(), "", false, true);
}

TEST_P(Test_Torch_layers, net_prelu)
{
    runTorchNet("net_prelu", GetParam());
}

TEST_P(Test_Torch_layers, net_cadd_table)
{
    runTorchNet("net_cadd_table", GetParam());
}

TEST_P(Test_Torch_layers, net_softmax)
{
    int targetId = GetParam();
    runTorchNet("net_softmax", targetId);
    runTorchNet("net_softmax_spatial", targetId);
}

TEST_P(Test_Torch_layers, net_logsoftmax)
{
    runTorchNet("net_logsoftmax");
    runTorchNet("net_logsoftmax_spatial");
}

TEST_P(Test_Torch_layers, net_lp_pooling)
{
    int targetId = GetParam();
    runTorchNet("net_lp_pooling_square", targetId, "", false, true);
    runTorchNet("net_lp_pooling_power", targetId, "", false, true);
}

TEST_P(Test_Torch_layers, net_conv_gemm_lrn)
{
    runTorchNet("net_conv_gemm_lrn", GetParam(), "", false, true);
}

TEST_P(Test_Torch_layers, net_inception_block)
{
    runTorchNet("net_inception_block", GetParam(), "", false, true);
}

TEST_P(Test_Torch_layers, net_normalize)
{
    runTorchNet("net_normalize", GetParam(), "", false, true);
}

TEST_P(Test_Torch_layers, net_padding)
{
    int targetId = GetParam();
    runTorchNet("net_padding", targetId, "", false, true);
    runTorchNet("net_spatial_zero_padding", targetId, "", false, true);
    runTorchNet("net_spatial_reflection_padding", targetId, "", false, true);
}

TEST_P(Test_Torch_layers, net_non_spatial)
{
    runTorchNet("net_non_spatial", GetParam(), "", false, true);
}

INSTANTIATE_TEST_CASE_P(/**/, Test_Torch_layers, availableDnnTargets());

typedef testing::TestWithParam<DNNTarget> Test_Torch_nets;

TEST_P(Test_Torch_nets, OpenFace_accuracy)
{
    const string model = findDataFile("dnn/openface_nn4.small2.v1.t7", false);
    Net net = readNetFromTorch(model);

    net.setPreferableTarget(GetParam());

    Mat sample = imread(findDataFile("cv/shared/lena.png", false));
    Mat sampleF32(sample.size(), CV_32FC3);
    sample.convertTo(sampleF32, sampleF32.type());
    sampleF32 /= 255;
    resize(sampleF32, sampleF32, Size(96, 96), 0, 0, INTER_NEAREST);

    Mat inputBlob = blobFromImage(sampleF32);

    net.setInput(inputBlob);
    Mat out = net.forward();

    Mat outRef = readTorchBlob(_tf("net_openface_output.dat"), true);
    normAssert(out, outRef);
}

TEST_P(Test_Torch_nets, ENet_accuracy)
{
    Net net;
    {
        const string model = findDataFile("dnn/Enet-model-best.net", false);
        net = readNetFromTorch(model, true);
        ASSERT_TRUE(!net.empty());
    }

    net.setPreferableTarget(GetParam());

    Mat sample = imread(_tf("street.png", false));
    Mat inputBlob = blobFromImage(sample, 1./255);

    net.setInput(inputBlob, "");
    Mat out = net.forward();
    Mat ref = blobFromNPY(_tf("torch_enet_prob.npy", false));
    // Due to numerical instability in Pooling-Unpooling layers (indexes jittering)
    // thresholds for ENet must be changed. Accuracy of resuults was checked on
    // Cityscapes dataset and difference in mIOU with Torch is 10E-4%
    normAssert(ref, out, "", 0.00044, 0.44);

    const int N = 3;
    for (int i = 0; i < N; i++)
    {
        net.setInput(inputBlob, "");
        Mat out = net.forward();
        normAssert(ref, out, "", 0.00044, 0.44);
    }
}

// Check accuracy of style transfer models from https://github.com/jcjohnson/fast-neural-style
// th fast_neural_style.lua \
//   -input_image ~/opencv_extra/testdata/dnn/googlenet_1.png \
//   -output_image lena.png \
//   -median_filter 0 \
//   -image_size 0 \
//   -model models/eccv16/starry_night.t7
// th fast_neural_style.lua \
//   -input_image ~/opencv_extra/testdata/dnn/googlenet_1.png \
//   -output_image lena.png \
//   -median_filter 0 \
//   -image_size 0 \
//   -model models/instance_norm/feathers.t7
TEST_P(Test_Torch_nets, FastNeuralStyle_accuracy)
{
    std::string models[] = {"dnn/fast_neural_style_eccv16_starry_night.t7",
                            "dnn/fast_neural_style_instance_norm_feathers.t7"};
    std::string targets[] = {"dnn/lena_starry_night.png", "dnn/lena_feathers.png"};

    for (int i = 0; i < 2; ++i)
    {
        const string model = findDataFile(models[i], false);
        Net net = readNetFromTorch(model);

        net.setPreferableTarget(GetParam());

        Mat img = imread(findDataFile("dnn/googlenet_1.png", false));
        Mat inputBlob = blobFromImage(img, 1.0, Size(), Scalar(103.939, 116.779, 123.68), false);

        net.setInput(inputBlob);
        Mat out = net.forward();

        // Deprocessing.
        getPlane(out, 0, 0) += 103.939;
        getPlane(out, 0, 1) += 116.779;
        getPlane(out, 0, 2) += 123.68;
        out = cv::min(cv::max(0, out), 255);

        Mat ref = imread(findDataFile(targets[i]));
        Mat refBlob = blobFromImage(ref, 1.0, Size(), Scalar(), false);

        normAssert(out, refBlob, "", 0.5, 1.1);
    }
}

INSTANTIATE_TEST_CASE_P(/**/, Test_Torch_nets, availableDnnTargets());

// TODO: fix OpenCL and add to the rest of tests
TEST(Torch_Importer, run_paralel)
{
    runTorchNet("net_parallel", DNN_TARGET_CPU, "l5_torchMerge");
}

TEST(Torch_Importer, DISABLED_run_paralel)
{
    runTorchNet("net_parallel", DNN_TARGET_OPENCL, "l5_torchMerge");
}

}
<commit_msg>Update Torch testdata<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "test_precomp.hpp"
#include "npy_blob.hpp"
#include <opencv2/dnn/shape_utils.hpp>

namespace opencv_test
{

using namespace std;
using namespace testing;
using namespace cv;
using namespace cv::dnn;

template<typename TStr>
static std::string _tf(TStr filename, bool inTorchDir = true)
{
    String path = "dnn/";
    if (inTorchDir)
        path += "torch/";
    path += filename;
    return findDataFile(path, false);
}

TEST(Torch_Importer, simple_read)
{
    Net net;
    ASSERT_NO_THROW(net = readNetFromTorch(_tf("net_simple_net.txt"), false));
    ASSERT_FALSE(net.empty());
}

static void runTorchNet(String prefix, int targetId = DNN_TARGET_CPU, String outLayerName = "",
                        bool check2ndBlob = false, bool isBinary = false)
{
    String suffix = (isBinary) ? ".dat" : ".txt";

    Net net = readNetFromTorch(_tf(prefix + "_net" + suffix), isBinary);
    ASSERT_FALSE(net.empty());

    net.setPreferableBackend(DNN_BACKEND_DEFAULT);
    net.setPreferableTarget(targetId);

    Mat inp, outRef;
    ASSERT_NO_THROW( inp = readTorchBlob(_tf(prefix + "_input" + suffix), isBinary) );
    ASSERT_NO_THROW( outRef = readTorchBlob(_tf(prefix + "_output" + suffix), isBinary) );

    if (outLayerName.empty())
        outLayerName = net.getLayerNames().back();

    net.setInput(inp, "0");
    std::vector<Mat> outBlobs;
    net.forward(outBlobs, outLayerName);
    normAssert(outRef, outBlobs[0]);

    if (check2ndBlob)
    {
        Mat out2 = outBlobs[1];
        Mat ref2 = readTorchBlob(_tf(prefix + "_output_2" + suffix), isBinary);
        normAssert(out2, ref2);
    }
}

typedef testing::TestWithParam<DNNTarget> Test_Torch_layers;

TEST_P(Test_Torch_layers, run_convolution)
{
    runTorchNet("net_conv", GetParam(), "", false, true);
}

TEST_P(Test_Torch_layers, run_pool_max)
{
    runTorchNet("net_pool_max", GetParam(), "", true);
}

TEST_P(Test_Torch_layers, run_pool_ave)
{
    runTorchNet("net_pool_ave", GetParam());
}

TEST_P(Test_Torch_layers, run_reshape)
{
    int targetId = GetParam();
    runTorchNet("net_reshape", targetId);
    runTorchNet("net_reshape_batch", targetId);
    runTorchNet("net_reshape_single_sample", targetId);
    runTorchNet("net_reshape_channels", targetId, "", false, true);
}

TEST_P(Test_Torch_layers, run_linear)
{
    runTorchNet("net_linear_2d", GetParam());
}

TEST_P(Test_Torch_layers, run_concat)
{
    int targetId = GetParam();
    runTorchNet("net_concat", targetId, "l5_torchMerge");
    runTorchNet("net_depth_concat", targetId, "", false, true);
}

TEST_P(Test_Torch_layers, run_deconv)
{
    runTorchNet("net_deconv", GetParam());
}

TEST_P(Test_Torch_layers, run_batch_norm)
{
    runTorchNet("net_batch_norm", GetParam(), "", false, true);
}

TEST_P(Test_Torch_layers, net_prelu)
{
    runTorchNet("net_prelu", GetParam());
}

TEST_P(Test_Torch_layers, net_cadd_table)
{
    runTorchNet("net_cadd_table", GetParam());
}

TEST_P(Test_Torch_layers, net_softmax)
{
    int targetId = GetParam();
    runTorchNet("net_softmax", targetId);
    runTorchNet("net_softmax_spatial", targetId);
}

TEST_P(Test_Torch_layers, net_logsoftmax)
{
    runTorchNet("net_logsoftmax");
    runTorchNet("net_logsoftmax_spatial");
}

TEST_P(Test_Torch_layers, net_lp_pooling)
{
    int targetId = GetParam();
    runTorchNet("net_lp_pooling_square", targetId, "", false, true);
    runTorchNet("net_lp_pooling_power", targetId, "", false, true);
}

TEST_P(Test_Torch_layers, net_conv_gemm_lrn)
{
    runTorchNet("net_conv_gemm_lrn", GetParam(), "", false, true);
}

TEST_P(Test_Torch_layers, net_inception_block)
{
    runTorchNet("net_inception_block", GetParam(), "", false, true);
}

TEST_P(Test_Torch_layers, net_normalize)
{
    runTorchNet("net_normalize", GetParam(), "", false, true);
}

TEST_P(Test_Torch_layers, net_padding)
{
    int targetId = GetParam();
    runTorchNet("net_padding", targetId, "", false, true);
    runTorchNet("net_spatial_zero_padding", targetId, "", false, true);
    runTorchNet("net_spatial_reflection_padding", targetId, "", false, true);
}

TEST_P(Test_Torch_layers, net_non_spatial)
{
    runTorchNet("net_non_spatial", GetParam(), "", false, true);
}

INSTANTIATE_TEST_CASE_P(/**/, Test_Torch_layers, availableDnnTargets());

typedef testing::TestWithParam<DNNTarget> Test_Torch_nets;

TEST_P(Test_Torch_nets, OpenFace_accuracy)
{
    const string model = findDataFile("dnn/openface_nn4.small2.v1.t7", false);
    Net net = readNetFromTorch(model);

    net.setPreferableTarget(GetParam());

    Mat sample = imread(findDataFile("cv/shared/lena.png", false));
    Mat sampleF32(sample.size(), CV_32FC3);
    sample.convertTo(sampleF32, sampleF32.type());
    sampleF32 /= 255;
    resize(sampleF32, sampleF32, Size(96, 96), 0, 0, INTER_NEAREST);

    Mat inputBlob = blobFromImage(sampleF32);

    net.setInput(inputBlob);
    Mat out = net.forward();

    Mat outRef = readTorchBlob(_tf("net_openface_output.dat"), true);
    normAssert(out, outRef);
}

TEST_P(Test_Torch_nets, ENet_accuracy)
{
    Net net;
    {
        const string model = findDataFile("dnn/Enet-model-best.net", false);
        net = readNetFromTorch(model, true);
        ASSERT_TRUE(!net.empty());
    }

    net.setPreferableTarget(GetParam());

    Mat sample = imread(_tf("street.png", false));
    Mat inputBlob = blobFromImage(sample, 1./255);

    net.setInput(inputBlob, "");
    Mat out = net.forward();
    Mat ref = blobFromNPY(_tf("torch_enet_prob.npy", false));
    // Due to numerical instability in Pooling-Unpooling layers (indexes jittering)
    // thresholds for ENet must be changed. Accuracy of resuults was checked on
    // Cityscapes dataset and difference in mIOU with Torch is 10E-4%
    normAssert(ref, out, "", 0.00044, 0.44);

    const int N = 3;
    for (int i = 0; i < N; i++)
    {
        net.setInput(inputBlob, "");
        Mat out = net.forward();
        normAssert(ref, out, "", 0.00044, 0.44);
    }
}

// Check accuracy of style transfer models from https://github.com/jcjohnson/fast-neural-style
// th fast_neural_style.lua \
//   -input_image ~/opencv_extra/testdata/dnn/googlenet_1.png \
//   -output_image lena.png \
//   -median_filter 0 \
//   -image_size 0 \
//   -model models/eccv16/starry_night.t7
// th fast_neural_style.lua \
//   -input_image ~/opencv_extra/testdata/dnn/googlenet_1.png \
//   -output_image lena.png \
//   -median_filter 0 \
//   -image_size 0 \
//   -model models/instance_norm/feathers.t7
TEST_P(Test_Torch_nets, FastNeuralStyle_accuracy)
{
    std::string models[] = {"dnn/fast_neural_style_eccv16_starry_night.t7",
                            "dnn/fast_neural_style_instance_norm_feathers.t7"};
    std::string targets[] = {"dnn/lena_starry_night.png", "dnn/lena_feathers.png"};

    for (int i = 0; i < 2; ++i)
    {
        const string model = findDataFile(models[i], false);
        Net net = readNetFromTorch(model);

        net.setPreferableTarget(GetParam());

        Mat img = imread(findDataFile("dnn/googlenet_1.png", false));
        Mat inputBlob = blobFromImage(img, 1.0, Size(), Scalar(103.939, 116.779, 123.68), false);

        net.setInput(inputBlob);
        Mat out = net.forward();

        // Deprocessing.
        getPlane(out, 0, 0) += 103.939;
        getPlane(out, 0, 1) += 116.779;
        getPlane(out, 0, 2) += 123.68;
        out = cv::min(cv::max(0, out), 255);

        Mat ref = imread(findDataFile(targets[i]));
        Mat refBlob = blobFromImage(ref, 1.0, Size(), Scalar(), false);

        normAssert(out, refBlob, "", 0.5, 1.1);
    }
}

INSTANTIATE_TEST_CASE_P(/**/, Test_Torch_nets, availableDnnTargets());

// TODO: fix OpenCL and add to the rest of tests
TEST(Torch_Importer, run_paralel)
{
    runTorchNet("net_parallel", DNN_TARGET_CPU, "l5_torchMerge");
}

TEST(Torch_Importer, DISABLED_run_paralel)
{
    runTorchNet("net_parallel", DNN_TARGET_OPENCL, "l5_torchMerge");
}

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: dx_textlayout.cxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include <ctype.h> // don't ask. msdev breaks otherwise...
#include <canvas/debug.hxx>
#include <canvas/verbosetrace.hxx>

#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/numeric/ftools.hxx>
#include "dx_bitmap.hxx"
#include "dx_textlayout.hxx"
#include "dx_spritecanvas.hxx"
#include "dx_textlayout_drawhelper.hxx"

using namespace ::com::sun::star;

namespace dxcanvas
{
    TextLayout::TextLayout( const rendering::StringContext&     aText,
                            sal_Int8                            nDirection,
                            sal_Int64                           /*nRandomSeed*/,
                            const CanvasFont::ImplRef&          rFont ) :
        TextLayout_Base( m_aMutex ),
        maText( aText ),
        maLogicalAdvancements(),
        mpFont( rFont ),
        mnTextDirection( nDirection )
    {
    }

    TextLayout::~TextLayout()
    {
    }

    void SAL_CALL TextLayout::disposing()
    {
        mpFont.reset();
    }

    // XTextLayout
    uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > > SAL_CALL TextLayout::queryTextShapes(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > >();
    }

    uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryInkMeasures(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return uno::Sequence< geometry::RealRectangle2D >();
    }

    uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryMeasures(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return uno::Sequence< geometry::RealRectangle2D >();
    }

    uno::Sequence< double > SAL_CALL TextLayout::queryLogicalAdvancements(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        return maLogicalAdvancements;
    }

    void SAL_CALL TextLayout::applyLogicalAdvancements( const uno::Sequence< double >& aAdvancements ) throw (lang::IllegalArgumentException, uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        if( aAdvancements.getLength() != maText.Length )
        {
            OSL_TRACE( "TextLayout::applyLogicalAdvancements(): mismatching number of advancements" );
            throw lang::IllegalArgumentException();
        }

        maLogicalAdvancements = aAdvancements;
    }

    geometry::RealRectangle2D SAL_CALL TextLayout::queryTextBounds( ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        uno::Reference< rendering::XGraphicDevice > xGraphicDevice;
        ::dxcanvas::TextLayoutDrawHelper aDrawHelper(xGraphicDevice);

        // render text
        const geometry::RealRectangle2D aBounds(
            aDrawHelper.queryTextBounds(
                maText,
                maLogicalAdvancements,
                mpFont.getRef(),
                mpFont->getFontMatrix()));

        return aBounds;
    }

    double SAL_CALL TextLayout::justify( double /*nSize*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return 0.0;
    }

    double SAL_CALL TextLayout::combinedJustify( const uno::Sequence< uno::Reference< rendering::XTextLayout > >& /*aNextLayouts*/,
                                                 double /*nSize*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return 0.0;
    }

    rendering::TextHit SAL_CALL TextLayout::getTextHit( const geometry::RealPoint2D& /*aHitPoint*/ ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return rendering::TextHit();
    }

    rendering::Caret SAL_CALL TextLayout::getCaret( sal_Int32 /*nInsertionIndex*/,
                                                    sal_Bool /*bExcludeLigatures*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return rendering::Caret();
    }

    sal_Int32 SAL_CALL TextLayout::getNextInsertionIndex( sal_Int32 /*nStartIndex*/,
                                                          sal_Int32 /*nCaretAdvancement*/,
                                                          sal_Bool /*bExcludeLigatures*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return 0;
    }

    uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryVisualHighlighting( sal_Int32 /*nStartIndex*/,
                                                                                sal_Int32 /*nEndIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return uno::Reference< rendering::XPolyPolygon2D >();
    }

    uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryLogicalHighlighting( sal_Int32 /*nStartIndex*/,
                                                                                sal_Int32 /*nEndIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return uno::Reference< rendering::XPolyPolygon2D >();
    }

    double SAL_CALL TextLayout::getBaselineOffset(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return 0.0;
    }

    sal_Int8 SAL_CALL TextLayout::getMainTextDirection(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        return mnTextDirection;
    }

    uno::Reference< rendering::XCanvasFont > SAL_CALL TextLayout::getFont(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        return mpFont.getRef();
    }

    rendering::StringContext SAL_CALL TextLayout::getText(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        return maText;
    }

    namespace
    {
        // TODO(P2): Check whether this gets inlined. If not, make functor
        // out of it
        inline Gdiplus::PointF gdiPlusPointFromDx( const double& dx )
        {
            return Gdiplus::PointF( static_cast<Gdiplus::REAL>(dx),
                                    0.0f );
        }
    }

    bool TextLayout::draw( const DXBitmapSharedPtr &rBitmap,
                           const rendering::ViewState&                          rViewState,
                           const rendering::RenderState&                        rRenderState,
                           const ::basegfx::B2ISize&                            rOutputOffset,
                           const uno::Reference< rendering::XGraphicDevice >&   xGraphicDevice ) const
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        ::dxcanvas::TextLayoutDrawHelper aDrawHelper(xGraphicDevice);

        // render text
        aDrawHelper.drawText(rBitmap,
            rViewState,
            rRenderState,
            rOutputOffset,
            maText,
            maLogicalAdvancements,
            mpFont.getRef(),
            mpFont->getFontMatrix());

        return true;
    }

#define SERVICE_NAME "com.sun.star.rendering.TextLayout"
#define IMPLEMENTATION_NAME "DXCanvas::TextLayout"

    ::rtl::OUString SAL_CALL TextLayout::getImplementationName() throw( uno::RuntimeException )
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
    }

    sal_Bool SAL_CALL TextLayout::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
    {
        return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
    }

    uno::Sequence< ::rtl::OUString > SAL_CALL TextLayout::getSupportedServiceNames()  throw( uno::RuntimeException )
    {
        uno::Sequence< ::rtl::OUString > aRet(1);
        aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );

        return aRet;
    }
}
<commit_msg>INTEGRATION: CWS canvas05 (1.2.2); FILE MERGED 2008/04/21 07:30:20 thb 1.2.2.2: RESYNC: (1.2-1.3); FILE MERGED 2008/01/22 00:25:24 thb 1.2.2.1: #i81092# Making gdiplus and dx canvas more independent<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: dx_textlayout.cxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_canvas.hxx"

#include <ctype.h> // don't ask. msdev breaks otherwise...
#include <canvas/debug.hxx>
#include <canvas/verbosetrace.hxx>

#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/numeric/ftools.hxx>
#include "dx_bitmap.hxx"
#include "dx_textlayout.hxx"
#include "dx_spritecanvas.hxx"
#include "dx_textlayout_drawhelper.hxx"

using namespace ::com::sun::star;

namespace dxcanvas
{
    TextLayout::TextLayout( const rendering::StringContext&     aText,
                            sal_Int8                            nDirection,
                            sal_Int64                           /*nRandomSeed*/,
                            const CanvasFont::ImplRef&          rFont ) :
        TextLayout_Base( m_aMutex ),
        maText( aText ),
        maLogicalAdvancements(),
        mpFont( rFont ),
        mnTextDirection( nDirection )
    {
    }

    TextLayout::~TextLayout()
    {
    }

    void SAL_CALL TextLayout::disposing()
    {
        mpFont.reset();
    }

    // XTextLayout
    uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > > SAL_CALL TextLayout::queryTextShapes(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > >();
    }

    uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryInkMeasures(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return uno::Sequence< geometry::RealRectangle2D >();
    }

    uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryMeasures(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return uno::Sequence< geometry::RealRectangle2D >();
    }

    uno::Sequence< double > SAL_CALL TextLayout::queryLogicalAdvancements(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        return maLogicalAdvancements;
    }

    void SAL_CALL TextLayout::applyLogicalAdvancements( const uno::Sequence< double >& aAdvancements ) throw (lang::IllegalArgumentException, uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        if( aAdvancements.getLength() != maText.Length )
        {
            OSL_TRACE( "TextLayout::applyLogicalAdvancements(): mismatching number of advancements" );
            throw lang::IllegalArgumentException();
        }

        maLogicalAdvancements = aAdvancements;
    }

    geometry::RealRectangle2D SAL_CALL TextLayout::queryTextBounds( ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        uno::Reference< rendering::XGraphicDevice > xGraphicDevice;
        ::dxcanvas::TextLayoutDrawHelper aDrawHelper(xGraphicDevice);

        // render text
        const geometry::RealRectangle2D aBounds(
            aDrawHelper.queryTextBounds(
                maText,
                maLogicalAdvancements,
                mpFont.getRef(),
                mpFont->getFontMatrix()));

        return aBounds;
    }

    double SAL_CALL TextLayout::justify( double /*nSize*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return 0.0;
    }

    double SAL_CALL TextLayout::combinedJustify( const uno::Sequence< uno::Reference< rendering::XTextLayout > >& /*aNextLayouts*/,
                                                 double /*nSize*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return 0.0;
    }

    rendering::TextHit SAL_CALL TextLayout::getTextHit( const geometry::RealPoint2D& /*aHitPoint*/ ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return rendering::TextHit();
    }

    rendering::Caret SAL_CALL TextLayout::getCaret( sal_Int32 /*nInsertionIndex*/,
                                                    sal_Bool /*bExcludeLigatures*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return rendering::Caret();
    }

    sal_Int32 SAL_CALL TextLayout::getNextInsertionIndex( sal_Int32 /*nStartIndex*/,
                                                          sal_Int32 /*nCaretAdvancement*/,
                                                          sal_Bool /*bExcludeLigatures*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return 0;
    }

    uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryVisualHighlighting( sal_Int32 /*nStartIndex*/,
                                                                                sal_Int32 /*nEndIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return uno::Reference< rendering::XPolyPolygon2D >();
    }

    uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryLogicalHighlighting( sal_Int32 /*nStartIndex*/,
                                                                                sal_Int32 /*nEndIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return uno::Reference< rendering::XPolyPolygon2D >();
    }

    double SAL_CALL TextLayout::getBaselineOffset(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        // TODO
        return 0.0;
    }

    sal_Int8 SAL_CALL TextLayout::getMainTextDirection(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        return mnTextDirection;
    }

    uno::Reference< rendering::XCanvasFont > SAL_CALL TextLayout::getFont(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        return mpFont.getRef();
    }

    rendering::StringContext SAL_CALL TextLayout::getText(  ) throw (uno::RuntimeException)
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        return maText;
    }

    namespace
    {
        // TODO(P2): Check whether this gets inlined. If not, make functor
        // out of it
        inline Gdiplus::PointF gdiPlusPointFromDx( const double& dx )
        {
            return Gdiplus::PointF( static_cast<Gdiplus::REAL>(dx),
                                    0.0f );
        }
    }

    bool TextLayout::draw( const GraphicsSharedPtr&                           rGraphics,
                           const rendering::ViewState&                        rViewState,
                           const rendering::RenderState&                      rRenderState,
                           const ::basegfx::B2ISize&                          rOutputOffset,
                           const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice,
                           bool                                               bAlphaSurface ) const
    {
        ::osl::MutexGuard aGuard( m_aMutex );

        ::dxcanvas::TextLayoutDrawHelper aDrawHelper(xGraphicDevice);

        // render text
        aDrawHelper.drawText(
            rGraphics,
            rViewState,
            rRenderState,
            rOutputOffset,
            maText,
            maLogicalAdvancements,
            mpFont.getRef(),
            mpFont->getFontMatrix(),
            bAlphaSurface);

        return true;
    }

#define SERVICE_NAME "com.sun.star.rendering.TextLayout"
#define IMPLEMENTATION_NAME "DXCanvas::TextLayout"

    ::rtl::OUString SAL_CALL TextLayout::getImplementationName() throw( uno::RuntimeException )
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
    }

    sal_Bool SAL_CALL TextLayout::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
    {
        return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
    }

    uno::Sequence< ::rtl::OUString > SAL_CALL TextLayout::getSupportedServiceNames()  throw( uno::RuntimeException )
    {
        uno::Sequence< ::rtl::OUString > aRet(1);
        aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );

        return aRet;
    }
}
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file
 **/

#include <limits>
#include <unordered_map>

#include "modules/common/configs/vehicle_config_helper.h"
#include "modules/common/log.h"
#include "modules/common/util/util.h"
#include "modules/planning/common/path_obstacle.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/common/speed/st_boundary.h"

namespace apollo {
namespace planning {

using common::VehicleConfigHelper;

namespace {
const double kStBoundaryDeltaS = 0.2;
}

const std::unordered_map<ObjectDecisionType::ObjectTagCase, int,
                         PathObstacle::ObjectTagCaseHash>
    PathObstacle::s_longitudinal_decision_safety_sorter_ = {
        {ObjectDecisionType::kIgnore, 0},
        {ObjectDecisionType::kOvertake, 100},
        {ObjectDecisionType::kFollow, 300},
        {ObjectDecisionType::kYield, 400},
        {ObjectDecisionType::kStop, 500}};

const std::unordered_map<ObjectDecisionType::ObjectTagCase, int,
                         PathObstacle::ObjectTagCaseHash>
    PathObstacle::s_lateral_decision_safety_sorter_ = {
        {ObjectDecisionType::kIgnore, 0}, {ObjectDecisionType::kNudge, 100}};

const std::string& PathObstacle::Id() const { return id_; }

PathObstacle::PathObstacle(const Obstacle* obstacle) : obstacle_(obstacle) {
  CHECK_NOTNULL(obstacle);
  id_ = obstacle_->Id();
}

bool PathObstacle::Init(const ReferenceLine& reference_line) {
  if (!reference_line.GetSLBoundary(obstacle_->PerceptionBoundingBox(),
                                    &perception_sl_boundary_)) {
    AERROR << "Failed to get sl boundary for obstacle: " << id_;
    return false;
  }
  BuildStBoundary(reference_line);
  return true;
}

void PathObstacle::BuildStBoundary(const ReferenceLine& reference_line) {
  if (obstacle_->IsStatic() ||
      obstacle_->Trajectory().trajectory_point().empty()) {
    std::vector<STPoint> points;
    points.emplace_back(perception_sl_boundary_.start_s(), 0.0);
    points.emplace_back(perception_sl_boundary_.start_s(), FLAGS_st_max_t);
    points.emplace_back(perception_sl_boundary_.end_s(), FLAGS_st_max_t);
    points.emplace_back(perception_sl_boundary_.end_s(), 0.0);
    st_boundary_ = StBoundary(points);
  } else {
    if (BuildTrajectoryStBoundary(reference_line, &st_boundary_)) {
      ADEBUG << "Found st_boundary for obstacle " << id_;
    } else {
      ADEBUG << "No st_boundary for obstacle " << id_;
    }
  }
}

bool PathObstacle::BuildTrajectoryStBoundary(
    const ReferenceLine& reference_line, StBoundary* const st_boundary) {
  const auto& object_id = obstacle_->Id();
  const auto& perception = obstacle_->Perception();
  const double object_width = perception.width();
  const double object_length = perception.length();
  const auto& trajectory_points = obstacle_->Trajectory().trajectory_point();
  if (trajectory_points.empty()) {
    AWARN << "object " << object_id << " has no trajectory points";
    return false;
  }
  const auto& adc_param =
      VehicleConfigHelper::instance()->GetConfig().vehicle_param();
  const double adc_length = adc_param.length();
  const double adc_half_length = adc_length / 2.0;
  const double adc_width = adc_param.width();
  common::math::Box2d min_box({0, 0}, 1.0, 1.0, 1.0);
  common::math::Box2d max_box({0, 0}, 1.0, 1.0, 1.0);
  const double s_step = kStBoundaryDeltaS;
  std::vector<common::math::Vec2d> polygon_points;
  for (int i = 1; i < trajectory_points.size(); ++i) {
    const auto& first_traj_point = trajectory_points[i - 1];
    const auto& second_traj_point = trajectory_points[i - 1];
    const auto& first_point = first_traj_point.path_point();
    const auto& second_point = second_traj_point.path_point();
    double total_length =
        object_length + common::util::Distance2D(first_point, second_point);
    common::math::Vec2d center((first_point.x() + second_point.x()) / 2.0,
                               (first_point.y() + second_point.y()) / 2.0);
    common::math::Box2d object_moving_box(center, first_point.theta(),
                                          total_length, object_width);
    SLBoundary object_boundary;
    if (!reference_line.GetSLBoundary(object_moving_box, &object_boundary)) {
      AERROR << "failed to calculate boundary";
      return false;
    }
    const double object_s_diff =
        object_boundary.end_s() - object_boundary.start_s();
    if (object_boundary.end_s() < 0) {
      // skip if behind adc
      continue;
    }
    const double delta_t =
        second_traj_point.relative_time() - first_traj_point.relative_time();
    for (double s = std::max(object_boundary.start_s() - adc_half_length, 0.0);
         s <
         std::min(object_boundary.end_s() + adc_half_length, FLAGS_st_max_s);
         s += s_step) {
      auto adc_trajectory_point = reference_line.GetReferencePoint(s);
      common::math::Box2d tmp_adc_box(adc_trajectory_point,
                                      adc_trajectory_point.heading(),
                                      adc_length, adc_width);
      if (tmp_adc_box.HasOverlap(object_moving_box)) {
        double mean_t = first_traj_point.relative_time();
        if (object_s_diff > common::math::kMathEpsilon) {
          mean_t = (first_traj_point.relative_time() +
                    std::fabs((s - object_boundary.start_s()) / object_s_diff) *
                        delta_t);
        }
        polygon_points.emplace_back(mean_t, s);
      }
    }
  }
  if (polygon_points.size() < 3) {
    ADEBUG << "object " << object_id << " has no st overlap";
    return false;
  }
  common::math::Polygon2d::ComputeConvexHull(polygon_points, st_boundary);
  return true;
}

const StBoundary& PathObstacle::st_boundary() const { return st_boundary_; }

bool PathObstacle::IsLateralDecision(const ObjectDecisionType& decision) {
  return decision.has_ignore() || decision.has_nudge();
}

bool PathObstacle::IsLongitudinalDecision(const ObjectDecisionType& decision) {
  return decision.has_ignore() || decision.has_stop() || decision.has_yield() ||
         decision.has_follow() || decision.has_overtake();
}

ObjectDecisionType PathObstacle::MergeLongitudinalDecision(
    const ObjectDecisionType& lhs, const ObjectDecisionType& rhs) {
  if (lhs.object_tag_case() == ObjectDecisionType::OBJECT_TAG_NOT_SET) {
    return rhs;
  }
  if (rhs.object_tag_case() == ObjectDecisionType::OBJECT_TAG_NOT_SET) {
    return lhs;
  }
  auto lhs_iter =
      s_longitudinal_decision_safety_sorter_.find(lhs.object_tag_case());
  DCHECK(lhs_iter != s_longitudinal_decision_safety_sorter_.end())
      << "decision : " << lhs.ShortDebugString()
      << " not found in safety sorter";
  auto rhs_iter =
      s_longitudinal_decision_safety_sorter_.find(rhs.object_tag_case());
  DCHECK(rhs_iter != s_longitudinal_decision_safety_sorter_.end())
      << "decision : " << rhs.ShortDebugString()
      << " not found in safety sorter";
  if (lhs_iter->second < rhs_iter->second) {
    return rhs;
  } else if (lhs_iter->second > rhs_iter->second) {
    return lhs;
  } else {
    if (lhs.has_ignore()) {
      return rhs;
    } else if (lhs.has_stop()) {
      return lhs.stop().distance_s() < rhs.stop().distance_s() ? lhs : rhs;
    } else if (lhs.has_yield()) {
      return lhs.yield().distance_s() < rhs.yield().distance_s() ? lhs : rhs;
    } else if (lhs.has_follow()) {
      return lhs.follow().distance_s() < rhs.follow().distance_s() ? lhs : rhs;
    } else if (lhs.has_overtake()) {
      return lhs.overtake().distance_s() > rhs.overtake().distance_s() ? lhs
                                                                       : rhs;
    } else {
      DCHECK(false) << "Unknown decision";
    }
  }
}

const ObjectDecisionType& PathObstacle::LongitudinalDecision() const {
  return longitudinal_decision_;
}

const ObjectDecisionType& PathObstacle::LateralDecision() const {
  return lateral_decision_;
}

bool PathObstacle::IsIgnore() const {
  return longitudinal_decision_.has_ignore() && lateral_decision_.has_ignore();
}

ObjectDecisionType PathObstacle::MergeLateralDecision(
    const ObjectDecisionType& lhs, const ObjectDecisionType& rhs) {
  if (lhs.object_tag_case() == ObjectDecisionType::OBJECT_TAG_NOT_SET) {
    return rhs;
  }
  if (rhs.object_tag_case() == ObjectDecisionType::OBJECT_TAG_NOT_SET) {
    return lhs;
  }
  auto lhs_iter = s_lateral_decision_safety_sorter_.find(lhs.object_tag_case());
  DCHECK(lhs_iter != s_lateral_decision_safety_sorter_.end())
      << "decision : " << lhs.ShortDebugString()
      << " not found in safety sorter";
  auto rhs_iter = s_lateral_decision_safety_sorter_.find(rhs.object_tag_case());
  DCHECK(rhs_iter != s_lateral_decision_safety_sorter_.end())
      << "decision : " << rhs.ShortDebugString()
      << " not found in safety sorter";
  if (lhs_iter->second < rhs_iter->second) {
    return rhs;
  } else if (lhs_iter->second > rhs_iter->second) {
    return lhs;
  } else {
    if (lhs.has_ignore()) {
      return rhs;
    } else if (lhs.has_nudge()) {
      DCHECK(lhs.nudge().type() == rhs.nudge().type())
          << "could not merge left nudge and right nudge";
      return std::fabs(lhs.nudge().distance_l()) >
                     std::fabs(rhs.nudge().distance_l())
                 ? lhs
                 : rhs;
    }
  }
  DCHECK(false) << "Does not have rule to merge decision: "
                << lhs.ShortDebugString()
                << " and decision: " << rhs.ShortDebugString();
}

bool PathObstacle::HasLateralDecision() const {
  return lateral_decision_.object_tag_case() !=
         ObjectDecisionType::OBJECT_TAG_NOT_SET;
}

bool PathObstacle::HasLongitudinalDecision() const {
  return longitudinal_decision_.object_tag_case() !=
         ObjectDecisionType::OBJECT_TAG_NOT_SET;
}

const Obstacle* PathObstacle::obstacle() const { return obstacle_; }

void PathObstacle::AddLongitudinalDecision(const std::string& decider_tag,
                                           const ObjectDecisionType& decision) {
  DCHECK(IsLongitudinalDecision(decision))
      << "Decision: " << decision.ShortDebugString()
      << " is not a longitudinal decision";
  longitudinal_decision_ =
      MergeLongitudinalDecision(longitudinal_decision_, decision);
  ADEBUG << decider_tag << " added obstacle " << Id()
         << " a longitudinal decision: " << decision.ShortDebugString()
         << ". The merged decision is: "
         << longitudinal_decision_.ShortDebugString();
  decisions_.push_back(decision);
  decider_tags_.push_back(decider_tag);
}

void PathObstacle::AddLateralDecision(const std::string& decider_tag,
                                      const ObjectDecisionType& decision) {
  DCHECK(IsLateralDecision(decision))
      << "Decision: " << decision.ShortDebugString()
      << " is not a lateral decision";
  lateral_decision_ = MergeLateralDecision(lateral_decision_, decision);
  ADEBUG << decider_tag << " added obstacle " << Id()
         << " a lateral decision: " << decision.ShortDebugString()
         << ". The merged decision is: "
         << lateral_decision_.ShortDebugString();
  decisions_.push_back(decision);
  decider_tags_.push_back(decider_tag);
}

const std::string PathObstacle::DebugString() const {
  std::stringstream ss;
  ss << "PathObstacle id: " << id_;
  for (std::size_t i = 0; i < decisions_.size(); ++i) {
    ss << " decision: " << decisions_[i].DebugString() << ", made by "
       << decider_tags_[i];
  }
  if (lateral_decision_.object_tag_case() !=
      ObjectDecisionType::OBJECT_TAG_NOT_SET) {
    ss << "lateral decision: " << lateral_decision_.ShortDebugString();
  }
  if (longitudinal_decision_.object_tag_case() !=
      ObjectDecisionType::OBJECT_TAG_NOT_SET) {
    ss << "longitutional decision: "
       << longitudinal_decision_.ShortDebugString();
  }
  return ss.str();
}

const SLBoundary& PathObstacle::perception_sl_boundary() const {
  return perception_sl_boundary_;
}

}  // namespace planning
}  // namespace apollo
<commit_msg>planning: temporariy disable StBoundary in path_obstacle<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file
 **/

#include <limits>
#include <unordered_map>

#include "modules/common/configs/vehicle_config_helper.h"
#include "modules/common/log.h"
#include "modules/common/util/util.h"
#include "modules/planning/common/path_obstacle.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/common/speed/st_boundary.h"

namespace apollo {
namespace planning {

using common::VehicleConfigHelper;

namespace {
const double kStBoundaryDeltaS = 0.2;
}

const std::unordered_map<ObjectDecisionType::ObjectTagCase, int,
                         PathObstacle::ObjectTagCaseHash>
    PathObstacle::s_longitudinal_decision_safety_sorter_ = {
        {ObjectDecisionType::kIgnore, 0},
        {ObjectDecisionType::kOvertake, 100},
        {ObjectDecisionType::kFollow, 300},
        {ObjectDecisionType::kYield, 400},
        {ObjectDecisionType::kStop, 500}};

const std::unordered_map<ObjectDecisionType::ObjectTagCase, int,
                         PathObstacle::ObjectTagCaseHash>
    PathObstacle::s_lateral_decision_safety_sorter_ = {
        {ObjectDecisionType::kIgnore, 0}, {ObjectDecisionType::kNudge, 100}};

const std::string& PathObstacle::Id() const { return id_; }

PathObstacle::PathObstacle(const Obstacle* obstacle) : obstacle_(obstacle) {
  CHECK_NOTNULL(obstacle);
  id_ = obstacle_->Id();
}

bool PathObstacle::Init(const ReferenceLine& reference_line) {
  if (!reference_line.GetSLBoundary(obstacle_->PerceptionBoundingBox(),
                                    &perception_sl_boundary_)) {
    AERROR << "Failed to get sl boundary for obstacle: " << id_;
    return false;
  }
  // BuildStBoundary(reference_line);
  return true;
}

void PathObstacle::BuildStBoundary(const ReferenceLine& reference_line) {
  if (obstacle_->IsStatic() ||
      obstacle_->Trajectory().trajectory_point().empty()) {
    std::vector<STPoint> points;
    points.emplace_back(perception_sl_boundary_.start_s(), 0.0);
    points.emplace_back(perception_sl_boundary_.start_s(), FLAGS_st_max_t);
    points.emplace_back(perception_sl_boundary_.end_s(), FLAGS_st_max_t);
    points.emplace_back(perception_sl_boundary_.end_s(), 0.0);
    st_boundary_ = StBoundary(points);
  } else {
    if (BuildTrajectoryStBoundary(reference_line, &st_boundary_)) {
      ADEBUG << "Found st_boundary for obstacle " << id_;
    } else {
      ADEBUG << "No st_boundary for obstacle " << id_;
    }
  }
}

bool PathObstacle::BuildTrajectoryStBoundary(
    const ReferenceLine& reference_line, StBoundary* const st_boundary) {
  const auto& object_id = obstacle_->Id();
  const auto& perception = obstacle_->Perception();
  const double object_width = perception.width();
  const double object_length = perception.length();
  const auto& trajectory_points = obstacle_->Trajectory().trajectory_point();
  if (trajectory_points.empty()) {
    AWARN << "object " << object_id << " has no trajectory points";
    return false;
  }
  const auto& adc_param =
      VehicleConfigHelper::instance()->GetConfig().vehicle_param();
  const double adc_length = adc_param.length();
  const double adc_half_length = adc_length / 2.0;
  const double adc_width = adc_param.width();
  common::math::Box2d min_box({0, 0}, 1.0, 1.0, 1.0);
  common::math::Box2d max_box({0, 0}, 1.0, 1.0, 1.0);
  const double s_step = kStBoundaryDeltaS;
  std::vector<common::math::Vec2d> polygon_points;
  for (int i = 1; i < trajectory_points.size(); ++i) {
    const auto& first_traj_point = trajectory_points[i - 1];
    const auto& second_traj_point = trajectory_points[i - 1];
    const auto& first_point = first_traj_point.path_point();
    const auto& second_point = second_traj_point.path_point();
    double total_length =
        object_length + common::util::Distance2D(first_point, second_point);
    common::math::Vec2d center((first_point.x() + second_point.x()) / 2.0,
                               (first_point.y() + second_point.y()) / 2.0);
    common::math::Box2d object_moving_box(center, first_point.theta(),
                                          total_length, object_width);
    SLBoundary object_boundary;
    if (!reference_line.GetSLBoundary(object_moving_box, &object_boundary)) {
      AERROR << "failed to calculate boundary";
      return false;
    }
    const double object_s_diff =
        object_boundary.end_s() - object_boundary.start_s();
    if (object_boundary.end_s() < 0) {
      // skip if behind adc
      continue;
    }
    const double delta_t =
        second_traj_point.relative_time() - first_traj_point.relative_time();
    for (double s = std::max(object_boundary.start_s() - adc_half_length, 0.0);
         s <
         std::min(object_boundary.end_s() + adc_half_length, FLAGS_st_max_s);
         s += s_step) {
      auto adc_trajectory_point = reference_line.GetReferencePoint(s);
      common::math::Box2d tmp_adc_box(adc_trajectory_point,
                                      adc_trajectory_point.heading(),
                                      adc_length, adc_width);
      if (tmp_adc_box.HasOverlap(object_moving_box)) {
        double mean_t = first_traj_point.relative_time();
        if (object_s_diff > common::math::kMathEpsilon) {
          mean_t = (first_traj_point.relative_time() +
                    std::fabs((s - object_boundary.start_s()) / object_s_diff) *
                        delta_t);
        }
        polygon_points.emplace_back(mean_t, s);
      }
    }
  }
  if (polygon_points.size() < 3) {
    ADEBUG << "object " << object_id << " has no st overlap";
    return false;
  }
  common::math::Polygon2d::ComputeConvexHull(polygon_points, st_boundary);
  return true;
}

const StBoundary& PathObstacle::st_boundary() const { return st_boundary_; }

bool PathObstacle::IsLateralDecision(const ObjectDecisionType& decision) {
  return decision.has_ignore() || decision.has_nudge();
}

bool PathObstacle::IsLongitudinalDecision(const ObjectDecisionType& decision) {
  return decision.has_ignore() || decision.has_stop() || decision.has_yield() ||
         decision.has_follow() || decision.has_overtake();
}

ObjectDecisionType PathObstacle::MergeLongitudinalDecision(
    const ObjectDecisionType& lhs, const ObjectDecisionType& rhs) {
  if (lhs.object_tag_case() == ObjectDecisionType::OBJECT_TAG_NOT_SET) {
    return rhs;
  }
  if (rhs.object_tag_case() == ObjectDecisionType::OBJECT_TAG_NOT_SET) {
    return lhs;
  }
  auto lhs_iter =
      s_longitudinal_decision_safety_sorter_.find(lhs.object_tag_case());
  DCHECK(lhs_iter != s_longitudinal_decision_safety_sorter_.end())
      << "decision : " << lhs.ShortDebugString()
      << " not found in safety sorter";
  auto rhs_iter =
      s_longitudinal_decision_safety_sorter_.find(rhs.object_tag_case());
  DCHECK(rhs_iter != s_longitudinal_decision_safety_sorter_.end())
      << "decision : " << rhs.ShortDebugString()
      << " not found in safety sorter";
  if (lhs_iter->second < rhs_iter->second) {
    return rhs;
  } else if (lhs_iter->second > rhs_iter->second) {
    return lhs;
  } else {
    if (lhs.has_ignore()) {
      return rhs;
    } else if (lhs.has_stop()) {
      return lhs.stop().distance_s() < rhs.stop().distance_s() ? lhs : rhs;
    } else if (lhs.has_yield()) {
      return lhs.yield().distance_s() < rhs.yield().distance_s() ? lhs : rhs;
    } else if (lhs.has_follow()) {
      return lhs.follow().distance_s() < rhs.follow().distance_s() ? lhs : rhs;
    } else if (lhs.has_overtake()) {
      return lhs.overtake().distance_s() > rhs.overtake().distance_s() ? lhs
                                                                       : rhs;
    } else {
      DCHECK(false) << "Unknown decision";
    }
  }
}

const ObjectDecisionType& PathObstacle::LongitudinalDecision() const {
  return longitudinal_decision_;
}

const ObjectDecisionType& PathObstacle::LateralDecision() const {
  return lateral_decision_;
}

bool PathObstacle::IsIgnore() const {
  return longitudinal_decision_.has_ignore() && lateral_decision_.has_ignore();
}

ObjectDecisionType PathObstacle::MergeLateralDecision(
    const ObjectDecisionType& lhs, const ObjectDecisionType& rhs) {
  if (lhs.object_tag_case() == ObjectDecisionType::OBJECT_TAG_NOT_SET) {
    return rhs;
  }
  if (rhs.object_tag_case() == ObjectDecisionType::OBJECT_TAG_NOT_SET) {
    return lhs;
  }
  auto lhs_iter = s_lateral_decision_safety_sorter_.find(lhs.object_tag_case());
  DCHECK(lhs_iter != s_lateral_decision_safety_sorter_.end())
      << "decision : " << lhs.ShortDebugString()
      << " not found in safety sorter";
  auto rhs_iter = s_lateral_decision_safety_sorter_.find(rhs.object_tag_case());
  DCHECK(rhs_iter != s_lateral_decision_safety_sorter_.end())
      << "decision : " << rhs.ShortDebugString()
      << " not found in safety sorter";
  if (lhs_iter->second < rhs_iter->second) {
    return rhs;
  } else if (lhs_iter->second > rhs_iter->second) {
    return lhs;
  } else {
    if (lhs.has_ignore()) {
      return rhs;
    } else if (lhs.has_nudge()) {
      DCHECK(lhs.nudge().type() == rhs.nudge().type())
          << "could not merge left nudge and right nudge";
      return std::fabs(lhs.nudge().distance_l()) >
                     std::fabs(rhs.nudge().distance_l())
                 ? lhs
                 : rhs;
    }
  }
  DCHECK(false) << "Does not have rule to merge decision: "
                << lhs.ShortDebugString()
                << " and decision: " << rhs.ShortDebugString();
}

bool PathObstacle::HasLateralDecision() const {
  return lateral_decision_.object_tag_case() !=
         ObjectDecisionType::OBJECT_TAG_NOT_SET;
}

bool PathObstacle::HasLongitudinalDecision() const {
  return longitudinal_decision_.object_tag_case() !=
         ObjectDecisionType::OBJECT_TAG_NOT_SET;
}

const Obstacle* PathObstacle::obstacle() const { return obstacle_; }

void PathObstacle::AddLongitudinalDecision(const std::string& decider_tag,
                                           const ObjectDecisionType& decision) {
  DCHECK(IsLongitudinalDecision(decision))
      << "Decision: " << decision.ShortDebugString()
      << " is not a longitudinal decision";
  longitudinal_decision_ =
      MergeLongitudinalDecision(longitudinal_decision_, decision);
  ADEBUG << decider_tag << " added obstacle " << Id()
         << " a longitudinal decision: " << decision.ShortDebugString()
         << ". The merged decision is: "
         << longitudinal_decision_.ShortDebugString();
  decisions_.push_back(decision);
  decider_tags_.push_back(decider_tag);
}

void PathObstacle::AddLateralDecision(const std::string& decider_tag,
                                      const ObjectDecisionType& decision) {
  DCHECK(IsLateralDecision(decision))
      << "Decision: " << decision.ShortDebugString()
      << " is not a lateral decision";
  lateral_decision_ = MergeLateralDecision(lateral_decision_, decision);
  ADEBUG << decider_tag << " added obstacle " << Id()
         << " a lateral decision: " << decision.ShortDebugString()
         << ". The merged decision is: "
         << lateral_decision_.ShortDebugString();
  decisions_.push_back(decision);
  decider_tags_.push_back(decider_tag);
}

const std::string PathObstacle::DebugString() const {
  std::stringstream ss;
  ss << "PathObstacle id: " << id_;
  for (std::size_t i = 0; i < decisions_.size(); ++i) {
    ss << " decision: " << decisions_[i].DebugString() << ", made by "
       << decider_tags_[i];
  }
  if (lateral_decision_.object_tag_case() !=
      ObjectDecisionType::OBJECT_TAG_NOT_SET) {
    ss << "lateral decision: " << lateral_decision_.ShortDebugString();
  }
  if (longitudinal_decision_.object_tag_case() !=
      ObjectDecisionType::OBJECT_TAG_NOT_SET) {
    ss << "longitutional decision: "
       << longitudinal_decision_.ShortDebugString();
  }
  return ss.str();
}

const SLBoundary& PathObstacle::perception_sl_boundary() const {
  return perception_sl_boundary_;
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>