void ColorPalette::draw_SV_palette( void ) { const int x0 = m_SV_palette.x0(); const int y0 = m_SV_palette.y0(); const int x1 = m_SV_palette.x1(); const int y1 = m_SV_palette.y1(); const float h = this->get_H_value(); const kvs::RGBColor c0( kvs::HSVColor( h, 1, 1 ) ); // top-right const kvs::RGBColor c1( kvs::HSVColor( h, 0, 1 ) ); // top-left const kvs::RGBColor c2( kvs::HSVColor( h, 0, 0 ) ); // bottom-left const kvs::RGBColor c3( kvs::HSVColor( h, 1, 0 ) ); // bottom-right // Draw SV palette. glBegin( GL_QUADS ); glColor3ub( c0.r(), c0.g(), c0.b() ); glVertex2i( x1, y0 ); glColor3ub( c1.r(), c1.g(), c1.b() ); glVertex2i( x0, y0 ); glColor3ub( c2.r(), c2.g(), c2.b() ); glVertex2i( x0, y1 ); glColor3ub( c3.r(), c3.g(), c3.b() ); glVertex2i( x1, y1 ); glEnd(); // Draw the cross lines. { const int margin = 4; const float color = 1.0f; const int cursor_x0 = kvs::Math::Max( m_S_indicator - margin, m_SV_palette.x0() ); const int cursor_y0 = kvs::Math::Max( m_V_indicator - margin, m_SV_palette.y0() ); const int cursor_x1 = kvs::Math::Min( m_S_indicator + margin, m_SV_palette.x1() ); const int cursor_y1 = kvs::Math::Min( m_V_indicator + margin, m_SV_palette.y1() ); glLineWidth( 1 ); glBegin( GL_LINES ); glColor3f( color, color, color ); glVertex2i( cursor_x0, cursor_y0 ); glVertex2i( cursor_x1, cursor_y0 ); // top glVertex2i( cursor_x0, cursor_y1 ); glVertex2i( cursor_x1, cursor_y1 ); // bottom glVertex2i( cursor_x0, cursor_y0 ); glVertex2i( cursor_x0, cursor_y1 + 1 ); // left glVertex2i( cursor_x1, cursor_y0 ); glVertex2i( cursor_x1, cursor_y1 + 1 ); // right glEnd(); glLineWidth( 1 ); glBegin( GL_LINES ); glColor3f( color, color, color ); // Horizontal lines. glVertex2i( x0, m_V_indicator ); glVertex2i( cursor_x0, m_V_indicator ); glVertex2i( cursor_x1, m_V_indicator ); glVertex2i( x1, m_V_indicator ); // Vertical lines. glVertex2i( m_S_indicator, y0 ); glVertex2i( m_S_indicator, cursor_y0 ); glVertex2i( m_S_indicator, cursor_y1 ); glVertex2i( m_S_indicator, y1 ); glEnd(); } // Draw border. ::DrawRectangle( m_SV_palette, 1, m_upper_edge_color, m_lower_edge_color ); }
/*===========================================================================*/ void SphereGlyph::draw_element( const kvs::RGBColor& color, const kvs::UInt8 opacity ) { KVS_GL_CALL( glColor4ub( color.r(), color.g(), color.b(), opacity ) ); const GLdouble radius = 0.5; gluSphere( m_sphere, radius, static_cast<GLint>(m_nslices), static_cast<GLint>(m_nstacks) ); }
void ColorPalette::draw_selected_color_value( void ) { const kvs::RGBColor current_color = this->color(); const int r = static_cast<int>( current_color.r() ); const int g = static_cast<int>( current_color.g() ); const int b = static_cast<int>( current_color.b() ); const float h = this->get_H_value(); const float s = this->get_S_value(); const float v = this->get_V_value(); char R[10]; sprintf( R, "R: %3d", r ); char G[10]; sprintf( G, "G: %3d", g ); char B[10]; sprintf( B, "B: %3d", b ); char H[10]; sprintf( H, "H: %3d", static_cast<int>( h * 255.0f + 0.5f ) ); char S[10]; sprintf( S, "S: %3d", static_cast<int>( s * 255.0f + 0.5f ) ); char V[10]; sprintf( V, "V: %3d", static_cast<int>( v * 255.0f + 0.5f ) ); int x = m_selected_color_box.x0(); int y = m_selected_color_box.y1() + 10; BaseClass::draw_text( x, y += BaseClass::characterHeight(), R ); BaseClass::draw_text( x, y += BaseClass::characterHeight(), G ); BaseClass::draw_text( x, y += BaseClass::characterHeight(), B ); BaseClass::draw_text( x, y += BaseClass::characterHeight(), "" ); BaseClass::draw_text( x, y += BaseClass::characterHeight(), H ); BaseClass::draw_text( x, y += BaseClass::characterHeight(), S ); BaseClass::draw_text( x, y += BaseClass::characterHeight(), V ); }
/*===========================================================================*/ void ColorMapPalette::mouseMoveEvent( kvs::MouseEvent* event ) { if ( !BaseClass::isShown() ) return; if ( BaseClass::isActive() ) { if ( m_palette.isActive() ) { // Color map palette geometry. const int x0 = m_palette.x0(); const int x1 = m_palette.x1(); const int y0 = m_palette.y0(); const int y1 = m_palette.y1(); // Current mouse cursor position. const int x = event->x(); const int y = event->y(); const int old_x = kvs::Math::Clamp( m_pressed_position.x(), x0, x1 ); const int old_y = kvs::Math::Clamp( m_pressed_position.y(), y0, y1 ); const int new_x = kvs::Math::Clamp( x, x0, x1 ); const int new_y = kvs::Math::Clamp( y, y0, y1 ); m_pressed_position.set( x, y ); const float old_ratio = static_cast<float>( y1 - old_y ) / ( y1 - y0 ); const float new_ratio = static_cast<float>( y1 - new_y ) / ( y1 - y0 ); const float diff_ratio = new_ratio - old_ratio; const float resolution = static_cast<float>( m_color_map.resolution() ); const int old_index = static_cast<int>( ( old_x - x0 ) * resolution / ( x1 - x0 ) + 0.5f ); const int new_index = static_cast<int>( ( new_x - x0 ) * resolution / ( x1 - x0 ) + 0.5f ); const float diff_index = static_cast<float>( new_index - old_index ); if ( m_color_palette ) m_drawing_color = m_color_palette->color(); const kvs::RGBColor drawing_color = m_drawing_color; const int begin_index = kvs::Math::Min( old_index, new_index ); const int end_index = kvs::Math::Max( old_index, new_index ); kvs::UInt8* data = const_cast<kvs::UInt8*>( m_color_map.table().data() ); kvs::UInt8* pdata = data + begin_index * 3; for ( int i = begin_index; i < end_index; i++, pdata += 3 ) { const float ratio = ( i - old_index ) * diff_ratio / diff_index + old_ratio; pdata[0] = static_cast<kvs::UInt8>( drawing_color.r() * ratio + pdata[0] * ( 1 - ratio ) ); pdata[1] = static_cast<kvs::UInt8>( drawing_color.g() * ratio + pdata[1] * ( 1 - ratio ) ); pdata[2] = static_cast<kvs::UInt8>( drawing_color.b() * ratio + pdata[2] * ( 1 - ratio ) ); } const size_t width = m_color_map.resolution(); m_texture.bind(); m_texture.load( width, data ); m_texture.unbind(); } BaseClass::screen()->redraw(); } }
/*===========================================================================*/ void SphereGlyph::attach_point( const kvs::PointObject* point ) { m_point = point; const size_t nvertices = point->numberOfVertices(); BaseClass::setCoords( point->coords() ); if ( BaseClass::directionMode() == BaseClass::DirectionByNormal ) { if ( point->numberOfNormals() != 0 ) { BaseClass::setDirections( point->normals() ); } } if ( point->numberOfSizes() == 1 ) { const kvs::Real32 size = point->size(); kvs::ValueArray<kvs::Real32> sizes( nvertices ); for ( size_t i = 0; i < nvertices; i++ ) sizes[i] = size; BaseClass::setSizes( sizes ); } else { BaseClass::setSizes( point->sizes() ); } if ( point->numberOfColors() == 1 ) { const kvs::RGBColor color = point->color(); kvs::ValueArray<kvs::UInt8> colors( nvertices * 3 ); for ( size_t i = 0, j = 0; i < nvertices; i++, j += 3 ) { colors[j] = color.r(); colors[j+1] = color.g(); colors[j+2] = color.b(); } BaseClass::setColors( colors ); } else { BaseClass::setColors( point->colors() ); } const kvs::UInt8 opacity = static_cast<kvs::UInt8>( 255 ); kvs::ValueArray<kvs::UInt8> opacities( nvertices ); for ( size_t i = 0; i < nvertices; i++ ) opacities[i] = opacity; BaseClass::setOpacities( opacities ); }
/*===========================================================================*/ void ColorMapPalette::mousePressEvent( kvs::MouseEvent* event ) { if ( !BaseClass::isShown() ) return; if ( BaseClass::contains( event->x(), event->y() ) ) { BaseClass::screen()->disable(); BaseClass::activate(); if ( m_palette.contains( event->x(), event->y(), true ) ) { m_palette.activate(); // Color map palette geometry. const int x0 = m_palette.x0(); const int x1 = m_palette.x1(); const int y0 = m_palette.y0(); const int y1 = m_palette.y1(); // Current mouse cursor position. const int x = event->x(); const int y = event->y(); m_pressed_position.set( x, y ); const float resolution = static_cast<float>( m_color_map.resolution() ); const float ratio = static_cast<float>( y1 - y ) / ( y1 - y0 ); const int index = static_cast<int>( ( x - x0 ) * resolution / ( x1 - x0 ) + 0.5f ); // Update the color data. if ( m_color_palette ) m_drawing_color = m_color_palette->color(); const kvs::RGBColor drawing_color = m_drawing_color; kvs::UInt8* data = const_cast<kvs::UInt8*>( m_color_map.table().data() ); kvs::UInt8* pdata = data; pdata = data + index * 3; pdata[0] = static_cast<kvs::UInt8>( drawing_color.r() * ratio + pdata[0] * ( 1 - ratio ) ); pdata[1] = static_cast<kvs::UInt8>( drawing_color.g() * ratio + pdata[1] * ( 1 - ratio ) ); pdata[2] = static_cast<kvs::UInt8>( drawing_color.b() * ratio + pdata[2] * ( 1 - ratio ) ); const size_t width = m_color_map.resolution(); m_texture.bind(); m_texture.load( width, data ); m_texture.unbind(); } BaseClass::screen()->redraw(); } }
kvs::ColorMap DivergingColorMap::Create( const kvs::RGBColor& rgb1, const kvs::RGBColor& rgb2, const size_t resolution ) { kvs::ColorMap::Table table( 3 * resolution ); kvs::UInt8* color = table.data(); for ( size_t i = 0; i < resolution; i++ ) { const kvs::Real32 ratio = kvs::Real32(i) / ( resolution - 1 ); const kvs::RGBColor rgb = ::Interpolate( rgb1, rgb2, ratio ); *( color++ ) = rgb.r(); *( color++ ) = rgb.g(); *( color++ ) = rgb.b(); } return kvs::ColorMap( table ); }
void ColorPalette::draw_selected_color_box( void ) { const int x0 = m_selected_color_box.x0(); const int y0 = m_selected_color_box.y0(); const int x1 = m_selected_color_box.x1(); const int y1 = m_selected_color_box.y1(); const kvs::RGBColor current_color = this->color(); glBegin( GL_QUADS ); glColor3ub( current_color.r(), current_color.g(), current_color.b() ); glVertex2i( x1, y1 ); glVertex2i( x0, y1 ); glVertex2i( x0, y0 ); glVertex2i( x1, y0 ); glEnd(); // Draw border. ::DrawRectangle( m_selected_color_box, 1, m_upper_edge_color, m_lower_edge_color ); }
void ColorPalette::draw_selected_color_value() { const kvs::RGBColor current_color = this->color(); const int r = static_cast<int>( current_color.r() ); const int g = static_cast<int>( current_color.g() ); const int b = static_cast<int>( current_color.b() ); char R[10]; sprintf( R, "R: %3d", r ); char G[10]; sprintf( G, "G: %3d", g ); char B[10]; sprintf( B, "B: %3d", b ); int x = m_selected_color_box.x0(); int y = m_selected_color_box.y1() + 10; const float height = BaseClass::painter().fontMetrics().height(); const kvs::Font font = BaseClass::painter().font(); BaseClass::painter().font().setStyleToRegular(); BaseClass::painter().drawText( kvs::Vec2( x, y += height ), R ); BaseClass::painter().drawText( kvs::Vec2( x, y += height ), G ); BaseClass::painter().drawText( kvs::Vec2( x, y += height ), B ); BaseClass::painter().setFont( font ); }
/*===========================================================================*/ void ScatterPlotRenderer::exec( kvs::ObjectBase* object, kvs::Camera* camera, kvs::Light* light ) { kvs::IgnoreUnusedVariable( light ); kvs::TableObject* table = kvs::TableObject::DownCast( object ); if ( !m_has_point_color ) if ( table->numberOfColumns() < 3 ) m_has_point_color = true; BaseClass::startTimer(); glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT ); ::BeginDraw(); glDisable( GL_LIGHTING ); glEnable( GL_POINT_SMOOTH ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); // X and Y values. const kvs::AnyValueArray& x_values = table->column(0); const kvs::AnyValueArray& y_values = table->column(1); const kvs::Real64 x_min_value = table->minValue(0); const kvs::Real64 x_max_value = table->maxValue(0); const kvs::Real64 y_min_value = table->minValue(1); const kvs::Real64 y_max_value = table->maxValue(1); const int x0 = m_left_margin; const int x1 = camera->windowWidth() - m_right_margin; const int y0 = m_top_margin; const int y1 = camera->windowHeight() - m_bottom_margin; // Draw background. if ( m_background_color.a() > 0.0f ) { const GLubyte r = static_cast<GLubyte>( m_background_color.r() ); const GLubyte g = static_cast<GLubyte>( m_background_color.g() ); const GLubyte b = static_cast<GLubyte>( m_background_color.b() ); const GLubyte a = static_cast<GLubyte>( m_background_color.a() * 255.0f ); glBegin( GL_QUADS ); glColor4ub( r, g, b, a ); glVertex2i( x0, y0 ); glVertex2i( x1, y0 ); glVertex2i( x1, y1 ); glVertex2i( x0, y1 ); glEnd(); } const kvs::UInt8 opacity = m_point_opacity; const kvs::Real32 size = m_point_size; if ( m_has_point_color ) { const kvs::RGBColor color = m_point_color; glPointSize( size ); glBegin( GL_POINTS ); glColor4ub( color.r(), color.g(), color.b(), opacity ); const kvs::Real64 x_ratio = kvs::Real64( x1 - x0 ) / ( x_max_value - x_min_value ); const kvs::Real64 y_ratio = kvs::Real64( y1 - y0 ) / ( y_max_value - y_min_value ); const size_t nrows = table->numberOfRows(); for ( size_t i = 0; i < nrows; i++ ) { if ( !table->insideRange( i ) ) continue; const kvs::Real64 x_value = x_values[i].to<kvs::Real64>(); const kvs::Real64 y_value = y_values[i].to<kvs::Real64>(); const double x = x0 + ( x_value - x_min_value ) * x_ratio; const double y = y1 - ( y_value - y_min_value ) * y_ratio; glVertex2d( x, y ); } glEnd(); } else { const float color_axis_min_value = static_cast<float>( table->minValue(2) ); const float color_axis_max_value = static_cast<float>( table->maxValue(2) ); const kvs::AnyValueArray& color_axis_values = table->column(2); m_color_map.setRange( color_axis_min_value, color_axis_max_value ); glPointSize( size ); glBegin( GL_POINTS ); const kvs::Real64 x_ratio = kvs::Real64( x1 - x0 ) / ( x_max_value - x_min_value ); const kvs::Real64 y_ratio = kvs::Real64( y1 - y0 ) / ( y_max_value - y_min_value ); const size_t nrows = table->numberOfRows(); for ( size_t i = 0; i < nrows; i++ ) { if ( !table->insideRange( i ) ) continue; const kvs::Real64 color_value = color_axis_values[i].to<kvs::Real64>(); const kvs::RGBColor color = m_color_map.at( static_cast<float>( color_value) ); glColor4ub( color.r(), color.g(), color.b(), opacity ); const kvs::Real64 x_value = x_values[i].to<kvs::Real64>(); const kvs::Real64 y_value = y_values[i].to<kvs::Real64>(); const double x = x0 + ( x_value - x_min_value ) * x_ratio; const double y = y1 - ( y_value - y_min_value ) * y_ratio; glVertex2d( x, y ); } glEnd(); } ::EndDraw(); glPopAttrib(); BaseClass::stopTimer(); }
/*===========================================================================*/ void ParallelCoordinatesRenderer::exec( kvs::ObjectBase* object, kvs::Camera* camera, kvs::Light* light ) { kvs::IgnoreUnusedVariable( light ); kvs::TableObject* table = kvs::TableObject::DownCast( object ); BaseClass::startTimer(); kvs::OpenGL::WithPushedAttrib attrib( GL_ALL_ATTRIB_BITS ); // Anti-aliasing. if ( m_enable_anti_aliasing ) { #if defined ( GL_MULTISAMPLE ) if ( m_enable_multisample_anti_aliasing ) { GLint buffers = 0; GLint samples = 0; kvs::OpenGL::GetIntegerv( GL_SAMPLE_BUFFERS, &buffers ); kvs::OpenGL::GetIntegerv( GL_SAMPLES, &samples ); if ( buffers > 0 && samples > 1 ) kvs::OpenGL::Enable( GL_MULTISAMPLE ); } else #endif { kvs::OpenGL::Enable( GL_LINE_SMOOTH ); KVS_GL_CALL( glHint( GL_LINE_SMOOTH_HINT, GL_NICEST ) ); } } kvs::OpenGL::Enable( GL_BLEND ); kvs::OpenGL::SetBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); ::BeginDraw(); const float color_axis_min_value = static_cast<float>( table->minValue( m_active_axis ) ); const float color_axis_max_value = static_cast<float>( table->maxValue( m_active_axis ) ); const kvs::AnyValueArray& color_axis_values = table->column( m_active_axis ); m_color_map.setRange( color_axis_min_value, color_axis_max_value ); const int x0 = m_left_margin; const int x1 = camera->windowWidth() - m_right_margin; const int y0 = m_top_margin; const int y1 = camera->windowHeight() - m_bottom_margin; const size_t nrows = table->column(0).size(); const size_t naxes = table->numberOfColumns(); const float stride = float( x1 - x0 ) / ( naxes - 1 ); for ( size_t i = 0; i < nrows; i++ ) { if ( !table->insideRange( i ) ) continue; KVS_GL_CALL( glLineWidth( m_line_width ) ); KVS_GL_CALL_BEG( glBegin( GL_LINE_STRIP ) ); const kvs::Real64 color_value = color_axis_values[i].to<kvs::Real64>(); const kvs::RGBColor color = m_color_map.at( static_cast<float>( color_value ) ); KVS_GL_CALL_VER( glColor4ub( color.r(), color.g(), color.b(), m_line_opacity ) ); for ( size_t j = 0; j < naxes; j++ ) { const kvs::Real64 min_value = table->minValue(j); const kvs::Real64 max_value = table->maxValue(j); const kvs::Real64 value = table->column(j)[i].to<kvs::Real64>(); const kvs::Real64 x = m_left_margin + stride * j; const kvs::Real64 y = y1 - ( y1 - y0 ) * ( value - min_value ) / ( max_value - min_value ); KVS_GL_CALL_VER( glVertex2d( x, y ) ); } KVS_GL_CALL_END( glEnd() ); } ::EndDraw(); BaseClass::stopTimer(); }
/*===========================================================================*/ void PointObject::add( const PointObject& other ) { if ( this->coords().size() == 0 ) { // Copy the object. BaseClass::setCoords( other.coords() ); BaseClass::setNormals( other.normals() ); BaseClass::setColors( other.colors() ); this->setSizes( other.sizes() ); BaseClass::setMinMaxObjectCoords( other.minObjectCoord(), other.maxObjectCoord() ); BaseClass::setMinMaxExternalCoords( other.minExternalCoord(), other.maxExternalCoord() ); } else { if ( !BaseClass::hasMinMaxObjectCoords() ) { BaseClass::updateMinMaxCoords(); } kvs::Vec3 min_object_coord( BaseClass::minObjectCoord() ); kvs::Vec3 max_object_coord( BaseClass::maxObjectCoord() ); min_object_coord.x() = kvs::Math::Min( min_object_coord.x(), other.minObjectCoord().x() ); min_object_coord.y() = kvs::Math::Min( min_object_coord.y(), other.minObjectCoord().y() ); min_object_coord.z() = kvs::Math::Min( min_object_coord.z(), other.minObjectCoord().z() ); max_object_coord.x() = kvs::Math::Max( max_object_coord.x(), other.maxObjectCoord().x() ); max_object_coord.y() = kvs::Math::Max( max_object_coord.y(), other.maxObjectCoord().y() ); max_object_coord.z() = kvs::Math::Max( max_object_coord.z(), other.maxObjectCoord().z() ); BaseClass::setMinMaxObjectCoords( min_object_coord, max_object_coord ); BaseClass::setMinMaxExternalCoords( min_object_coord, max_object_coord ); // Integrate the coordinate values. kvs::ValueArray<kvs::Real32> coords; const size_t ncoords = this->coords().size() + other.coords().size(); coords.allocate( ncoords ); kvs::Real32* pcoords = coords.data(); // x,y,z, ... + x,y,z, ... = x,y,z, ... ,x,y,z, ... memcpy( pcoords, this->coords().data(), this->coords().byteSize() ); memcpy( pcoords + this->coords().size(), other.coords().data(), other.coords().byteSize() ); BaseClass::setCoords( coords ); // Integrate the normal vectors. kvs::ValueArray<kvs::Real32> normals; if ( this->normals().size() > 0 ) { if ( other.normals().size() > 0 ) { // nx,ny,nz, ... + nx,ny,nz, ... = nx,ny,nz, ... ,nx,ny,nz, ... const size_t nnormals = this->normals().size() + other.normals().size(); normals.allocate( nnormals ); kvs::Real32* pnormals = normals.data(); memcpy( pnormals, this->normals().data(), this->normals().byteSize() ); memcpy( pnormals + this->normals().size(), other.normals().data(), other.normals().byteSize() ); } else { // nx,ny,nz, ... + (none) = nx,ny,nz, ... ,0,0,0, ... const size_t nnormals = this->normals().size() + other.coords().size(); normals.allocate( nnormals ); kvs::Real32* pnormals = normals.data(); memcpy( pnormals, this->normals().data(), this->normals().byteSize() ); memset( pnormals + this->normals().size(), 0, other.coords().byteSize() ); } } else { if ( other.normals().size() > 0 ) { const size_t nnormals = this->coords().size() + other.normals().size(); normals.allocate( nnormals ); kvs::Real32* pnormals = normals.data(); // (none) + nx,ny,nz, ... = 0,0,0, ... ,nz,ny,nz, ... memset( pnormals, 0, this->coords().byteSize() ); memcpy( pnormals + this->coords().size(), other.normals().data(), other.normals().byteSize() ); } } BaseClass::setNormals( normals ); // Integrate the color values. kvs::ValueArray<kvs::UInt8> colors; if ( this->colors().size() > 1 ) { if ( other.colors().size() > 1 ) { // r,g,b, ... + r,g,b, ... = r,g,b, ... ,r,g,b, ... const size_t ncolors = this->colors().size() + other.colors().size(); colors.allocate( ncolors ); kvs::UInt8* pcolors = colors.data(); memcpy( pcolors, this->colors().data(), this->colors().byteSize() ); memcpy( pcolors + this->colors().size(), other.colors().data(), other.colors().byteSize() ); } else { // r,g,b, ... + R,G,B = r,g,b, ... ,R,G,B, ... ,R,G,B const size_t ncolors = this->colors().size() + other.coords().size(); colors.allocate( ncolors ); kvs::UInt8* pcolors = colors.data(); memcpy( pcolors, this->colors().data(), this->colors().byteSize() ); pcolors += this->colors().size(); const kvs::RGBColor color = other.color(); for ( size_t i = 0; i < other.coords().size(); i += 3 ) { *(pcolors++) = color.r(); *(pcolors++) = color.g(); *(pcolors++) = color.b(); } } } else { if ( other.colors().size() > 1 ) { // R,G,B + r,g,b, ... = R,G,B, ... ,R,G,B, r,g,b, ... const size_t ncolors = this->coords().size() + other.colors().size(); colors.allocate( ncolors ); kvs::UInt8* pcolors = colors.data(); const kvs::RGBColor color = this->color(); for ( size_t i = 0; i < this->coords().size(); i += 3 ) { *(pcolors++) = color.r(); *(pcolors++) = color.g(); *(pcolors++) = color.b(); } memcpy( pcolors, other.colors().data(), other.colors().byteSize() ); } else { const kvs::RGBColor color1 = this->color(); const kvs::RGBColor color2 = other.color(); if ( color1 == color2 ) { // R,G,B + R,G,B = R,G,B const size_t ncolors = 3; colors.allocate( ncolors ); kvs::UInt8* pcolors = colors.data(); *(pcolors++) = color1.r(); *(pcolors++) = color1.g(); *(pcolors++) = color1.b(); } else { // R,G,B + R,G,B = R,G,B, ... ,R,G,B, ... const size_t ncolors = this->coords().size() + other.coords().size(); colors.allocate( ncolors ); kvs::UInt8* pcolors = colors.data(); for ( size_t i = 0; i < this->coords().size(); i += 3 ) { *(pcolors++) = color1.r(); *(pcolors++) = color1.g(); *(pcolors++) = color1.b(); } for ( size_t i = 0; i < other.coords().size(); i += 3 ) { *(pcolors++) = color2.r(); *(pcolors++) = color2.g(); *(pcolors++) = color2.b(); } } } } BaseClass::setColors( colors ); // Integrate the size values. kvs::ValueArray<kvs::Real32> sizes; if ( this->sizes().size() > 1 ) { if ( other.sizes().size() > 1 ) { // s, ... + s, ... = s, ... ,s, ... const size_t nsizes = this->sizes().size() + other.sizes().size(); sizes.allocate( nsizes ); kvs::Real32* psizes = sizes.data(); memcpy( psizes, this->sizes().data(), this->sizes().byteSize() ); memcpy( psizes + this->sizes().size(), other.sizes().data(), other.sizes().byteSize() ); } else { // s, ... + S = s, ... ,S, ... ,S const size_t nsizes = this->sizes().size() + other.coords().size(); sizes.allocate( nsizes ); kvs::Real32* psizes = sizes.data(); memcpy( psizes, this->sizes().data(), this->sizes().byteSize() ); psizes += this->colors().size(); const kvs::Real32 size = other.size(); for ( size_t i = 0; i < other.coords().size(); i++ ) { *(psizes++) = size; } } } else { if ( other.sizes().size() > 1 ) { // S + s, ... = S, ... ,S, s, ... const size_t nsizes = this->coords().size() + other.sizes().size(); sizes.allocate( nsizes ); kvs::Real32* psizes = sizes.data(); const kvs::Real32 size = this->size(); for ( size_t i = 0; i < this->coords().size(); i++ ) { *(psizes++) = size; } memcpy( psizes, other.sizes().data(), other.sizes().byteSize() ); } else { const kvs::Real32 size1 = this->size(); const kvs::Real32 size2 = other.size(); if ( size1 == size2 ) { // S + S = S const size_t nsizes = 1; sizes.allocate( nsizes ); kvs::Real32* psizes = sizes.data(); *(psizes++) = size1; } else { // S + S = S, ... , S, ... const size_t nsizes = this->coords().size() + other.coords().size(); sizes.allocate( nsizes ); kvs::Real32* psizes = sizes.data(); for ( size_t i = 0; i < this->coords().size(); i++ ) { *(psizes++) = size1; } for ( size_t i = 0; i < other.coords().size(); i++ ) { *(psizes++) = size2; } } } } this->setSizes( sizes ); } }