jjzjj

c++ - 找到一组相交的矩形

coder 2024-02-19 原文

我有一个矩形列表(它们不能旋转):

struct Rectangle {
  double centerX;
  double centerY;
  double width;
  double height;

  Rectangle(double x, double y, double w, double h):centerx(x),centery(y),width(w),height(h){}
};

std::vector<Rectangle> rectangles;
rectangles.push_back(Rectangle(0  ,  0  , 1  , 1  );
rectangles.push_back(Rectangle(0.5,  0.5, 1  , 1  );
rectangles.push_back(Rectangle(3  ,  2  , 0.5, 0.6);
rectangles.push_back(Rectangle(0.2,  0.5, 0.5, 0.6);
rectangles.push_back(Rectangle(2  , -0.3, 0.4, 0.4);
rectangles.push_back(Rectangle(0.2, -0.4, 0.3, 0.4);

我想计算一组至少有一个交集且具有传递性的矩形。即,如果 r1 与 r2 相交且 r2 与 r3 相交,则 r1、r2、r3 属于同一组。

在此示例中,组将是

{{3}, {4, 1, 2}, {5, 6}}

组内的组顺序和元素顺序并不重要。

如何计算这些组?如有必要,我可以更改数据结构。

例如,我可以将 std::vector 更改为 std::set 并按左顶点 X 坐标对矩形进行排序。这样我就可以使用扫描线算法。但我找不到任何可应用于我的问题的示例。

如何获得交叉组?

最佳答案

我认为集合 vector 可以完成这项工作。

像这样:

std::vector< std::set< int > > groups;

// loop over rectangles
for( int r1 = 0; r1 < rectangles.size(); r1++ )
{
    // check if rectngle already in group
    auto g_it = groups.end();
    for( auto group = groups.begin();
        group != groups.end(); group++ )
    {
        auto group_r1_it = group->find( r1 );
        if( group_r1_it != group->end() )
        {
            g_it = group;
            break;
        }
    }
    if( g_it == groups.end() )
    {
        // not already in group, so create new group
        set<int> s;
        s.insert( r1 );
        groups.push_back( s );
        g_it = groups.end()-1;
    }

    // loop over remaining rectangles
    for( int r2 = r1+1; r2 < rectangles.size(); r2++ )
    {
        // check for intersection
        if( rectangles[r1].Intersect( rectangles[r2] ))
        {
            //report intersection
            cout << r1+1 <<" " <<r2+1 << endl;

            // add to group
            g_it->insert( r2 );

        }
    }

}
    // Display results
    for ( auto group : groups )
    {
        cout << "{ ";
        for( auto r : group )
        {
            cout << r+1 << " ";
        }
        cout << "} ";
    }
    cout << endl;

为了编写更清晰的代码,我建议升级您的矩形,使其与 STL 配合得很好......

class Rectangle
{
public:
    double centerX;
    double centerY;
    double width;
    double height;
    int myID;
    static int lastID;

    Rectangle(double x, double y, double w, double h)
        :centerX(x),centerY(y),width(w),height(h),
         myID( ++lastID )
    {        }

    bool Intersect( const Rectangle& other ) const
    {
        ...
    }
    bool operator ==(const Rectangle& other ) const
    {
        return myID == other.myID;
    }
    bool operator <(const Rectangle& other ) const
    {
        return myID < other.myID;
    }
};

int Rectangle::lastID = 0;

...添加一个类来处理集合的 vector ...

class RectangleGroups
{
public:
    typedef std::set< Rectangle > group_t;
    typedef std::vector< group_t >::iterator iter;

    iter begin()
    {
        return groups.begin();
    }
    iter end()
    {
        return groups.end();
    }
    /**  Build the groups of intersecting trinagles

    @param[in] rectangles  vector of rectangles
    @param[in] intersections vector of pairs of intersecting rectangles
    */
    void Make(
        std::vector< Rectangle > rectangles,
        std::vector< std::pair< Rectangle&, Rectangle& > >& intesections )
    {
        // loop over intersecting triangles
        for( auto rp : intesections )
        {
            iter g_it = Find( rp.first );
            if( g_it != groups.end() )
            {
                g_it->insert( rp.second );
                continue;
            }
            g_it = Find( rp.second );
            if( g_it != groups.end() )
            {
                g_it->insert( rp.first );
                continue;
            }
            // neither rectangle is already in group, so add new group
            g_it = Add( rp.first );
            g_it->insert( rp.second );

        }
        // Add orphans
        for(  auto& r : rectangles )
        {
            if ( Find( r ) == groups.end() )
            {
                Add( r );
            }
        }
    }
    /// Display rectangle IDs in groups marked off with curly braces
    void Display()
    {
        for ( auto group : groups )
        {
            cout << "{ ";
            for( auto r : group )
            {
                cout << r.myID << " ";
            }
            cout << "} ";
        }
        cout << endl;
    }

private:
        std::vector< group_t > groups;

            ///  Add new group containing a copy of a rectangle, return iterator pointing to new group
    iter Add( const Rectangle& r )
    {
        group_t s;
        s.insert( r );
        groups.push_back( s );
        return groups.end()-1;

    }
    ///  Find group containing rectangle, return iterator pointing to found group or to end
    iter Find( const Rectangle& r )
    {
        for( iter it = groups.begin(); it != groups.end(); it++  )
        {
            auto group_it = it->find( r );
            if( group_it != it->end() )
            {
                return it;
            }
        }
        return groups.end();
    }
};

...这样我们就可以写...

 // vector of intesections
 // you can build this using various algorithms, even a sweepline
// here I will use a simple pair of nested for loops
   std::vector< std::pair< Rectangle&, Rectangle& > > intersections;
// loop over rectangles
    for( auto& r1 : rectangles )
    {
        // loop over remaining rectangles
        for( auto& r2 : rectangles )
        {
            if( r2 < r1 || r1 == r2 )
                continue;

            // check for intersection
            if( r1.Intersect( r2 ))
            {
                intersections.push_back( std::pair<Rectangle&, Rectangle& >( r1, r2 ) );
            }
        }
    }

    // Construct a vector of rectangle groups
    // The groups will contain interesecting rectangles.
    RectangleGroups groups;

    groups.Make(
            rectangles,
            intersections );

// Display results
groups.Display();

关于c++ - 找到一组相交的矩形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25741440/

有关c++ - 找到一组相交的矩形的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby-on-rails - capybara ::ElementNotFound:无法找到 xpath "/html" - 2

    我正在学习http://ruby.railstutorial.org/chapters/static-pages上的RubyonRails教程并遇到以下错误StaticPagesHomepageshouldhavethecontent'SampleApp'Failure/Error:page.shouldhave_content('SampleApp')Capybara::ElementNotFound:Unabletofindxpath"/html"#(eval):2:in`text'#./spec/requests/static_pages_spec.rb:7:in`(root)'

  3. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  4. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

  5. ruby - 如何找到调用当前方法的方法 - 2

    如何找到调用此方法的位置?defto_xml(options={})binding.pryoptions=options.to_hifoptions&&options.respond_to?(:to_h)serializable_hash(options).to_xml(options)end 最佳答案 键入caller。这将返回当前调用堆栈。文档:Kernel#caller.例子[0]%rspecspec10/16|===================================================62=====

  6. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  7. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  8. python - 帮我找到合适的 ruby​​/python 解析器生成器 - 2

    我使用的第一个解析器生成器是Parse::RecDescent,它的指南/教程很棒,但它最有用的功能是它的调试工具,特别是tracing功能(通过将$RD_TRACE设置为1来激活)。我正在寻找可以帮助您调试其规则的解析器生成器。问题是,它必须用python或ruby​​编写,并且具有详细模式/跟踪模式或非常有用的调试技术。有人知道这样的解析器生成器吗?编辑:当我说调试时,我并不是指调试python或ruby​​。我指的是调试解析器生成器,查看它在每一步都在做什么,查看它正在读取的每个字符,它试图匹配的规则。希望你明白这一点。赏金编辑:要赢得赏金,请展示一个解析器生成器框架,并说明它的

  9. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  10. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

    出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

随机推荐