Programming Languages & Computer Graphics
प्रोग्रामिंग भाषाएँ
Unit overview: the topics below, with their summaries, are the syllabus for this unit. The comprehensive note further down covers every topic in full — explanations, definitions, worked examples, tables, exam points and practice questions — and the short revision note after it is only a quick recap. Standalone one-topic learning pages are not built yet — every topic on this page is covered in the notes and the practice questions below, and each topic card links to those sections.
Premium chapters for this unit
Programming paradigms & scope → premium chapter · free preview · ~15 min · 4 practice questions
OOP concepts → premium chapter · free preview · ~14 min · 4 practice questions
Computer graphics basics → premium chapter · free preview · ~15 min · 4 practice questions
Topics checklist — with weightage (platform estimate from past-question frequency, not an NTA guarantee)
Programming paradigms & scope
High weightageBinding, scope, recursion, parameter passing.
OOP concepts
High weightageEncapsulation, inheritance, polymorphism — with Java/Python examples.
Computer graphics basics
MediumRasterisation, transformations, clipping, 3D viewing.
Comprehensive unit note · ~22 min read
Programming languages are the tools through which human ideas about computation are turned into precise, executable instructions. This unit studies two linked questions: how languages are designed, and how computers draw pictures. The first question covers paradigms, scope, binding, parameter passing and object orientation. The second covers the mathematics of drawing lines, circles and shapes on a raster screen, transforming them, and deciding what is visible. A paradigm is a style of organising computation. Imperative programming describes step-by-step changes to state. Object-oriented programming groups state and behaviour into objects. Functional programming treats computation as the evaluation of functions without mutable state. Logic programming describes facts and rules and asks the system to derive answers. No paradigm is universally best; each fits some problems better, and modern languages often blend several. Scope, lifetime and binding decide which name means what, and when. Static scope resolves a name from the text of the program; dynamic scope resolves it from the call chain at run time. A variable lifetime is the period during which its storage exists, which is not the same as its visibility. Parameter passing decides whether a change inside a function reaches the caller. Computer graphics completes the unit. A raster display is a grid of pixels, so drawing a mathematically straight line or a perfect circle requires approximation, pixel by pixel. Transformation matrices move, scale and rotate objects, clipping discards the parts outside a window, and the viewing pipeline maps a three-dimensional scene onto a two-dimensional screen. The algorithms here are small and exact: you should be able to run Bresenham by hand and apply Cohen-Sutherland outcodes.
Learning objectives
- Classify a language or code fragment by paradigm and justify the classification from its defining features.
- Distinguish static from dynamic scope and binding, and predict the value printed by a program under each rule.
- Compare parameter-passing modes and predict whether a caller variable changes after a call.
- Explain encapsulation, inheritance, polymorphism and abstraction and apply overloading versus overriding correctly.
- Execute DDA and Bresenham line drawing and midpoint circle drawing step by step for small inputs.
- Apply 2D translation, scaling and rotation matrices to points and compose transformations in the correct order.
- Apply Cohen-Sutherland clipping and describe the viewing pipeline and hidden-surface removal approaches.
- Identify the common traps in scope, polymorphism, transformation order and clipping that cost marks in MCQs.
Overview
This unit has two halves that are examined differently. The programming-languages half rewards precise definitions and careful tracing: given a short program, what is printed, which function is called, and what changes? The graphics half rewards hand computation: given two endpoints, which pixels light up, and given a point and a matrix, where does the point land? Study them with different habits. For languages, trace small programs on paper under each rule before you look at the answer. For graphics, work one algorithm at a time with a table of steps, and check each row against the rule, not against a remembered picture.
Programming paradigms & scope
A programming paradigm is a coherent set of concepts for structuring programs. The imperative paradigm is built on variables, assignment and control flow: a program is a sequence of commands that changes state, as in C and Pascal. The object-oriented paradigm organises state and behaviour into objects that exchange messages; it is often implemented on top of imperative ideas, as in Java, C++ and Python. The functional paradigm treats computation as function evaluation, avoids mutable state and side effects where possible, and favours recursion, higher-order functions and immutable data, as in Haskell and the functional parts of Python. The logic paradigm, exemplified by Prolog, declares facts and rules; execution is search for a proof that satisfies a query, with unification binding variables to values. Declarative programming is the wider family that includes functional and logic styles: the programmer states what is wanted rather than the exact steps.
Binding is the association of a name with a property, such as its type, its value or its storage. Static binding is fixed before or at compile time, for example a variable declared with a fixed type in C, or a non-virtual function call resolved by the compiler. Dynamic binding is deferred to run time, for example a virtual function call in C++ or Java, where the method executed depends on the actual object type, not the declared reference type. Early binding is efficient; late binding is flexible and powers runtime polymorphism.
Scope is the region of the program where a name is visible. Under static, or lexical, scope, a free variable refers to the declaration in the nearest enclosing block in the program text. Most modern languages use static scope. Under dynamic scope, a free variable refers to the most recent binding on the call stack at run time, so the same function can print different values depending on who called it. Lifetime is different from scope: it is the interval during which storage for a variable exists. A local variable typically lives only during its function activation, while a static variable in C lives for the whole program run even though it is visible only inside its function. A global variable has both wide scope and long lifetime. Confusing scope with lifetime is a classic exam trap.
Parameter passing determines the relationship between an actual argument and a formal parameter. Pass by value copies the value, so changes to the parameter do not affect the caller; C passes by value by default. Pass by reference gives the parameter access to the caller's variable itself, so changes persist; C++ references and the effect of passing a pointer in C achieve this. Pass by name, historically in Algol, substitutes the argument expression textually and re-evaluates it on every use, which can give surprising results when the expression has side effects. Pass by value-result copies in on entry and copies back on return, so intermediate changes are invisible to the caller until the function returns. Python uses a model often called pass by object reference: the reference to the object is copied, so mutating a list inside a function is visible to the caller, but rebinding the parameter name is not.
Type systems add another dimension. A statically typed language checks types at compile time; a dynamically typed language checks them at run time. Strong typing restricts implicit conversions that would change meaning; weak typing permits them more freely. Type checking can be static or dynamic independently of strong or weak typing, and the exam often tests the four combinations. Recursion is the technique of defining a function in terms of itself, with a base case that stops the recursion and a recursive case that reduces the problem; without a reachable base case the program recurses until the stack overflows. A closure is a function together with the environment in which it was defined, so it can remember variables from its enclosing scope after that scope has finished executing.
How this is examined: expect questions that ask which paradigm a snippet belongs to, what a program prints under static versus dynamic scope, whether a caller variable changes under a given passing mode, and which binding time applies to a virtual call. Work by naming the rule first, then tracing, never by intuition about what the program ought to do.
OOP concepts
Object-oriented programming organises a program around objects, which bundle data and the operations on that data. Encapsulation is the bundling itself together with hiding of internal details: an object exposes an interface and keeps its representation private, so clients depend on behaviour rather than on fields. Abstraction is the related idea of exposing only the essential features and suppressing irrelevant detail; an abstract class or interface is abstraction made explicit in code. Inheritance lets a new class reuse and extend an existing class: the subclass inherits fields and methods and can add or replace behaviour. Polymorphism means one interface with many forms: the same call can behave differently depending on the object it acts on. Together these four ideas explain most object-oriented design questions.
A class is a blueprint; an object is an instance of a class. A constructor is a special method that runs when an object is created and initialises its state. In Java a constructor has the same name as the class and no return type; in Python the initialiser is the method named __init__. A default constructor takes no arguments; a parameterised constructor takes arguments. In garbage-collected languages, finaliser timing is not guaranteed, so it must not be relied on for essential cleanup.
Overloading and overriding are the two faces of polymorphism and are constantly confused. Overloading is compile-time polymorphism: several methods in the same class share a name but differ in their parameter lists, in number, type or order of parameters. The compiler picks the version by matching the call arguments. Overriding is runtime polymorphism: a subclass provides its own implementation of a method already defined in its superclass, with the same name and the same parameter list. The version executed is chosen at run time from the actual object type, provided the method is virtual or dynamically dispatched. Overloading is resolved by the compiler; overriding is resolved at run time. Changing only the return type does not overload a method in Java, and changing the parameter list does not override one.
An abstract class is a class that cannot be instantiated directly and may contain abstract methods without bodies; subclasses must implement them unless they are also abstract. An interface declares a contract of methods without, in the classic form, providing implementations; a class implements an interface by supplying all its methods. A class in Java extends one superclass but can implement several interfaces, which is how Java provides multiple inheritance of type without multiple inheritance of implementation. Access control shapes all of this: public members are visible everywhere, private members only inside the class, and protected members inside the class, its subclasses and, in Java, its package. A static member belongs to the class rather than to any instance, and a final member in Java cannot be reassigned, overridden or extended, depending on what it qualifies.
Inheritance has forms worth naming. Single inheritance has one direct superclass; multilevel inheritance chains classes; hierarchical inheritance has several subclasses of one superclass; multiple inheritance has several direct superclasses, permitted in C++ and Python but not as class inheritance in Java. The diamond problem arises in multiple inheritance when two superclasses share a common ancestor and the subclass inherits the same member through both paths; languages resolve it by rules such as method resolution order in Python or by virtual inheritance in C++. Composition, where a class holds an object of another class, is often preferable when the relationship is has-a rather than is-a.
How this is examined: expect code-tracing questions asking which overloaded method matches a call, which overridden method runs for a reference of one type holding an object of another, whether a class can be instantiated, and which access modifier permits a given access. Answer by checking, in order, the reference type, the object type, the parameter list and the dispatch rule, rather than by reading the code as if it were prose.
Computer graphics basics
Computer graphics produces pictures from numerical descriptions. In raster graphics the picture is a grid of pixels, each with a colour value stored in a frame buffer; in vector graphics the picture is a list of geometric primitives such as lines and curves, which are resolution independent but must be rasterised to display. A raster display needs algorithms that decide which pixels best approximate a mathematical shape.
Line drawing is the fundamental case. The Digital Differential Analyzer, or DDA, samples a line at unit steps in the dominant direction: if the absolute slope is at most one, step x by one and add the slope to y; otherwise step y by one and add the reciprocal slope to x, rounding each computed coordinate to the nearest pixel. DDA is simple but uses floating-point addition and rounding at every step, which makes it slower and less accurate over long lines. Bresenham line algorithm uses only integer arithmetic. For a line with slope between zero and one, it maintains a decision parameter that tracks the error between the true line and the chosen pixel; at each step it moves one pixel in x and decides, from the sign of the parameter, whether to also move one pixel in y, updating the parameter by fixed integer amounts. Bresenham is faster, exact in integer arithmetic, and is the standard answer when a question asks for the efficient line algorithm. The midpoint circle algorithm applies the same decision-parameter idea to circles, exploiting eight-way symmetry: compute pixels for one octant and mirror them to the other seven. It starts at the top of the circle and steps in x, deciding at each step whether to move in y, with the decision parameter updated by integer rules derived from the circle equation.
Transformations change the position, size or orientation of objects. In two dimensions, translation by (tx, ty) sends (x, y) to (x plus tx, y plus ty). Scaling by (sx, sy) sends (x, y) to (sx times x, sy times y). Rotation by angle theta about the origin sends (x, y) to (x cos theta minus y sin theta, x sin theta plus y cos theta). Using homogeneous coordinates, a point is written as (x, y, 1) and each transformation becomes a three by three matrix, so transformations can be composed by matrix multiplication and applied in one step. Order matters: matrix multiplication is not commutative, so scaling then translating generally differs from translating then scaling. Rotation and scaling are normally performed about the origin, so rotating about another point requires translating that point to the origin, rotating, and translating back. Three-dimensional transformations extend the same idea with four by four matrices.
Clipping removes the parts of a picture outside a viewing window. The Cohen-Sutherland line clipping algorithm assigns each endpoint a four-bit outcode recording whether the point is above, below, to the left of, or to the right of the window. If the bitwise AND of the two outcodes is non-zero, the line is trivially rejected because both endpoints share an outside region. If both outcodes are zero, the line is trivially accepted. Otherwise the line is partially visible: an endpoint outside the window is replaced by its intersection with a window edge, its outcode is recomputed, and the process repeats. The viewing pipeline as a whole runs from modelling coordinates, through world coordinates, to viewing coordinates, then to normalised device coordinates, and finally to device or screen coordinates by a viewport mapping. Hidden-surface removal decides which surfaces are visible in a three-dimensional scene: the depth-buffer, or Z-buffer, algorithm keeps, for each pixel, the smallest depth seen so far and draws only a surface nearer than the stored value; the painter algorithm sorts surfaces by depth and draws them back to front, which is simpler but fails when surfaces overlap cyclically or intersect.
How this is examined: expect a Bresenham table for a short line, a matrix applied to a point, a statement of which transformation order is correct, a Cohen-Sutherland accept or reject decision from outcodes, and a comparison of DDA with Bresenham or of Z-buffer with painter.
Key definitions
- Paradigm: A style of organising computation, such as imperative, object-oriented, functional or logic programming.
- Binding: The association of a name with a property such as type or storage; static binding is fixed before run time, dynamic binding at run time.
- Scope: The region of a program in which a name is visible and can be referred to; static scope uses program text, dynamic scope uses the run-time call chain.
- Lifetime: The interval during which storage for a variable exists, which is distinct from the region in which its name is visible.
- Closure: A function together with its defining environment, accessible after that scope has finished.
- Encapsulation: Bundling data and the operations on it into an object and hiding internal representation behind an interface.
- Abstraction: Exposing only the essential features of an object while suppressing irrelevant detail, often expressed through abstract classes or interfaces.
- Inheritance: A mechanism by which a subclass reuses and extends the fields and methods of a superclass.
- Polymorphism: One interface taking many forms, so the same call behaves differently depending on the object it acts on.
- Overloading: Compile-time polymorphism in which several methods in one class share a name but differ in their parameter lists.
- Overriding: Runtime polymorphism in which a subclass supplies its own implementation of a superclass method with the same name and parameter list.
- Abstract class: A class that cannot be instantiated directly and may contain abstract methods that subclasses must implement.
- Interface: A contract declaring methods that an implementing class must supply, without providing their implementations in the classic form.
- Raster graphics: Graphics represented as a grid of pixels with colour values, stored in a frame buffer.
- Vector graphics: Graphics represented as geometric primitives such as lines and curves, which are resolution independent.
- DDA algorithm: A line-drawing algorithm that samples at unit steps in the dominant direction using floating-point increments and rounding.
- Bresenham algorithm: An integer-only line-drawing algorithm that uses a decision parameter to choose, at each step, whether to increment the secondary coordinate.
- Homogeneous coordinates: Representing a 2D point as (x, y, 1) so that translation, scaling and rotation can all be expressed as matrix multiplication.
- Clipping: Removing the parts of a picture that lie outside a specified viewing window.
- Z-buffer: A hidden-surface method that stores, for each pixel, the depth of the nearest surface drawn so far and draws only nearer surfaces.
Formulas
- 2D translation: (x, y) -> (x + tx, y + ty)
- 2D scaling: (x, y) -> (sx * x, sy * y)
- 2D rotation: x_new = x cos theta - y sin theta; y_new = x sin theta + y cos theta
- Bresenham (slope 0 to 1): p0 = 2 dy - dx; if p < 0 then p = p + 2 dy, else p = p + 2 dy - 2 dx and y increases by 1
- DDA step: if |m| <= 1, x increases by 1 and y increases by m; otherwise y increases by 1 and x increases by 1/m
- Midpoint circle decision: p0 = 1 - r; if p < 0 then p = p + 2x + 3, else p = p + 2x - 2y + 5 and y decreases by 1
Worked examples
Example 1: Run Bresenham line drawing from (0, 0) to (5, 3) and list the pixels chosen.
Here dx = 5 - 0 = 5 and dy = 3 - 0 = 3, so the slope is between 0 and 1 and x is the driving axis. The initial decision parameter is p0 = 2 dy - dx = 2 times 3 - 5 = 1. Start at (0, 0) with p = 1. Step 1: p is not less than 0, so move to (1, 1) and update p = 1 + 2 dy - 2 dx = 1 + 6 - 10 = -3. Step 2: p is less than 0, so move to (2, 1) and update p = -3 + 2 dy = -3 + 6 = 3. Step 3: p is not less than 0, so move to (3, 2) and update p = 3 + 6 - 10 = -1. Step 4: p is less than 0, so move to (4, 2) and update p = -1 + 6 = 5. Step 5: p is not less than 0, so move to (5, 3) and stop. The pixels are (0, 0), (1, 1), (2, 1), (3, 2), (4, 2) and (5, 3).
Example 2: Apply scaling by (2, 3) followed by translation by (4, -1) to the point (3, 2). Then show what translating first would give, to demonstrate that order matters.
Scale first: (3, 2) scaled by (2, 3) gives (2 times 3, 3 times 2) = (6, 6). Then translate by (4, -1) to get (6 + 4, 6 - 1) = (10, 5). Translate first instead: (3, 2) translated by (4, -1) gives (7, 1). Then scaling by (2, 3) gives (2 times 7, 3 times 1) = (14, 3). The results (10, 5) and (14, 3) differ, so composition order matters and must be stated in any answer.
Example 3: A window runs from x = 10 to x = 30 and y = 10 to y = 30. A line has endpoints A = (5, 20) and B = (40, 20). Use Cohen-Sutherland outcodes to decide the first step.
Use the bit order top, bottom, right, left. Point A = (5, 20) is left of the window, so its outcode is 0001. Point B = (40, 20) is right of the window, so its outcode is 0010. The bitwise AND is 0000, so the line is not trivially rejected. Neither outcode is 0000, so it is not trivially accepted either. It is a candidate for clipping: the outside endpoint is replaced by its intersection with a window edge, here (10, 20) for A or (30, 20) for B, and the outcodes are recomputed. The final visible segment is from (10, 20) to (30, 20).
Example 4: A Java reference of superclass type holds a subclass object, and both classes define a method show with the same parameter list. Which version runs, and why?
The subclass version runs. Overriding is resolved at run time from the actual object type, not the declared reference type, because the method is dynamically dispatched. If the subclass had instead used a different parameter list, that would be overloading, chosen by the compiler from the call arguments.
Parameter-passing modes compared
| Mode | What the parameter receives | Caller change visible? |
|---|---|---|
| Pass by value | A copy of the value | No |
| Pass by reference | The caller variable itself | Yes |
| Pass by name | The argument expression, re-evaluated on each use | Depends on the expression and its side effects |
| Pass by value-result | A copy in, copied back on return | Only after return |
Overloading versus overriding
| Feature | Overloading | Overriding |
|---|---|---|
| When resolved | Compile time | Run time |
| Where | Same class | Subclass versus superclass |
| Parameter list | Must differ | Must be the same |
| Also called | Compile-time polymorphism | Runtime polymorphism |
DDA versus Bresenham
| Feature | DDA | Bresenham |
|---|---|---|
| Arithmetic | Floating point | Integer only |
| Speed | Slower, with rounding each step | Faster |
| Accuracy over long lines | Drift from rounding can accumulate | Exact in integer arithmetic |
Scope and binding contrasts
| Pair | First member | Second member |
|---|---|---|
| Scope | Static: program text decides | Dynamic: call chain decides |
| Name property | Scope: where visible | Lifetime: how long storage exists |
| Binding time | Static: before or at compile time | Dynamic: at run time |
Diagrams (described)
Viewing pipeline flowchart: modelling coordinates -> world coordinates -> viewing coordinates -> normalised device coordinates -> viewport mapping -> device coordinates.
Cohen-Sutherland window diagram: a rectangle divided into nine regions by extending its edges, with the central region coded 0000 and each surrounding region coded by its position (top, bottom, right, left bits).
Bresenham decision diagram: the true line passing between two candidate pixels at each x step, with the decision parameter selecting the nearer pixel and the error carried to the next step.
Class hierarchy diagram: a superclass box with shared fields and methods, arrows to subclass boxes that add fields, add methods, or override a method, labelled is-a.
Exam points
- Bresenham uses integer arithmetic only; DDA uses floating-point increments and rounding, which is why Bresenham is preferred for speed and accuracy.
- Static scope resolves names from program text; dynamic scope resolves them from the run-time call stack. Most modern languages use static scope.
- Overloading differs in the parameter list and is resolved at compile time; overriding keeps the same parameter list and is resolved at run time.
- In homogeneous coordinates, translation becomes matrix multiplication, which is why transformations can be composed by multiplying matrices.
- Cohen-Sutherland trivial rejection needs a non-zero bitwise AND of the two endpoint outcodes; a zero AND does not mean the line is visible.
- A midpoint circle algorithm computes one octant and mirrors it by eight-way symmetry; it does not compute all pixels independently.
- Pass by value cannot change a caller scalar variable; passing a pointer in C or a reference in C++ can. In Python, mutating a passed list is visible but rebinding the parameter name is not.
- An abstract class cannot be instantiated; an interface in its classic form declares methods that the implementing class must supply.
- Transformation order matters because matrix multiplication is not commutative: scale then translate differs from translate then scale.
- The Z-buffer stores per-pixel depth and draws only nearer surfaces; the painter algorithm draws back to front and fails on cyclic overlaps.
Common mistakes
- Mistake: treating scope and lifetime as the same thing. Correction: scope is where a name is visible; lifetime is how long its storage exists. A static local has narrow scope but program-long lifetime.
- Mistake: calling any same-name method overriding. Correction: same parameter list in a subclass is overriding; a different parameter list in the same class is overloading. Check the list first.
- Mistake: assuming a zero bitwise AND in Cohen-Sutherland means the line is visible. Correction: zero AND only rules out trivial rejection; the line may still be partially outside and need clipping.
- Mistake: applying transformations in the wrong order. Correction: write the intended sequence explicitly and multiply matrices in that order; test with a point, as the worked example does.
- Mistake: saying DDA is faster because it is simpler. Correction: DDA is simpler to describe but uses floating-point arithmetic and rounding each step; Bresenham is the faster integer method.
- Mistake: claiming pass by value in Python means a list cannot change. Correction: Python passes a reference to the object, so mutating the list is visible; only rebinding the parameter name is invisible to the caller.
- Mistake: instantiating an abstract class or expecting a destructor to run at a predictable time in a garbage-collected language. Correction: abstract classes cannot be instantiated, and finaliser timing is not guaranteed.
Practice questions from this note (original practice — not official PYQs)
Checking login…
Quick revision: Paradigms: imperative changes state step by step; object-oriented groups state and behaviour; functional evaluates functions without mutable state; logic derives answers from facts and rules. Scope: static uses program text, dynamic uses the call stack; lifetime is storage duration, not visibility. Binding: static is fixed early, dynamic waits until run time and powers overriding. Passing: value copies, reference shares the variable, name re-evaluates, Python passes an object reference so mutation shows but rebinding does not. OOP: encapsulation hides representation, abstraction exposes essentials, inheritance is is-a, polymorphism is one interface with many forms; overloading differs in parameters at compile time, overriding keeps parameters at run time. Graphics: DDA floats and rounds, Bresenham uses integers and a decision parameter; midpoint circle uses one octant plus symmetry; transformations compose by matrix multiplication and order matters; Cohen-Sutherland uses outcodes, non-zero AND means reject; Z-buffer keeps nearest depth per pixel.
Unit revision note (quick recap)
Languages differ in how they bind names, pass arguments and organise code. Graphics differs in how a picture is represented and transformed.
Learning objectives
- Explain scope, binding and parameter passing
- Explain OOP pillars
- Explain graphics transformations
Key concepts
- Lexical (static) scope: A variable’s binding is decided by where code is written, not where it is called from.
- Encapsulation: Bundling data with the methods that operate on it, hiding internal state.
- Polymorphism: One interface, many forms: the same call behaves differently by object type.
- Rasterisation: Converting vector shapes into pixels.
Worked examples
- An ATM hides its cash box behind deposit/withdraw methods — encapsulation in one sentence.
Exam points
- Call by value copies; call by reference shares the variable.
- Inheritance reuses, composition assembles — prefer composition when reuse is not an "is-a" relation.
Common mistakes
- Calling every reuse "inheritance" — a car "has" an engine, it is not an engine.
Quick revision: Paradigms, scope/binding, OOP, graphics pipeline, transformations, clipping.
Practice questions from the whole unit bank (33 in the bank)
This unit's practice bank — the note above has its own smaller practice set drawn from the same bank, so a question can appear in both lists. The list below shows the free sample or the full bank depending on your plan.
Checking login…
Related tests
Unit test for this unit (33 bank questions, 40 min) · Full Mock — CS Paper 2 (100 questions) · Combined 150-question mock (180 min). All +2 per correct, no negative marking.
Revision summary
Paradigms, scope/binding, OOP, graphics pipeline, transformations, clipping.
After revising, take the unit test above, then check your unit-wise report on the Dashboard to find weak topics.