{"action":"opened","issue":{"url":"https://api.github.com/repos/openlayers/ol3/issues/4049","labels_url":"https://api.github.com/repos/openlayers/ol3/issues/4049/labels{/name}","comments_url":"https://api.github.com/repos/openlayers/ol3/issues/4049/comments","events_url":"https://api.github.com/repos/openlayers/ol3/issues/4049/events","html_url":"https://github.com/openlayers/ol3/issues/4049","id":103228158,"number":4049,"title":"[ol.geom.*] constructor parameters consistency: positional arguments vs. object","user":{"login":"quentinlampin","id":2759092,"avatar_url":"https://avatars.githubusercontent.com/u/2759092?v=3","gravatar_id":"","url":"https://api.github.com/users/quentinlampin","html_url":"https://github.com/quentinlampin","followers_url":"https://api.github.com/users/quentinlampin/followers","following_url":"https://api.github.com/users/quentinlampin/following{/other_user}","gists_url":"https://api.github.com/users/quentinlampin/gists{/gist_id}","starred_url":"https://api.github.com/users/quentinlampin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/quentinlampin/subscriptions","organizations_url":"https://api.github.com/users/quentinlampin/orgs","repos_url":"https://api.github.com/users/quentinlampin/repos","events_url":"https://api.github.com/users/quentinlampin/events{/privacy}","received_events_url":"https://api.github.com/users/quentinlampin/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-08-26T10:00:39Z","updated_at":"2015-08-26T10:00:39Z","closed_at":null,"body":"Hello there,\r\n\r\nI'm writing a set of angular directives on top of OpenLayers and I'm trying to keep it as D.R.Y as possible, i.e. using a directive factory (illustration at the end). \r\n\r\nWhile Most OpenLayers class constructors accept an object parameter named `options`, geometry constructors use positional arguments. This inconsistency makes it cumbersome to write a generic directive factory, i.e. one that would generate the directives based on the OL \"objects\" relationships, e.g. ol.View requires a center and zoom and depends on an ol.Map, and their constructors.\r\n\r\nWould it be acceptable to make ol.geom.* follow the same convention as the rest  or at least modify the constructor so that it checks the type of the parameter that is passed and handle it accordingly ?\r\n\r\nI will take a look at the code and see if I can manage a PR that implements it.\r\n\r\nIllustration of what I'm trying to achieve: \r\n\r\n```\r\n[...]\r\ndirective: function(manifest) {\r\n        var scope;\r\n        var require;\r\n        var transclude;\r\n        var replace;\r\n        var template;\r\n        var controller;\r\n        var link;\r\n        var model;\r\n\r\n        name = manifest.name;\r\n        scope = {model: '=' + aol.NAMESPACE + 'Model'};\r\n        require = [name];\r\n        transclude = manifest.transclude;\r\n        replace = manifest.replace;\r\n        template = manifest.template;\r\n        model = new manifest.modelConstructor();\r\n\r\n        angular.forEach(model.options, function(value, key) {\r\n            scope[key] = '@' + aol.NAMESPACE + key.charAt(0).toUpperCase() + key.slice(1);\r\n        });\r\n        angular.forEach(manifest.require, function(req) {\r\n            require.push(req);\r\n        });\r\n\r\n        controller = function($scope, $q) {\r\n            var _this = this;\r\n            var deferred_ = $q.defer();\r\n            var callbacks_ = {};\r\n            _this.getPromise = function() {\r\n                return deferred_.promise;\r\n            };\r\n            _this.resolvePromise_ = function(instance) {\r\n                deferred_.resolve(instance);\r\n            };\r\n            _this.setCallbacks_ = function(callbacks) {\r\n                /* exposing instance events */\r\n            };\r\n            angular.forEach(model.options, function(value, key) {\r\n                var optionUpperCasedName = key.charAt(0).toUpperCase() + key.slice(1);\r\n                _this['set' + optionUpperCasedName] = function(value) {\r\n                    $scope[key] = value;\r\n                };\r\n                _this['get' + optionUpperCasedName] = function() {\r\n                    return $scope[key];\r\n                };\r\n            });\r\n        };\r\n        link = function(scope, element, attrs, controllers) {\r\n      \r\n            var instance;\r\n            /* retrieve instance controller and parent controller if needed */\r\n            instanceController = controllers[0];\r\n            if (angular.isString(manifest.parentCtrlMethod) || angular.isString(manifest.parentInstMethod)) {\r\n               /* retrieving the parent Controller*/\r\n               parentController = [...] /*curated to shrink the size of the post*/\r\n            }\r\n            /**\r\n             *  in case ol-model is not provided, i.e. scope.model is undefined, build an empty\r\n             *  model whose values will be supplanted by other bound values or included directives\r\n             *  via parentInstMethod.\r\n             */\r\n            if (!angular.isObject(scope.model)) {\r\n                scope.model = new manifest.modelConstructor();\r\n                console.log(manifest.name + ' initializing model: ', scope.model);\r\n            }\r\n            angular.forEach(scope.model.options, function(value, key) {\r\n                if (angular.isDefined(scope[key]) && !angular.isDefined(value)) {\r\n                    scope.model.options[key] = scope[key];\r\n                    console.log(manifest.name + ' overriding ' + key + ': ', scope.model.options[key]);\r\n                }\r\n            });\r\n            /* HERE: it gets interesting! */\r\n            instance = new manifest.constructor(scope.model.options); \r\n            instanceController.resolvePromise_(instance);\r\n\r\n            /* if a parentCtrlMethod is provided, call it right now */\r\n            if (angular.isObject(parentController) && angular.isString(manifest.parentCtrlMethod)) {\r\n                parentController[manifest.parentCtrlMethod](instance);\r\n            }\r\n            /**\r\n             * if a parentInstMethod is provided, get a promise on the parent instance then\r\n             * call the parentInstMethod.\r\n             * */\r\n            if (angular.isObject(parentController) && angular.isString(manifest.parentInstMethod)) {\r\n                parentController.getPromise().then(function(parentInstance) {\r\n                    parentInstance[manifest.parentInstMethod](instance);\r\n                });\r\n            }\r\n        };\r\n```\r\nExamples of directive manifests: \r\n```\r\n{\r\n        name: 'aolView',\r\n        require: ['^aolMap'],\r\n        transclude: false,\r\n        replace: false,\r\n        constructor: ol.View,\r\n        modelConstructor: aol.service.View,\r\n        parentCtrlMethod: 'setView',\r\n        parentInstMethod: undefined,\r\n        preInstFunction: undefined,\r\n        postInstFunction: undefined\r\n    }\r\n```\r\n\r\n```\r\n{\r\n            name: 'aolLayerVector',\r\n            require: ['^aolMap'],\r\n            transclude: false,\r\n            replace: true,\r\n            constructor: ol.layer.Vector,\r\n            modelConstructor: aol.service.layer.Vector,\r\n            parentCtrlMethod: undefined,\r\n            parentInstMethod: 'addLayer',\r\n            preInstFunction: undefined,\r\n            postInstFunction: undefined\r\n}\r\n```\r\n\r\n\r\n"}}