AU Class
AU Class
class - AU

Dynamo for Software Developers: C#, Python, and More—Workshop - Part 1 of 4

Share this class
Search for keywords in videos, presentation slides and handouts:

Description

Are the out of the box nodes in Dynamo not enough? Ever felt like you wanted a way to customize the Dynamo experience for not only your team but your clients? Then come join us for the Dynamo for Software Developers workshop! You’ll learn how to extend Dynamo by using code to develop on top of it. We will teach you when and how to use different development tools to build your own nodes using C# and Python. We will even teach you how to manipulate the Dynamo experience using extensions to build custom UI or interactions. Please note: This class is targeted at software developers with experience writing source code: We will not be covering entry level Dynamo. If you are a beginner or have never used Dynamo before consider attending the Dynamo Beginner session held during the main AU conference or invest in beginner training ahead of time.Participants will be paired at provided computers (1 computer for 2 participants). Includes the Tuesday AU General Session. Don’t forget to add the AU Full Conference Pass and sign up for the Wednesday evening DynaLightning talks and party.

Key Learnings

  • Learn when and how to Use Python in Dynamo
  • Learn C# basics and how to use the Revit API in Dynamo
  • Learn how to build your own zero-touch, read-only nodes using C#
  • Learn how to control and manipulate the Dynamo UI and interactions using Extensions

Speakers_few

  • Фотография профиля Thomas Mahon
    Thomas Mahon
    Founding Director of Bimorph Consultancy, Software Engineer and computational design/BIM specialist. Creator of bimorphNodes. Authorized Autodesk Developer. Bimorph is a digital engineering firm transforming the way Architects, Engineers and Building Contractors realise buildings
  • Racel Williams
    Racel Williams is an AI Development Manager for the Building, Infrastructure, and Design Group. She has a B.S. in Marketing from the University of Florida and Master’s degrees in Architecture and Human-Computer Interaction from Georgia Tech where her research focus was Augmented Reality and Tangible Interaction. In 2013, she joined Autodesk as an intern where she developed a mobile AR prototype for in-situ annotation and visualization. After becoming full-time, she went on to become the UX Designer for FormIt, Dynamo, and other related projects. Later, she became the Product Owner of Dynamo and led the development team in shipping multiple versions of Dynamo. She has given numerous talks and workshops on Dynamo around the world. Currently, she is now helping Autodesk shape how the company will integrate AI and Machine Learning in AEC workflows by leading a team of ML researchers and engineers to build the next generation of AEC tools.
Video Player is loading.
Current Time 0:00
Duration 1:44:11
Loaded: 0.16%
Stream Type LIVE
Remaining Time 1:44:11
 
1x
  • Chapters
  • descriptions off, selected
  • en (Main), selected
Transcript

PRESENTER 1: Cool. So I'm going to be real quick so that I can hand you over to Tom and start the first session, which is on Python. So a real quick summary of what we're going to look at today so you guys know what to expect. And if the clicker works-- it's plugged into yours already. I'm just going to stand here.

So today, we are going to be pretending that we are Spacework, a company that provides office space. And what we are going to be trying to do by the end of the day is subdivide the room with partitions, create a desk arrangement, and measure its efficiency, place desks in a Revit room, and then calculate the escape routes. And then finally, extend Dynamo with an extension that can make this kind of workflow easier. That's a lot of stuff to pack into a day, and it's stuff that we would have to do if we wanted to kind of be a very efficient office space provider.

So to do that, we've mapped these tasks to sessions. And without kind of going into too much detail, they're about Python, C#, Zero Touch nodes, and extensions. So as a very, very brief intro before we go into the first session, we wanted to let you know a bit about development for Dynamo in general. And we saw, we go all the way from Python to extensions and host integrations, like into Alias or Civil.

And this is a graph that kind of shows the relative complexity and difficulty of making one of these Dynamo things, whether a zero touch package or an extension, and the actual power they have. So starting off at the bottom, we have custom nodes, which are very easy to make, but also very kind of limited. You go up to zero touch and Python nodes, which we're going to have a look at. And then extensions are even more powerful, but they're a bit harder to make. And then right at the top, the most powerful, but also the very hardest to make are host integrations, like Dynamo Revit, for example. There's a lot of work that goes into that.

You should all be kind of familiar with how these things look like, but just as a refresher, custom nodes look like they're going back in time. They have this kind of nice fading out icon on the Dynamo canvas. Design scripts nodes are kind of code block nodes. So I'm sure you've seen those before.

Python nodes just [INAUDIBLE] Python script. And if you edit the script, you get a nice kind of visual interface to edit your code there. And then zero touch nodes look exactly like any other nodes, because that's what most Dynamo nodes actually are. So those you write with code, and we import them into Dynamo.

And finally, the last type of development we can do for Dynamo in terms of nodes are the UI nodes. These are nodes that have custom UI on them, so things like the color range node, or things like the dropdown lists that you have in Dynamo Revit. Those are custom UI nodes, which are relatively hard to make because of this thing called abstract syntax tree, which I won't go too far into, but you have to kind of start knowing these things when you go down the UI nodes, which isn't very nice. So we're not going to do them today. We're going to do other, more fun stuff.

So putting it all together, going from left to right, kind of from easy to harder, we have custom nodes, code blocks, Python scripts, zero touch, UI nodes, and then hovering somewhere behind this are our extensions. How many of you are familiar with extensions? Not that many. So maybe I should introduce what they are.

They are kind of a new addition to Dynamo where you can extend Dynamo itself. So rather than write code to make a node, we're putting a plug-in into Dynamo, where we can control Dynamo itself, and the graph, and the user interface. So you can do things like, I think this is DynaMonito. Yes. By Andreas Dieckmann. He's also made Clockwork, where you can zoom into error nodes or all of the nodes that have warnings. You can really speed up your Dynamo offering.

Other examples are-- shameless plug-- this Dyno server extension I made, which lets you remotely control Dynamo from a web browser. So I've put a little server inside Dynamo. And I could be halfway around the globe and be sending commands to my Dynamo application. Oh, run this graph, or clear that workspace and load a new one. So very powerful. You can think of lots of use cases for this.

Crash course into development. So now we are going to hand it over to Tom for the first session on Python. I don't think you need that. Do you? Oh. Disconnected the--

Whilst Tom is plugging in, if you guys have questions at any point during the workshop, raise your hand. Either me, Racelle, or Keith, or Erin will come and kind of help you out. Also, if you have a general question, just raise your hand and shout it out.

TOM: Good. Thank you. So yeah, good morning, everyone. And welcome to AU Vegas 2019. As you know, I'm Tom. I'll just introduce myself again very, very quickly.

So I run Biomorph. It's a digital engineering company. And I typically develop apps for either Dynamo or Revit. [INAUDIBLE] apps for organizations thta are in construction that want to automate their processes. And it can range from, say, applying comp sci techniques, all the way through to comp design, comp bim. And really, a lot of this has been kind of informed through my career as an architect. And I kind of migrate into doing what I do today, which is basically program every single day.

So I've got a lot of experience using comp design tools like Dynamo. Also other applications like [INAUDIBLE] Components for many years. And I've just got a real passion for it. So hopefully by the end of today, both [INAUDIBLE] and I will be able to kind of share some of our knowledge and some of our kind of pro dev techniques, and really help you guys to kind of kick start your kind of journey into programming.

Because that is actually what it is. You never stop learning. And it's incredibly rewarding. So I would encourage all of you, even if today you find it a bit difficult. Because it can be very difficult. You don't learn programming overnight. It takes a long time to perfect. It's like really any kind of discipline. But yeah, stay focused, because it is really an amazing skill to have, certainly with within construction. And it can really augment what you do on a day to day basis.

So to kick things off then, we're going to start with Python. Python itself is actually a very easy language to learn. Part of the reason why is the syntaxes are very clean. It's very readable. Python, it's almost like reading English. That's how the syntax actually appears. And it's a very powerful language.

It's generally pretty quick so when it comes to execution. Although, C# actually gives you a performance edge. It depends on what you're trying to do. So today, in this first session, what I'm going to introduce you to are some professional techniques for using Python within Dynamo. It uses a variant of Python called Iron Python. And the only difference being it can read and understand something known as .net libraries.

So, for example, the Revit API is a library. And in that library there are all methods which you can call. And that library is built on .net. So if you're just using ordinary Python, it can't read that library. If you're using Iron Python, it can, which is why Dynamo uses it.

But really, there's no actual major difference in the languages. So the first exercise then, which I'm going to get all of you to do, is, first of all, configure something called Visual Studio Code, which is just an IDE. So that is an Integrated Development Environment. And generally, that's what programmers use to help structure their programs. So when they're writing their code and they're organizing all of their various different documents, they'll use an IDE. And a really, really powerful and useful IDE for Iron Python is Visual Studio Code.

So we'll get that set up in a second. It's very easy to do. I'll also introduce you to something called a boilerplate, and also teach you some little shortcuts, which all good developers do. And then we're actually going to start doing some basic code, and then gradually kind of ramp up, throughout today, the exercises.

So they're gradually going to get more and more kind of interesting and more complicated. But all the data sets are on GitHub. They're all freely available. So if you do find that perhaps you're struggling, or if maybe you just want to sit back and watch, by all means, do that, cause you can always redo all these exercises in your own time, and drill into it and understand it. And, of course, if you've got any questions, ask Radu, myself, or any of the other guys from Dynamo, or on the forum as well. That's really active as well.

OK. So first of all, the first exercise. It's going to be really straightforward. All we're going to do is we're going to learn about some built in functions within Python. We're going to simply select some desks in our sample project file. And we're just going to get our Python script to tell us how many desks we've selected.

So you notice I'm just using some out of the box nodes here. If I go ahead and select some desks, it's going to tell me how many there are. Dead simple. And really the purpose of this first exercise is to actually introduce you to some of the core concepts, and kind of like a foundational understanding of how Python is implemented into Dynamo just to kind of get you guys kickstarted.

So without further ado then, within the data set, if you can just make sure that you've got this file open. So it's the AU 2019 S1 Python file. You'll find that if you just log into the cloud environment, go to the Dynamo For Software Developers folder. Inside Python, you'll find a file called AU 2019 S1 Python. And if you just open up that file.

AUDIENCE: Can you run through the file again?

TOM: Oh, yeah. Sure. So if you open up all the sample files for our workshop, you'll find S1 Python, which is what we're doing now. So this is the first session. S2 C# Fundamentals is what we're going to be doing for the second session. That'll be Radu. Then we'll do S3 Zero Touch in the afternoon. That'll be me. And then finally, we're doing extensions, which is S4. And that's what Radu will be doing.

So inside the first folder, the S1 Python folder, you'll find the complete data set, which you guys don't need to touch, because that is only if you just want to, perhaps, sit back.

PRESENTER 1: Two seconds, Tom. So if you're struggling to find where the folder is, there should be a shortcut on the desktop called Data Sets. If you double click that, it'll launch you into a very long list of folders. Look for something starting with DW. And then it says Dynamo For Software Developers.

TOM: Thanks.

PRESENTER 1: I feel like I'm struggling.

TOM: OK? OK. So if you're already there--

PRESENTER 1: [INAUDIBLE]

TOM: Yeah. That's what I'm going to do. Yeah. Thanks.

