logo

Seeker

#Script written by Luis Quinones
#Seeker Smart Search Algorithm
#Script Copywritten by complicitMatter.com
#www.complicitMatter.com
#www.computationalMatter.com

import rhinoscriptsyntax as rs
import math
import random
from System.Drawing import Color
import sys
import random
import scriptcontext

class myLOCATOR:
    
    def __init__(self,txtcoord,ptCoords,pts,init,coord,colorThresh,colorSet):

        self.txtPt = txtcoord
        self.ptIDS = pts
        self.ptCOORDS = ptCoords
        self.current = init
        self.pos = coord
        self.cTHRESH = colorThresh
        self.dTHRESH = 12
        self.colors = colorSet

        self.CASEA = False
        self.CASEB = False
        self.CASEC = False
        self.CASED = False
        self.tempList = []
        self.tempColorList = []
        self.creationHistory = []
        
        self.waveTwoThreshCOUNT = 6
        self.searchPASSES = []

    def search(self):
                
        #ALL THE ACTION
        cCHECKDARK = [x for x in self.tempColorList if x < self.cTHRESH] #CHECK THE LIST FOR VALUES THAT ARE SMALLER THAN COLOR THRESHOLD

        if len(cCHECKDARK) > 0 and len(cCHECKDARK) != len(self.tempColorList) and all(k > self.cTHRESH for k in self.tempColorList) and closestColor > self.cTHRESH:
            print "AT LEAST ONE DARK ONE"
            self.CASEA = True #MEANS THERE IS AT LEAST ONE DARK ONE IN THE MIX
            
        if len(cCHECKDARK) == len(self.tempColorList):
            print "ALL DARK ONES"
            self.CASEB = True #MEANS THEY ARE ALL DARK
            txtE = rs.AddText("CASE-B",[self.txtPt[0],self.txtPt[1],self.txtPt[2]-6],0.5)
            
        cCHECKLIGHT = [m for m in self.tempColorList if m >= self.cTHRESH]
        if len(cCHECKLIGHT) > 0 and len(cCHECKLIGHT) != len(self.tempColorList) and len(cCHECKDARK) > 0 :
            print "AT LEAST ONE LIGHT ONE IN MIX OF DARK"
            self.CASEC = True #THERES AT LEAST ONE BRIGHT VALUE IN THE MIX OF DARK ONES
            txtE = rs.AddText("CASE-C",[self.txtPt[0],self.txtPt[1],self.txtPt[2]-6],0.5)
            
        elif len(cCHECKLIGHT) == len(self.tempColorList):
            print "ALL LIGHT ONES"
            print "LIGHTPTS = " + str(len(cCHECKLIGHT)) 
            print "DARK PTS = " + str(len(cCHECKDARK)) 
            self.CASED = True #THEYRE ALL BRIGHT
            txtE = rs.AddText("CASE-D",[self.txtPt[0],self.txtPt[1],self.txtPt[2]-6],0.5)
            
        return [cCHECKDARK,cCHECKLIGHT]
        
    def closestFriends(self,nearPOINTS,nearDIST,nearPOINTCOLOR,currentWAVEONEPT,count):
        closestDUDES = [] 
        closestDUDESDIST = []
        closestDUDESCOLOR = []
        sortList = nearDIST[:] #make a duplicate list
        sortList.sort() #sort the distances to get the first 3 which are closest

        sum = 0
        for i in range(0,self.waveTwoThreshCOUNT): #loop through how many neighborgs you want
            nearIndex = nearDIST.index(sortList[i]) #get index 
            #print nearIndex
            closestDUDES.append(nearPOINTS[nearIndex]) #store the closest 3 points and dist and color
            closestDUDESCOLOR.append(nearPOINTCOLOR[nearIndex])
            closestDUDESDIST.append(nearDIST[nearIndex])
            sum = sum + nearPOINTCOLOR[nearIndex]
            
        average = closestDUDESCOLOR
        waveTWOCOLORAVE = sum/self.waveTwoThreshCOUNT
            
        for j in range(len(closestDUDES)):
            circ2 = rs.AddCircle(closestDUDES[j],2)
            rs.ObjectLayer(circ2,"wave2")
            self.creationHistory.append(circ2)
        closestNeighborghIND = rs.PointArrayClosestPoint(closestDUDES,currentWAVEONEPT)
        closestDude = closestDUDES[closestNeighborghIND]
        circ = rs.AddCircle(closestDude,0.5)
        rs.ObjectLayer(circ,"clos")
        self.creationHistory.append(circ)
        dot = rs.AddTextDot(count,closestDude)
        rs.ObjectLayer(circ,"CLOSE")
        self.creationHistory.append(dot)
        del sortList[:]
        return [closestDUDES,waveTWOCOLORAVE,closestDude]
        
    def decisionMaker(self):
    
        rs.EnableRedraw(False)
        #if theyre all white
        #get closest points within another threshold - 5 UNITS
        nearPOINTS = [] #LIST OF WAVE 2 POINTS
        nearDIST = [] #LIST OF DISTANCE FROM WAVE 1 PTS TO WAVE 2 POINTS
        nearPOINTCOLOR = [] #LIST OF WAVE 2 COLORS
        tempOUTPTS = self.ptCOORDS
        tempOUTCOL = self.colors
        averageCOLORSET = [] #LIST OF CLOSEST WAVE 2 COLOR AVERAGE
        closestNEIGHPOS = [] #LIST OF Closest WAVE 2 PTS TO EACH WAVE 1 PT
        nextPosHolder = [] #HOLDS LIST OF WAVE 1 POSITIONS WAITING FOR WAVE 2 OUTPUT
        closestSOLO = [] #CLOSEST WAVE 2 PT TO WAVE PT
        stopper = []
        
        #ONLY USE IF YOU WANT TO REMOVE ALL WAVE 1 POINTS FROM WAVE 2 - otherwise just remove current Wave 1 Point from Wave 2
        #-----------------------------------------------------------------------------------------------------------------------
        #for x in range(len(self.tempList)): #loop through the 1st wave points
            #loc = self.ptCOORDS.index(self.tempList[x]) #get the index of 1st wave to remove from 2nd wave
            #tempOUTPTS.remove(self.ptCOORDS[loc])
            #tempOUTCOL.remove(self.colors[loc])
        #-----------------------------------------------------------------------------------------------------------------------
        
        for i in range(len(self.tempList)): #loop through everypoint against each point in wave 1
            if scriptcontext.escape_test(False):
                print "ESC pressed "
                break   
            #RESET LISTS
            dotStopper = stopper[:]
            dotStopperHELP = nearDIST[:]
            
            stopper = []
            nearPOINTS = [] 
            nearDIST = [] 
            nearPOINTCOLOR = []
            
            for j in range(len(tempOUTPTS)):
                checkDist = rs.Distance(tempOUTPTS[j],self.tempList[i]) #check dist if dist within 2nd wave thresh and current isnt me and z is smaller and mine and if wave1 current does not match wave2 current then store it
                #if tempOUTPTS[j] != self.tempList[i] and tempOUTPTS[j] != self.pos and tempOUTPTS[j][2] >= self.tempList[i][2] : #THIS DOES NOT ALLOW LOOKING BACK
                if tempOUTPTS[j] != self.tempList[i] and tempOUTPTS[j] != self.pos: #THIS ALLOWS LOOKING BACK SEARCHING PREV HISTORY
                    if dotStopper == dotStopperHELP:
                        dot = rs.AddTextDot("WAVE 2 - " + str(tempOUTCOL[j]),tempOUTPTS[j])
                        rs.ObjectLayer(dot,"DOTS_DARK")
                        self.creationHistory.append(dot)
                    nearPOINTS.append(tempOUTPTS[j]) #store 2nd wave points
                    nearDIST.append(checkDist) #store 2nd wave dist
                    nearPOINTCOLOR.append(tempOUTCOL[j]) #store 2nd wave colors
                    stopper.append("0")
            #print "THIS MANY OUTTER POINTS - " + str(len(nearPOINTS))
            newCirc = rs.AddCircle(self.tempList[i],1)
            rs.ObjectLayer(newCirc,"wave1")
            self.creationHistory.append(newCirc)
            output = self.closestFriends(nearPOINTS,nearDIST,nearPOINTCOLOR,self.tempList[i],i) #CALL CLOSEST FRIENDS FUNCTION
            averageCOLORSET.append(output[1]) #STORE LIST OF RETURNED COLOR AVERAGES FROM WAVE 2
            closestNEIGHPOS.append(output[0]) #STORE ARRAY OF RETURNED PT POS FROM WAVE 2
            nextPosHolder.append(self.tempList[i]) #STORE WAVE 1 PTS TO FIND INDEX FOR NEXT POS
            closestSOLO.append(output[2]) #STORE CLOSEST SINGLE POS FROM WAVE 2
            
            #COUNTERS
            #-----------------------------------------------------------------------------------------------------------------------
            txtA = rs.AddText(str(len(output[0])),self.txtPt,0.5)
            self.creationHistory.append(txtA)
            txtB = rs.AddText(str(len(self.searchPASSES)+1),[self.txtPt[0],self.txtPt[1],self.txtPt[2]-1],0.5)
            self.creationHistory.append(txtB)
            txtC = rs.AddText(str(self.waveTwoThreshCOUNT),[self.txtPt[0],self.txtPt[1],self.txtPt[2]-2],0.5)
            self.creationHistory.append(txtC)
            txtE = rs.AddText(str(self.dTHRESH),[self.txtPt[0],self.txtPt[1],self.txtPt[2]-5],0.5)
            self.creationHistory.append(txtE)
            #-----------------------------------------------------------------------------------------------------------------------
            rs.EnableRedraw(True)
            for x in range(len(output[0])):
                #sampletest = rs.AddTextDot(str(averageCOLORSET),closestNEIGHPOS[0][x])
                #rs.TextDotHeight(sampletest,20)
                refLine = rs.AddLine(output[0][x],self.tempList[i])
                rs.ObjectLayer(refLine,"w1w2_Conn")
                self.creationHistory.append(refLine)
                refLinemid = rs.CurveMidPoint(refLine)
                newDot2 = rs.AddTextDot(x,refLinemid)
                rs.ObjectLayer(newDot2,"w1w2_Conn")
                self.creationHistory.append(newDot2)
                
        print "THAT COUNT MAAAAN = " + str(len(nextPosHolder))

        txtD = rs.AddText(str(len(nearPOINTS)),[self.txtPt[0],self.txtPt[1],self.txtPt[2]-3],0.5)
        rs.DeleteObject(txtD)
        self.creationHistory.append(txtD)
        copy = nearPOINTS
            
        print "NextPHOLD = " + str(nextPosHolder)
        print "P1 = " + str(nextPosHolder[1])
        print "Average Color = " + str(averageCOLORSET)
        low = min(averageCOLORSET) #GET THE MIN VALUE FROM THE NETWORK COLORS
        high = max(averageCOLORSET) #GET THE MAX VALUE FROM THE NETWORK COLORS
        print "Low Value = " + str(low)
        lowIndex = averageCOLORSET.index(low) #GET THE POS ON LIST WHERE THE LOWEST VALUE IS
        print "Index = " + str(lowIndex)
        

        lowCount = averageCOLORSET.count(low)

        if low == high: #IF LOW AND HIGH VALUE ARE THE SAME IE 255 ALL WHITE / EITHER CHOOSE RANDOMLY FROM WAVE 1 OR CHOOSE CLOSEST FROM WAVE 1
            self.searchPASSES.append("0")
            print "LOW = HIGH"
            deleted = rs.DeleteObjects(self.creationHistory)
            print "# ITEMS IN LIST = " + str(len(self.creationHistory))
            print "# of DELETED Objects = " + str(deleted)
            self.creationHistory = []
            #nextPosInd = rs.PointArrayClosestPoint(self.tempList,self.pos)
            nextPos = False
            
            self.waveTwoThreshCOUNT = self.waveTwoThreshCOUNT + 1 
            #self.dTHRESH = self.dTHRESH+4
            return nextPos

        else:
            self.waveTwoThreshCOUNT = 6
            nextPos = nextPosHolder[lowIndex] #NEXT POSITION BASED ON THE WAVES RESULTS
            txtD = rs.AddText(str(len(copy)),[self.txtPt[0],self.txtPt[1],self.txtPt[2]-3],0.5)
            print "FINAL POS = " + str(nextPos)
            return nextPos

    def execution(self,lightCOLORCOUNT):
        if self.CASEB == True: #IF THEY ARE ALL DARK THEN JUST FIND CLOSEST DARK VALUE
            closestIndex = rs.PointArrayClosestPoint(self.tempList,self.pos)
            closestVert = self.tempList[closestIndex]
            closestColor = self.tempColorList[closestIndex]
            line = rs.AddLine(self.pos,closestVert)
            self.creationHistory.append(line)
            
        elif self.CASEC == True: #IF THERE ARE ANY LIGHT ONES IN THE LIST
            newTempList = self.tempList #MAKE A DUP LIST OF VERTS
            #print len(newTempList)
            newTempCOLOR = self.tempColorList #MAKE A DUP LIST OF COLORS
            counter = len(lightCOLORCOUNT) #GET THE NUMBER OF LIGHT VALUES IN LIST
            if len(lightCOLORCOUNT)>0: 
                for p in range(0,counter): #LOOP THROUGH ALL THE BRIGHT COLORS
                    loc = self.tempColorList.index(lightCOLORCOUNT[p]) #GET THE INDEX OF THE DUP LIST WHERE THE BRIGHT VALUE IS
                    #print loc
                    newdot = rs.AddTextDot("OUT",self.tempList[loc])
                    self.creationHistory.append(newdot)
                    newTempList.remove(self.tempList[loc]) #REMOVE THE POINT WHERE THE BRIGHT VALUE IS
                    newTempCOLOR.remove(self.tempColorList[loc]) #REMOVE THE COLORVALUE FROM LIST 
                    
            closestIndex = rs.PointArrayClosestPoint(newTempList,self.pos) #GET THE NEW CLOSEST INDEX WITHIN THE REMAINING DARK VALUES
            closestVert = newTempList[closestIndex] #CLOSEST POINT
            closestColor = newTempCOLOR[closestIndex] #CLOSEST COLOR
            newLine = rs.AddLine(self.pos,closestVert) 
            self.creationHistory.append(newLine)
            
        elif self.CASED == True: #IF THERE ARE ONLY LIGHT ONES IN THE LIST
           print "SEARCHING!"
           output = self.decisionMaker() #FUNCTION TO DECIDE WHAT TO DO
           print "outPut = " + str(output)
           if output != False:
               nextPosLine = rs.AddLine(self.pos,output)
               rs.ObjectLayer(nextPosLine,"bigDaddy")
               self.creationHistory.append(nextPosLine)
           else:
               return output
               
        #DIAGRAMING ONLY
        #-----------------------------------------------------------------------------------------------------------------------
           self.creationHistory.append(nextPosLine)
           #deleted = rs.DeleteObjects(self.creationHistory)
           
           finalDot = rs.AddTextDot("NEXT POSITION",output)
           rs.TextDotHeight(finalDot,15)
           finalCirc = rs.AddCircle(output,1.5)
           rs.ObjectLayer(finalCirc,"bigDaddy")
           rs.SelectObject(finalDot)
           rs.SelectObject(finalCirc)
           rs.EnableRedraw(False)
           print len(self.creationHistory)
           for f in range(len(self.creationHistory)):
                rs.ObjectLayer(self.creationHistory[f],"end")
           rs.EnableRedraw(True)
        #-----------------------------------------------------------------------------------------------------------------------
        
    def infoGrab(self):
        self.tempList = []
        self.tempColorList = []
        for i in range(len(self.ptCOORDS)): #loop through and store coordinates and check distance

            dist = rs.Distance(self.ptCOORDS[i],self.pos)
            
            if dist <= self.dTHRESH and self.ptCOORDS[i] != self.pos and self.pos[2] <= self.ptCOORDS[i][2]: #if distance is withint thresh and i am not myself put those values on a separate list
                self.tempList.append(self.ptCOORDS[i])
                self.tempColorList.append(self.colors[i])
                #locLine = rs.AddLine(self.pos,self.ptCOORDS[i])
                #rs.ObjectLayer(locLine,"locLine")
            
        for j in range(len(self.tempList)): #Visualization ONLY
            dot = rs.AddTextDot(str(self.tempColorList[j]),self.tempList[j])
            rs.ObjectLayer(dot,"cVAL")
            #rs.ObjectColor(dot,[self.tempColorList[j],self.tempColorList[j],self.tempColorList[j]])
            self.creationHistory.append(dot)
            
        results = self.search() #CALL THE SEARCH FUNCTION
        checkPt = self.execution(results[1]) #CALL THE EXECUTE FUNCTION
        print "TOTAL SEARCH PASSES UNTIL FOUND MATCH = " + str(len(self.searchPASSES))
        #print [self.CASEA,self.CASEB,self.CASEC,self.CASED]
        if checkPt == False:
            print "GOING AT IT AGAIN"
            return checkPt
    
def main():
    pts = rs.GetObjects("POINTS",rs.filter.point)
    init = rs.GetObject("POINT",rs.filter.point)
    coord = rs.PointCoordinates(init)
    textPt = rs.GetObject("txtPt",rs.filter.point)
    txtcoord = rs.PointCoordinates(textPt)

    colorThresh = 200
    txtE = rs.AddText(str(colorThresh),[txtcoord[0],txtcoord[1],txtcoord[2]-4],0.5)
    
    ptCoords = []
    colorSet = []
    for x in range(len(pts)):
        coords = rs.PointCoordinates(pts[x])
        ptCoords.append(coords)
        color = rs.ObjectColor(pts[x])
        colorR = rs.ColorRedValue(color)
        colorSet.append(colorR)
        
    rs.HideObject(textPt)
    
    loc = myLOCATOR(txtcoord,ptCoords,pts,init,coord,colorThresh,colorSet)
    info = loc.infoGrab()
    print info
    while info == False:
        info = loc.infoGrab()
        if scriptcontext.escape_test(False):
            print "ESC pressed "
            break 
main()
Update
  • Share