我想在ruby中的一个变量中存储几个矩形。这是为了添加必须刷新屏幕的矩形。我尝试了一个带有top,left,height和with的矩形类,并在数组中存储了矩形变量。但是当迭代它并用它计算时,它太慢了。
添加新矩形时,屏幕上不应有任何重复项进行刷新,并且不需要花费太多时间来计算以删除重复项(在最佳情况下没有时间)。
对不起,我不是母语为英语的人,非常感谢你的想法!
需要'矩形'
类Rectangle
attr_accessor :top,:left,:height,:width
def initialize(options={})
@top=options[:top]
@left=options[:left]
@height=options[:height]
@width=options[:width]
end
def bottom
@top+@height-1
end
def right
@left+@width-1
end
def coveredBy?(rectangle)
return false if @top<rectangle.top
return false if @left<rectangle.left
return false if bottom>rectangle.bottom
return false if right>rectangle.right
return true
end
def intersection!(rectangle)
if @top<rectangle.top
@top=rectangle.top
end
if @left<rectangle.left
@left=rectangle.left
end
if bottom>(t=rectangle.bottom)
@height=rectangle.bottom+1-@top
end
if right>(t=rectangle.right)
@width=rectangle.right+1-@left
end
end
def &(rectangle)
if @top>=rectangle.top
top=@top
else
top=rectangle.top
end
if @left>=rectangle.left
left=@left
else
left=rectangle.left
end
if bottom<=rectangle.bottom
height=bottom+1-top
else
height=rectangle.bottom+1-top
end
return nil if height<=0
if right<=rectangle.right
width=right+1-left
else
width=rectangle.right+1-left
end
return nil if width<=0
return Rectangle.new(
:top=>top,
:left=>left,
:height=>height,
:width=>width
)
end
def -(rectArg)
return [] if empty?
return [self] if bottom<rectArg.top
return [self] if @top>rectArg.bottom
return [self] if right<rectArg.left
return [self] if @left>rectArg.right
ret=[]
line=@top
if @top<rectArg.top
ret[ret.count]=Rectangle.new(
:top=>line,
:left=>@left,
:height=>[rectArg.top-@top,@height].min,
:width=>@width
)
line=ret.first.bottom+1
end
if @left<rectArg.left
ret[ret.count]=Rectangle.new(
:top=>line,
:left=>@left,
:height=>[rectArg.bottom+1-line,bottom+1-line].min,
:width=>[rectArg.left-@left,@width].min
)
end
if right>rectArg.right
ret[ret.count]=Rectangle.new(
:top=>line,
:left=>rectArg.right+1,
:height=>[rectArg.bottom+1-line,bottom+1-line].min,
:width=>[right-rectArg.right,@width].min
)
end
if bottom>rectArg.bottom
ret[ret.count]=Rectangle.new(
:top=>rectArg.bottom+1,
:left=>@left,
:height=>[bottom-rectArg.bottom,@height].min,
:width=>@width
)
end
ret
end
# Mit return true geht es deutlich schneller als mit ||.
def outside?(rectangle)
return true if empty?
return true if rectangle.empty?
return true if bottom<rectangle.top
return true if @top>rectangle.bottom
return true if right<rectangle.left
return true if @left>rectangle.right
return false
end
# nebeneinander oder Überschneidung
public def touching?(rectangle)
horizontalRange=((rectangle.left-1..(rectangle.left+rectangle.width)))
verticalRange=((rectangle.top-1..(rectangle.top+rectangle.height)))
horizontalRange.any?{|column|
column==@left||column==@left+@width
} &&
verticalRange.any?{|line|
line==@top||line==@top+@height
}
end
def ==(rectangle)
#rectangle.kind_of?(self.class) &&
@top==rectangle.top &&
@height==rectangle.height &&
@left==rectangle.left &&
@width==rectangle.width
end
def !=(rectangle)
!(self==rectangle)
end
def empty?
return true if top.nil?
return true if left.nil?
return true if height.nil?
return true if height<=0
return true if width.nil?
return true if width<=0
# @empty=@height<=0 || @width<=0 if @empty.nil?
# @empty
end
public def area
# @area||=@height*@width
# @area
@height*@width
end
# nur wenn sie passgenau nebeneinander liegen
# (Überschneidungen darf es nicht geben)
public def mergeHorizontally(rectangle)
return nil if @top!=rectangle.top
return nil if @height!=rectangle.height
if @left+@width==rectangle.left
return Rectangle.new(
:top=>@top,
:left=>@left,
:height=>@height,
:width=>@width+rectangle.width
)
elsif rectangle.left+rectangle.width==@left
return Rectangle.new(
:top=>rectangle.top,
:left=>rectangle.left,
:height=>rectangle.height,
:width=>rectangle.width+@width
)
else
return nil
end
end
# nur wenn sie passgenau nebeneinander liegen
# (Überschneidungen darf es nicht geben)
public def mergeVertically(rectangle)
return nil if @left!=rectangle.left
return nil if @width!=rectangle.width
if @top+@height==rectangle.top
# return nil
return Rectangle.new(
:top=>@top,
:left=>@left,
:height=>@height+rectangle.height,
:width=>@width
)
elsif rectangle.top+rectangle.height==@top
# return nil
return Rectangle.new(
:top=>rectangle.top,
:left=>rectangle.left,
:height=>rectangle.height+@height,
:width=>rectangle.width
)
else
return nil
end
end
public def to_rects
Rectangles.new([self])
end
public def >(rectangle)
return true if @height>rectangle.height
return true if @width>rectangle.width
return false
end
public def +(rectArg)
# @@log<<"Rectangle#+ ==================================================="
# @@log<<"rectArg: #{rectArg.class}"
newTop=[@top,rectArg.top].min
newLeft=[@left,rectArg.left].min
newHeight=[bottom,rectArg.bottom].max+1-newTop
newWidth=[right,rectArg.right].max+1-newLeft
Rectangle.new(
:top=>newTop,
:left=>newLeft,
:height=>newHeight,
:width=>newWidth
)
end
端
答案 0 :(得分:1)
您必须定义自己的方法以确定对象是否相等。
class Rectangle
attr_accessor :top, :left, :width, :height
def initialize(top, left, width, height)
@top = top
@left = left
@width = width
@height = height
end
def ==(rect)
@top == rect.top &&
@left == rect.left &&
@width == rect.width &&
@height == rect.height
end
end
rect1 = Rectangle.new(10, 10, 20, 30)
rect2 = Rectangle.new(20, 20, 10, 15)
rectangles = [rect1, rect2]
rect3 = Rectangle.new(30, 30, 10, 10)
rectangles.include?(rect3) # false
rect_dup = rect1.dup
rectangles.include?(rect_dup) # true
编辑:添加基准
require 'benchmark'
rectangles = []
1.upto(1000) do |i|
rectangles << Rectangle.new(i, i, 10, 10)
end
Benchmark.bm do |x|
x.report(:missing_rectangles) do
1.upto(1000) do |i|
rect = Rectangle.new(i, i + 5, 10, 10)
rectangles.include?(rect)
end
end
end
结果:
user system total real
missing_rectangles 0.110000 0.000000 0.110000 ( 0.107022)