/********************************************************************** * File: stepblob.cpp (Formerly cblob.c) * Description: Code for C_BLOB class. * Author: Ray Smith * Created: Tue Oct 08 10:41:13 BST 1991 * * (C) Copyright 1991, Hewlett-Packard Ltd. ** 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. * **********************************************************************/ #include "mfcpch.h" #include "stepblob.h" ELISTIZE_S (C_BLOB) /********************************************************************** * position_outline * * Position the outline in the given list at the relevant place * according to its nesting. **********************************************************************/ static void position_outline( //put in place C_OUTLINE *outline, //thing to place C_OUTLINE_LIST *destlist //desstination list ) { C_OUTLINE *dest_outline; //outline from dest list C_OUTLINE_IT it = destlist; //iterator //iterator on children C_OUTLINE_IT child_it = outline->child (); if (!it.empty ()) { do { dest_outline = it.data (); //get destination //encloses dest if (*dest_outline < *outline) { //take off list dest_outline = it.extract (); //put this in place it.add_after_then_move (outline); //make it a child child_it.add_to_end (dest_outline); while (!it.at_last ()) { it.forward (); //do rest of list //check for other children dest_outline = it.data (); if (*dest_outline < *outline) { //take off list dest_outline = it.extract (); child_it.add_to_end (dest_outline); //make it a child if (it.empty ()) break; } } return; //finished } //enclosed by dest else if (*outline < *dest_outline) { position_outline (outline, dest_outline->child ()); //place in child list return; //finished } it.forward (); } while (!it.at_first ()); } it.add_to_end (outline); //at outer level } /********************************************************************** * plot_outline_list * * Draw a list of outlines in the given colour and their children * in the child colour. **********************************************************************/ #ifndef GRAPHICS_DISABLED static void plot_outline_list( //draw outlines C_OUTLINE_LIST *list, //outline to draw ScrollView* window, //window to draw in ScrollView::Color colour, //colour to use ScrollView::Color child_colour //colour of children ) { C_OUTLINE *outline; //current outline C_OUTLINE_IT it = list; //iterator for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) { outline = it.data (); //draw it outline->plot (window, colour); if (!outline->child ()->empty ()) plot_outline_list (outline->child (), window, child_colour, child_colour); } } #endif /********************************************************************** * reverse_outline_list * * Reverse a list of outlines and their children. **********************************************************************/ static void reverse_outline_list( //reverse outlines C_OUTLINE_LIST *list //outline to reverse ) { C_OUTLINE *outline; //current outline C_OUTLINE_IT it = list; //iterator for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) { outline = it.data (); outline->reverse (); //reverse it if (!outline->child ()->empty ()) reverse_outline_list (outline->child ()); } } /********************************************************************** * C_BLOB::C_BLOB * * Constructor to build a C_BLOB from a list of C_OUTLINEs. * The C_OUTLINEs are not copied so the source list is emptied. * The C_OUTLINEs are nested correctly in the blob. **********************************************************************/ C_BLOB::C_BLOB( //constructor C_OUTLINE_LIST *outline_list //in random order ) { C_OUTLINE *outline; //current outline C_OUTLINE_IT it = outline_list;//iterator while (!it.empty ()) { //grab the list outline = it.extract (); //get off the list //put it in place position_outline(outline, &outlines); if (!it.empty ()) it.forward (); } it.set_to_list (&outlines); for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) { outline = it.data (); if (outline->turn_direction () < 0) { outline->reverse (); reverse_outline_list (outline->child ()); outline->set_flag (COUT_INVERSE, TRUE); } else { outline->set_flag (COUT_INVERSE, FALSE); } } } /********************************************************************** * C_BLOB::bounding_box * * Return the bounding box of the blob. **********************************************************************/ TBOX C_BLOB::bounding_box() { //bounding box C_OUTLINE *outline; //current outline C_OUTLINE_IT it = &outlines; //outlines of blob TBOX box; //bounding box for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) { outline = it.data (); box += outline->bounding_box (); } return box; } /********************************************************************** * C_BLOB::area * * Return the area of the blob. **********************************************************************/ inT32 C_BLOB::area() { //area C_OUTLINE *outline; //current outline C_OUTLINE_IT it = &outlines; //outlines of blob inT32 total; //total area total = 0; for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) { outline = it.data (); total += outline->area (); } return total; } /********************************************************************** * C_BLOB::perimeter * * Return the perimeter of the top and 2nd level outlines. **********************************************************************/ inT32 C_BLOB::perimeter() { C_OUTLINE *outline; // current outline C_OUTLINE_IT it = &outlines; // outlines of blob inT32 total; // total perimeter total = 0; for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) { outline = it.data(); total += outline->perimeter(); } return total; } /********************************************************************** * C_BLOB::outer_area * * Return the area of the blob. **********************************************************************/ inT32 C_BLOB::outer_area() { //area C_OUTLINE *outline; //current outline C_OUTLINE_IT it = &outlines; //outlines of blob inT32 total; //total area total = 0; for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) { outline = it.data (); total += outline->outer_area (); } return total; } /********************************************************************** * C_BLOB::count_transitions * * Return the total x and y maxes and mins in the blob. * Chlid outlines are not counted. **********************************************************************/ inT32 C_BLOB::count_transitions( //area inT32 threshold //on size ) { C_OUTLINE *outline; //current outline C_OUTLINE_IT it = &outlines; //outlines of blob inT32 total; //total area total = 0; for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) { outline = it.data (); total += outline->count_transitions (threshold); } return total; } /********************************************************************** * C_BLOB::move * * Move C_BLOB by vector **********************************************************************/ void C_BLOB::move( // reposition blob const ICOORD vec // by vector ) { C_OUTLINE_IT it(&outlines); // iterator for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) it.data ()->move (vec); // move each outline } /********************************************************************** * C_BLOB::plot * * Draw the C_BLOB in the given colour. **********************************************************************/ #ifndef GRAPHICS_DISABLED void C_BLOB::plot( //draw it ScrollView* window, //window to draw in ScrollView::Color blob_colour, //main colour ScrollView::Color child_colour //for holes ) { plot_outline_list(&outlines, window, blob_colour, child_colour); } #endif