AUDIENCE: [INAUDIBLE]. There are two folders [INAUDIBLE].

PRESENTER 1: If there's two folders, pick the one that's shorter. Not the one that says C# Python stuff. The one that just says Dynamo for Software Development.

TOM: Yeah.

OK. So if everyone is there, if you can also launch Dynamo. And inside the same location where you opened up the Revit file, you'll find the folder called Start Data Set. And in that folder, there's something called the boilerplate, which we'll use in just a second. But if you just go to the DYN folder, and if you just open up Exercise One, DYN. And you should see a graph that looks like this.

OK. So this graph then, you can see that there's a Python node already there, which is going to be reading our code, which we're about to write. There's actually two different Python nodes which you can use within Dynamo, which I'm sure a lot of you are probably already aware of. There's the ordinary Python script, and there's the Python script from string.

We're going to be using the Python script from string. Reason being, that's actually how we can get that node to read our Python files, which we're going to be developing within Visual Studio Code. You can, of course, just use the ordinary Python script node. And if you do want to use that, you can double click on it. And then from there, modify your code through the editor.

But generally, this is actually not as flexible when it comes to actually developing your code. So there's the first pro tip. That's why we would use Visual Studio Code, because what we can do is we can actually create a range of different Python files. They're easy to then distribute. And we can also add a lot of other useful files inside our IDE, which we can always reuse, which we're actually going to be doing in just a second. And I'll show you that as soon as we get on to that step.

So to actually explain then what we're doing here, we're going to be browsing to a file which contains Python code. That file's going to be read, converted into a string, and then it's going to be passed into our Python script from string node. And that's going to execute a process for us.

So if you jump into Visual Studio Code, what I'd like you to do is, perhaps on your desktops, create a new folder. And we're can just call that folder AU Vegas 2019. And within that folder perhaps create another folder. And just call that S1 Python.

So I've already got my-- or I'll create it now. So yeah. Just a new folder. And we'll just call that AU Vegas 2019. And in that folder, we're just going to call this one S1 Python.

So this folder, S1 Python, is where we're going to store all of our code files which we're going to be developing today. And within Visual Studio Code, what we're going to do is we're just going to reference this folder by going File at the top there, and then Open Folder. And we just want to browse to this location, and then select that folder. And this just tells Visual Studio Code that the folder which we're about to open is going to contain all of our code.

OK. Right. So one of the first things which is really useful to have at your disposal whenever it comes to developing within Python is something called boilerplate.

PRESENTER 1: Tom, can you repeat again from making the file in the folder.

TOM: Yeah. Sure. So on your desktop, just create a folder called AU Vegas 2019. That's just going to be our folder for today where we can just develop all of our code.

So on your desktop, once you've created that folder, create another folder inside AU Vegas 2019, and just call that one S1 Python. And once you've done that, in Visual Studio Code, you just want to do File, and then Open Folder. And then just select that folder there. So S1 Python.

And when you do select that folder, and when you actually find it, just click on the folder. Do Select Folder. And then that will then load it into the Explorer on the left. So you'll know that you've done it correctly, because you'll see S1 Python in the dropdown there.

All right. Is that OK? OK. So this concept then of a boilerplate. All a boilerplate is is it's essentially reusable code. It's a term used mainly in programming. And that reusable code, for our purposes, basically contains a range of different import statements, which I'll explain in a second. Which basically just loads in things like the Revit API into the Python interpreter. Cause the interpreter's what actually reads your code and executes on your behalf all the instructions which you've written.

And you need to tell the interpreter where to actually look to make certain commands, or [INAUDIBLE] certain commands. So, for example, if you want to build a wall, programmatically use the Revit API, you can't just make a call to API and expect Python to know where to look, because that call could have come from anywhere. So in the import statements within the boilerplate-- and I'll just show you that now-- you'll actually see a reference to the Revit API. And that's what you can see up here.

So you've got a range of numbers that are being imported, proto geometry, which is from Dynamo, Revit nodes, also from Dynamo. And then here you've got Revit API. And all you're doing there is you're just telling the Python interpreter to load in those libraries. And then you can make calls to those libraries to do really cool stuff.

So that's what the import statements are for. Generally, with the boilerplate you don't even need to learn these things. Literally just have the boilerplate at your disposal. And then every time you want to start writing a new Python code, you just copy and paste your boilerplate into a new PY file, and then you're good to go, which is what we're going to do now.

So inside Visual Studio then, if you go back to your S1 folder, what I'd like you to do is from the data set you'll find there is a file aptly named Boilerplate. What I'd like you to do is just drag it into here. And that's going to copy the boilerplate for you. So all I've done is just found a file from the data set, and then just drag it over into the Explorer. And that's going to create a copy of the boilerplate for you. And now you can view it within Visual Studio Code.

And the boilerplate should just be left as is. And you should always just copy it into a new file, which is, as I said, what we're about to do in just a second. OK. Yes. OK. Yeah, thanks.

OK. Next step then, we're actually going to start writing some code. Now, this is the technique which you need to learn. Whenever it comes to writing any Python code, you should always just copy that boilerplate. So what I'd like you to do is where you've got your AU Vegas 2019 and you've got the option for a new file, click on that. And inside here we're just going to call this Exercise1.py. So you just need to tell Visual Studio Code what kind of code file that is. And for Python, it always uses the PY file extension.

So this is actually just a raw Python script. And we're going to be loading that into Dynamo. And that's what our Python from string is actually going to be reading and executing. So as soon as you've done that, you'll notice that you've just got like a blank canvas. And as already mentioned, the boilerplate, go back to it just by clicking on it within the Explorer. We just do Control All, Control-C. Go back to Exercise1.py, and just paste it in there.

So that step that I just took of copying the boilerplate and pasting it into an new PY file is the step that all of you should be taking every time you want to start writing any bit of Python code. Because it just basically configures that script so it's compatible with Dynamo. And then it's going to be reading all the various different libraries, which you're typically going to be calling from when it comes to writing your code.

And don't forget, the boilerplate only contains a few libraries. There's nothing stopping you from also referencing any other library out there which you can think of. I mean, you could even, in theory, develop your own set of, say, zero touch nodes, which are going to be compiled libraries, which, as you know, you're going to be learning today. And even import that into your Python scripts.

I mean, as an example, I've developed Bimorph nodes for Dynamo. That's a compiled library written in C#. And on the forum, sometimes users want to be able to write in Python and make calls to Bimoprh nodes by importing the library. And they can do that very easily using this technique.

AUDIENCE: [INAUDIBLE]

TOM: Ah. OK. Sure. OK. I'll let everyone just catch up a bit as well. So while you're catching up, what I will do is maybe just kind of give a very, very kind of brief, I guess, overview of what these import statements are actually doing.

They are literally just finding a DLL library on your computer. That library will contain a bunch of instructions to do stuff. So let's just take the Revit API as an example. There'll be methods inside the API that enable us to build a wall, or place a family instance. And those libraries need to be imported into your Python interpreter. And when it's in the interpreter, you can then tell that interpreter to go and do something for you.

So you might write an instruction saying, place a desk instance in my model. And to do that, you need to import the library. Yeah.

AUDIENCE: [INAUDIBLE]

TOM: OK. Can I just have a raise of hands as to where everyone is at? First of all, has everyone managed to get their folder into Visual Studio Code?

OK. Does anyone want to catch up now? Cause if you do, then [INAUDIBLE], go ahead and do that now.

Has everyone copied the boilerplate into their S1 folder? OK. Cool. And has everyone created their brand new PY file called Exercise1 and copied the boilerplate into there?

OK. Good. All right. Is anyone--

AUDIENCE: [INAUDIBLE]

TOM: That's just the folder. This one here. So you've got the S1 folder, and then these two files here. Yeah.

AUDIENCE: Tom, can you zoom in [INAUDIBLE].

TOM: Yeah. I can't zoom in for some reason. It's not allowing me to do it. I don't know why. Ah, there we go. Is that better?

AUDIENCE: [INAUDIBLE]

TOM: More?

PRESENTER 3: OK. If anybody's not at this point, can you raise your hand and we'll come and help you? OK.

TOM: OK.

[INTERPOSING VOICES]

TOM: Yeah. Sure. So just to clarify where that folder should be, on your desktop, well, just create a folder called AU Vegas 2019. Inside that folder, create another folder called S1 Python. My folders are a little bit in disarray on my desktop. But yeah, AU Vegas 2019. And then a new folder in there called S1 Python. So your folder should look like this.

What's the status, [INAUDIBLE]? Am I going too fast?

[LAUGHS]

[INTERPOSING VOICES]

TOM: OK.

PRESENTER 1: Particularly this.

TOM: Yeah. OK. All right. Should I give everyone two more minutes? Should I give everyone two more minutes, or should I carry on?

PRESENTER 1: Like one minute and [INAUDIBLE].

TOM: Yeah. All right.

You can if you want. It actually makes no difference. Yeah.

PRESENTER 1: Anyone else need help to get to this point? No? We're good. All right.

PRESENTER 3: Wait.

TOM: Oh, right, it is in the corner over there.

PRESENTER 1: One more. All right. Yeah.

PRESENTER 3: [INAUDIBLE]

TOM: Yeah.

PRESENTER 3: [INAUDIBLE]. This guy is asking me [INAUDIBLE].

TOM: Yeah.

PRESENTER 3: So what was he supposed to do? He was supposed to make a folder on the desktop.

TOM: Yeah.

PRESENTER 3: And then do what?

TOM: And just call it AU Vegas.

PRESENTER 3: OK.

TOM: And then inside there, another folder called S1 Python.

PRESENTER 3: Yeah.

TOM: And then what I want you to do is go File, Open Folder.

PRESENTER 3: Yeah.

TOM: And then browse that location.

PRESENTER 3: OK. Yeah.

TOM: Find the folder. And then Set Folder.

PRESENTER 3: And then where does he get the boilerplate from?

TOM: The data set.

PRESENTER 3: OK. And the data set is?

TOM: From the set frame.

PRESENTER 3: Yeah.

TOM: So if he goes to the data set, it would look like this. Dynamo for Developers. S1 Python. There.

PRESENTER 3: And he just drags it.

TOM: Yeah.

PRESENTER 3: Got it. OK.

TOM: Can I turn up here?

PRESENTER 3: I think it has to be on the-- just try to talk loud, as loud as you can.

TOM: I will try and bellow. I'll just start shouting. OK.

PRESENTER 3: Try maybe recalculating your act [INAUDIBLE].

TOM: OK. OK. I think everyone is kind of up to where we are now. So just to do a quick recap then, we've created a brand new folder called S1 Python. Inside there we're going to be developing all of our Python code. And in that folder, you should have your boilerplate, which we've copied from the data set. And that boilerplate is kind of your Swiss army knife. It contains all of the various bits of code which you need to get you started writing Python code.

And by the way, part of the reason why I'm not going to drill into any detail about the import statements is-- here's another tip-- if there's [INAUDIBLE] disposal, which you can reuse them, all good developers do this. And part of the reason why is because actually it enables you as developers to focus on actually solving a problem.

So when it comes to this boilerplate, I'm not joking. I don't even think about it. I copy it, paste it, and then I start writing my code. I just don't want to even think about it. And all good developers do this. So these are kind of skills which you should learn.

