Exemple #1
0
//--------------------------------------------------------
void ttRope::updateAccelerometer(ofPoint acc){
    
    if (ropeNum == 0) {
        if (acc.y<-0.15&&counter !=2) {
            
            ofPoint end_pos(endPos.x+translate_A.x, endPos.y+translate_A.y+offset_A.y);
            ofPoint charB_pos(translate_B.x, translate_B.y+offset_B.y);
            if (counter == 0) {
                bRopeInUse = true;
                counter=1;
            }
            
            if (end_pos.distance(charB_pos)>10 && bHooked == false) {
                endPos.y +=10;
            }else{
                bHooked = true;
                counter = 2;
            }
        }
        
        if(acc.y>-0.15){
            endPos.y = 0;
            endPos.x = 0;
            bRopeInUse = false;
            bHooked = false;
            counter = 0;
        }
    }
    
    
    if (ropeNum == 1) {
        if (acc.y>0.15&&counter !=2) {
            
            ofPoint end_pos(endPos.x+translate_B.x, endPos.y+translate_B.y+offset_B.y);
            ofPoint charB_pos(translate_A.x, translate_A.y+offset_A.y);
            if (counter == 0) {
                bRopeInUse = true;
                counter=1;
            }
            
            if (end_pos.distance(charB_pos)>10 && bHooked == false) {
                endPos.y -=10;
            }else{
                bHooked = true;
                counter = 2;
            }
        }
        
        if(acc.y<0.15){
            endPos.y = 0;
            endPos.x = 0;
            bRopeInUse = false;
            bHooked = false;
            counter = 0;
        }
    }
}
Exemple #2
0
void CMap::Input(Vec2I position)
{
	Vec2I end_pos(position.x / GRID_WIDTH, position.y / GRID_HEIGHT);
	DEBUG_TRACE("start:%d,%d\tend:%d,%d\n", m_pos.x, m_pos.y, end_pos.x, end_pos.y);

	if (! IsFree(end_pos))
		return;

	QWORD start_time = GetTimer()->GetTime();
	if (m_Astar.FindPath(m_pos, end_pos))
	{
		QWORD end_time = GetTimer()->GetTime();
		DEBUG_TRACE("find path time:%f\n", GetTimer()->GetTimeMillisec(end_time - start_time));

		m_findPath.clear();
		std::vector<Vec2I>& vec = m_Astar.GetPath();
		m_findPath.reserve(vec.size());
		for (int i = 0; i < vec.size(); ++i)
		{
			Vec2I pt = vec[i];
			m_findPath.push_back(Grid2CenterPt(pt));
		}
		m_pos = end_pos;
		m_rect.SetRect(m_pos.x * GRID_WIDTH, m_pos.y * GRID_HEIGHT, (m_pos.x + 1) * GRID_WIDTH, (m_pos.y + 1) * GRID_HEIGHT);
	}
}
Exemple #3
0
/* -------------------------------------------
	・Draw() : 描画処理処理関数
		描画はスプライトを使用
-------------------------------------------- */
void CSceneTitle::Draw() {
	/* ----- 各表示矩形を設定 ----- */
	RECT	bg_rc		= {0, 0, 640, 480},
			logo_rc		= {0, 0, 360, 240},
			cirno_rc	= {0, 0, 424, 424},
			start_rc	= {0, 0, 136, 48},
			option_rc	= {0, 0, 136, 48},
			end_rc		= {0, 0, 136, 48},
			cursor_rc	= {0, 0, 64, 64};

	/* ----- 各表示位置を設定 ----- */
	D3DXVECTOR3 center(0, 0, 0); 
	D3DXVECTOR3 bg_pos(0, 0, 0),
				logo_pos(10, 50, 0),
				cirno_pos(216, 56, 0),
				start_pos(107, 294, 0),
				option_pos(107, 344, 0),
				end_pos(107, 394, 0),
				cursor_pos((float)m_Cursor.x, (float)m_Cursor.y, 0);		

	CDxGraphic::m_pD3DXSprite->Begin( D3DXSPRITE_ALPHABLEND );
	CDxGraphic::m_pD3DXSprite->Draw( CTextureManager::GetTexture(_T("img\\Title_BG.png")), &bg_rc, &center, &bg_pos, 0xFFFFFFFF );				// タイトル背景
	CDxGraphic::m_pD3DXSprite->Draw( CTextureManager::GetTexture(_T("img\\Title_Cirno.dds")), &cirno_rc, &center, &cirno_pos, 0xFFFFFFFF );		// チルノ
	CDxGraphic::m_pD3DXSprite->Draw( CTextureManager::GetTexture(_T("img\\Title_Logo.dds")), &logo_rc, &center, &logo_pos, 0xFFFFFFFF );			// タイトルロゴ
	CDxGraphic::m_pD3DXSprite->Draw( CTextureManager::GetTexture(_T("img\\Title_StartPanel.dds")), &start_rc, &center, &start_pos, 0xFFFFFFFF );		// すたーとパネル
	CDxGraphic::m_pD3DXSprite->Draw( CTextureManager::GetTexture(_T("img\\Title_OptionPanel.dds")), &option_rc, &center, &option_pos, 0xFFFFFFFF );	// おぷしょんパネル
	CDxGraphic::m_pD3DXSprite->Draw( CTextureManager::GetTexture(_T("img\\Title_EndPanel.dds")), &end_rc, &center, &end_pos, 0xFFFFFFFF );				// おわるパネル
	CDxGraphic::m_pD3DXSprite->Draw( CTextureManager::GetTexture(_T("img\\Snow_S.dds")), &cursor_rc, &center, &cursor_pos, 0xFFFFFFFF );			// 雪カーソル

	CDxGraphic::m_pD3DXSprite->End();
}
Exemple #4
0
  void path::m_path_iterator_decrement(path::iterator & it)
  {
    BOOST_ASSERT(it.m_pos && "path::iterator decrement past begin()");

    size_type end_pos(it.m_pos);

    // if at end and there was a trailing non-root '/', return "."
    if (it.m_pos == it.m_path_ptr->m_pathname.size()
      && it.m_path_ptr->m_pathname.size() > 1
      && is_separator(it.m_path_ptr->m_pathname[it.m_pos-1])
      && is_non_root_separator(it.m_path_ptr->m_pathname, it.m_pos-1) 
       )
    {
      --it.m_pos;
      it.m_element = dot_path;
      return;
    }

    size_type root_dir_pos(root_directory_start(it.m_path_ptr->m_pathname, end_pos));

    // skip separators unless root directory
    for (
      ; 
      end_pos > 0
      && (end_pos-1) != root_dir_pos
      && is_separator(it.m_path_ptr->m_pathname[end_pos-1])
      ;
      --end_pos) {}

    it.m_pos = filename_pos(it.m_path_ptr->m_pathname, end_pos);
    it.m_element = it.m_path_ptr->m_pathname.substr(it.m_pos, end_pos - it.m_pos);
    if (it.m_element.m_pathname == preferred_separator_string)
      it.m_element.m_pathname = separator_string;  // needed for Windows, harmless on POSIX
  }
