void configure(simulator::Simulation& simulation, const config::Configuration& config) override { const float px = 0.3; const auto filepath = config.buildFilePath(config.get("filename")); // SVG image NSVGimage* image = nsvgParseFromFile(filepath.string().c_str(), "px", 96); if (!image) throw RuntimeException("Cannot parse SVG"); auto obstacle = simulation.buildObject("obstacle.Polygon"); auto& shapes = obstacle->getMutableShapes(); const auto size = Vector<float>(image->width, image->height); // Coordinate scale const auto scale = simulation.getWorldSize() / size; const auto offset = size * 0.5; // Foreach shapes for (NSVGshape* shape = image->shapes; shape != nullptr; shape = shape->next) { ShapeEdges oShape; // Foreach paths for (NSVGpath* path = shape->paths; path != nullptr; path = path->next) { storePath([&oShape, &offset, &scale] (Vector<float> vec) { const auto v = (vec - offset) * scale * Vector<float>(1, -1); if (oShape.edges.empty() || oShape.edges.back().distanceSquared(v).value() > 0.05) { oShape.edges.push_back(v); Log::debug(v.getX(), "; ", v.getY()); } }, path, px * 1.5); } shapes.push_back(std::move(oShape)); } obstacle->initShapes(); }
void Program::loadConfig(simulator::Simulation& simulation, const config::Configuration& config) { if (config.has("filename")) { m_source.initFile(config.get("filename")); } else { m_source.initSource(config.getContent()); } // Store function pointer m_call = m_source.getFunction("__call__"); // Fallback if (!m_call) m_call = m_source.getFunction("call"); if (!m_call) throw InvalidArgumentException("Python program doesn't have '__call__' or 'call' function"); }
void Simulation::configure(const config::Configuration& config) { // Resize world { auto size = config.get<SizeVector>("world-size"); if (size.getWidth() == Zero || size.getHeight() == Zero) throw config::Exception("Width or height is zero!"); setWorldSize(size); } // Time step setTimeStep(config.get<units::Time>("dt")); if (config.has("length-coefficient")) { m_converter.setLengthCoefficient(config.get<RealType>("length-coefficient")); } // Set gravity setGravity(config.get("gravity", getGravity())); // Number of iterations setIterations(config.get("iterations", getIterations())); // Background color setBackgroundColor(config.get("background", getBackgroundColor())); #if CONFIG_RENDER_TEXT_ENABLE setFontColor(config.get("text-color", getBackgroundColor().inverted())); #endif #if CONFIG_RENDER_TEXT_ENABLE setFontSize(config.get("text-size", getFontSize())); #endif #if CONFIG_RENDER_TEXT_ENABLE setSimulationTimeRender(config.get("show-simulation-time", isSimulationTimeRender())); #endif #ifdef CECE_ENABLE_RENDER setVisualized(config.get("visualized", isVisualized())); #endif // Parse plugins for (auto&& pluginConfig : config.getConfigurations("plugin")) { // Returns valid pointer or throws an exception requirePlugin(pluginConfig.get("name"))->configure(*this, pluginConfig); } // Parse parameters for (auto&& parameterConfig : config.getConfigurations("parameter")) { setParameter(parameterConfig.get("name"), units::parse(parameterConfig.get("value"))); } // Register user types for (auto&& typeConfig : config.getConfigurations("type")) { addObjectType({ typeConfig.get("name"), typeConfig.get("base"), typeConfig.toMemory() }); } // Parse init for (auto&& initConfig : config.getConfigurations("init")) { const String typeName = initConfig.has("language") ? initConfig.get("language") : initConfig.get("type"); auto initializer = getPluginContext().createInitializer(typeName); if (initializer) { // Configure initializer initializer->loadConfig(*this, initConfig); // Register initializer addInitializer(std::move(initializer)); } } // Parse modules for (auto&& moduleConfig : config.getConfigurations("module")) { // Get name auto name = moduleConfig.get("name"); if (hasModule(name)) continue; const String typeName = moduleConfig.has("language") ? moduleConfig.get("language") : moduleConfig.has("type") ? moduleConfig.get("type") : name ; auto module = getPluginContext().createModule(typeName, *this); if (module) { module->loadConfig(*this, moduleConfig); addModule(std::move(name), std::move(module)); } } // Parse programs for (auto&& programConfig : config.getConfigurations("program")) { const String typeName = programConfig.has("language") ? programConfig.get("language") : programConfig.get("type"); auto program = getPluginContext().createProgram(typeName); if (program) { // Configure program program->loadConfig(*this, programConfig); // Register program addProgram(programConfig.get("name"), std::move(program)); } } // Parse objects for (auto&& objectConfig : config.getConfigurations("object")) { // Create object auto object = buildObject( objectConfig.get("class"), objectConfig.get("type", object::Object::Type::Dynamic) ); if (object) object->configure(objectConfig, *this); } if (config.has("data-out-objects-filename")) { m_dataOutObjects = makeUnique<OutFileStream>(config.get("data-out-objects-filename")); *m_dataOutObjects << "iteration;totalTime;id;typeName;posX;posY;velX;velY\n"; } }