That's not to say be completely ignorant of all these things. It's still important to understand what all of that syntax actually means. But just in terms of getting started, I would recommend that you focus more on actually solving a problem and making progress, rather than, I guess, getting bogged down by all of the nitty gritty details about programming language, because they're vast, and you might find that actually you just lose interest, because it gets boring. Don't do that. Just get into coding. And then as time goes by, learn what, say, more of the nuances of the language actually mean as you start developing as a developer.

OK. So if we're here then, you should have your Exercise1.py file inside your Visual Studio project. And you've copied the boilerplate ever, so we're actually good to go.

Now, this first exercise, as you know, is very, very straightforward. All we're going to be doing is getting our Python script to count the number of desks for us. It's dead easy. And the purpose of this exercise is more just to show you a few things.

So first thing's first, what we're going to be doing is selecting a bunch of desks using an out of the box select model elements node. And from this node we're going to be selecting some desks. That's going to be input into our Python script. And then our Python script is going to tell us how many of those desks there are. So it's dead simple. And this is more just to convey some of the other concepts, which you're going to need to understand for passing data into your Python script, and also passing data out of your Python script as well.

So how this actually works then. Since we know what our inputs are going to be-- it's just going to be some desks-- what I'd like you to do is to where you've got this command line here in your boilerplate, uncomment it. And to uncomment in Python you just remove the hash. So if you want to write a comment in Python, you just type a hash and start typing a comment.

Your interpreter will never ever attempt to execute anything which is preceded by a hash. So it is just a comment. It's for you as a developer just to add some additional commentary to your code, which you can do if it's necessary to do so.

So we're going to declare our first variable. There's actually already a kind of temporary variable declared for you. It's just called T. And all good developers always use descriptive phraseology for their variables. And a variable [INAUDIBLE], by the way, is just a container.

When you declare a variable, you could put anything you want into that variable. And to actually put something in it, you use the assignment operator, which is just the equals sign. So you just do my variable equals, and then any object you like.

And to get a bit techy with you, because I am a bit of a tech head, but I think it's worthwhile just mentioning what that is actually doing inside your computer is actually allocating memory on your machine. And in that memory address, whatever object you've assigned to that variable gets put in there and stored on memory.

And I think the reason why it's worthwhile saying that is just to help you guys actually understand behind the scenes what's happening here. I mean, really you don't need to know that. But I think it's useful just to be aware of, as you're typing code, what is actually doing? And it is doing something. And that's actually what it's doing.

So a variable, it just allocates some memory. And in that memory you can store objects into it. That's literally all a variable is. So just imagine a bit like a container. That's what a variable is.

But we should be descriptive. So since we know the input into our Python script is going to be a collection of desks, then really what we should call this then is desks, cause it's meaningful. Now we know what that is.

Another pro tip, try to avoid abbreviations unless it's a variable or node abbreviation. Min and max. Doc I'm not so keen on, but most people know doc means document within Revit. The reason why you shouldn't abbreviate, and the reason why you should be very descriptive with your naming variables is because your code then reads almost like a paragraph. It's then human readable. If anyone else reads your code, they understand it. If in a few months time, your manager says, ah, that great script, can we just update it? And you're rereading your own code, and you've just use meaningless names everywhere, you're going to have to unpick your entire code line by line to work out what it was doing just to be able to make the change that your manager's asking you to do.

So a pro tip is always be descriptive with your variable names. I would actually say probably the single biggest barrier for people that are just getting into developing is poor naming convention. That is one of the biggest barriers. So don't do it.

Always be descriptive. Don't go too over the top, like trying to be kind of pertinent and concise with your naming. And this technique is true no matter what language you're using, whether it's C#, Python, I mean, you name it. That's actually, I would say, one of the single most important things you should learn. Always be descriptive.

We also camel case as well. So camel casing just means that when you declare your variable name, say we were to call this desk list or something, then every new word that we put inside that variable name should be capitalized. That's why it's called camel casing. Variables always start with lowercase. So these are some well-known kind of standards.

They're not enforced by the interpreter or the language we're using. They're actually, ultimately, down to you as a developer to make sure that you adhere to these standards. But these are widely known standards which you should adhere to. And I guess one last comment. You can't start a variable with a number in C# or Python. So it has always got to start with a letter.

OK. So we create our variable called desks. We use our equals assignment to assign something to it. And what we're going to assign to it, we can actually get rid of the unwrap element, because we'll explore that in a few of the other exercises later. But we're just going to assign to it this weird word called in, followed by some square brackets with a number in the middle of it. And this will all make sense in just a second.

So if you've done that, then you've actually already configured your Python script to accept an input from Dynamo. And so what does that actually mean? First of all, in is a variable, just like desks. It's just a bit of memory which has been allocated in your machine. And it's going to store something.

And the in variable name within Python is actually Dynamo specific. So it's not some special keyword in Python. It's actually a configuration of Python within Dynamo. And the in variable is literally just a list. And that list can store a collection of any object you'd like within Python. And you'll notice that on your Python node, if we just go back to our graph, it's got a bunch of input ports which have, funnily enough, the word in, followed by square brackets, and then an integer or a number in the square brackets.

So just to get a bit more techy then and explain what this actually means, a list, as you know, is a collection of objects. So you can store an unlimited number of-- well, not unlimited. It depends on how big your computer's memory is, but it stores an unlimited number of elements or entities.

And when it comes to actually selecting elements out of that list-- so imagine, the best way to kind of visualize a list, everyone is familiar with Excel. If you visualize the first row in Excel, each row has a cell, and in that cell you can put what you like in there, a number, a date, even an image, that actually represents a list. So inside each cell you can put something inside each slot. And in each slot in Excel it's called a reference.

And the same is true within programming languages. And it's actually very simple to understand. And this is true for actually any language which you can use as far as I'm aware of. That slot is indexed. And the index always starts from zero.

So, for example, if you have a list of inputs into a Python script stored inside that in variable, the very first item in that list is what you connect into your node. That's the first item. So if we want to grab that first item, we index the list, which is always using square bracket notation. And inside the square brackets, we always have to input an integer, which is an index.

So again, we can either use Excel as an analogy, or even like a library. Imagine if you go to a library and you want to find a book, that book's got a reference number. And if you want to locate that book you have to go to the right shelf. And then you find the number of the book, and you can get the book off the shelf. That is the concept of indexing a list. It's exactly the same.

Just remember that it always starts from zero. So if you declare your own list, first index is zero. And it just increments sequentially. And all of this is done on your behalf by the interpreter, and by the language which you're using. So you do not need to specify an index. Just remember that it starts from zero, and if you want to index a list, it's always square brackets. And the syntax is always the variable name. And it's immediately preceded by the square brackets.

So if we just check this out then, we've got the in variable, which is Dynamo specific. It's just a list. And we want to say, OK, give us whatever you've got at index zero, so the first item in the list, and assign it to desks.

So what's happening back in Dynamo then, if you connect your [INAUDIBLE] elements into the first index--

PRESENTER 1: [INAUDIBLE]

TOM: OK. Yeah. It's all right. Yeah. So sorry, Radu was just saying that not everyone's opened up exercise one yet inside Dynamo.

PRESENTER 1: [INAUDIBLE]

TOM: Ah. Yeah. OK. I've not got to that step yet. OK. So yeah. Just going back to our script then.

So yeah. You can see what's happening hopefully when we actually just compare the two side by side. We're connecting our [INAUDIBLE] elements into the first input port of our Python script node. And our in variable is basically capturing that input. And it's placing it at the first index in the in list.

And so them back in our Python code all we're doing is we're giving that in variable, and the first item in that list a meaningful name. In theory, we could actually just use in, and then index that first item throughout our entire code base. But that would not only be bad programming, because it's ambiguous. Like what does index 0 actually mean? Like it's got no meaning in our code. And also, it would be quite cumbersome. And imagine if you needed to change an input port. You'd then have to go back through all your code, modify the indexes at every place where you've put it. And it would just be a nightmare. So this is actually a really good dev technique as well.

Typically all good Python developers within Dynamo will do this. They will have a list of variables at the start of their script. And that will then just be taking an item out of their in list and just assigning it to a more meaningful variable. So that's the concept there. So now you know how to pass inputs into your Python script from Dynamo. It's just using this in keyword, and then you just index.

And if that's still a bit confusing, then here's an even simpler way of putting it. Whatever the name of the input port is in your Python script, just type that out again inside Python, and it's going to work. I mean, it's literally that simple.

OK. So we're almost there. We've got our input going in. And if we want to just double check that this is most certainly working, then here's another little trick. If you just uncomment that out variable-- and this should now be self-explanatory if you've understood what the in variable does-- out is the variable which Dynamo uses-- again, it's Dynamo specific-- to return items out of your Python script. So what we're going to see inside Dynamo itself will be an output from the Python node. Whatever the output is is what we define as developers. So whatever we assign to that out variable is what is returned.

And the output can either be a single item, or it can be at list. It's up to you as a developer to decide and determine what your script should be outputting. But what we can do is we can just pass desks in, and we can pass desks out, and just check that this is all working. So I'd like you to just go ahead and do that.

If you just copy your desks variable, assign it to out, if you just save your script, which is the most important thing to do, and we're finally going to get to the point where we can actually start reading the script which you've just written within Dynamo. And to do that, you just literally browse to your PWAR file using this file path node. And that's going to do the rest of the necessary steps for you.

So if I go ahead and find that file-- OK. So what I'm basically putting into the node is also coming out of the node. So I know that everything's working. And as you know, the purpose of this exercise was to count the number of desks which we're actually inputting into the node. And so for that we can use one of Python's built in functions.

So a function, again, if we use Excel as an analogy. If you're familiar with Excel, which a lot of construction professionals are, whenever you use any kind of function within Excel, that is a method. So a method and a function, kind of they mean the same thing. And typically, what a function will do is you provide a bunch of inputs. And then it gives you an output. That's usually what a function does, a bit like a calculator.

Although, there is a caveat to that. Not all functions will return something. It depends. Like within programming, you can declare a function that returns something. And you can also declare a function that just doesn't return anything. Because it might do something for you. It might, I don't know, set a parameter within a family instance. If that method sets the parameter, you don't need to return anything out of it. Cause all it's doing is just setting a bit of data for you. So that's the caveat there.

But nevertheless, all we're going to be doing here then is just measuring the total length of this list, as in we're going to count. And then we're going to output this from a Python script. So we just return back to our code. And all we're going to do is in the out variable, we're just going to wrap our desks variable inside a function. And that function which we're going to use is a built in function in Python. And it's called len. And all len does is it counts the length, or the total number of items inside a collection, so inside a list.

And as soon as I do that-- and you need to remember to save it. So you've got to save your file. And when you do that, your script should automatically update. And now it's going to tell you how many desks that you've actually selected.

So the purpose of this exercise then is to show you the boilerplate, to have you guys understand what the in and out variable do, and also to understand the basics of indexing a list. And you're going to be doing that a lot no matter what language you use. So these are really important concepts to understand.

OK. Sure. Go ahead.

AUDIENCE: [INAUDIBLE]

PRESENTER 1: Yeah.

AUDIENCE: [INAUDIBLE]

