Pular para o conteúdo

Exemplo de Script: Criando objetos

Scripting é uma ferramenta eficaz para modificação de dados, mas também pode ser usado para criar novos dados. Este exemplo mostra como importar dados seguindo um exemplo que cria um novo estado de tráfego usando dados de um arquivo externo.

Criação de objetos

Qualquer objeto derivado de GKObject deve ser criado (salvo indicação específica) usando um Novo Command. Esses comandos criam e inicializam novas referências de objeto, adicionam o objeto à sua camada ou pasta e reduzem o código a ser escrito. Por exemplo:

cmd = GKTurningNewCmd()
cmd.setTurning( origin, destination )
cmd.setUndoable( False )

Este exemplo chama o construtor, define as informações mínimas necessárias para o objeto e define desfazível como false para impedir o new comando sendo desfeito na GUI.

O novo comando precisa ser incluído no model commander para garantir a execução instantânea do comando e manter as referências do comando para fins de ações de desfazer/refazer:

model.getCommander().addCommand( cmd )

Depois que o comando tiver sido executado e quisermos acessar o novo objeto, qualquer comando New o retorna a partir de createdObject() método:

newTurn = cmd.createdObject()

Se o novo comando para o GKType que você está procurando não existir, há uma forma alternativa de criar objetos, que é usando o GKSystem::newObject() chamada. Esta chamada criará um novo objeto, o inicializará e o adicionará ao catálogo do modelo atual.

Criar um novo objeto derivado de GKObject de qualquer outra forma pode corromper o modelo atual ou fazer o sistema falhar mais tarde. Portanto, para criar um novo objeto de um tipo cujo NewCmd não está disponível (GKMyType, por exemplo), o código será:

state = GKSystem.getSystem().newObject( "GKMyType", model )

e não:

state = GKMyType() # NEVER do this!!!

Esta chamada instrui o sistema a criar um novo objeto de um tipo específico (um objeto GKMyType neste exemplo) no modelo fornecido. O novo objeto ficará sem título, portanto é aconselhável atribuir-lhe um nome usando o GKObject::setName() método:

state.setName( "New my type object" )

Organização de objetos

O Aimsun Next organiza objetos de duas maneiras, dependendo do seu tipo. Objetos gráficos são organizados em camadas e exibidos nas vistas 2D e 3D. Objetos não gráficos são organizados em pastas e exibidos na Janela do Projeto.

Após criar um objeto sem usar seu comando New, um novo objeto deve ser adicionado a uma camada ou a uma pasta, dependendo de ele ser gráfico ou não gráfico.

Imagine que o objeto GKMyType criado na seção anterior seja um objeto não gráfico. Como objeto não gráfico, ele deve ser adicionado a uma pasta. Vamos imaginar que queremos adicioná-lo à pasta de estados de tráfego. No entanto, essa pasta deve ser criada se ainda não existir. O código a seguir cria a pasta:

folderName = "GKModel::trafficStates"
folder = model.getCreateRootFolder().findFolder( folderName )
if folder == None:
    folder = GKSystem.getSystem().createFolder( model.getCreateRootFolder(), folderName )

Primeiro, este código procura a pasta usando o GKFolder::findFolder() call. Ele procura na pasta raiz do modelo, que é o local normal. Se a pasta não estiver lá, ela será criada. Porque o Estados de Tráfego pasta é uma pasta do sistema, precisamos apenas passar o nome interno da pasta para que o sistema crie a estrutura correta. Consulte a tabela abaixo para o nome interno das pastas do sistema.

Nomes internos das pastas do sistema

Nome externo Nome Interno (único)
Configurações de Centroides GKModel::centroidsConf
Controle GKModel::top::control
Planos de Controle GKModel::controlPlans
Análise de Dados GKModel::top::dataAnalysis
Dados de Demanda GKModel::top::traffic
Localizações dos Detectores GKModel::detectorLocations
Funções GKModel::functions
Infraestrutura GKModel::top::infrastructure
Tipos de Faixa GKModel::laneTypes
Planos de Controle Mestres GKModel::masterControlPlans
Matrizes OD GKCentroidConfiguration::matrices
Rotas OD GKCentroidConfiguration::routes
Transporte Público GKModel::top::publicTransport
Linhas de Transporte Público GKModel::publicLines
Planos de transporte público GKModel::publicPlans
Conjuntos de dados reais GKModel::realDataSets
Tipos de vias GKModel::roadTypes
Cenários GKModel::top::scenarios
Scripts GKModel::top::scripts
Subcaminhos GKModel::subPaths
Estratégias GKModel::strategies
Condições de Tráfego GKModel::trafficConditions
Demandas de Tráfego GKModel::trafficDemand
Gestão de Tráfego GKModel::top::trafficmanagement
Estados de Tráfego GKModel::trafficStates
Gatilhos GKModel::triggers
Veículos GKModel::vehicles
Modos de Visualização GKModel::viewModes
Estilos de Visualização GKModel::viewStyles

