Exemplo de Script: Criando objetos¶
A script é uma ferramenta eficaz para modificação de dados, mas também pode ser usada para criar novos dados. Este exemplo mostra como importar dados seguindo um exemplo que cria um novo estado de trânsito usando dados de um arquivo externo.
Criação de Objeto¶
Qualquer objeto que deriva de GKObject deve ser criado (a menos que seja indicado especificamente) usando um Comando Novo. Esses comandos criam e inicializam novas referências de objetos, adicionam o objeto à sua camada ou pasta e reduzem o código a ser escrito. Por exemplo:
cmd = GKTurningNewCmd()
cmd.setTurning( origem, destino )
cmd.setUndoable( False )
Este exemplo chama o construtor, define as informações mínimas necessárias para o objeto e define undoable como falso para impedir que o comando novo seja desfeito na interface gráfica.
O novo comando precisa ser incluído no comandante do modelo para garantir a execução instantânea do comando e manter as referências de comando para fins de ação desfazer/refazer:
model.getCommander().addCommand( cmd )
Uma vez que o comando foi executado e queremos acessar o novo objeto, qualquer comando Novo retorna-o do método createdObject():
newTurn = cmd.createdObject()
Se o comando novo para o tipo GK que você está procurando não existir, há uma maneira alternativa de criar objetos que é usando a chamada GKSystem::newObject(). Esta chamada criará um novo objeto, o inicializará e o adicionará ao catálogo do modelo atual.
Criar um novo objeto que deriva de GKObject de qualquer outra maneira pode corromper o modelo atual ou fazer o sistema travar 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() # NUNCA faça isso!!!
Essa chamada instrui o sistema a criar um novo objeto de um tipo particular (um objeto GKMyType neste exemplo) no modelo fornecido. O novo objeto será sem título, portanto, é aconselhável dar-lhe um nome usando o método GKObject::setName():
state.setName( "Novo objeto do meu tipo" )
Organização de Objetos¶
Aimsun Next organiza objetos de duas maneiras, dependendo de seu tipo. Objetos gráficos são organizados em camadas e mostrados nas visões 2D e 3D. Objetos não gráficos são organizados em pastas e mostrados na Janela do Projeto.
Depois de criar um objeto sem usar seu comando Novo, um novo objeto deve ser adicionado a uma camada ou a uma pasta, dependendo se é 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ânsito. 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, esse código procura a pasta usando a chamada GKFolder::findFolder(). Ele busca na pasta raiz do modelo, que é o local normal. Se a pasta não estiver lá, então ela será criada. Como a pasta Estados de Trânsito é uma pasta do sistema, só precisamos passar o nome interno da pasta para o sistema criar 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 Centróides | 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 de Detectores | GKModel::detectorLocations |
Funções | GKModel::functions |
Infraestrutura | GKModel::top::infrastructure |
Tipos de Faixa | GKModel::laneTypes |
Planos de Controle Master | 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 Via | GKModel::roadTypes |
Cenários | GKModel::top::scenarios |
Scripts | GKModel::top::scripts |
Subcaminhos | GKModel::subPaths |
Estrategias | 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 |
Finalmente, 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á utilizada. Isso é encontrado usando a chamada getActiveLayer():
(model.getGeoModel().getActiveLayer()).
Por exemplo, se o comando Novo para criar um detector não existisse (o GKSectionObjectNewCmd é o que deve ser utilizado para isso), os passos que precisaríamos seguir para escrever um script que criasse um detector no meio de uma seção seriam: Primeiro, criar o detector, em seguida, definir seus parâmetros (nome, faixas e comprimento). Adicioná-lo no topo de uma seção (um detector não pode existir por conta própria), e finalmente adicioná-lo ao GeoModel, colocando-o na mesma camada da seção. Se o script for adicionado ao menu de contexto da Seção, então a variável target é usada para se referir à seção:
detector = GKSystem.getSystem().newObject( "GKDetector", model )
detector.setName( "Um novo detector" )
detector.setLanes( 0, 1 )
detector.setLength( 4.5 )
detector.setPosition( target.length2D() / 2.0 )
target.addTopObject( detector )
model.getGeoModel().add( target.getLayer(), detector )
Todos os passos acima para objetos não gráficos e gráficos são automaticamente gerenciados ao usar os comandos Novos.
Destruição de Objetos¶
Objetos são removidos do modelo em duas etapas:
- Obter o comando de deleção para o objeto chamando GKObject::getDelCmd()
- Executar o comando
Por exemplo:
myObjectToDelete = model.getCatalog().find(104) #recuperar objeto
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 deleção permanente (não desmanchável), adicione um comando nulo:
model.getCommander().addCommand(None)
Lendo um Arquivo¶
Depois de criar um Estado de Tráfego, a próxima etapa é definir os fluxos de entrada lendo-os de um arquivo. Este será um arquivo ASCII com as informações organizadas em duas colunas no 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 a vírgula como separador.
Use o catálogo para procurar a seção usando seu ID. Se, em vez de identificadores, identificadores externos ou nomes forem usados, o método pode ser alterado para se referir a esses.
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():
# Separar a linha em colunas
columns = line.split( "," )
# A primeira coluna contém o id da seção
section = model.getCatalog().find(int(columns[0]))
# A segunda coluna contém o fluxo
flow = float(columns[1])
# Definir o valor se a seção for válida
if section != None:
state.setEntranceFlow( section, None, flow )
Tratamento de Erros¶
Suponha que o arquivo de entrada tenha um erro e contenha um identificador para um centróide em vez de uma seção. O catálogo retornará o objeto com aquele identificador – um centróide – e quando setEntranceFlow() for chamado usando aquele centróide. Aimsun Next relatará um erro conforme mostrado aqui:
Erro Python (exceptions.TypeError): argumento 1 de GKTrafficState.setEntranceFlow() tem um tipo inválido
Um erro de tipo inválido é dado, uma vez que a função espera uma seção, mas em vez disso recebeu um centróide. Note que o código já se protege contra 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" ):