PRESENTER 1: You can to a certain extent. So the only way to do it, say if you want to get-- it's known [INAUDIBLE]. That's the kind of more common word for it. You can only do that with the Revit API using stubs. And stubs, I think they are essentially text files, which store a representation of the Revit API. And that is then cached inside, say, Visual Studio Code. So when you type, it'll give you a list of suggestions when you do your dot operator. But it's not quite, I would say, as powerful and as useful as, say, running in C# and using it there. But you can do it, but that's the only way that I'm aware of that you can do it. Yeah.

AUDIENCE: [INAUDIBLE]

TOM: Yeah. If you just Google-- so if you want to get kind of like a dropdown of suggestions, I think it is-- hang on.

Yeah. So you want to go to this repo here. If you just do Iron Python stubs, it's in there. There's really good instructions. I can never pronounce the gentleman's name who's done this. But he does Revit API docs. A really amazing guy. But yeah, all the instructions are on there if you did want suggestions when you type your code.

OK. So first of all, has everyone got to this stage here? I'm sorry. Go ahead.

AUDIENCE: [INAUDIBLE]

TOM: OK. It's a really good question. In general, try to avoid doing this kind of thing. Like there's select reasons. I mean, with this being such a simple example, there's no harm in that. It's very expressive. You're just saying out, length of list. So I don't have a problem with that.

Say, for example, though, if we wanted to use length to do something else in our code, that could be really bad, because that means we're kind of fragmenting our code. We're also breaking that first rule as well of being descriptive and actually not even tell ourselves, but perhaps other people that are reading our code what this is actually doing. So what might be more sensible, even though it looks a bit redundant doing this, is just to actually just say total desks equals. And then you just assign that to the variable. And then we return to our desks.

Again, you can see immediately that's got way more meaning than just returning len and then in, and then indexing the list. So I would say this is probably something which you'll just learn over time through experience, like when you should do this and when you shouldn't do this. I was being a bit naughty there and just doing a bit of a shortcut. But yeah, in general, my recommendation will be to code like that, cause it's very descriptive. You know exactly what it's doing. And anyone else that looks at your code can tell immediately what it's actually doing. It's just obvious. And that should always be your number one objective when it comes to writing code. Code readability, above all else, is the most important thing.

If you see really unwieldy, long lines of code with loads of different functions all embedded into other functions-- and you probably see this actually more commonly in Excel-- it's the worst thing ever. Do not do that. It's really, really bad. Just add extra lines of code and be descriptive. There's nothing wrong with that.

You're not a good developer if you're insulating loads and loads of different methods inside another method. That, to me, is actually a sign of inexperience. So don't do it.

OK. Thanks. OK. Right. Great. So we've already completed the first exercise. So everyone then should see the following inside Dynamo. You should be able to select your desks, read your Python file. And you should be getting an output [INAUDIBLE] the total number of desks that are coming from the node. And hopefully everyone now can explain to me what in and out variable means, what indexed list means, and what boilerplate is. So if you understand all those concepts, that's great. That means that you've already actually begun your journey as a developer, and they're really core concepts to understand.

OK. So the next step then is to look at a more advanced example. I think what I'm going to do, because we might run out of time if we do all three, we'll jump straight to a more complex exercise. OK? What we're going to be doing now is we're actually going to be making cores to the Revit API.

This might take a bit longer than the time we've got left. But let's see how far we get. Essentially what we're going to be doing is the following. We're going to be subdividing one of the rooms in our model. So if you've got the model open, just jump up to our [INAUDIBLE]. And you will see a rather large space, which we want to basically partition using briny wall objects.

And what we're going to be doing is the following. We are going to be making calls to the Revit API. Again, employing a lot of the techniques which we've just learned already to dynamically place partitions in that room and subdivide it. So by the time you finish, it should look something a little bit like this.

So I've got a slider. And this graph, by the way, you can open. So a lot of the hardware is already done for you. [INAUDIBLE] made modifications. Can you see that I'm now subdividing the space by a set number of partitions? So as I'm making this change, the model is automatically updating. And to do this we're going to be making, as I said, calls to the Revit API. And this code is going to be a little bit more complex.

OK. So without further ado then-- in fact, before I move on to this, has anyone got any questions about what we've just been doing up until this point? No. OK. Good.

All right. So what I'd like to do then is, if you can just open up the Exercise 4 DYN. So again, if you just go to the Data Set folder, Start Data Set, and then DYN you'll find it inside there. And when you open it, you should see a graph that looks like this.

So the first thing which we need to do is we need to select basically two walls which we're going to then create our politicians between. And those two walls are just going to be this wall here, and the wall below it as well. So where you've got Select Wall Element, if you just go ahead and pick those walls, you should see their location curves appear inside Dynamo as well.

[LAUGHTER]

Yeah.

AUDIENCE: [INAUDIBLE]

TOM: Really? OK.

[INTERPOSING VOICES]

TOM: Yep.

[INTERPOSING VOICES]

TOM: Sorry?

AUDIENCE: [INAUDIBLE]

TOM: Yeah. Exactly. Sorry?

AUDIENCE: You now selected it [INAUDIBLE].

TOM: No. No. Because we want to just draw partitions between those two lines. So we're just going to take points, array them along the line, project them, and then we're going to just draw partitions between those two lines. So we're going to need the two. Is it back online? Yeah.

PRESENTER 1: Is everyone's frame back online? Can you see stuff moving on the screen? Is it reacting? Yeah? OK.

TOM: OK.

AUDIENCE: [INAUDIBLE]

TOM: Yeah. Yeah. OK. Right. So in exercise four then, after you've started the two walls, the next thing which you need to do is jump back into Visual Studio Code. And I just want you to create a brand new file. And I think hopefully you know the procedure now. I've actually called it Excercise4. That's partly because exercise three is just running through Visual Studio. But I'm going to just skip that so we can focus on this exercise, cause it's more fun.

So I'd just like you to create a brand new file called Exercise4.py inside your S1 Python folder. And as I said, hopefully you know the procedure. Go to our boilerplate, copy it, and paste it into our new PY file. That's always the step that we take every time. We just copy our boilerplate over.

And you'll notice the ease at which we can do this because we're using Visual Studio Code. If we were just using that text editor inside Dynamo, we don't have this kind of convenience. So that's why it's always good to be within, say, Visual Studio Code, have you boilerplate at your disposal. And then when you create all of your new PY files, not only can you easily distribute them to the rest of your office, or whoever might need them, but it's also very easy for you to just copy your boilerplate over and just have everything in one concise place. So it's a really good environment in which to develop for Python nodes.

OK. So first of all, you know what our objective is. It's to basically create partitions within that room. And to do this we're going to take the following inputs. We're going to take the wall location curve that we've selected from Dynamo. So I'll just jump back in there so we can all see what it's actually doing. Yep.

So this line here, the wall location curve at the top, we're going to have that as an input. We're also going to have the other location curve, which is this one down here, which, by the way, has just been elevated up to the same height as the other line, cause the other one was actually done at the ground level. That's what this geometry translate node is doing. They're going to be the first two inputs into our node. The reason why they're going to be the first two inputs is because what we want to do is we want to draw partitions between those two walls. And we want to array points along the top of that curve, project them to the curve opposite, draw new lines. And those lines are then going to determine the location curves of our new walls. That's the concept.

So now that we've got our end goal-- and that's always important to establish as well. Whenever you start with any kind of script, no matter what it is, and even if you just use Dynamo, say, using visual programming, you've always got to have that end goal to kind of know where you need to get to. And then it's all about that journey of how you go from starting off with essentially nothing, and then getting to what it is you're trying to achieve at the very, very end. And that's, I think, part of the fun of it as well.

OK. So they're going to be our first two inputs. We also want to define how many partitions we want, how many times we want to subdivide that space up. And for that, we're just going to have a simple slider. So that's what this node here is going to do.

So in my case, I've got nine partitions, and on rather nine different spaces. And that's going to be one of our other inputs. So all we're doing here is we're just establishing, what does our Python script actually need before we can even start typing any code? So that's going to be the first thing.

PRESENTER 1: Tom, can you show us what elements to select again, please?

TOM: Yes. Sure. So it's literally just two walls. First of all, make sure you're on level two. And when you're on level two, you're going to be selecting in the first select wall element. And the order doesn't matter. So make sure the first stepped model element node, you're picking the wall here, which is the wall kind of North most. And then for the second set element node you're going to pick that other wall that's facing southward.

So as I said, those are the two curves that are input. We also want to have a slider determining the number of subdivisions. And there's going to be two other inputs which we'll need for actually generating our walls. One of them is the wall type. So we actually want to have that as an input so we can easily change between the various different wall types. And then the final input is going to be a level. So we just want to specify which level those walls are actually going to be hosted on to. And then we've got all of our inputs into our node.

And although I'm telling you this now, like I'm telling you about all the various inputs that we need for this script, generally, you won't actually know what all your inputs are when you first started running your script. And really, I would say there's sometimes no way to even know what they're going to be. That's part of that journey. When you get into your end goal, you might have an idea in your mind of how you actually go about solving something. You go down that path, and then you just hit, no pun intended, a brick wall. Sorry. And then you have to rethink, how do you kind of draw back your idea, and then perhaps branch off into a different avenue to try and get to your end goal. And through that process, that will always dictate what your inputs are.

So sometimes you'll know. Sometimes you won't know. And there's nothing wrong with that. Try and be organic with your approach, and don't be too rigid. Because you try and define everything from the outset, I can tell you right now you'll spend all your time just doing that and never resolving anything. So, I would say, just jump headfirst into it. Get coding. And then work out what your inputs are as you make each progressive step nearer and nearer to your end goal.

OK. But as we all already know this, because I can tell you right now what all the inputs are. So let's go ahead and start defining that now.

We already know how to declare our inputs. I'll just create a new line up here. The first input, we're just going to call it wall location curve top. And we're just going to assign that to the first input variable.

OK. [INAUDIBLE] just copy and paste all the inputs?

PRESENTER 1: No.

TOM: Sure. OK.

OK. Copy and paste that variable. And this time we're going to call the second one bottom. And we're going to assign that to the second input into the Python node. So again, each time I'm assigning an input to a variable, I'm always remembering to just increment that index. So now I'm taking what's going to be at the second slot in my list, which is indicated by index one, to the wall location curve bottom input.

OK. The next one is just going to be the total number of partitions. So for that, it's just going to be a total partitions. And this, again, gets assigned to number two. So index number two in the list. Again, I'm using camel casing here when it comes to naming variables, and I'm just being descriptive. So these are key concepts which you guys should all adhere to be really good developers.

The next one is called wall type. I'm going to have to do something a little bit different with this input, because this is actually going to be an element from Revit. It's an actual wall type. Now, without getting too technical, because I don't want to kind of overwhelm everyone-- hopefully you'll kind of understand this throughout the day-- but there's this concept that Dynamo uses to basically interface with Revit.

And that concept is called wrapping. And basically what Dynamo does to be able to understand elements within Revit, and also for Revit to perhaps respond to changes that might be happening within Dynamo is this concept of wrapping. And wrapping, to kind of [INAUDIBLE] is, I guess, imagine it like a bridge. And that bridge connects two different islands. And one of those islands is Revit, and the other island is Dynamo. And for the two to be able to kind of communicate, you've always got to cross that bridge.