Exemple #5
0
 path path::parent_path() const
 {
  size_type end_pos(m_parent_path_end());
  return end_pos == string_type::npos
    ? path()
    : path(m_pathname.c_str(), m_pathname.c_str() + end_pos);
 }
Exemple #6
0
double RefEdge::get_chord_length()
{
  CubitVector start_pos(start_vertex()->coordinates());
  CubitVector end_pos(start_vertex()->coordinates());
  double distance = (start_pos - end_pos).length();
  return distance;
}
Exemple #7
0
void path::m_path_iterator_increment(path::iterator & it)
{
    BOOST_ASSERT(it.m_pos < it.m_path_ptr->m_pathname.size() && "path::basic_iterator increment past end()");

    // increment to position past current element
    it.m_pos += it.m_element.m_pathname.size();

    // if end reached, create end basic_iterator
    if (it.m_pos == it.m_path_ptr->m_pathname.size())
    {
        it.m_element.clear();
        return;
    }

    // both POSIX and Windows treat paths that begin with exactly two separators specially
    bool was_net(it.m_element.m_pathname.size() > 2
                 && is_separator(it.m_element.m_pathname[0])
                 && is_separator(it.m_element.m_pathname[1])
                 && !is_separator(it.m_element.m_pathname[2]));

    // process separator (Windows drive spec is only case not a separator)
    if (is_separator(it.m_path_ptr->m_pathname[it.m_pos]))
    {
        // detect root directory
        if (was_net
#       ifdef BOOST_WINDOWS_API
                // case "c:/"
                || it.m_element.m_pathname[it.m_element.m_pathname.size()-1] == colon
#       endif
           )
        {
            it.m_element.m_pathname = separator;
            return;
        }

        // bypass separators
        while (it.m_pos != it.m_path_ptr->m_pathname.size()
                && is_separator(it.m_path_ptr->m_pathname[it.m_pos]))
        {
            ++it.m_pos;
        }

        // detect trailing separator, and treat it as ".", per POSIX spec
        if (it.m_pos == it.m_path_ptr->m_pathname.size()
                && is_non_root_separator(it.m_path_ptr->m_pathname, it.m_pos-1))
        {
            --it.m_pos;
            it.m_element = dot_path;
            return;
        }
    }

    // get next element
    size_type end_pos(it.m_path_ptr->m_pathname.find_first_of(separators, it.m_pos));
    if (end_pos == string_type::npos) end_pos = it.m_path_ptr->m_pathname.size();
    it.m_element = it.m_path_ptr->m_pathname.substr(it.m_pos, end_pos - it.m_pos);
}
Exemple #8
0
    void graphic_ui::create_the_animation_objects()
    {
        if(movements_info.size())
        {
            for(auto& elem:movements_info)
            {
                sf::Vector2f begin_pos(elem.x_from*x_s,elem.y_from*y_s),
                             end_pos(elem.x_to*x_s,elem.y_to*y_s);

                sf::Texture grid_movement_texture;
                grid_movement_texture.create(x_s,y_s);
                sf::Uint32 pixel=(0xff<<24)|//Assuming a little endian machine.. from RGBA to ABGR :|
                                 ((sf::Uint32)num_colors[elem.num].b<<16)|
                                 ((sf::Uint32)num_colors[elem.num].g<<8)|
                                 ((sf::Uint32)num_colors[elem.num].r);
                std::vector<sf::Uint32> pixel_map(x_s*y_s,pixel);
                grid_movement_texture.update((sf::Uint8*)&pixel_map.front());
                sf::Sprite obj_sprite(grid_movement_texture);

                animation_engine::anim_texture_ptr object=animation_engine::animated_texture::create(obj_sprite);
                object->set_begin_position(begin_pos);
                object->set_end_position(end_pos);
                object->prepare_to_render();
                object->set_animation_duration(0.07);

                anim_engine->register_object(object,animation_engine::animated_obj_completion_opt::ACTION_DONT_MOVE);
                //Add the text
                std::stringstream text_ss;
                text_ss<<elem.num;
                sf::Text text(text_ss.str().c_str(),font,52);
                text.setColor(sf::Color::Black);
                text.setStyle(sf::Text::Bold);
                animation_engine::anim_text_ptr object_text=animation_engine::animated_text::create(text);
                //Set the proper offset
                int x_offset=x_s/2-text.getCharacterSize()*text_ss.str().size()/4,
                    y_offset=y_s/2-text.getCharacterSize()/2;
                begin_pos.x+=x_offset;
                begin_pos.y+=y_offset;
                end_pos.x+=x_offset;
                end_pos.y+=y_offset;
                object_text->set_begin_position(begin_pos);
                object_text->set_end_position(end_pos);
                object_text->prepare_to_render();
                object_text->set_animation_duration(0.07);
                anim_engine->register_object(object_text,animation_engine::animated_obj_completion_opt::ACTION_DONT_MOVE);
            }
            movements_info.clear();
            draw_movement=true;
        }
        else draw_movement=false;
    }
