sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    Raytest Alternative?

    Scheduled Pinned Locked Moved Developers' Forum
    7 Posts 2 Posters 459 Views 2 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • A Offline
      ArjunaMeridian
      last edited by

      I'm using code to iterate through a series of faces, taking each center point, and testing each individually using raytest to see if the face is "visible" to another far away test point, given the other geometry present in the model (ie, if the ray "hits" something else, it isn't visible).

      It works great EXCEPT that it is excruciatingly slow, especially when there are many faces and/or test points.

      Is there a better way?

      Here's a snippet:

      def self.test_points(face)
               center = face.bounds.center
               normal = face.normal
               counter = 1
               0.upto(test_points.length-1) {|s|
               ray = [center,test_points[s]]
               item = @model.raytest(ray,false)
               #puts item         
               if item == nil
                  sv = center.vector_to test_points[s]
                  an = normal.angle_between sv
                  counter += Math.cos(an)
               end
      
      1 Reply Last reply Reply Quote 0
      • TIGT Offline
        TIG Moderator
        last edited by

        I don't fully follow your code πŸ˜’
        You suddenly seem to recall the 'test_points' method from within itself to no affect ?
        Where does the 'test_points' come from that you use - it is used as an array BUT you also have a method with the same name that is passed a (face)... πŸ˜•
        If you are declaring an array of 'test_points' then name it '@test_points' and use that - because the reference is loss across methods without the @ !!
        You also seem to be passing points as vectors in the raytest πŸ˜• πŸ˜•
        And when the test fails incrementing a counter by an[gle] that unused elsewhere anyway πŸ˜• πŸ˜• πŸ˜•

        TIG

        1 Reply Last reply Reply Quote 0
        • A Offline
          ArjunaMeridian
          last edited by

          You're absolutely correct...I pulled the code out of context of a longer section of code, re-(mis-)labeled a few things, all in an effort to minimize the reading required by anyone attempting to help me out, since RAYTEST seems to be the crux of the problem (I think).

          In case you care to read my entire code, it is below, though I've added a big comment block with #RAYTEST SECTION# if you want to skip to that.

          The test point array is '@suns'

          Thank you for trying to help me

          module MC_sun_tools
             @model = Sketchup.active_model
             @ents = @model.entities
             @sel = @model.selection
          
          
          
             def MC_sun_tools.generate_suns
          
               
               # Initialize some variables
          
               tz = -5.0  
               altitude = 1000.m #We'll generate points 1km away
          
                @suns = [] # An array to hold our "suns"
          
                si = @model.shadow_info
          
                ct = si["ShadowTime"]   #the class of ct is Time
          
                yr = ct.year
                mon = 9 #ct.month
                day = ct.day
          
                # The points we add will be part of a new group
          
                #my_verts = @sel[0].vertices
          
                new_ent = @ents.add_group
                new_ent.name = "{mon}-{day}"
          
                0.upto(24*4-1) {|hour|
                   t = Time.local(yr, mon, day, hour/4, (hour.to_f/4 % 1)*60)
                   si['ShadowTime'] = t
                   v = si["SunDirection"]
                   v.length = altitude
                   pt = ORIGIN + v
                   new_ent.entities.add_cpoint(pt)
                   new_ent.entities.add_text(((hour/4-tz) % 24).to_i.to_s, pt)
                   @suns << pt #if pt.is_a? Sketchup;;Point3d
                }
            end
          
             def MC_sun_tools.get_faces
                 my_faces = []
                    @sel.each {|e|
                       if e.is_a? Sketchup;;Face
                       my_faces << e
                    end
                 }
                 my_faces.each {|e|
                     MC_sun_tools.test_suns(e)
                 }
                 puts my_faces.length
             end
          ######################################################
          #########RAYTEST SECTION##############################
             
             def MC_sun_tools.test_suns(face)
                center = face.bounds.center
                normal = face.normal
                face.material= @color_hash[1]
                counter = 1
                0.upto(@suns.length-1) {|s|
                   ray = [center,@suns[s]]
                   item = @model.raytest(ray,false)
                   #puts item         
                   if item == nil
                      sun_vector = center.vector_to @suns[s]
                      an = normal.angle_between sun_vector
                      counter = counter + Math.cos(an)*0.8
                      #puts cos(an)     
                      #@ents.add_cline(center, @suns[s])
                      
                   end
                   
                }
                face.material = @color_hash[[counter.to_i, 25].min]
             end
          ########################################################
          
          @color_hash = [[0, 0, 180], 
          [0, 30, 180], 
          [0, 60, 180], 
          [0, 90, 180], 
          [0, 120, 180], 
          [0, 150, 180], 
          [0, 180, 180], 
          [0, 180, 150], 
          [0, 180, 120], 
          [0, 180, 90], 
          [0, 180, 60], 
          [0, 180, 30], 
          [0, 180, 0], 
          [30, 180, 0], 
          [60, 180, 0], 
          [90, 180, 0], 
          [120, 180, 0], 
          [150, 180, 0], 
          [180, 180, 0], 
          [180, 150, 0], 
          [180, 120, 0], 
          [180, 90, 0], 
          [180, 60, 0], 
          [180, 30, 0], 
          [180, 0, 0]] 
          
          end
          
          plug_menu = UI.menu("Plugins")
          plug_menu.add_item("Generate Suns") {MC_sun_tools.generate_suns}
          plug_menu.add_item("Test Suns") {MC_sun_tools.test_suns}
          plug_menu.add_item("Get Faces") {MC_sun_tools.get_faces}
          
          1 Reply Last reply Reply Quote 0
          • TIGT Offline
            TIG Moderator
            last edited by

            Why do you mess with si["SunDirection"] ?
            Why not pass that as a vector to the @suns array...
            Messing on adding it to the ORIGIN etc just causes me confusion ?
            I deduce you are testing sun-angles across time and seeing if a face's center can see the sun...
            I don't think you need to make it quite so convoluted...

            TIG

            1 Reply Last reply Reply Quote 0
            • A Offline
              ArjunaMeridian
              last edited by

              You're right about what the code is attempting to do, and no doubt it needs to be cleaned up and modularized a bit. To answer your question: I call si["SunDirection"] when generating the @sun array because the Point3ds (generated from vectors about ORIGIN) will depend on the geolocation and date of the model. Hence, Colorado's suns will differ from London's.

              Regardless, the ShadowInfo calls within the sun array routine aren't the time constraint within the code-- RayTest seems to be the culprit. Given the profusion of rendering programs which are undoubtedly doing MANY more collision calculations, I'm wondering if there's an obvious, less computationally expensive substitute to calling RayTest.

              1 Reply Last reply Reply Quote 0
              • TIGT Offline
                TIG Moderator
                last edited by

                It seems to work fast enough for me ?

                Also remember that the sun's vector is the same irrespective of where you 'place it' ?
                Setting it's length to 1km does nothing to it when you use it in the raytest - I realize you want it for the 'sun location...
                Adding it .to_a to the ORIGIN returns a point.

                A simple raytest is
                model.raytest([point,vector])
                So for any 'point' you pass to the raytest using the sun_direction vector [unaltered] will return 'nil' if it hits nothing or a two element array otherwise - which in your case you can just ignore.

                I assume your code should then 'color' faces depending on if their center fails the raytest and its angle towards the sun...

                The raytesting itself should be relatively quick - how many faces are you testing ?

                TIG

                1 Reply Last reply Reply Quote 0
                • A Offline
                  ArjunaMeridian
                  last edited by

                  Well I hadn't thought of the sun vector that way, but that is great advice-- should certainly speed things up, a little at least.

                  As for the number of faces...I'd like to take a surface and run it with arbitrary granularity; so, thousands. Running my code as it stands for 1000 faces takes on the order of 15 minutes to run.

                  Making the change you suggested now...

                  1 Reply Last reply Reply Quote 0
                  • 1 / 1
                  • First post
                    Last post
                  Buy SketchPlus
                  Buy SUbD
                  Buy WrapR
                  Buy eBook
                  Buy Modelur
                  Buy Vertex Tools
                  Buy SketchCuisine
                  Buy FormFonts

                  Advertisement