And what wrapping does is it creates that bridge for you. And the best analogy that I can think of, although it's a little bit daft, I think it does express it quite clearly, we've all got mobile phones. And imagine if when we walked into this room, because we're in a top secret developer workshop, you are not allowed to have your phones on you because you weren't allowed to record or take photos. They all got kept at the back there by somebody. And, of course, everyone's got the same kind of iPhone. So what we thought of doing is writing our names on the phone with a marker pen.

And if all of our phones are made of glass, we can all see what the problem is. It all starts rubbing off of the phone. Right? So what we can do is we can actually modify the properties of the phone by wrapping it. I know this is daft, but just bear with me. If we were to wrap our phones in paper, and then write our names on those phones, now, all of a sudden, we've solved the problem. So if they collected our phones when we walked in, and we've written our names on those phones because they're wrapped in paper, it now can't rub off the screen, because we've changed the properties of the phone.

So we've now imbued additional properties to our phones by virtue of wrapping it in that paper where we can write our names on it. And that is the first kind of, I guess, analogy of wrapping. But there's a bit of a problem. When you get your phone back, if you want to make a phone call, you can't, because it's wrapped in paper. So what do you need to do? You need to unwrap it. Right?

So that's the concept of wrapping. That's why whenever you have an element from Revit in Dynamo, it's got to be wrapped. Because that then imbues it with those extra properties that Dynamo can understand. It can then interface with that object from Revit, because, by the way, Dynamo does not understand Revit. The two are complete independent applications. The only way Dynamo can actually interface and understand Revit is through wrapping. So it wraps into its own kind of classes that Dynamo understands. And now it's like, ah, I understand a wall. I understand the floor. I understand all these things from Revit, cause it could read its own classes.

So to kind of complete the analogy then, if you want to make calls to the Revit API and you selected an element from Dynamo that's in Revit, that element will always be wrapped. There's no ifs and buts. It will always be wrapped.

So if you want to then pass that element-- in our case, it's going to be a level and a wall type. They're both Revit elements. We're selecting them via Dynamo, and we're passing them into our Python node.

If you want to make Revit API calls on those elements, or if you want to make an API call like what we're going to do to build a wall, and we're going to provide the level and the wall type as inputs into that method to create the wall, then we have to unwrap, because if we don't do that our phone is still wrapped in paper. If we want to make a call, we can't.

So we've got to unwrap it, now we can make the call, and everything's going to work. And also, on the flip side, after we've made that call, and we want to return it back out of our node, we also then need to re-wrap it, because Dynamo only understands elements that are wrapped. It doesn't understand unwrapped elements. So that's the concept of wrapping and unwrapping. It's essentially an interface between the two applications. And it's a means of, I guess, Dynamo and Revit understanding one another. And I guess, it's a technique for adding additional information properties to objects. So if you're developing your own application, like what, say, the Dynamo developers have done, you can get it to interface with other applications that have got no awareness of it. That's what wrapping does.

Wrapping also has one other important concept to understand. That's this concept of element binding. And to cut a long story short, I'll show you actually what happens if we don't do element binding in this example. But basically, all element binding does is it synchronizes your geometry or elements that you're creating through your Python scripts via Dynamo in Revit, such that in our case we're going to have a slider that's going to determine how many partitions we have in a room. And as we move that slider, which is occurring in Dynamo, that action that we're making within Dynamo is going to be sent back into Revit. And Revit's then going to respond to that.

If we don't do element binding, as we move that slider, Dynamo is going to be sending a signal to Revit it basically create these walls. And we're going to end up with a million walls all over the show, because there's no synchronization between the two applications. So wrapping also serves the purpose of binding. It's just a synchronization between Dynamo and Revit, such that if we make changes inside Dynamo, Revit gets a response. And also the flip side. If you make a change inside Revit, Dynamo will also see that change as well. So that's what wrapping also does.

OK. So to unwrap an element then, we just use the unwrap element method, which, again, is just coming from our Dynamo libraries that we've imported. If you want to know specifically, it actually comes from Revit nodes. But as I've already said before with the boilerplate, we don't need to worry about it. We just need to know that it works.

So unwrap element. And for this, of course, it's going to be index three. And the final input is going to be level. And that's going to be index four.

OK? So your code should look like that when you're done. So we've got all of our inputs. We're remembering to index 0, 1, 2, 3, 4. So it's all sequential. And again, that's how lists are naturally created. So we need to define our indexes. We are going to need to call the indexes to actually access the object. And for the very last two inputs, we're going to unwrap them using Dynamo's unwrap command.

And one last thing as well, you can actually call unwrap on anything. If an element isn't from Revit and you call unwrap, it doesn't harm it. It just returns it unmodified. So if you want to be, well, I guess super kind of bullish and not really care, that's not going to cause any harm whatsoever.

So you can be quite, I guess, relaxed about coding, and I wouldn't worry too much about what these methods are actually going to do. But certainly for Revit elements, we've always got to unwrap.

OK. The next one which we need to do then is we need to convert these curves, which are currently Dynamo curves, into Revit curves. The reason why we're going to do this is because we need those curves to create the walls. And these walls, which we're going to look at in just a second, are going to be generated from a call to the Revit API.

So what I would like you to do now is open up Visual Studio. So we've got open up Visual Studio Code. You should be able to find Visual Studio. And I'd like you to browse to the data set again. And we're going to open up the zero touch node project just temporarily. And we're going to use that to actually view the Revit API.

So if you just find Visual Studio 2019. You might have to just search for it inside your list of programs on your desktops. But you're looking for Visual Studio 2019. And before we do any more code, I want to actually jump straight to our end goal, which is the creation of those walls. And I'm going to take a code snippet from the Revit API. And we're going to paste it back into our Python script. And then we're going to structure all of our code around that end goal. So once you've opened up Visual Studio, if you just click on [INAUDIBLE] solution. And again, just browse to the data set. And we'll go into the S3 folder.

I'll try and fit it in. It's going to be a stretch. But let's see. Yeah. OK. OK. So yeah, if you just go to the zero touch nodes, and workshop template start, you'll find that inside the S3 Zero Touch folder. And as soon as you open up this location, you'll find a file with the extension SLN. And you just want to go ahead and open up that file.

OK. So as soon as you've opened up the solution, inside References if, like me, you've got perhaps those kind of warning signs, where you see Revit API, I want you to just right click it, and just do remove.

On the Visual Studio I can't zoom in. It won't allow me, unfortunately. Radu, you might want to maybe help a few people. We're just going to remove Revit API from the list of references.

I guess what I could do is just show it maybe on screen. I think that might be easier. OK. Because we're running out of time, I'm just going to add the reference in. And then when I put the code back into Python, you'll kind of see it much larger on screen, and we're good to go after that.

I'll just do this really, really quickly. And then we can show you in more detail when we actually move onto the zero touch workshop.

PRESENTER 1: So feel free to skip this step and just watch Tom do it. You'll be doing this again in the third session. So we'll cover that in more detail then.

TOM: OK. What I'm doing, just in case you're wondering, I'm basically going to the Revit API via Visual Studio. The reason why I'm using Visual Studio is because it's a really great environment for, well, coding C#, amongst other languages, and also for viewing the API. And I'm just finding a method inside the API that allows me to create a wall using a wall type, a curve, and a level.

So as soon as I've found the method which I know will work, then I'm literally just going to copy that code. So I've just found the method here. I'm going to copy the code from Visual Studio. I'm going to paste that into my Python script. So right now, I've found the class wall, cause that's what I want to create. It's got a method called Create, which is quite handy. And there's a bunch of options there in terms of how I can create that wall. And I've just found the one which requires a level and a type as an input, which is actually that one there.

OK. So I'm going to copy that from the description within Visual Studio. And then I'm going to paste this into my code. So you guys, you don't have to type this all out, of course. I'll just leave it on my screen. But once you've pasted it in, it will look something a bit like this. And what we're going to do now is we're going to go about structuring that core to the Revit API to create our wall. And then we're going to store the result of that core, which is going to be the output of a brand new wall object, in a list. And that's going to then be returned out of this method.

So we're going to leave that where it is for now. What I'd like you to do on your script for now is just type that. So if you just do wall create, then that saves you having to type everything else out. And we'll worry about the inputs shortly.

So if you just do wall create. OK. And what we want to do is basically the number of partitions that we've specified via our slider, we want to create what's known as a for loop within Python. And we're going to use a for loop to basically iteratively access that list. So that's what a for loop does. It basically takes a block of code. And it will repeatedly call that block of code the number of times you specify. That's what a for loop is.

So we're going to get that for loop to run the same bit of code as many times as there are partitions. And with each loop, it's going to generate a new wall for us. So inside the block of code in our for loop that does something-- in our case it's going to build a new wall-- that's what each iteration of our for loop is actually going to do.

So we are going to get a bit more advanced now. We're actually going to declare a for loop in our code. But the syntax is actually really easy to remember. We first of all, declare the for keyword. We then need to give an accessor-- so the actual variable that's going to go into our list to access the item is going to pull the item out of the list and then store it for us. And when that item is stored, we can then use it in the main body of our for loop.

In our case, of course, it's going to be the creation of this wall object. So our access there is actually just going to be-- and I know I'm breaking a rule here, cause I'm using, well, just a single character here for a variable name. But actually, this isn't that bad, because all we're going to be accessing is that number from our list of integers, or rather, the number from our list of partitions.

So generally speaking, with four loops, if all you're doing is you're accessing numbers, then it's OK to just use a single digit. And usually, it's IJK that's usable in four loops. And it's also widely used within C#.

OK. So accessor is just a variable. And you can call it what you like. In our case, it's called I. We then follow it by the keyword in. And then we're going to use another built in function within Python called range. And all range is going to do it it's going to return a series of numbers, starting from zero. And it's going to end based on a number, which we input into the method.

So the method is always defined using the curved brackets after the name of the method which you're calling. And all we're going to put into that method is total partitions.

So what range is going to do, say if our total partitions is nine, it's going to output a list of numbers starting from 0, going all the way up to 9. So 0, 1, 2, 3, 4, 5, 6, 7, all the way up. So just literally a number. And then we just end our for loop with a colon. And that's the syntax for a for loop.

So it's very, very straightforward to remember. The other thing to remember with Python as well, it uses indentation when you declare your statement body for things like for loops and any other kind of function, like a definition. So if I want to actually specify what is going to happen within the for loop, you always indent. And what I tend to use is just a tab. You can use spaces. But it's more cumbersome. I just use a tab.

So now, it means that when this for loop starts executing, whatever is indented beneath the for loop is actually what's going to get executed. Anything that isn't indented is not going to be executed by that for loop. So the statement body, the actual statement which is going to be executed by that for loop is always defined via your indentation.

OK. So let's start creating these walls then. First of all, we know the method in the API which we're going to create. So what I would do immediately is declare a new variable and assign the core that we're going to make to the Revit API as such.

So we just say, I'm going to create a new wall. I'm going to assign the core to the Revit API, which creates our new wall for us, and assign it just using the ordinary assignment technique.

The other thing which we need to do is we need to actually define our location curves for our walls. So at the moment, we've got our curves coming in from Dynamo. They're still Dynamo curves, which, unfortunately, are not compatible with the Revit API. So we do need to convert them into Revit API curves, which is very easy to do, because there's one method which we can call on that curve that will convert it for us.