Exemple #9
0
  string_type::size_type path::m_parent_path_end() const
  {
    size_type end_pos(filename_pos(m_pathname, m_pathname.size()));

    bool filename_was_separator(m_pathname.size()
      && is_separator(m_pathname[end_pos]));

    // skip separators unless root directory
    size_type root_dir_pos(root_directory_start(m_pathname, end_pos));
    for (; 
      end_pos > 0
      && (end_pos-1) != root_dir_pos
      && is_separator(m_pathname[end_pos-1])
      ;
      --end_pos) {}

   return (end_pos == 1 && root_dir_pos == 0 && filename_was_separator)
     ? string_type::npos
     : end_pos;
  }
bool GCodePlanner::setExtruder(int extruder)
{
    if (extruder == currentExtruder)
    {
        return false;
    }
    SettingsBase* train = storage.meshgroup->getExtruderTrain(currentExtruder);
    bool end_pos_absolute = train->getSettingBoolean("machine_extruder_end_pos_abs");
    Point end_pos(train->getSettingInMicrons("machine_extruder_end_pos_x"), train->getSettingInMicrons("machine_extruder_end_pos_y"));
    addTravel((end_pos_absolute)? end_pos : lastPosition + end_pos);
    
    currentExtruder = extruder; // the extruder switch
    
    forceNewPathStart();
    
    train = storage.meshgroup->getExtruderTrain(currentExtruder);
    bool start_pos_absolute = train->getSettingBoolean("machine_extruder_start_pos_abs");
    Point start_pos(train->getSettingInMicrons("machine_extruder_start_pos_x"), train->getSettingInMicrons("machine_extruder_start_pos_y"));
    lastPosition = (start_pos_absolute)? start_pos : lastPosition + start_pos;
    return true;
}
Exemple #11
0
/**
 * \brief The fonction called when new_score game variable changes.
 * \param value The value of the variable new_score.
 */