Por fim, o novo objeto deve ser adicionado à pasta:

folder.append( state )

Objetos gráficos devem ser adicionados ao GeoModel. Dentro do GeoModel, os objetos devem ser atribuídos a uma camada. Na maioria dos casos, a camada ativa será usada. Isso é encontrado usando o getActiveLayer() chamada:

(model.getGeoModel().getActiveLayer()).

Por exemplo, se o comando New para criar um detector não existisse (o GKSectionObjectNewCmd é o que deve ser usado para isso), as etapas que precisaríamos seguir para escrever um script que criasse um detector no meio de uma seção seriam: primeiro criar o detector e, em seguida, definir seus parâmetros (nome, faixas e comprimento). Adicioná-lo sobre uma seção (um detector não pode existir por conta própria) e, por fim, adicioná-lo ao GeoModel, colocando-o na mesma camada da seção. Se o script for adicionado ao menu de contexto Section, então a variável target é usado para se referir à seção:

detector = GKSystem.getSystem().newObject( "GKDetector", model )
detector.setName( "A new detector" )
detector.setLanes( 0, 1 )
detector.setLength( 4.5 )
detector.setPosition( target.length2D() / 2.0 )
target.addTopObject( detector )
model.getGeoModel().add( target.getLayer(), detector )


Adicionar script ao Menu de Contexto

Todas as etapas acima para objetos não gráficos e gráficos são tratadas automaticamente ao usar os comandos New.

Destruição de objeto

Os objetos são removidos do modelo em duas etapas:

  1. Obtém o comando de exclusão para o objeto chamando GKObject::getDelCmd()
  2. Executar o comando

Por exemplo:

myObjectToDelete = model.getCatalog().find(104) #retrieve object
if myObjectToDelete!=None:
    cmd = myObjectToDelete.getDelCmd()
    model.getCommander().addCommand(cmd)

Como a classe GKObjectDelCmd é derivada de GKCommand, ela fornece funcionalidade de desfazer. Portanto, para tornar a exclusão permanente (não desfazível), adicione um comando nulo:

model.getCommander().addCommand(None)

Lendo um Arquivo

Após criar um Traffic State, a próxima etapa é definir os fluxos de entrada lendo-os a partir de um arquivo. Este será um arquivo ASCII com as informações organizadas em duas colunas em formato separado por vírgulas. A primeira coluna contém o identificador da seção; a segunda contém o fluxo de entrada.

Primeiro, abra o arquivo e leia-o linha por linha. Em seguida, divida cada linha usando vírgula como separador.

Use o catálogo para procurar a seção usando seu ID. Se, em vez de identificadores, foram usados identificadores externos ou nomes. O método pode ser alterado para fazer referência a estes.

Com a seção e o fluxo, definimos o fluxo no estado de tráfego:

def importState( model, state, fileName ):
for line in open( fileName, "r" ).readlines():
    # Separate the line in columns
    columns = line.split( "," )
    # First column contains the id of the section
    section = model.getCatalog().find(int(columns[0]))
    # Second column contains the flow
    flow = float(columns[1])
    # Set the value if the section is valid
    if section != None:
        state.setEntranceFlow( section, None, flow )

Tratamento de erros

Suponha que o arquivo de entrada tivesse um erro e contivesse um identificador para um centroide em vez de uma seção. O catálogo retornará o objeto com esse identificador – um centroide – e quando setEntranceFlow() é chamado usando esse centroide. O Aimsun Next reportará um erro como mostrado aqui:

Python Error (exceptions.TypeError): argument 1 of GKTrafficState.setEntranceFlow() has an invalid type

Um erro de tipo inválido é gerado, pois a função espera uma seção, mas recebeu um centroide. Observe que o código já se protege de objetos None; None é retornado quando nenhum objeto é encontrado.

Portanto, ao procurar um objeto no catálogo, é aconselhável verificar primeiro se ele foi encontrado e, em segundo lugar, se é do tipo correto usando o seguinte código:

if section != None and section.isA( "GKSection" ):