So what I'd like you to do is, where you've got those first few variables at the top, just copy paste them like that. And what we're going to do is we're going to call these Revit at the end, just so we know these are Revit curve types.

And we need to just copy the variable names again, like that. And to convert them, you do the dot operator. And then we're just going to call to Revit type. And that's just a help method that Dynamo gives us that enables us to very, very easily convert Dynamo geometry into Revit API geometry, because, unfortunately, they're two geometry engines which are not compatible. They don't understand one another.

So a Dynamo curve is not the same thing as a Revit API curve. And if we want to use these curves as inputs into calls to the Revit API, in our case, it's the creation of this wall object, which requires a location curve. We can't just pass it this Dynamo curve, because the Revit API is not going to understand. It's just going to be like, well, this could be anything to the Revit API, which is why we've always got to do the conversion.

So I know some of these concepts might be kind of way out there if you've never seen this before. But it's like anything. Practice makes perfect. And if this does seem a bit overwhelming, don't fear, because we've all got to start somewhere with these programs. And these are just techniques that you learn.

I mean, a bit like Revit. When you first started off using Revit, I'm sure you find it intimidating. I'm sure after a few years, it's like a toy, because it's just so easy to use. And the same is true for coding as well.

OK. So we've got our location curves converting to Revit types, which is perfect. So we're almost at a point now where we can actually start building up all of the inputs into our wall creation, and then finally output it.

So as we want to output a list of walls, outside of the for loop we should create a list. And that list is going to store all of our new wall objects. So to declare a list, you always use square brackets. So don't get confused between square brackets for indexing and square brackets for lists. That's how you declare lists within Python.

The reason why the Python interpreter knows that you're not trying to index anything when it sees those two square brackets is because it's not preceded by a variable name. So you're not declaring [INAUDIBLE] in, and then immediately afterwards you're doing your square brackets. You're just declaring your square brackets in isolation. That tells the Python interpreter, you want a list.

So you're actually declaring a brand new list. And now that list can start accepting elements. And in our case, it's going to be new walls.

PRESENTER 1: 10 minute warning.

TOM: Thanks. We'll try and get it done. OK. So first thing's first then, we want to generate a point along that top curve based on the number of partitions. And then that point that we generate on that top curve, we want to project to the bottom curve. And then between those two points, we generate a line. And that line is then going to be used to generate our wall.

So the concept is quite simple. And we're going to go ahead and do that now. So first of all, what we want to do is we want to declare inside our for loop, cause don't forget, as we're iterating through the number of partitions that we want to generate, we want that point to shift along by an even distribution of subdivisions.

So let's go ahead and do that now. The first thing which we need to do is we need to just measure the length of the curve, which is very easy to do, because what we want to do is we want to divide that curve by the number of partitions. And then what we want to do is just a simple multiplication. So as our for loop is iterating, we multiply that number by the count. Because i is going to continue to go up, by the way. It's going to start at 0. And then it's going to go 1, and then 2, and then 3 and 4 with each loop of that for loop. And we're just going to use that as a multiplier.

So outside of our four loop again, we just want to declare the curve length. So that's really straightforward to do. We declare a new variable.

Take the Revit curve. Do the dot operator at the very end of it. And we're going to extract a property out of the curve. And, of course, that's just going to be its length. So the curve has a property called length.

And we can view this all through the API, but we'll actually look at that in the zero touch workshop. For now, just for expediency, I'm just going to tell you that there is a property called length. The subdivision length is another, or rather subdivided.

It is another variable. And inside there, we're just going to take the curve length. And we're going to divide it by the [INAUDIBLE] partitions plus 1. The reason why we want to do plus 1 is because we don't want a room at the end, or a wall, say, at the end that's already overlapping another wall. If we do plus one, it means that actually all our partitions end up inside that space. And then the far two walls at the far side then, of course, complete the first and the last space.

So we just do [INAUDIBLE] partitions, and then plus one. So it's just basic math.

OK. So now we've got our subdivided length. We can now inside, back in our for loop, start getting our for loop to do all the hard work for us. So the first thing which it's going to do is it's going to create the point along our curve. And for that, we actually just call it point along curve.

Again, be descriptive. I mean, it's already telling us the story. We don't even need to write comments if we declare our code like this. Point along a curve is really, really easy to understand. And all we're going to do is we're going to take our location curve again. So this is the Revit curve at the top here. Paste it in. We do a dot operator again.

And we're just going to evaluate that curve. And we're going to just place a point using the curve evaluation. So it evaluates a method in the API that enables you to basically specify a point along a curve by a given distance.

So again, we just do dot operator on the top Revit curve. We call it evaluate, which is a method.

[INTERPOSING VOICES]

TOM: Thanks. Yeah. My spelling isn't the greatest. Right. OK. So inside evaluate then, we just want to, as I said, specify the distance along the curve based on the subdivision length. So we've got the subdivided length. So we can put that inside there.

And the very, very first i is always zero. And what we don't want to do is have a zero subdivision length, cause if we do 0 multiplied by the subdivided length, that's going to result in 0. We don't want a zero subdivision of a wall, cause that's just going to be overlapping the very first wall. So what we're going to do instead is we're just going to plus 1 to i.

So if we just do the following, and then we multiply the subdivided length, we're now going to get a very convenient step of subdivisions along that curve. And that creates that first point along the top curve.

To create the curve along the bottom, I'll just allow you guys to catch up. Although, we are stretched for time, so I want to kind of race through this. But we just want to do project [INAUDIBLE]. And we're going to call it a result.

And there is a reason why. It's because the method which we're about to use in the API that enables us to project a point returns an intersection result. It's an actual type of object, and not a point. But from that object, we can get the point.

So project [INAUDIBLE] result is the next variable. And we want to take the bottom Revit curve. And we just want to call project on this curve. And project takes a point, which is going to be this point here.

So we've got the point along the curve. And we pass that into project. OK. We're almost there. So now what we've got to do is just generate our new wall. And if you remember, the wall creation method, it takes these inputs.

I'll just move this all the way back up to here, just so you can kind of see what the inputs are so that when I paste this from Visual Studio, I can see all of this. And then it's really, really convenient for me to start passing all the inputs, a bit like in Excel, to then satisfy all of the required inputs to then create my new wall.

So the first thing which it wants is a document. And by pure convenience in our boilerplate, we've already got that object. So we've got doc at the top here. And that then just gets passed into this first input. So in your [INAUDIBLE] create method, you should see that now. You should see wall.create. The first input is the document.

We want to then provide a curve. That curve we actually need to create. So again, that journey that we have to go through when it comes to getting to our end goal, we now need to create that curve. So for that we'll just create one more variable, and call it new location curve.

And there's a method in the API, or rather there's a class called line with a method called by I think it's-- yeah. It's create bound. And all that takes is two points. And hopefully you should know where the two points are. It's that one, and this one here.

And that new location curve then goes into here. So that then forms our second input. You'll notice that now I've done all the hard work, this final step is actually far easier. Thanks.

The next input is the wall type ID. And we've already got the wall type input. And crucially, we've unwrapped it. So as we've unwrapped it, we know with absolute certainty that it's going to be compatible with this Revit API call, because it's not a Dynamo wrapped element anymore.

And as it takes an element ID, we need to do the following. Input wall type into that third input. Dot operator, and then ID. That's going to return the element ID from that object.

So you'll notice the utility of that dot operator in Python. And actually, this is true for practically any program language out there. The dot operator always enables you to access things like methods. So I'll call a method, like, for example, project on a curve. Or if you want to access a property, for example, the length of the curve, you'll notice that it's always using that dot operator. So there is a consistency behind these languages that kind of makes it, I would say, easier to understand once you learn these few techniques.

OK. So we've done wall type ID. The next input that it wants is the level ID. So hopefully you'll know exactly what to do for the next input. We just pass in level.id. So that's the next one.

By the way, Python doesn't support multi-line calls like this. So you will need to make sure that your codes are on one line, not on two lines like what I'm showing now. It's just to fit it on the screen for you.

OK. It wants a height. The height, because we're making calls through the API, it always has to be declared in decimal feet. Revit API only uses decimal feet, even if your Revit file is using millimeters. And you can't change it. So if you want to, for example, import 2.5 meters into your Python script, in your Python script you need to do the conversion yourself. So you can't change the internal units of Revit. It's always decimal feet.

But for the purposes of today, and also because I guess we're in the United States, we'll just make this wall 10 feet high. So I'm just going to type in 10.

We don't want to give the wall any kind of offset. So that can just be 0. We also don't want to flip it. And the type that we have to provide is a Boolean, which is just true or false. It's one or the other. And there's no in betweens.

So in Python, we do not want to fit the wall. So we just say false, and declare false. It's a keyword in Python. And it always starts with capital F.

So the Python interpreter will read that as a Boolean, as true or false. You just got to make sure that you capitalize the first letter. And it's also asking us whether it should be structured or not. And the answer to that is going to be no. So we can just say false to that.

OK. And we've now just programmatically created a wall using the Revit API. So the final step then is simply just to store our result. And to do that, we declare our list again, purely for the purposes of calling the dot operator on it. And Python has a method called append for lists. And all append does is it just adds another item into your list. That's literally all it's doing.

So with each loop, we generate the location curve. We create the new wall object. And then we're going to append that new wall into this list.

So if we were to just do that, unfortunately we're going to be returning an unwrapped Revit API wall into Dynamo. We need to do our wrapping before we pass it into the list. So really what we should do is call it new wall wrapped. And a bit like when we unwrap, unfortunately, there isn't a method called re-wrap. It's unintuitively called 2DS type. So what we have to do is the following. You just have to do new will, dot operator. And then it's 2DS type, like that.

And it's a method. So methods always have curved brackets. And that's doing the wrapping, and also the binding for us at the same time. And this takes one input, which is either true or false. So it's a Boolean. And it's true if the element came into the node from Revit, and you input false if your Python script is generating it, which, in our case, is exactly what it's doing.

So we should be specifying false here. And that is actually an important distinction. If you input the wrong Boolean, then you either don't get element binding, and you might end up with some weird results when you kind of get back into Revit. So try to remember it. It's easy to remember. Just ask yourself who created it? Did Dynamo create it? Or did Revit create it? If Dynamo created the element for you, then it's always false. If it was created inside Revit, then it's always true. So that's what you input into 2DS type.

OK. So you append the new wall wrapped into our list, and the final step then is just to simply output this to the out variable, and then save a script. And then don't forget just to browse to the script inside Dynamo to run it. And if you've done everything, even though we did it at a million miles an hour, but if you managed to keep up and run that, then you should see a bunch of new walls being created when you move your slider.

Yeah. Sure.

AUDIENCE: [INAUDIBLE]

TOM: Oh, just here.

AUDIENCE: [INAUDIBLE]

TOM: Oh, whereabouts? Sorry?

AUDIENCE: [INAUDIBLE]

TOM: Yeah. Yeah. Yeah.

PRESENTER 1: [INAUDIBLE] Tom.

TOM: Yeah. So if I run this now-- I'll just browse to my script.

Oh, hang on. I've got an error. OK. Yeah. So if you're getting that error, which I think you probably will be, all that means is that range method that we called, it only takes a whole number. So whole numbers are integers. And right now we're actually giving it a double, which means a decimal number. So if you hear the term double and integer, then that's the distinction. Integers are always whole numbers. And doubles are decimal numbers. And there is a significant distinction within a program application.

