sketchucation logo sketchucation
    • 登入
    Oops, your profile's looking a bit empty! To help us tailor your experience, please fill in key details like your SketchUp version, skill level, operating system, and more. Update and save your info on your profile page today!
    ⚠️ Important | Libfredo 15.6b introduces important bugfixes for Fredo's Extensions Update

    REQ: Checking if components (solids) intersect

    已排程 已置頂 已鎖定 已移動 Plugins
    22 貼文 5 Posters 2.2k 瀏覽 5 Watching
    正在載入更多貼文
    • 從舊到新
    • 從新到舊
    • 最多點贊
    回覆
    • 在新貼文中回覆
    登入後回覆
    此主題已被刪除。只有擁有主題管理權限的使用者可以查看。
    • TIGT 離線
      TIG Moderator
      最後由 編輯

      My 'simple' example expects both of the passed objects [group/component-instance] to be in the same context - just as you might when doing the intersection manually on two selected objects.
      If they are not in the same entities-context they probably won't intersect logically, unless you somehow apply both of their 'transformations' in the intersection-tests - I'll have to think about that...


      Here's a breakdown of the code...

      grp = ens.add_group() This adds a temporary group to contain the intersection edges, if any
      grp.transform!(tr1) ### so can see cut lines IF erase! is disabled at the end ! It's as the ### note says - it moves the intersection lines back to where you'd expect them to be, rather than at the ORIGIN - if you erase! the grp you never see it...
      ges = grp.entities A reference to the grp entities context
      es1.intersect_with(true, tr1, ges, tr1, true, e2) The complicated 'intersect_with' - the first passed group/component-instance 'e1' [referenced earlier as 'es1'] is intersected with the second passed group/component-instance 'e2' [final argument in the ()], the other arguments in the () are 'true' to tell it to put the intersected geometry into another context, 'ges' sets the destination of the intersected geometry [the grp's entities], 'tr1' the transformation of 'e1', 'true' to include any hidden objects in the intersection, and as mentioned before 'e2' the second object that is being intersected with...
      if ges[0] int = true else int = false end This final part tests for any entities inside the 'grp' entities-context 'ges': if so 'int' is 'true' otherwise it's 'false'...
      Not included in your snippet - it then does grp.erase! to remove the temporary group, and return 'int'...


      It would be difficult to test for a full intersection rather than a touching.
      If you make two box groups and place them so the definitely overlap and select them and do a context-menu 'intersect-selection' you'll get a set of edges - visible if you move the two groups away.
      If you move a group so that 'kiss' - i.e. touch on a face - and repeat the intersect-selection, you still get geometry where they touch.
      There is no easily identifiable difference between the two - the full-intersection set is clearly '3d' BUT a touching set of edges could be equally complex...

      The only way to test otherwise... is to consider every vertex in a group and see if its position [adjusted for the container's transformation AND the potentially intersected second container's transformation] is inside the second object - probably with a 'raytest'.
      But even then it'd be quite possible to intersect two objects in such a way that no vertices from one are inside the other, BUT a true intersection still exists !


      Any suggestions on how a full-intersection versus a touching-intersection can be determined would be appreciated...

      TIG

      1 條回覆 最後回覆 回覆 引用 0
      • B 離線
        Bobvandevoort
        最後由 編輯

        Thanks for the really awesome explanation.

        I know a way that works (and just finished writing it) however it requires the pro version.

        I wrote it "ruby code editor" plugin and there for used the selection in the model to set the two components. (link http://www.alexschreyer.net/projects/sketchup-ruby-code-editor/)

        it works good so far only got a little error when I try to turn the material red of the intersecting component part.

        mod = Sketchup.active_model # Open model
        ent = mod.entities # All entities in model
        sel = mod.selection # Current selection
         instance1 = sel[0]
         instance2 = sel[1]
         ci_def = instance1.definition 
         tr1 = instance1.transformation
         test1 = Sketchup.active_model.entities.add_instance ci_def, tr1
         ci_def2 = instance2.definition 
         tr2 = instance2.transformation
         test2 = Sketchup.active_model.entities.add_instance ci_def2, tr2
         result = test1.intersect(test2) # I can delete this later using something like an observer but would have to figure out how that works, also need to figure out how to make this work for more than 2 components and I need to figure out how to do it (multi)nested components.
         cnt = result.entities.count 
        if  cnt > 0
         int=true
         result.material='red'
           # result.definition.entities.each {|ent|           ###When I run this in the plugin in console I get the following error "Done. Ruby says; uninitialized constant AS_RubyEditor;;RubyEditor;;Face"
           #   if ent.is_a? Sketchup;;Face
           #    Face.material = 'red' #Sketchup;;Color.new(255, 0, 0)
           #  end}
        else
         int=false
        end
        
        #return int
        
        

        If I run the code normally I get the following output "Done. Ruby says: red"
        However the faces aren't red they just stay the original color.

        1 條回覆 最後回覆 回覆 引用 0
        • G 離線
          glro
          最後由 編輯

          @bobvandevoort said:

          ..
          If I run the code normally I get the following output "Done. Ruby says: red"
          However the faces aren't red they just stay the original color.

          they are red, actually... but inside. Faces a reversed

          1 條回覆 最後回覆 回覆 引用 0
          • TIGT 離線
            TIG Moderator
            最後由 編輯

            It's not Face.material = 'red'
            it'd be ent.material = 'red'

            TIG

            1 條回覆 最後回覆 回覆 引用 0
            • P 離線
              pgarmyn
              最後由 編輯

              @TIG
              In method def self.intersectALL()

              (ens.length-1).times{|i|
                       (ens.length-1).times{|j|
                          next if j<=i # in place of  ; next if j==i
                          if self.intersect?(ens[i], ens[j])
                             ss.add(ens[i])
                             ss.add(ens[j])
                          end
                       }
              

              next if j<=i ( in place of next if j==i )
              prevents double checking (slower) and double results.
              If intersect?(ens[1], ens[2]) has been tested, then we don't have to test intersect?(ens[2], ens[1])

              1 條回覆 最後回覆 回覆 引用 0
              • G 離線
                glro
                最後由 編輯

                @pgarmyn said:

                @TIG
                In method def self.intersectALL()

                (ens.length-1).times{|i|
                >          (ens.length-1).times{|j|
                >             next if j<=i # in place of  ; next if j==i
                >             if self.intersect?(ens[i], ens[j])
                >                ss.add(ens[i])
                >                ss.add(ens[j])
                >             end
                >          }
                

                next if j<=i ( in place of next if j==i )
                prevents double checking (slower) and double results.
                If intersect?(ens[1], ens[2]) has been tested, then we don't have to test intersect?(ens[2], ens[1])

                I don't know why, but neither TIG's version, nor yours, works on my computer

                this is how i changed the code:

                		model=Sketchup.active_model
                		ss=model.selection
                		ents=model.active_entities
                		ss.clear
                		gps=ents.grep(Sketchup;;Group)
                		ins=ents.grep(Sketchup;;ComponentInstance)
                		ens=gps+ins
                		ens.uniq!
                		ens.compact!
                		for i in (0..ens.length-1)
                			for j in ((i+1)..ens.length-1)
                				if TIG.intersect?(ens[i], ens[j])
                					ss.add(ens[i])
                					ss.add(ens[j])
                				end
                			end
                		end
                        puts "Any intersecting groups/component-instances are highlighted..."
                

                length-1 because it because i begins at 0...
                and the i+1 to avoid comparing i to itself

                is this version much slower than yours?

                1 條回覆 最後回覆 回覆 引用 0
                • P 離線
                  pgarmyn
                  最後由 編輯

                  @giro

                  		model=Sketchup.active_model
                  		ss=model.selection
                  		ents=model.active_entities
                  		ss.clear
                  		gps=ents.grep(Sketchup;;Group)
                  		ins=ents.grep(Sketchup;;ComponentInstance)
                  		ens=gps+ins
                  		ens.uniq!
                  		ens.compact!
                  		for i in (0..ens.length-2)  ############changed from length-1 to length-2
                  			for j in ((i+1)..ens.length-1)
                  				if TIG.intersect?(ens[i], ens[j])
                  					ss.add(ens[i])
                  					ss.add(ens[j])
                  				end
                  			end
                  		end
                          puts "Any intersecting groups/component-instances are highlighted..."
                  

                  I think, in this case, the last TIG.intersect?(ens[i], ens[j]) is with i=length-2 and j=length-1
                  Otherwise j = i+1 will become ens.length : for 5 elements (0 to 4) in ens, j will be 5.

                  1 條回覆 最後回覆 回覆 引用 0
                  • G 離線
                    glro
                    最後由 編輯

                    @pgarmyn said:

                    @glro

                    I think, in this case, the last TIG.intersect?(ens[i], ens[j]) is with i=length-2 and j=length-1
                    Otherwise j = i+1 will become ens.length : for 5 elements (0 to 4) in ens, j will be 5.

                    yes, i agree
                    it works in both cases, but your version should be faster

                    1 條回覆 最後回覆 回覆 引用 0
                    • B 離線
                      Bobvandevoort
                      最後由 編輯

                      @tig said:

                      It's not Face.material = 'red'
                      it'd be ent.material = 'red'

                      Thanks this solved it 😄

                      Btw there's a way to do it with the intersect_with function and rule out most of the touching elements.
                      Any 3d volume needs at least 4 faces, so do a face count for ges and see if it equals 4 or more.
                      I know there probably some odd situations where it would still only be touching but then you could check if the faces form a solid if it doesn't form a solid it's a touch (I think this should be a correct way to implement this).

                      Let me know your thought about this method 😉

                      (in any real 3d modeling you only need to find volumetric intersections and if you also want to find out of they are thouching we already have the method you previously described.

                      Everybody else thanks for the response and sorry for the delay on my side with responding, I have been away for 2 days.

                      1 條回覆 最後回覆 回覆 引用 0
                      • P 離線
                        pgarmyn
                        最後由 編輯

                        @bobvandevoort
                        To rule out most of the elements :
                        You can exclude elements based on boundingbox values :
                        Elements a and b won't intersect
                        If a.bounds.max.x < b.bounds.min.x
                        If a.bounds.min.x > b.bounds.max.x
                        If ..... 4 other tests with .y and .z

                        I'm not shure if this will speed up your code. I can imagen that those tests are also done by the (faster) intersect method of the API

                        1 條回覆 最後回覆 回覆 引用 0
                        • G 離線
                          glro
                          最後由 編輯

                          @pgarmyn said:

                          @giro

                          		model=Sketchup.active_model
                          > 		ss=model.selection
                          > 		ents=model.active_entities
                          > 		ss.clear
                          > 		gps=ents.grep(Sketchup;;Group)
                          > 		ins=ents.grep(Sketchup;;ComponentInstance)
                          > 		ens=gps+ins
                          > 		ens.uniq!
                          > 		ens.compact!
                          > 		for i in (0..ens.length-2)  ############changed from length-1 to length-2
                          > 			for j in ((i+1)..ens.length-1)
                          > 				if TIG.intersect?(ens[i], ens[j])
                          > 					ss.add(ens[i])
                          > 					ss.add(ens[j])
                          > 				end
                          > 			end
                          > 		end
                          >         puts "Any intersecting groups/component-instances are highlighted..."
                          

                          I think, in this case, the last TIG.intersect?(ens[i], ens[j]) is with i=length-2 and j=length-1
                          Otherwise j = i+1 will become ens.length : for 5 elements (0 to 4) in ens, j will be 5.

                          i tried to run this code in sketchup 15 64 bits, thinking it could run faster than is sketchup 8

                          All the contrary

                          it is much slower in sketchup 15 64 bits... (about 10 times...)

                          i am very disapointed

                          am i the only one to experience that?

                          1 條回覆 最後回覆 回覆 引用 0
                          • B 離線
                            Bobvandevoort
                            最後由 編輯

                            This is my version of the srcipt for now that seems to work for all non nested component instances

                            module Bob
                            
                            # Huge parts of this code were written by TIG this is a sligthly modified version
                            
                            	def self.intersectBob?(e1=nil, e2=nil)
                            	
                            		mod = Sketchup.active_model # Open model
                            		ent = mod.entities # All entities in model
                            		instance1 = e1 #sel[0]
                            		instance2 = e2 #sel[1]
                            		ci_def = instance1.definition 
                            		tr1 = instance1.transformation
                            		test1 = Sketchup.active_model.entities.add_instance ci_def, tr1
                            		ci_def2 = instance2.definition 
                            		tr2 = instance2.transformation
                            		test2 = Sketchup.active_model.entities.add_instance ci_def2, tr2
                            		result = test1.intersect(test2) 
                            		cnt = result.entities.count 
                            		if  cnt > 0
                            			int=true
                            			result.definition.entities.each {|ent|
                            			if ent.is_a? Sketchup;;Face
                            				ent.material = 'red' #Sketchup;;Color.new(255, 0, 0)
                            			end}
                            		else
                            		int=false
                            		end
                            		
                            	return int
                            	end 
                            	
                            	#def self.del()	#does not work like this typing Bob.del into the ruby console, meaning result has to be changed from local to global variable but I don't know how yet
                            	#result.erase!	
                            	#end	
                            
                            	def self.intersectALL()
                            		model=Sketchup.active_model
                            		ss=model.selection
                            		ents=model.active_entities
                            		ss.clear
                            		gps=ents.grep(Sketchup;;Group)
                            		ins=ents.grep(Sketchup;;ComponentInstance)
                            		ens=gps+ins
                            		ens.uniq!
                            		ens.compact!
                            		(ens.length).times{|i|
                            			(ens.length).times{|j|
                            				next if j<=i
                            				if self.intersectBob?(ens[i], ens[j])
                            					ss.add(ens[i])
                            					ss.add(ens[j])
                            				end
                            			}
                            		}
                            		puts "Any intersecting component-instances are highlighted..."
                            	end
                            end
                            
                            

                            In this script I still need to fix the deleting function which later will have to be added to an observer class so as soon as another is clicked (or a button is pressed) the resulting intersection is deleted.

                            The more important function that still has to be added is that it does the check for all the nested components (and possibly groups).

                            @giro
                            I only have the 32 bits version so can't say

                            1 條回覆 最後回覆 回覆 引用 0
                            • 1
                            • 2
                            • 1 / 2
                            • 第一個貼文
                              最後的貼文
                            Buy SketchPlus
                            Buy SUbD
                            Buy WrapR
                            Buy eBook
                            Buy Modelur
                            Buy Vertex Tools
                            Buy SketchCuisine
                            Buy FormFonts

                            Advertisement