void rp::score_component::on_new_score(bool value)
{
  if ( value )
    {
      bear::visual::position_type pos(get_layer_size()/2);
      pos.x +=
        ( game_variables::get_score_rate_x() * get_layer_size().x);
      pos.y +=
        ( game_variables::get_score_rate_y() * get_layer_size().y);

      bear::visual::position_type end_pos(pos);
      end_pos.y = get_layer_size().y;

      floating_score_component f(get_level_globals());

      m_floating_score.push_back(f);
      m_floating_score.back().set_position
        (pos, get_render_position() +
         bear::universe::position_type( width() / 2, 0 ) );

      game_variables::set_new_score(false);
    }
} // score_component::on_new_score()
Exemple #12
0
void main_menu_dlg::on_init_dialog()
{
	h_screen_paradigm scr_paradigm = get_framework()->get_screen_paradigm();
	h_string suffix = get_framework()->get_screen_paradigm_suffix(scr_paradigm);

	scene_manager* scene_manager = get_ctrl()->get_scene_manager();

	int w_scr = get_framework()->get_display_settings().width;
	int h_scr = get_framework()->get_display_settings().height;
	set_size(h_vector((float)w_scr, (float)h_scr));

	h_scene_object_base_ptr background(new h_scene_object_base("background_panel"));
	add_child(background);
	background->add_sprite("/images/menu/dlg_base" + suffix, "background_panel");
	background->set_pos(scene_manager->get_scene_center() - background->get_size() / 2);

	//scene_manager* scene_manager = get_ctrl()->get_scene_manager();

	static const float height_button_t0[3] = { 43, 73, 86 };
	static const float height_button_t1[3] = { 65, 111, 130 };

	static const float width_button[3] = { 165, 280, 329 };

	h_button_ptr button_sel_tree;
	h_button_ptr button_sel_background;
	h_button_ptr button_share_social;
	h_button_ptr button_email;
	h_button_ptr button_to_img;
	h_button_ptr button_clear;


	h_vector offset_img(0, 0);
	// select tree..
	{
		/*button_sel_tree.reset(new h_button("select_tree"));
		add_child(button_sel_tree); 

		h_vector pos_coord_img_tl = h_vector(0, 0) + offset_img;
		h_vector pos_coord_img_br = h_vector(width_button[scr_paradigm], height_button_t0[scr_paradigm]) + offset_img;
		button_sel_tree->load_images("/images/menu/menu_buttons_0" + suffix, 
									 pos_coord_img_tl, pos_coord_img_br,
									 pos_coord_img_tl, pos_coord_img_br);
		button_sel_tree->set_action(std::tr1::bind(&scene_manager::on_change_tree, 
													get_ctrl()->get_scene_manager()));
		offset_img += h_vector(0, height_button_t0[scr_paradigm]);*/
	}
	 
	// select background..
	{

		button_sel_background.reset(new h_button("select_background"));
		background->add_child(button_sel_background); 

		h_vector pos_coord_img_tl = h_vector(0, 0) + offset_img;
		h_vector pos_coord_img_br = h_vector(width_button[scr_paradigm], height_button_t0[scr_paradigm]) + offset_img;
		button_sel_background->load_images("/images/menu/menu_buttons_0" + suffix, 
									 pos_coord_img_tl, pos_coord_img_br,
									 pos_coord_img_tl, pos_coord_img_br);
		button_sel_background->set_action(std::tr1::bind(&scene_manager::on_change_background, 
												   get_ctrl()->get_scene_manager()));
		offset_img += h_vector(0, height_button_t0[scr_paradigm]);
	}

	// share to social..
	{

		//button_share_social.reset(new h_button("share_social"));
		//background->add_child(button_share_social); 

		//h_vector pos_coord_img_tl = h_vector(0, 0) + offset_img;
		//h_vector pos_coord_img_br = h_vector(width_button[scr_paradigm], height_button_t1[scr_paradigm]) + offset_img;
		//button_share_social->load_images("/images/menu/menu_buttons_0" + suffix, 
		//							 pos_coord_img_tl, pos_coord_img_br,
		//							 pos_coord_img_tl, pos_coord_img_br);
		////button_sel_tree->set_action(std::tr1::bind(&scene_manager::on_select_toys_dlg, 
		////							get_ctrl()->get_scene_manager(), dlg_balls));
		//offset_img += h_vector(0, height_button_t1[scr_paradigm]);
	}


	// export to image..
	{

		button_to_img.reset(new h_button("to_img"));
		background->add_child(button_to_img); 

		h_vector pos_coord_img_tl = h_vector(0, 0) + offset_img;
		h_vector pos_coord_img_br = h_vector(width_button[scr_paradigm], height_button_t1[scr_paradigm]) + offset_img;
		button_to_img->load_images("/images/menu/menu_buttons_0" + suffix, 
									 pos_coord_img_tl, pos_coord_img_br,
									 pos_coord_img_tl, pos_coord_img_br);
		button_to_img->set_action(std::tr1::bind(&scene_manager::on_export_image, 
									get_ctrl()->get_scene_manager()));
		offset_img += h_vector(0, height_button_t1[scr_paradigm]);
	}

	// send..
	{

		button_email.reset(new h_button("email"));
		background->add_child(button_email); 

		h_vector pos_coord_img_tl = h_vector(0, 0) + offset_img;
		h_vector pos_coord_img_br = h_vector(width_button[scr_paradigm], height_button_t0[scr_paradigm]) + offset_img;
		button_email->load_images("/images/menu/menu_buttons_0" + suffix, 
									 pos_coord_img_tl, pos_coord_img_br,
									 pos_coord_img_tl, pos_coord_img_br);
		button_email->set_action(std::tr1::bind(&scene_manager::send_email, 
									get_ctrl()->get_scene_manager()));
		offset_img += h_vector(0, height_button_t0[scr_paradigm]);
	}


	// clear..
	{
		button_clear.reset(new h_button("clear"));
		background->add_child(button_clear); 

		h_vector pos_coord_img_tl = h_vector(0, 0) + offset_img;
		h_vector pos_coord_img_br = h_vector(width_button[scr_paradigm], height_button_t0[scr_paradigm]) + offset_img;
		button_clear->load_images("/images/menu/menu_buttons_0" + suffix, 
									 pos_coord_img_tl, pos_coord_img_br,
									 pos_coord_img_tl, pos_coord_img_br);
		button_clear->set_action(std::tr1::bind(&scene_manager::on_clear, 
									get_ctrl()->get_scene_manager()));
		//offset_img += h_vector(0, height_button_t0[scr_paradigm]);
	}
	h_scene_object_ptr buttons[g_num_buttons] = { button_sel_background, 
												  button_to_img,
												  button_email,
												  button_clear };
	float height_all_buttons = 0;
	for (int i = 0; i < g_num_buttons; i++)	{
		height_all_buttons += buttons[i]->get_size().y;
		buttons[i]->get_sprites()->get_sprite(0)->set_filter(true);
	}

	float w = buttons[0]->get_size().x;

	float menu_height = background->get_size().y;
	float v = menu_height - height_all_buttons;
	float vx = background->get_size().x - w;

	float seg = v / (g_num_buttons + 1);
	float y_offset = background->get_size().y;
	for (int i = 0; i < g_num_buttons; i++)
	{
		float height = buttons[i]->get_size().y;
		y_offset += -height;//seg; 
		buttons[i]->set_pos(h_vector(vx / 2, y_offset - v / 2));
	}
	
	h_vector center = scene_manager->get_scene_center() - get_size() / 2;
	h_vector start_pos = h_vector(center.x, -get_size().y);
	h_vector end_pos(center);
	//static const float offset_from_center[3] = { 35, 70, 0 };
	//offset_pos(h_vector(0, offset_from_center[scr_paradigm]));

	h_transition_ptr trans(new h_transition_position(start_pos, end_pos, 170));
	add_transition(trans, true);
	trans->start();
}
Exemple #13
0
// Extracts Tesseract features and appends them to the features vector.
// Startpt to lastpt, inclusive, MUST have the same src_outline member,
// which may be nullptr. The vector from lastpt to its next is included in
// the feature extraction. Hidden edges should be excluded by the caller.
// If force_poly is true, the features will be extracted from the polygonal
// approximation even if more accurate data is available.
static void ExtractFeaturesFromRun(
    const EDGEPT* startpt, const EDGEPT* lastpt,
    const DENORM& denorm, double feature_length, bool force_poly,
    GenericVector<INT_FEATURE_STRUCT>* features) {
  const EDGEPT* endpt = lastpt->next;
  const C_OUTLINE* outline = startpt->src_outline;
  if (outline != nullptr && !force_poly) {
    // Detailed information is available. We have to normalize only from
    // the root_denorm to denorm.
    const DENORM* root_denorm = denorm.RootDenorm();
    int total_features = 0;
    // Get the features from the outline.
    int step_length = outline->pathlength();
    int start_index = startpt->start_step;
    // pos is the integer coordinates of the binary image steps.
    ICOORD pos = outline->position_at_index(start_index);
    // We use an end_index that allows us to use a positive increment, but that
    // may be beyond the bounds of the outline steps/ due to wrap-around, to
    // so we use % step_length everywhere, except for start_index.
    int end_index = lastpt->start_step + lastpt->step_count;
    if (end_index <= start_index)
      end_index += step_length;
    LLSQ prev_points;
    LLSQ prev_dirs;
    FCOORD prev_normed_pos = outline->sub_pixel_pos_at_index(pos, start_index);
    denorm.NormTransform(root_denorm, prev_normed_pos, &prev_normed_pos);
    LLSQ points;
    LLSQ dirs;
    FCOORD normed_pos(0.0f, 0.0f);
    int index = GatherPoints(outline, feature_length, denorm, root_denorm,
                             start_index, end_index, &pos, &normed_pos,
                             &points, &dirs);
    while (index <= end_index) {
      // At each iteration we nominally have 3 accumulated sets of points and
      // dirs: prev_points/dirs, points/dirs, next_points/dirs and sum them
      // into sum_points/dirs, but we don't necessarily get any features out,
      // so if that is the case, we keep accumulating instead of rotating the
      // accumulators.
      LLSQ next_points;
      LLSQ next_dirs;
      FCOORD next_normed_pos(0.0f, 0.0f);
      index = GatherPoints(outline, feature_length, denorm, root_denorm,
                           index, end_index, &pos, &next_normed_pos,
                           &next_points, &next_dirs);
      LLSQ sum_points(prev_points);
      // TODO(rays) find out why it is better to use just dirs and next_dirs
      // in sum_dirs, instead of using prev_dirs as well.
      LLSQ sum_dirs(dirs);
      sum_points.add(points);
      sum_points.add(next_points);
      sum_dirs.add(next_dirs);
      bool made_features = false;
      // If we have some points, we can try making some features.
      if (sum_points.count() > 0) {
        // We have gone far enough from the start. Make a feature and restart.
        FCOORD fit_pt = sum_points.mean_point();
        FCOORD fit_vector = MeanDirectionVector(sum_points, sum_dirs,
                                                prev_normed_pos, normed_pos);
        // The segment to which we fit features is the line passing through
        // fit_pt in direction of fit_vector that starts nearest to
        // prev_normed_pos and ends nearest to normed_pos.
        FCOORD start_pos = prev_normed_pos.nearest_pt_on_line(fit_pt,
                                                              fit_vector);
        FCOORD end_pos = normed_pos.nearest_pt_on_line(fit_pt, fit_vector);
        // Possible correction to match the adjacent polygon segment.
        if (total_features == 0 && startpt != endpt) {
          FCOORD poly_pos(startpt->pos.x, startpt->pos.y);
          denorm.LocalNormTransform(poly_pos, &start_pos);
        }
        if (index > end_index && startpt != endpt) {
          FCOORD poly_pos(endpt->pos.x, endpt->pos.y);
          denorm.LocalNormTransform(poly_pos, &end_pos);
        }
        int num_features = ComputeFeatures(start_pos, end_pos, feature_length,
                                           features);
        if (num_features > 0) {
          // We made some features so shuffle the accumulators.
          prev_points = points;
          prev_dirs = dirs;
          prev_normed_pos = normed_pos;
          points = next_points;
          dirs = next_dirs;
          made_features = true;
          total_features += num_features;
        }
        // The end of the next set becomes the end next time around.
        normed_pos = next_normed_pos;
      }
      if (!made_features) {
        // We didn't make any features, so keep the prev accumulators and
        // add the next ones into the current.
        points.add(next_points);
        dirs.add(next_dirs);
      }
    }
  } else {
    // There is no outline, so we are forced to use the polygonal approximation.
    const EDGEPT* pt = startpt;
    do {
      FCOORD start_pos(pt->pos.x, pt->pos.y);
      FCOORD end_pos(pt->next->pos.x, pt->next->pos.y);
      denorm.LocalNormTransform(start_pos, &start_pos);
      denorm.LocalNormTransform(end_pos, &end_pos);
      ComputeFeatures(start_pos, end_pos, feature_length, features);
    } while ((pt = pt->next) != endpt);
  }
}