Like computers aren't smart like us. They can distinguish between one type and another. And believe it or not, an integer is actually very from a double. So what we need to do then to fix that is just tell the Python interpreter what to actually do with that number.

So if you just go all the way back into your code, find where you've called a range, and you're inputting into our partitions. And we just want to make sure that's definitely an integer. And to do that we can just use the in method there.

So if we do that-- and all that's saying is, if that number of partitions, although it might say 9, if it's 9.0, that's a decimal. So if we call int on 9, and even if it's not [INAUDIBLE], say it was 9.5, I would just round it to the nearest whole number. And then we rerun this. [INAUDIBLE] that should fix it. OK.

Well, there's one more thing which I need to fix. So evaluate. It takes two inputs. The second input is true or false as to whether we want it to use a normalized representation of the curve or not. So without getting too mathy on you, if you say false, it's going to use the true length of the line to do the subdivisions, which is what we want. If you say true, then it will use a parameterization of that curve. Or to cut a long story short, it will use a percentage of that curve to define the point. So if you were to type in, for example, 0.5, you would get a point in the middle of the curve.

But we don't want that. We're specifying an actual length. So we want to use the true length of the curve. So we just say false to this method. And has that fixed it?

Ah. OK. Yeah. One last update. And by the way, this is actually quite normal. Like when you're actually coding, we are only human. So invariably, you're going to be making all these calls, running, say, chunks of code. And you hit these problems and these snags. Don't fret. It's completely normal. And it can be quite frustrating sometimes. But just try to read the warnings that it gives you.

And admittedly, if you're new to this, it might be difficult to interpret what those warnings mean. But with time, you will understand how to overcome these issues.

So to finally resolve this-- and I can assure you after this, it will work-- famous last words.

AUDIENCE: [INAUDIBLE]

TOM: Which line? Sorry.

AUDIENCE: [INAUDIBLE]

TOM: Oh, no. no. It's tricking you. Good spot, though.

OK. So yeah. Where we've got our projected to bottom result, this isn't actually a point. And the line requires two points. This actually stores a point, though, the resolving section, the last update here. And all we can just do is just type the following, dot operator, xyz point.

OK. Now it's worked. OK. So sorry. I'll just reopen that. So that will be the final update. So you just want to make sure that you've got the updates, which I've just done, false as an input into the evaluate method, xyz point, which is a property of the projected to bottom result, and also just making sure that our two partitions is an integer, which we pass into the range method.

They're the three final updates that I've made to this. And then, as I said, once those updates are complete, and we start moving with the slider, we should now see lots of partitions being created for us. And it works.

So if you kept up with all of that, then that's amazing, because we did go through that quite rapidly. But yeah, that's what you should be seeing coming out of this node at the end.

And also, I guess, just one last thing, if you don't do any element binding, then this is what's going to happen. So if I omit that, and then I start making changes, you can see what's happening. I'm now getting a million walls all over the show, because basically Dynamo is not communicating with Revit if I don't do binding, which, as you know, is done through the virtue of wrapping.

So there's pros and cons to that. Cause you might actually want binding. You might, for example, be placing desks in a room. And you don't want it to just be placing a desk in one room, and then jumping to the next room, and then before you know it you've only got one desk in the whole building. So you could actually use element binding to your advantage. But in our case, we want to make sure that it's definitely available.

So yeah. That actually brings us up to the end of this session. Thanks for listening. And I hope it was kind of insightful. And, of course, if you've got any more questions, then just come and grab me like whenever, and I'll be more than happy to discuss it with you. So yeah, thanks very much.

[APPLAUSE]

PRESENTER 1: All right, everyone. So here's the agenda. How did that feel? Did it feel like being thrown in the deep end a bit? Yeah?

Next few sessions we're going to reel it back in and start with basics, and kind of build up from that. This is kind of the Python experience in Dynamo. You have to know lots of stuff. You have to read lots of documentation. So if you felt like you were drowning a little bit, it's going to feel a lot better in the next few sessions.

We're going to take a break now. And make sure you're back here 2, 4, 10 past. Don't look at Tom's clock. It's the UK time. So 10 past 11:00? Is that the right one? Yeah. 10 past 11:00.

And what we're going to do is we're going to start with C#. So a different language, but you'll see that it is friendlier. It gives you a lot more help. And we're going to basically take what Tom's made and move it along.

The other thing to note is that every single one of these sessions is self-contained. So even if you didn't follow on one, you can pick up the next one without any issues. We've structured them to be kind of standalone exercises. OK?

So lots more stuff coming. It's fun stuff.

AUDIENCE: Yes!

PRESENTER 1: One last thing for everyone, since I got asked, the files are all on a GitHub repository. I will flash up the address in the next session. So you can download all of this when you get home.

______
icon-svg-close-thick

Настройки cookie

Ваша конфиденциальность и оптимизация возможностей работы важны для нас. Мы собираем данные об использовании вами этого сайта с целью адаптации информации и разработки приложений.

Можем ли мы собирать и использовать ваши данные?

Узнайте подробнее о службах сторонних разработчиков., которые мы используем, и нашем заявлении о конфиденциальности.

Обязательные к использованию: требуются для корректной работы нашего сайта и предоставления сервисов

Эти cookie позволяют нам регистрировать ваши предпочтения или информацию о входе в систему, отвечать на ваши запросы или сохранять данные о вашей корзине.

Оптимизация работы: позволят демонстрировать только релевантную информацию

Эти cookie позволят предоставить вам расширенные функциональные возможности и персонализацию. Они могут быть установлены нами или сторонними поставщиками, чьи сервисы мы используем для предоставления информации и персонализации. Если вы не разрешите использование cookie этого типа, некоторые или все сервисы могут оказаться недоступны.

Персонализация рекламы: позволят предлагать вам целевую рекламу

Эти cookie собирают данные о пользователях на основе их действий и интересов, с целью демонстрации релевантных объявлений и отслеживания эффективности. Благодаря им, пользователю будут доступны рекламные материалы, наиболее соответствующие его интересам. Если вы не разрешите использование cookie этого типа, рекламные материалы будут носить менее адресный характер.

icon-svg-close-thick

СЛУЖБЫ СТОРОННИХ РАЗРАБОТЧИКОВ

Узнайте подробнее о службах сторонних разработчиков, которые мы используем для каждой категории, и получите сведения о том, как мы используем данные, которые собрали о вас в интернете.

icon-svg-hide-thick

icon-svg-show-thick

Обязательные к использованию: требуются для корректной работы нашего сайта и предоставления сервисов

Qualtrics
Мы используем Qualtrics для обеспечения обратной связи с клиентами через опросы или онлайн-формы. Вас могут выбрать случайно для участия в опросе или вы можете самостоятельно решить оставить отзыв. Чтобы лучше понять ваш опыт работы с нами, перед заполнением опроса мы собираем данные о ваших действиях. Это помогает нам решить проблемы, с которыми вы могли столкнуться. Политика конфиденциальности Qualtrics
Akamai mPulse
Для сбора данных о поведении клиентов на наших сайтах мы используем Akamai mPulse. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Akamai mPulse
Digital River
Для сбора данных о поведении клиентов на наших сайтах мы используем Digital River. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Digital River
Dynatrace
Для сбора данных о поведении клиентов на наших сайтах мы используем Dynatrace. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Dynatrace
Khoros
Для сбора данных о поведении клиентов на наших сайтах мы используем Khoros. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Khoros
Launch Darkly
Для сбора данных о поведении клиентов на наших сайтах мы используем Launch Darkly. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Launch Darkly
New Relic
Для сбора данных о поведении клиентов на наших сайтах мы используем New Relic. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности New Relic
Salesforce Live Agent
Для сбора данных о поведении клиентов на наших сайтах мы используем Salesforce Live Agent. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Salesforce Live Agent
Wistia
Для сбора данных о поведении клиентов на наших сайтах мы используем Wistia. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Wistia
Tealium
Для сбора данных о поведении клиентов на наших сайтах мы используем Tealium. Это могут быть посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Tealium
Upsellit
Для сбора данных о поведении клиентов на наших сайтах мы используем Upsellit. Это могут быть посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Upsellit
CJ Affiliates
Для сбора данных о поведении клиентов на наших сайтах мы используем CJ Affiliates. Это могут быть посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности CJ Affiliates
Commission Factory
Для сбора данных о поведении клиентов на наших сайтах мы используем Commission Factory. Это могут быть посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Commission Factory
Google Analytics (Strictly Necessary)
Для сбора данных о поведении клиентов на наших сайтах мы используем Google Analytics (Strictly Necessary). Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Google Analytics (Strictly Necessary)
Typepad Stats
Для сбора данных о поведении клиентов на наших сайтах мы используем Typepad Stats. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Typepad Stats
Geo Targetly
Мы используем Geo Targetly, чтобы направлять посетителей сайта на наиболее подходящие веб-страницы и/или показывать контент, подобран-ный с учетом их местоположения. Geo Targetly определяет местоположение посетителя сайта по IP-адресу его устройства. Таким образом на сайте (с большой вероятностью) отображается контент на языке региона пользователя.Политика конфиденциальности Geo Targetly
SpeedCurve
Мы используем SpeedCurve для мониторинга и определения производительности вашего веб-сайта путем измерения времени загрузки веб-страницы, а также отклика последующих элементов, таких как изображения, сценарии и текст.Политика конфиденциальности SpeedCurve
Qualified
Qualified is the Autodesk Live Chat agent platform. This platform provides services to allow our customers to communicate in real-time with Autodesk support. We may collect unique ID for specific browser sessions during a chat. Qualified Privacy Policy

icon-svg-hide-thick

icon-svg-show-thick

Оптимизация работы: позволят демонстрировать только релевантную информацию

Google Optimize
Мы используем Google Optimize для тестирования новых возможностей наших сайтов и их адаптации в соответствии с вашими потребностями. Для этого пока вы работаете с сайтами, мы собираем данные поведения. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса, идентификаторы устройств, учетные записи Autodesk и прочее. На основании тестирования возможностей изменяются версии сайтов. Кроме того, на основе атрибутов посетителей на сайтах появляется персонализированный контент. Политика конфиденциальности Google Optimize
ClickTale
Мы используем ClickTale, чтобы получить представление о трудностях, с которыми вы можете столкнуться на наших сайтах. Мы используем записи сеансов, чтобы узнать, как вы взаимодействуете с нашими сайтами, включая все элементы страниц. Ваша личная информация скрыта и не собирается. Политика конфиденциальности ClickTale
OneSignal
Мы используем OneSignal для развертывания цифровой рекламы на сайтах, поддерживаемых OneSignal. Реклама основывается на данных OneSignal и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными OneSignal от клиентов. Мы используем данные, которые предоставляем OneSignal, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности OneSignal
Optimizely
Мы используем Optimizely для тестирования новых возможностей наших сайтов и их адаптации в соответствии с вашими потребностями. Для этого пока вы работаете с сайтами, мы собираем данные поведения. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса, идентификаторы устройств, учетные записи Autodesk и прочее. На основании тестирования возможностей изменяются версии сайтов. Кроме того, на основе атрибутов посетителей на сайтах появляется персонализированный контент. Политика конфиденциальности Optimizely
Amplitude
Мы используем Amplitude для тестирования новых возможностей наших сайтов и их адаптации в соответствии с вашими потребностями. Для этого пока вы работаете с сайтами, мы собираем данные поведения. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса, идентификаторы устройств, учетные записи Autodesk и прочее. На основании тестирования возможностей изменяются версии сайтов. Кроме того, на основе атрибутов посетителей на сайтах появляется персонализированный контент. Политика конфиденциальности Amplitude
Snowplow
Для сбора данных о поведении клиентов на наших сайтах мы используем Snowplow. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Snowplow
UserVoice
Для сбора данных о поведении клиентов на наших сайтах мы используем UserVoice. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности UserVoice
Clearbit
Služba Clearbit umožňuje doplňování dat v reálném čase za účelem poskytování individuálního a relevantního prostředí pro naše zákazníky. Mezi data, která shromažďujeme, mohou patřit vámi navštívené stránky, aktivované zkušební verze, přehraná videa, provedené nákupy a vaše IP adresa nebo ID zařízení. Политика конфиденциальности Clearbit
YouTube
YouTube — платформа для обмена видеороликами, через которую пользователи могут просматривать и размещать встроенные видеоролики на наших веб-сайтах. YouTube предоставляет данные о зрительской аудитории. Политика конфиденциальности YouTube

icon-svg-hide-thick

icon-svg-show-thick

Персонализация рекламы: позволят предлагать вам целевую рекламу

Adobe Analytics
Для сбора данных о поведении клиентов на наших сайтах мы используем Adobe Analytics. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Adobe Analytics
Google Analytics (Web Analytics)
Для сбора данных о поведении клиентов на наших сайтах мы используем Google Analytics (Web Analytics). Это могут быть посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Google Analytics (Web Analytics)
AdWords
Мы используем AdWords для развертывания цифровой рекламы на сайтах, поддерживаемых AdWords. Реклама основывается на данных AdWords и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными AdWords от клиентов. Мы используем данные, которые предоставляем AdWords, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности AdWords
Marketo
Мы используем Marketo для своевременной отправки более актуальных сообщений клиентам по электронной почте. Для этого мы собираем данные о вашем поведении в интернете и взаимодействии с отправляемыми нами сообщениями электронной почты. Данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса, идентификаторы устройств, коэффициенты открытия сообщений электронной почты, сведения о переходах по ссылкам и др. Мы можем объединять эти данные с данными, полученными из других источников, чтобы оптимизировать ваш опыт работы с отделом продаж или службой технической поддержки, а также предлагать более подходящие материалы на основании использования передовых средств анализа данных. Политика конфиденциальности Marketo
Doubleclick
Мы используем Doubleclick для развертывания цифровой рекламы на сайтах, поддерживаемых Doubleclick. Реклама основывается на данных Doubleclick и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Doubleclick от клиентов. Мы используем данные, которые предоставляем Doubleclick, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Doubleclick
HubSpot
Мы используем HubSpot для своевременной отправки более актуальных сообщений клиентам по электронной почте. Для этого мы собираем данные о вашем поведении в интернете и взаимодействии с отправляемыми нами сообщениями электронной почты. Данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса, идентификаторы устройств, коэффициенты открытия сообщений электронной почты, сведения о переходах по ссылкам и др. Политика конфиденциальности HubSpot
Twitter
Мы используем Twitter для развертывания цифровой рекламы на сайтах, поддерживаемых Twitter. Реклама основывается на данных Twitter и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Twitter от клиентов. Мы используем данные, которые предоставляем Twitter, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Twitter
Facebook
Мы используем Facebook для развертывания цифровой рекламы на сайтах, поддерживаемых Facebook. Реклама основывается на данных Facebook и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Facebook от клиентов. Мы используем данные, которые предоставляем Facebook, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Facebook
LinkedIn
Мы используем LinkedIn для развертывания цифровой рекламы на сайтах, поддерживаемых LinkedIn. Реклама основывается на данных LinkedIn и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными LinkedIn от клиентов. Мы используем данные, которые предоставляем LinkedIn, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности LinkedIn
Yahoo! Japan
Мы используем Yahoo! Japan для развертывания цифровой рекламы на сайтах, поддерживаемых Yahoo! Japan. Реклама основывается на данных Yahoo! Japan и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Yahoo! Japan от клиентов. Мы используем данные, которые предоставляем Yahoo! Japan, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Yahoo! Japan
Naver
Мы используем Naver для развертывания цифровой рекламы на сайтах, поддерживаемых Naver. Реклама основывается на данных Naver и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Naver от клиентов. Мы используем данные, которые предоставляем Naver, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Naver
Quantcast
Мы используем Quantcast для развертывания цифровой рекламы на сайтах, поддерживаемых Quantcast. Реклама основывается на данных Quantcast и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Quantcast от клиентов. Мы используем данные, которые предоставляем Quantcast, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Quantcast
Call Tracking
Мы используем Call Tracking для предоставления адаптированных телефонных номеров для наших рекламных кампаний. При этом вы получаете быстрый доступ к нашим агентам, а мы можем получить более точную оценку своей работы. Мы можем собирать данные о вашем поведении на наших сайтах на основе предоставленного телефонного номера. Политика конфиденциальности Call Tracking
Wunderkind
Мы используем Wunderkind для развертывания цифровой рекламы на сайтах, поддерживаемых Wunderkind. Реклама основывается на данных Wunderkind и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Wunderkind от клиентов. Мы используем данные, которые предоставляем Wunderkind, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Wunderkind
ADC Media
Мы используем ADC Media для развертывания цифровой рекламы на сайтах, поддерживаемых ADC Media. Реклама основывается на данных ADC Media и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными ADC Media от клиентов. Мы используем данные, которые предоставляем ADC Media, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности ADC Media
AgrantSEM
Мы используем AgrantSEM для развертывания цифровой рекламы на сайтах, поддерживаемых AgrantSEM. Реклама основывается на данных AgrantSEM и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными AgrantSEM от клиентов. Мы используем данные, которые предоставляем AgrantSEM, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности AgrantSEM
Bidtellect
Мы используем Bidtellect для развертывания цифровой рекламы на сайтах, поддерживаемых Bidtellect. Реклама основывается на данных Bidtellect и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Bidtellect от клиентов. Мы используем данные, которые предоставляем Bidtellect, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Bidtellect
Bing
Мы используем Bing для развертывания цифровой рекламы на сайтах, поддерживаемых Bing. Реклама основывается на данных Bing и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Bing от клиентов. Мы используем данные, которые предоставляем Bing, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Bing
G2Crowd
Мы используем G2Crowd для развертывания цифровой рекламы на сайтах, поддерживаемых G2Crowd. Реклама основывается на данных G2Crowd и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными G2Crowd от клиентов. Мы используем данные, которые предоставляем G2Crowd, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности G2Crowd
NMPI Display
Мы используем NMPI Display для развертывания цифровой рекламы на сайтах, поддерживаемых NMPI Display. Реклама основывается на данных NMPI Display и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными NMPI Display от клиентов. Мы используем данные, которые предоставляем NMPI Display, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности NMPI Display
VK
Мы используем VK для развертывания цифровой рекламы на сайтах, поддерживаемых VK. Реклама основывается на данных VK и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными VK от клиентов. Мы используем данные, которые предоставляем VK, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности VK
Adobe Target
Мы используем Adobe Target для тестирования новых возможностей наших сайтов и их адаптации в соответствии с вашими потребностями. Для этого пока вы работаете с сайтами, мы собираем данные поведения. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса, идентификаторы устройств, учетные записи Autodesk и прочее. На основании тестирования возможностей изменяются версии сайтов. Кроме того, на основе атрибутов посетителей на сайтах появляется персонализированный контент. Политика конфиденциальности Adobe Target
Google Analytics (Advertising)
Мы используем Google Analytics (Advertising) для развертывания цифровой рекламы на сайтах, поддерживаемых Google Analytics (Advertising). Реклама основывается на данных Google Analytics (Advertising) и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Google Analytics (Advertising) от клиентов. Мы используем данные, которые предоставляем Google Analytics (Advertising), для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Google Analytics (Advertising)
Trendkite
Мы используем Trendkite для развертывания цифровой рекламы на сайтах, поддерживаемых Trendkite. Реклама основывается на данных Trendkite и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Trendkite от клиентов. Мы используем данные, которые предоставляем Trendkite, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Trendkite
Hotjar
Мы используем Hotjar для развертывания цифровой рекламы на сайтах, поддерживаемых Hotjar. Реклама основывается на данных Hotjar и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Hotjar от клиентов. Мы используем данные, которые предоставляем Hotjar, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Hotjar
6 Sense
Мы используем 6 Sense для развертывания цифровой рекламы на сайтах, поддерживаемых 6 Sense. Реклама основывается на данных 6 Sense и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными 6 Sense от клиентов. Мы используем данные, которые предоставляем 6 Sense, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности 6 Sense
Terminus
Мы используем Terminus для развертывания цифровой рекламы на сайтах, поддерживаемых Terminus. Реклама основывается на данных Terminus и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Terminus от клиентов. Мы используем данные, которые предоставляем Terminus, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Terminus
StackAdapt
Мы используем StackAdapt для развертывания цифровой рекламы на сайтах, поддерживаемых StackAdapt. Реклама основывается на данных StackAdapt и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными StackAdapt от клиентов. Мы используем данные, которые предоставляем StackAdapt, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности StackAdapt
The Trade Desk
Мы используем The Trade Desk для развертывания цифровой рекламы на сайтах, поддерживаемых The Trade Desk. Реклама основывается на данных The Trade Desk и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными The Trade Desk от клиентов. Мы используем данные, которые предоставляем The Trade Desk, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности The Trade Desk
RollWorks
We use RollWorks to deploy digital advertising on sites supported by RollWorks. Ads are based on both RollWorks data and behavioral data that we collect while you’re on our sites. The data we collect may include pages you’ve visited, trials you’ve initiated, videos you’ve played, purchases you’ve made, and your IP address or device ID. This information may be combined with data that RollWorks has collected from you. We use the data that we provide to RollWorks to better customize your digital advertising experience and present you with more relevant ads. RollWorks Privacy Policy

Вы уверены, что не хотите узнать обо всех возможностях работы с нашими службами в интернете?

Мы хотим, чтобы вам было комфортно работать с нами. Если вы выберете «Да» для категорий на предыдущем экране, мы будем собирать и использовать ваши данные для адаптации возможностей работы и оптимизации приложений. Настройки можно изменить в любой момент, посетив страницу заявления о конфиденциальности.

Удобство работы зависит от вас.

Мы заботимся о вашей конфиденциальности. Собираемые данные помогают нам понять, как вы используете наши продукты, какая информация может вас заинтересовать, а также, что можно изменить для улучшения вашего взаимодействия с компанией Autodesk.

Можем ли мы собирать и использовать ваши данные для адаптации возможностей работы?

Ознакомьтесь с преимуществами адаптированных возможностей работы благодаря управлению параметрами конфиденциальности для этого сайта или перейдите к нашему заявлению о конфиденциальности, чтобы узнать больше о возможных вариантах.